diff --git a/ui/app/components/TaskDefinitionEditor.vue b/ui/app/components/TaskDefinitionEditor.vue index 7d6de469..9d7729f6 100644 --- a/ui/app/components/TaskDefinitionEditor.vue +++ b/ui/app/components/TaskDefinitionEditor.vue @@ -437,7 +437,7 @@ const isBusy = computed(() => loading.value || submitting.value) const headerTitle = computed(() => props.title) const guiLimitations = 'Only simple match globs, a single container selector and per-field extractors are exposed. ' + - 'More advanced constructs require editing the JSON.' + 'More advanced constructs require raw view mode.' const resetGuiState = (state: GuiState): void => { guiState.name = state.name @@ -471,7 +471,7 @@ const toGui = (document: TaskDefinitionDocument): GuiState | null => { return null } - const entry = document as Record + const entry = document const match = entry.match if (!Array.isArray(match) || match.some(item => 'string' !== typeof item)) { return null @@ -614,7 +614,7 @@ const fromGui = (state: GuiState): TaskDefinitionDocument => { doc.request = request } - return doc as TaskDefinitionDocument + return doc as unknown as TaskDefinitionDocument } const parseImportedDocument = (payload: unknown): TaskDefinitionDocument => { @@ -637,7 +637,7 @@ const parseImportedDocument = (payload: unknown): TaskDefinitionDocument => { } const clone = JSON.parse(JSON.stringify(base)) as TaskDefinitionDocument - const cloneRecord = clone as Record + const cloneRecord = clone if ('name' in record && 'string' === typeof record.name) { cloneRecord.name = record.name diff --git a/ui/app/components/TaskInspect.vue b/ui/app/components/TaskInspect.vue new file mode 100644 index 00000000..78752dad --- /dev/null +++ b/ui/app/components/TaskInspect.vue @@ -0,0 +1,154 @@ + + + + + + diff --git a/ui/app/pages/task_definitions.vue b/ui/app/pages/task_definitions.vue index c9a1dbff..47a0ea5b 100644 --- a/ui/app/pages/task_definitions.vue +++ b/ui/app/pages/task_definitions.vue @@ -12,13 +12,19 @@

-

+

+ +

+

+ + + + + @@ -237,6 +248,7 @@ const editorLoading = ref(false) const editorSubmitting = ref(false) const workingDefinition = ref(null) const workingId = ref(null) +const inspect = ref(false) const display_style = useStorage<'list' | 'grid'>('task-definitions:display', 'grid') const currentSummary = computed(() => { diff --git a/ui/app/pages/tasks.vue b/ui/app/pages/tasks.vue index 3533f8c9..daed0bbf 100644 --- a/ui/app/pages/tasks.vue +++ b/ui/app/pages/tasks.vue @@ -200,6 +200,11 @@ Run now + + + Inspect Handler + + @@ -324,6 +329,11 @@ Run now + + + Inspect Handler + + @@ -376,6 +386,10 @@ + + + + @@ -383,6 +397,8 @@ import moment from 'moment' import { useStorage } from '@vueuse/core' import { CronExpressionParser } from 'cron-parser' +import Modal from '~/components/Modal.vue' +import TaskInspect from '~/components/TaskInspect.vue' import type { task_item, exported_task, error_response } from '~/types/tasks' const box = useConfirm() @@ -405,6 +421,7 @@ const masterSelectAll = ref(false) const massRun = ref(false) const massDelete = ref(false) const table_container = ref(false) +const inspectTask = ref(null) const reset_dialog = () => ({ visible: false, diff --git a/ui/app/types/task_inspect.d.ts b/ui/app/types/task_inspect.d.ts new file mode 100644 index 00000000..7ce17e16 --- /dev/null +++ b/ui/app/types/task_inspect.d.ts @@ -0,0 +1,20 @@ +// Types for api/tasks/inspect + +export interface TaskInspectRequest { + url: string; + preset?: string; + handler?: string; +} + +export interface TaskInspectSuccess { + // The structure depends on TaskResult, but at minimum: + success?: boolean; + [key: string]: unknown; +} + +export interface TaskInspectError { + error: string; + message?: string; +} + +export type TaskInspectResponse = TaskInspectSuccess | TaskInspectError;