From c2ba681a169ab43406d749fd662b5fabd53fedb2 Mon Sep 17 00:00:00 2001 From: Alex Tideman Date: Tue, 29 Oct 2024 15:28:32 -0500 Subject: [PATCH 01/30] Use __user_metadata query if it exists --- src/lib/pages/workflow-query.svelte | 19 +++++++++------ src/lib/services/query-service.ts | 24 +++++++++++++++++-- .../utilities/get-query-types-from-error.ts | 6 ++--- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/lib/pages/workflow-query.svelte b/src/lib/pages/workflow-query.svelte index e85e548c8..3406630ff 100644 --- a/src/lib/pages/workflow-query.svelte +++ b/src/lib/pages/workflow-query.svelte @@ -37,11 +37,15 @@ $: edited = initialQueryType !== queryType || input !== initialInput; - let queryTypes = getQueryTypes({ - namespace, - workflow: params, - }).then((queryTypes) => { - queryType = queryType || queryTypes[0]; + let queryTypes = getQueryTypes( + { + namespace, + workflow: params, + }, + $page.data?.settings, + $authUser?.accessToken, + ).then((queryTypes) => { + queryType = queryType || queryTypes[0]?.name; query(queryType); return queryTypes; }); @@ -96,12 +100,13 @@
diff --git a/src/lib/services/query-service.ts b/src/lib/services/query-service.ts index c0c9b1940..a1291ac34 100644 --- a/src/lib/services/query-service.ts +++ b/src/lib/services/query-service.ts @@ -91,10 +91,30 @@ async function fetchQuery( } export async function getQueryTypes( + options: WorkflowParameters, + settings: Settings, + accessToken: string, +): Promise<{ name: string; description?: string }[]> { + try { + const response = await getQuery( + { ...options, queryType: '__temporal_workflow_metadata' }, + settings, + accessToken, + ); + const results = parseWithBigInt(response); + return results?.definition?.queryDefinitions?.filter((query) => { + return query?.name !== '__stack_trace'; + }); + } catch (e) { + return getQueryTypesByError(options); + } +} + +export async function getQueryTypesByError( options: WorkflowParameters, request = fetch, -): Promise { - return new Promise((resolve, reject) => { +): Promise<{ name: string }[]> { + return new Promise<{ name: string }[]>((resolve, reject) => { fetchQuery( { ...options, queryType: '@@temporal-internal__list' }, request, diff --git a/src/lib/utilities/get-query-types-from-error.ts b/src/lib/utilities/get-query-types-from-error.ts index d6fddf2d2..3016299da 100644 --- a/src/lib/utilities/get-query-types-from-error.ts +++ b/src/lib/utilities/get-query-types-from-error.ts @@ -1,4 +1,4 @@ -export const getQueryTypesFromError = (message: string): string[] => { +export const getQueryTypesFromError = (message: string): { name: string }[] => { const indexOfOpeningBracket = message.indexOf('['); const indexOfClosingBracket = message.indexOf(']'); @@ -8,9 +8,9 @@ export const getQueryTypesFromError = (message: string): string[] => { .filter((query: string) => query !== '__stack_trace') .map((query: string) => { if (query.endsWith(',')) { - return query.slice(0, query.length - 1); + return { name: query.slice(0, query.length - 1) }; } else { - return query; + return { name: query }; } }); }; From 29de6adc0465d732fdbad9e8e9f962e8870fce97 Mon Sep 17 00:00:00 2001 From: Alex Tideman Date: Tue, 29 Oct 2024 15:39:49 -0500 Subject: [PATCH 02/30] Update unit tests --- .../utilities/get-query-types-from-error.test.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/lib/utilities/get-query-types-from-error.test.ts b/src/lib/utilities/get-query-types-from-error.test.ts index 5612745fb..f1c306388 100644 --- a/src/lib/utilities/get-query-types-from-error.test.ts +++ b/src/lib/utilities/get-query-types-from-error.test.ts @@ -30,22 +30,22 @@ const javaSDKError = { describe('getQueryTypesFromError', () => { it('should return an array of query types', () => { - const queryTypes = ['__open_sessions']; + const queryTypes = [{ name: '__open_sessions' }]; expect(getQueryTypesFromError(error.message)).toEqual(queryTypes); }); it('should omit __stack_traces', () => { - expect(getQueryTypesFromError(error.message)).not.toContain( - '__stack_trace', - ); + expect(getQueryTypesFromError(error.message)).not.toContain({ + name: '__stack_trace', + }); }); it('should work with the Java SDK', () => { expect(getQueryTypesFromError(javaSDKError.message)).toEqual([ - 'getLoan', - 'getNextPaymentDue', - 'getPaymentObligations', - 'getNextPaymentObligation', + { name: 'getLoan' }, + { name: 'getNextPaymentDue' }, + { name: 'getPaymentObligations' }, + { name: 'getNextPaymentObligation' }, ]); }); }); From 44f385108a0e704308d87a668ab92a23cc8e3521 Mon Sep 17 00:00:00 2001 From: Alex Tideman Date: Wed, 30 Oct 2024 10:56:06 -0500 Subject: [PATCH 03/30] Use __user_metadata query if it exists (#2411) * Use __user_metadata query if it exists * Update unit tests * Fix tests to not mock response --- src/lib/services/query-service.ts | 46 +++++++------------------------ temporal/codec-server.ts | 11 ++------ tests/e2e/storageState.json | 12 +------- tests/e2e/workflows.spec.ts | 7 +++-- 4 files changed, 17 insertions(+), 59 deletions(-) diff --git a/src/lib/services/query-service.ts b/src/lib/services/query-service.ts index a1291ac34..1be933fd2 100644 --- a/src/lib/services/query-service.ts +++ b/src/lib/services/query-service.ts @@ -4,14 +4,8 @@ import type { Eventual, Settings } from '$lib/types/global'; import { convertPayloadToJsonWithCodec } from '$lib/utilities/decode-payload'; import { getQueryTypesFromError } from '$lib/utilities/get-query-types-from-error'; import { has } from '$lib/utilities/has'; -import { - parseWithBigInt, - stringifyWithBigInt, -} from '$lib/utilities/parse-with-big-int'; -import { - isTemporalAPIError, - requestFromAPI, -} from '$lib/utilities/request-from-api'; +import { stringifyWithBigInt } from '$lib/utilities/parse-with-big-int'; +import { requestFromAPI } from '$lib/utilities/request-from-api'; import { routeForApi } from '$lib/utilities/route-for-api'; type QueryRequestParameters = { @@ -96,42 +90,23 @@ export async function getQueryTypes( accessToken: string, ): Promise<{ name: string; description?: string }[]> { try { - const response = await getQuery( + const result = await getQuery( { ...options, queryType: '__temporal_workflow_metadata' }, settings, accessToken, ); - const results = parseWithBigInt(response); - return results?.definition?.queryDefinitions?.filter((query) => { + return result?.definition?.queryDefinitions?.filter((query) => { return query?.name !== '__stack_trace'; }); } catch (e) { - return getQueryTypesByError(options); + if (e.message?.includes('__temporal_workflow_metadata')) { + return getQueryTypesFromError(e.message); + } else { + throw e; + } } } -export async function getQueryTypesByError( - options: WorkflowParameters, - request = fetch, -): Promise<{ name: string }[]> { - return new Promise<{ name: string }[]>((resolve, reject) => { - fetchQuery( - { ...options, queryType: '@@temporal-internal__list' }, - request, - (response) => { - if ( - isTemporalAPIError(response.body) && - response.body.message.includes('@@temporal-internal__list') - ) { - resolve(getQueryTypesFromError(response.body.message)); - } else { - reject(response); - } - }, - ); - }); -} - export async function getQuery( options: QueryRequestParameters, settings: Settings, @@ -158,8 +133,7 @@ export async function getQuery( data = convertedAttributes.payloads[0]; } } - - return parseWithBigInt(data); + return data; } catch (e) { if (typeof data !== 'string') { return stringifyWithBigInt(data); diff --git a/temporal/codec-server.ts b/temporal/codec-server.ts index f443b51d7..3d37ab476 100644 --- a/temporal/codec-server.ts +++ b/temporal/codec-server.ts @@ -24,13 +24,6 @@ interface Body { const PORT = 8888; -const MOCK_DECODED_PAYLOAD = { - metadata: { - encoding: Buffer.from('json/plain').toString('base64'), - }, - data: 'Mock decoded payload', -}; - let codecServer: CodecServer; export const getCodecServer = (): CodecServer => codecServer; @@ -46,7 +39,7 @@ export async function createCodecServer( app.post('/encode', async (req, res) => { try { const { payloads: raw } = req.body as Body; - res.json({ payloads: raw.map(() => MOCK_DECODED_PAYLOAD) }).end(); + res.json({ payloads: raw }).end(); } catch (err) { console.error('Error in /encode', err); res.status(500).end('Internal server error'); @@ -56,7 +49,7 @@ export async function createCodecServer( app.post('/decode', async (req, res) => { try { const { payloads: raw } = req.body as Body; - res.json({ payloads: raw.map(() => MOCK_DECODED_PAYLOAD) }).end(); + res.json({ payloads: raw }).end(); } catch (err) { console.error('Error in /decode', err); res.status(500).end('Internal server error'); diff --git a/tests/e2e/storageState.json b/tests/e2e/storageState.json index 8d0a4c6cf..f4ec35503 100644 --- a/tests/e2e/storageState.json +++ b/tests/e2e/storageState.json @@ -1,14 +1,4 @@ { "cookies": [], - "origins": [ - { - "origin": "http://localhost:3000", - "localStorage": [ - { - "name": "locale", - "value": "en-US" - } - ] - } - ] + "origins": [] } \ No newline at end of file diff --git a/tests/e2e/workflows.spec.ts b/tests/e2e/workflows.spec.ts index 4cbdd3734..7d5e86f2b 100644 --- a/tests/e2e/workflows.spec.ts +++ b/tests/e2e/workflows.spec.ts @@ -12,7 +12,8 @@ test.describe('Workflow Execution Page', () => { .click({ force: true }); const inputAndResult = page.getByTestId('input-and-result'); - await expect(inputAndResult).toContainText('Mock decoded payload'); + await expect(inputAndResult).toContainText('Plain text input 1'); + await expect(inputAndResult).toContainText('Received Plain text input 1'); }); test('should render decoded call stack', async ({ page }) => { @@ -26,7 +27,7 @@ test.describe('Workflow Execution Page', () => { await tab.click(); const codeBlock = page.getByRole('textbox'); - await expect(codeBlock).toContainText('Mock decoded payload'); + await expect(codeBlock).toContainText('at workflow'); }); test('should render decoded query results', async ({ page }) => { @@ -42,6 +43,6 @@ test.describe('Workflow Execution Page', () => { await page.getByRole('button', { name: /query/i }).click(); const codeBlock = page.getByTestId('query-result').getByRole('textbox'); - await expect(codeBlock).toContainText('Mock decoded payload'); + await expect(codeBlock).toContainText('true'); }); }); From 62de71f08dac55e5f73f5b53213e2d497a2f20f0 Mon Sep 17 00:00:00 2001 From: Alex Tideman Date: Wed, 30 Oct 2024 13:56:49 -0500 Subject: [PATCH 04/30] Add types, update start workflow to pass a summary and details, update Workflow Header to show summary and details and workflow stats above tabs --- package.json | 14 +-- pnpm-lock.yaml | 100 +++++++++--------- .../lines-and-dots/workflow-detail.svelte | 18 ++-- .../lines-and-dots/workflow-details.svelte | 39 ++++--- .../payload-input-with-encoding.svelte | 3 +- src/lib/holocene/monaco/markdown.svelte | 2 +- src/lib/layouts/workflow-header.svelte | 12 ++- .../layouts/workflow-history-layout.svelte | 2 - src/lib/layouts/workflow-run-layout.svelte | 4 +- src/lib/models/workflow-execution.ts | 8 ++ src/lib/pages/start-workflow.svelte | 35 ++++++ src/lib/services/workflow-service.ts | 8 ++ src/lib/types/workflows.ts | 13 ++- 13 files changed, 171 insertions(+), 87 deletions(-) diff --git a/package.json b/package.json index fa446eacb..8083fac16 100644 --- a/package.json +++ b/package.json @@ -137,13 +137,13 @@ "@sveltejs/adapter-vercel": "^4.0.0", "@sveltejs/kit": "^2.5.0", "@sveltejs/vite-plugin-svelte": "^3.0.2", - "@temporalio/activity": "1.10.3", - "@temporalio/client": "1.10.3", - "@temporalio/common": "1.10.3", - "@temporalio/proto": "1.10.3", - "@temporalio/testing": "1.10.3", - "@temporalio/worker": "1.10.3", - "@temporalio/workflow": "1.10.3", + "@temporalio/activity": "1.11.3", + "@temporalio/client": "1.11.3", + "@temporalio/common": "1.11.3", + "@temporalio/proto": "1.11.3", + "@temporalio/testing": "1.11.3", + "@temporalio/worker": "1.11.3", + "@temporalio/workflow": "1.11.3", "@types/base-64": "^1.0.0", "@types/cors": "^2.8.13", "@types/express": "^4.17.17", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index db4d666f1..84fbc67c1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -185,26 +185,26 @@ devDependencies: specifier: ^3.0.2 version: 3.0.2(svelte@4.0.0)(vite@5.2.14) '@temporalio/activity': - specifier: 1.10.3 - version: 1.10.3 + specifier: 1.11.3 + version: 1.11.3 '@temporalio/client': - specifier: 1.10.3 - version: 1.10.3 + specifier: 1.11.3 + version: 1.11.3 '@temporalio/common': - specifier: 1.10.3 - version: 1.10.3 + specifier: 1.11.3 + version: 1.11.3 '@temporalio/proto': - specifier: 1.10.3 - version: 1.10.3 + specifier: 1.11.3 + version: 1.11.3 '@temporalio/testing': - specifier: 1.10.3 - version: 1.10.3(esbuild@0.13.15) + specifier: 1.11.3 + version: 1.11.3(esbuild@0.13.15) '@temporalio/worker': - specifier: 1.10.3 - version: 1.10.3(esbuild@0.13.15) + specifier: 1.11.3 + version: 1.11.3(esbuild@0.13.15) '@temporalio/workflow': - specifier: 1.10.3 - version: 1.10.3 + specifier: 1.11.3 + version: 1.11.3 '@types/base-64': specifier: ^1.0.0 version: 1.0.0 @@ -5455,60 +5455,60 @@ packages: '@swc/counter': 0.1.3 dev: true - /@temporalio/activity@1.10.3: - resolution: {integrity: sha512-2wGEnH3lzfRkAPsM29Uih4jaXPjsRDCsXdSFJqmHz2fxcfodcjSjgTAJERFKRVOb9JfYmzsITRIrkKAfs3kvxA==} + /@temporalio/activity@1.11.3: + resolution: {integrity: sha512-XH923/I7wvKSxrMiB/vF7Xuix3lBEd1vLGMtgkj0wF2t8WBITjbHXQLzpJUlQm8O0hjixI7bDqFNRCan3Ov1xQ==} dependencies: - '@temporalio/common': 1.10.3 + '@temporalio/common': 1.11.3 abort-controller: 3.0.0 dev: true - /@temporalio/client@1.10.3: - resolution: {integrity: sha512-0xGYlURFoHrWByIJB3vNCaY7p9lnUkvrlA4uVAG92AwI0z/kcXdkUwn+VTOBBJi83iX6NZ0QS47HA6sCr00OPw==} + /@temporalio/client@1.11.3: + resolution: {integrity: sha512-2x30xAXbUuqelrWe3Vd1FVC0+Z2Cfh6m2W5yDUZBjqTMdNP6qd8nH4S4mceRtZ4TipYSPmaONaiWoAU2VvwEIg==} dependencies: '@grpc/grpc-js': 1.10.8 - '@temporalio/common': 1.10.3 - '@temporalio/proto': 1.10.3 + '@temporalio/common': 1.11.3 + '@temporalio/proto': 1.11.3 abort-controller: 3.0.0 long: 5.2.3 uuid: 9.0.1 dev: true - /@temporalio/common@1.10.3: - resolution: {integrity: sha512-0LF4UZQomMy+K3dGR0PGkBAqBByavjldeUKyMONtDrVqtq4sO2+2NtLW9mvmXGCH15jsabye1pQZdZxlTGP/CQ==} + /@temporalio/common@1.11.3: + resolution: {integrity: sha512-dzCrwiE9ox/Q16AjBsUKr4djg1ovYHNCjH36WZadwsemXINRWa5eW53j0WZOlmFF8/CbcHIhiD5N18rZqjiYkg==} dependencies: - '@temporalio/proto': 1.10.3 + '@temporalio/proto': 1.11.3 long: 5.2.3 ms: 3.0.0-canary.1 proto3-json-serializer: 2.0.1 dev: true - /@temporalio/core-bridge@1.10.3: - resolution: {integrity: sha512-TJV8Th8h0pv6gwwEqcTUIbOZVqfKj/6qWgNBnZuHi3BYd1WKzvXGGg0r1gorwlfapaC3Mms/Rqed9Xlnl9xjDQ==} + /@temporalio/core-bridge@1.11.3: + resolution: {integrity: sha512-dUPJiS/ZQtFnttmu0V1BLLjUE5wQxrwI0+xSvUc6JEiC1q9Z6BmhobSKbcEKCvJgh5OMZKh/jn6yu1N7oLsZPw==} requiresBuild: true dependencies: - '@temporalio/common': 1.10.3 + '@temporalio/common': 1.11.3 arg: 5.0.2 cargo-cp-artifact: 0.1.8 which: 4.0.0 dev: true - /@temporalio/proto@1.10.3: - resolution: {integrity: sha512-ugp04SpQFNmOa0+/kpg2vLfWMBPD2UW4s4XRaN23v9RREZ0HqV+DB+ZTT+03F9jeZlIFB0hxbF1Xd65tAF6fKg==} + /@temporalio/proto@1.11.3: + resolution: {integrity: sha512-X+xV75m11BvvS5MljagtYCybRNxpLNJM24eWyfv+uyU4WZSvgQCUh21fY4FOUDJS66DPvO1mefSPu0Nunp1PHg==} dependencies: long: 5.2.3 protobufjs: 7.2.5 dev: true - /@temporalio/testing@1.10.3(esbuild@0.13.15): - resolution: {integrity: sha512-c88EapF8Y0wf2X/OjNX9LJH9loDJhMVbDqs1Lb99INbeYpyTHs1l4wttkAezhAnP5Ct6o6pzpyqKe20Uk0n7zw==} + /@temporalio/testing@1.11.3(esbuild@0.13.15): + resolution: {integrity: sha512-C0T+po9prQcTjjCGbDJadW74Ttl+VEqa8RUfmgLYtoXz/LhnqafsWW05JxsjbxfRDZvijbjPZ3qUJlMu+DCa3w==} dependencies: - '@temporalio/activity': 1.10.3 - '@temporalio/client': 1.10.3 - '@temporalio/common': 1.10.3 - '@temporalio/core-bridge': 1.10.3 - '@temporalio/proto': 1.10.3 - '@temporalio/worker': 1.10.3(esbuild@0.13.15) - '@temporalio/workflow': 1.10.3 + '@temporalio/activity': 1.11.3 + '@temporalio/client': 1.11.3 + '@temporalio/common': 1.11.3 + '@temporalio/core-bridge': 1.11.3 + '@temporalio/proto': 1.11.3 + '@temporalio/worker': 1.11.3(esbuild@0.13.15) + '@temporalio/workflow': 1.11.3 abort-controller: 3.0.0 transitivePeerDependencies: - '@swc/helpers' @@ -5517,17 +5517,17 @@ packages: - webpack-cli dev: true - /@temporalio/worker@1.10.3(esbuild@0.13.15): - resolution: {integrity: sha512-IGHSpp9usFcn1kuYs234xOP2xjBJVyEtjborV8ZEFi9Eu01s7BfrNrVZUMQjs6dRTOCvvvkiFhU3MNuyk2qkWA==} + /@temporalio/worker@1.11.3(esbuild@0.13.15): + resolution: {integrity: sha512-CwiqsiQ5pKIyEcYOlfjRudu4pXCHU9PXm3Qycn1owpgdL1fbbpFiJ8yCoTWqrlB23BsWMhOpUyaQLnTF8D+4aQ==} engines: {node: '>= 16.0.0'} dependencies: '@swc/core': 1.5.7 - '@temporalio/activity': 1.10.3 - '@temporalio/client': 1.10.3 - '@temporalio/common': 1.10.3 - '@temporalio/core-bridge': 1.10.3 - '@temporalio/proto': 1.10.3 - '@temporalio/workflow': 1.10.3 + '@temporalio/activity': 1.11.3 + '@temporalio/client': 1.11.3 + '@temporalio/common': 1.11.3 + '@temporalio/core-bridge': 1.11.3 + '@temporalio/proto': 1.11.3 + '@temporalio/workflow': 1.11.3 abort-controller: 3.0.0 heap-js: 2.3.0 memfs: 4.7.7 @@ -5545,11 +5545,11 @@ packages: - webpack-cli dev: true - /@temporalio/workflow@1.10.3: - resolution: {integrity: sha512-XnP1Srb4r1dhl4g5U/KDTSSJ9zixIeqBd5lfC0wol257ItjfJPJgXAYUNg0YqPg4HyE77OlG7Qh6qhyAU80ubg==} + /@temporalio/workflow@1.11.3: + resolution: {integrity: sha512-TT4TqzMveLY9UsWQUSkFyb9Qvoz4VvCcJCPCyKLQyrp5BuAsf7owOByOfs74gz2tgTQiPjk1TtV4YXXEPRb4yA==} dependencies: - '@temporalio/common': 1.10.3 - '@temporalio/proto': 1.10.3 + '@temporalio/common': 1.11.3 + '@temporalio/proto': 1.11.3 dev: true /@testing-library/dom@9.3.4: diff --git a/src/lib/components/lines-and-dots/workflow-detail.svelte b/src/lib/components/lines-and-dots/workflow-detail.svelte index 1317faf39..e1b840236 100644 --- a/src/lib/components/lines-and-dots/workflow-detail.svelte +++ b/src/lib/components/lines-and-dots/workflow-detail.svelte @@ -13,6 +13,7 @@ export let href: string = null; export let icon: IconName | undefined = undefined; export let tooltip: string = ''; + export let badge = false;

@@ -33,7 +34,8 @@ {#if href} {content} {#if filterable} @@ -42,8 +44,8 @@ {:else} {content}{content} {/if} @@ -56,12 +58,16 @@ {/if} {#if href} - {content} + {content} {:else} {content}{content} {/if} diff --git a/src/lib/components/lines-and-dots/workflow-details.svelte b/src/lib/components/lines-and-dots/workflow-details.svelte index a78d7c750..b5c7cba3f 100644 --- a/src/lib/components/lines-and-dots/workflow-details.svelte +++ b/src/lib/components/lines-and-dots/workflow-details.svelte @@ -23,10 +23,15 @@

-

Summary

+ + + +
+
- - + class="order-8" + /> -->
diff --git a/src/lib/components/payload-input-with-encoding.svelte b/src/lib/components/payload-input-with-encoding.svelte index 3b17e6a97..a5df83942 100644 --- a/src/lib/components/payload-input-with-encoding.svelte +++ b/src/lib/components/payload-input-with-encoding.svelte @@ -24,6 +24,7 @@ export let encoding: Writable; export let error = false; export let loading = false; + export let label = translate('workflows.input'); const clearValues = () => { $encoding = 'json/plain'; @@ -33,7 +34,7 @@
-
{translate('workflows.input')}
+
{label}
diff --git a/src/lib/holocene/monaco/markdown.svelte b/src/lib/holocene/monaco/markdown.svelte index 31b903be0..593fff0a8 100644 --- a/src/lib/holocene/monaco/markdown.svelte +++ b/src/lib/holocene/monaco/markdown.svelte @@ -20,7 +20,7 @@ on:load={resizeIframe} title="output" src="/render?content={encodeURIComponent(content)}&theme={theme}" - class="w-full rounded-md shadow-md dark:shadow-slate-900" + class="w-full rounded-md" /> {/key} diff --git a/src/lib/layouts/workflow-header.svelte b/src/lib/layouts/workflow-header.svelte index 0dd495706..c706f566f 100644 --- a/src/lib/layouts/workflow-header.svelte +++ b/src/lib/layouts/workflow-header.svelte @@ -3,6 +3,7 @@ import { page } from '$app/stores'; + import WorkflowDetails from '$lib/components/lines-and-dots/workflow-details.svelte'; import WorkflowActions from '$lib/components/workflow-actions.svelte'; import WorkflowStatus from '$lib/components/workflow-status.svelte'; import WorkflowVersioningHeader from '$lib/components/workflow-versioning-header.svelte'; @@ -11,6 +12,7 @@ import Copyable from '$lib/holocene/copyable/index.svelte'; import Icon from '$lib/holocene/icon/icon.svelte'; import Link from '$lib/holocene/link.svelte'; + import Markdown from '$lib/holocene/monaco/markdown.svelte'; import TabList from '$lib/holocene/tab/tab-list.svelte'; import Tab from '$lib/holocene/tab/tab.svelte'; import Tabs from '$lib/holocene/tab/tabs.svelte'; @@ -63,6 +65,10 @@ $fullEventHistory, $namespaces, ); + + $: { + console.log('Workflow, ', workflow); + }
@@ -102,7 +108,7 @@
+ {#if workflow?.details} + + {/if} +
- {#if workflowTaskFailedError} {#if workflowError} {:else if !$workflowRun.workflow} {:else} -
+
diff --git a/src/lib/models/workflow-execution.ts b/src/lib/models/workflow-execution.ts index 020dab70f..c75ffed4b 100644 --- a/src/lib/models/workflow-execution.ts +++ b/src/lib/models/workflow-execution.ts @@ -116,6 +116,12 @@ export const toWorkflowExecution = ( toPendingNexusOperations(response?.pendingNexusOperations); const pendingWorkflowTask = response?.pendingWorkflowTask; const callbacks = toCallbacks(response?.callbacks); + const summary = decodePayload( + response?.executionConfig?.userMetadata?.summary, + ); + const details = decodePayload( + response?.executionConfig?.userMetadata?.details, + ); return { name, @@ -138,6 +144,8 @@ export const toWorkflowExecution = ( pendingNexusOperations, pendingWorkflowTask, callbacks, + summary, + details, parentNamespaceId, parent, stateTransitionCount, diff --git a/src/lib/pages/start-workflow.svelte b/src/lib/pages/start-workflow.svelte index 2708eac9a..6e190d2db 100644 --- a/src/lib/pages/start-workflow.svelte +++ b/src/lib/pages/start-workflow.svelte @@ -12,8 +12,10 @@ import AddSearchAttributes from '$lib/components/workflow/add-search-attributes.svelte'; import Alert from '$lib/holocene/alert.svelte'; import Button from '$lib/holocene/button.svelte'; + import Card from '$lib/holocene/card.svelte'; import Input from '$lib/holocene/input/input.svelte'; import Link from '$lib/holocene/link.svelte'; + import Editor from '$lib/holocene/monaco/editor.svelte'; import { translate } from '$lib/i18n/translate'; import { getPollers } from '$lib/services/pollers-service'; import { @@ -41,6 +43,8 @@ let taskQueue = ''; let workflowType = ''; let input = ''; + let summary = ''; + let details = ''; let encoding: Writable = writable('json/plain'); let inputRetrieved = 0; @@ -76,6 +80,8 @@ taskQueue, workflowType, input, + summary, + details, encoding: $encoding, searchAttributes, }); @@ -166,6 +172,11 @@ !workflowCreateDisabled($page); $: checkTaskQueue(taskQueueParam); + + $: { + console.log('Details: ', details); + console.log('Summary: ', summary); + }
@@ -242,6 +253,30 @@ {/key} {#if viewAdvancedOptions} + +

User Metadata

+ + (details = event.detail.value)} + /> + + +
{/if}
diff --git a/src/lib/services/workflow-service.ts b/src/lib/services/workflow-service.ts index af748b4dd..03861cb5c 100644 --- a/src/lib/services/workflow-service.ts +++ b/src/lib/services/workflow-service.ts @@ -92,6 +92,8 @@ type StartWorkflowOptions = { workflowType: string; input: string; encoding: string; + summary: string; + details: string; searchAttributes: SearchAttributeInput[]; }; @@ -498,6 +500,8 @@ export async function startWorkflow({ taskQueue, workflowType, input, + summary, + details, encoding, searchAttributes, }: StartWorkflowOptions): Promise<{ runId: string }> { @@ -524,6 +528,10 @@ export async function startWorkflow({ name: workflowType, }, input: payloads ? { payloads } : null, + userMetadata: { + summary: setBase64Payload(summary), + details: setBase64Payload(details), + }, searchAttributes: searchAttributes.length === 0 ? null diff --git a/src/lib/types/workflows.ts b/src/lib/types/workflows.ts index 392d447b0..bf61d2fba 100644 --- a/src/lib/types/workflows.ts +++ b/src/lib/types/workflows.ts @@ -53,12 +53,21 @@ export type WorkflowExecutionConfig = Replace< { defaultWorkflowTaskTimeout: Duration } >; +export type UserMetadata = { + summary?: Payload; + details?: Payload; +}; + +export type WorkflowExecutionConfigWithMetadata = WorkflowExecutionConfig & { + userMetadata?: UserMetadata; +}; + export type WorkflowExecutionAPIResponse = Optional<{ workflowExecutionInfo: WorkflowExecutionInfo; pendingActivities: PendingActivityInfo[]; pendingChildren: PendingChildren[]; pendingNexusOperations: PendingNexusOperation[]; - executionConfig: WorkflowExecutionConfig; + executionConfig: WorkflowExecutionConfigWithMetadata; callbacks: Callbacks; pendingWorkflowTask: PendingWorkflowTaskInfo; }>; @@ -153,6 +162,8 @@ export type WorkflowExecution = { defaultWorkflowTaskTimeout: Duration; canBeTerminated: boolean; callbacks: Callbacks; + summary?: string; + details?: string; }; export type WorkflowTaskFailedCause = From cc3c77d2a4aca40399d09a7af0ab4d75b76a46a5 Mon Sep 17 00:00:00 2001 From: Alex Tideman Date: Wed, 30 Oct 2024 15:35:06 -0500 Subject: [PATCH 05/30] Add dynamic page param replacement in markdown, allow pop-up scripts --- src/lib/holocene/monaco/markdown.svelte | 22 +++++++++++++++++++++- src/routes/(app)/render/+server.ts | 2 +- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/lib/holocene/monaco/markdown.svelte b/src/lib/holocene/monaco/markdown.svelte index 593fff0a8..4e18a0d62 100644 --- a/src/lib/holocene/monaco/markdown.svelte +++ b/src/lib/holocene/monaco/markdown.svelte @@ -1,7 +1,10 @@
@@ -19,7 +39,7 @@ bind:this={iframe} on:load={resizeIframe} title="output" - src="/render?content={encodeURIComponent(content)}&theme={theme}" + src="/render?content={encodeURIComponent(templatedContent)}&theme={theme}" class="w-full rounded-md" /> {/key} diff --git a/src/routes/(app)/render/+server.ts b/src/routes/(app)/render/+server.ts index c3e025094..27c1c2a25 100644 --- a/src/routes/(app)/render/+server.ts +++ b/src/routes/(app)/render/+server.ts @@ -25,7 +25,7 @@ const generateNonce = (): string => crypto.randomBytes(16).toString('hex'); * @returns */ const generateContentSecurityPolicy = ({ nonce }: RenderOptions) => { - return `base-uri 'self'; default-src 'none'; style-src 'nonce-${nonce}'; script-src 'nonce-${nonce}'; frame-ancestors 'self'; form-action 'none'; sandbox allow-same-origin allow-popups;`; + return `base-uri 'self'; default-src 'none'; style-src 'nonce-${nonce}'; script-src 'nonce-${nonce}'; frame-ancestors 'self'; form-action 'none'; sandbox allow-same-origin allow-popups allow-popups-to-escape-sandbox;`; }; /** From 961783f6517b1b0543719d8f6fa7fce8a5460d0e Mon Sep 17 00:00:00 2001 From: Alex Tideman Date: Wed, 30 Oct 2024 15:42:26 -0500 Subject: [PATCH 06/30] Add label for Details on start workflow --- src/lib/pages/start-workflow.svelte | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/pages/start-workflow.svelte b/src/lib/pages/start-workflow.svelte index 6e190d2db..22db86d70 100644 --- a/src/lib/pages/start-workflow.svelte +++ b/src/lib/pages/start-workflow.svelte @@ -14,6 +14,7 @@ import Button from '$lib/holocene/button.svelte'; import Card from '$lib/holocene/card.svelte'; import Input from '$lib/holocene/input/input.svelte'; + import Label from '$lib/holocene/label.svelte'; import Link from '$lib/holocene/link.svelte'; import Editor from '$lib/holocene/monaco/editor.svelte'; import { translate } from '$lib/i18n/translate'; @@ -261,6 +262,7 @@ maxLength={255} bind:value={summary} /> +