diff --git a/frontend/src/routes/(root)/(logged)/resources/+page.svelte b/frontend/src/routes/(root)/(logged)/resources/+page.svelte index 298a60ef3b..01ea3597fa 100644 --- a/frontend/src/routes/(root)/(logged)/resources/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/resources/+page.svelte @@ -60,7 +60,6 @@ import EditableSchemaWrapper from '$lib/components/schema/EditableSchemaWrapper.svelte' import ResourceEditorDrawer from '$lib/components/ResourceEditorDrawer.svelte' import GfmMarkdown from '$lib/components/GfmMarkdown.svelte' - import Scroll from '$lib/components/Scroll.svelte' type ResourceW = ListableResource & { canWrite: boolean; marked?: string } type ResourceTypeW = ResourceType & { canWrite: boolean } @@ -610,423 +609,421 @@

Page not available for operators

{:else} - - - -
- - -
-
-
- { - if (e.detail == 'cache') { - loading.resources = true - loadCache() - } else if (e.detail == 'states') { - loading.resources = true - loadState() - } - }} - > - -
- - Workspace -
-
- -
- Resource Types - - Every resource has a Resource Type attached to it which contains its schema and make - it easy in scripts and flows to accept only resources of a specific resource type. - -
-
- -
- States - - States are actually resources (but excluded from the Workspace tab for clarity). - States are used by scripts to keep data persistent between runs of the same script - by the same trigger (schedule or user) - -
-
- -
- Cache - - Cached results are actually resources (but excluded from the Workspace tab for - clarity). Cache are used by flows's step to cache result to avoid recomputing - unnecessarily - -
-
- -
- Theme - - Theme are actually resources (but excluded from the Workspace tab for clarity). - Theme are used by the apps to customize their look and feel. - -
-
-
-
-
+ + +
+ +
- {#if tab == 'workspace' || tab == 'states' || tab == 'cache' || tab == 'theme'} -
- -
- - {#if tab != 'states' && tab != 'cache'} - - {:else} -
- {/if} + +
+ { + if (e.detail == 'cache') { + loading.resources = true + loadCache() + } else if (e.detail == 'states') { + loading.resources = true + loadState() + } + }} + > + +
+ + Workspace +
+
+ +
+ Resource Types + + Every resource has a Resource Type attached to it which contains its schema and make + it easy in scripts and flows to accept only resources of a specific resource type. + +
+
+ +
+ States + + States are actually resources (but excluded from the Workspace tab for clarity). + States are used by scripts to keep data persistent between runs of the same script by + the same trigger (schedule or user) + +
+
+ +
+ Cache + + Cached results are actually resources (but excluded from the Workspace tab for + clarity). Cache are used by flows's step to cache result to avoid recomputing + unnecessarily + +
+
+ +
+ Theme + + Theme are actually resources (but excluded from the Workspace tab for clarity). Theme + are used by the apps to customize their look and feel. + +
+
+
+
+
+
+ {#if tab == 'workspace' || tab == 'states' || tab == 'cache' || tab == 'theme'} +
+ +
+ + {#if tab != 'states' && tab != 'cache'} + + {:else} +
+ {/if} -
- {#if loading.resources} - - {#each new Array(6) as _} - - {/each} - {:else if filteredItems?.length == 0} -
-
No resources found
-
- Try changing the filters or creating a new resource -
-
- {:else} - - - - - Path - Resource type - Description - - - - - - {#if filteredItems} - {#each filteredItems as { path, description, resource_type, extra_perms, canWrite, is_oauth, is_linked, account, refresh_error, is_expired, marked, is_refreshed }} - - - - - - resourceEditor?.initEdit?.(path)} - >{#if marked}{@html marked}{:else}{path}{/if} - - - { - const linkedRt = resourceTypes?.find((rt) => rt.name === resource_type) - if (linkedRt) { - resourceTypeViewerObj = { - rt: linkedRt.name, - //@ts-ignore - schema: linkedRt.schema, - description: linkedRt.description ?? '', - formatExtension: linkedRt.format_extension - } - resourceTypeViewer.openDrawer?.() - } else { - sendUserToast( - `Resource type ${resource_type} not found in workspace.`, - true - ) - } - }} - > - - - - - - {removeMarkdown(truncate(description ?? '', 30))} - - - -
-
- {#if is_linked} - - -
- This resource is linked with a variable of the same path. They are - deleted and renamed together. -
-
- {/if} -
-
- {#if is_refreshed} - - -
- The OAuth token will be kept up-to-date in the background by - Windmill using its refresh token -
-
- {/if} -
- - {#if is_oauth} -
- {#if refresh_error} - - -
- Latest exchange of the refresh token did not succeed. Error: {refresh_error} -
-
- {:else if is_expired} - - - -
- The access_token is expired, it will get renewed the next time - this variable is fetched or you can request is to be refreshed - in the dropdown on the right. -
-
- {:else} - - -
- The resource was connected through OAuth and the token is not - expired. -
-
- {/if} -
- {/if} -
-
- - { - shareModal.openDrawer?.(path, 'resource') - } - }, - { - displayName: 'Edit', - icon: Pen, - disabled: !canWrite, - action: () => { - resourceEditor?.initEdit?.(path) - } - }, - ...(isDeployable('resource', path, deployUiSettings) - ? [ - { - displayName: 'Deploy to prod/staging', - icon: FileUp, - action: () => { - deploymentDrawer.openDrawer(path, 'resource') - } - } - ] - : []), - { - displayName: 'Delete', - disabled: !canWrite, - icon: Trash, - type: 'delete', - action: (event) => { - // TODO - // @ts-ignore - if (event?.shiftKey) { - deleteResource(path, account) - } else { - deleteConfirmedCallback = () => { - deleteResource(path, account) - } - } - } - }, - ...(account != undefined - ? [ - { - displayName: 'Refresh token', - icon: RotateCw, - action: async () => { - await OauthService.refreshToken({ - workspace: $workspaceStore ?? '', - id: account ?? 0, - requestBody: { - path - } - }) - sendUserToast('Token refreshed') - loadResources() - } - } - ] - : []) - ]} - /> - -
- {/each} - {/if} - -
- {/if} -
- {:else if tab == 'types'} - {#if loading.types} +
+ {#if loading.resources} {#each new Array(6) as _} {/each} - {:else} -
- - - - Name - Description - - - - - {#if resourceTypes} - {#each resourceTypes as { name, description, schema, canWrite, format_extension }} - - - { - resourceTypeViewerObj = { - rt: name, - //@ts-ignore - schema: schema, - description: description ?? '', - formatExtension: format_extension - } - - resourceTypeViewer.openDrawer?.() - }} - > - - - - - - {removeMarkdown(truncate(description ?? '', 200))} - - - - {#if !canWrite} - - Shared globally - - This resource type is from the 'admins' workspace shared with all - workspaces - - - {:else if $userStore?.is_admin || $userStore?.is_super_admin} -
- - -
- {:else} - - Non Editable - - Since resource types are shared with the whole workspace, only admins - can edit/delete them - - - {/if} -
-
- {/each} - {/if} - -
+ {:else if filteredItems?.length == 0} +
+
No resources found
+
+ Try changing the filters or creating a new resource +
+ {:else} + + + + + Path + Resource type + Description + + + + + + {#if filteredItems} + {#each filteredItems as { path, description, resource_type, extra_perms, canWrite, is_oauth, is_linked, account, refresh_error, is_expired, marked, is_refreshed }} + + + + + + resourceEditor?.initEdit?.(path)} + >{#if marked}{@html marked}{:else}{path}{/if} + + + { + const linkedRt = resourceTypes?.find((rt) => rt.name === resource_type) + if (linkedRt) { + resourceTypeViewerObj = { + rt: linkedRt.name, + //@ts-ignore + schema: linkedRt.schema, + description: linkedRt.description ?? '', + formatExtension: linkedRt.format_extension + } + resourceTypeViewer.openDrawer?.() + } else { + sendUserToast( + `Resource type ${resource_type} not found in workspace.`, + true + ) + } + }} + > + + + + + + {removeMarkdown(truncate(description ?? '', 30))} + + + +
+
+ {#if is_linked} + + +
+ This resource is linked with a variable of the same path. They are + deleted and renamed together. +
+
+ {/if} +
+
+ {#if is_refreshed} + + +
+ The OAuth token will be kept up-to-date in the background by + Windmill using its refresh token +
+
+ {/if} +
+ + {#if is_oauth} +
+ {#if refresh_error} + + +
+ Latest exchange of the refresh token did not succeed. Error: {refresh_error} +
+
+ {:else if is_expired} + + + +
+ The access_token is expired, it will get renewed the next time + this variable is fetched or you can request is to be refreshed in + the dropdown on the right. +
+
+ {:else} + + +
+ The resource was connected through OAuth and the token is not + expired. +
+
+ {/if} +
+ {/if} +
+
+ + { + shareModal.openDrawer?.(path, 'resource') + } + }, + { + displayName: 'Edit', + icon: Pen, + disabled: !canWrite, + action: () => { + resourceEditor?.initEdit?.(path) + } + }, + ...(isDeployable('resource', path, deployUiSettings) + ? [ + { + displayName: 'Deploy to prod/staging', + icon: FileUp, + action: () => { + deploymentDrawer.openDrawer(path, 'resource') + } + } + ] + : []), + { + displayName: 'Delete', + disabled: !canWrite, + icon: Trash, + type: 'delete', + action: (event) => { + // TODO + // @ts-ignore + if (event?.shiftKey) { + deleteResource(path, account) + } else { + deleteConfirmedCallback = () => { + deleteResource(path, account) + } + } + } + }, + ...(account != undefined + ? [ + { + displayName: 'Refresh token', + icon: RotateCw, + action: async () => { + await OauthService.refreshToken({ + workspace: $workspaceStore ?? '', + id: account ?? 0, + requestBody: { + path + } + }) + sendUserToast('Token refreshed') + loadResources() + } + } + ] + : []) + ]} + /> + +
+ {/each} + {/if} + +
{/if} +
+ {:else if tab == 'types'} + {#if loading.types} + + {#each new Array(6) as _} + + {/each} + {:else} +
+ + + + Name + Description + + + + + {#if resourceTypes} + {#each resourceTypes as { name, description, schema, canWrite, format_extension }} + + + { + resourceTypeViewerObj = { + rt: name, + //@ts-ignore + schema: schema, + description: description ?? '', + formatExtension: format_extension + } + + resourceTypeViewer.openDrawer?.() + }} + > + + + + + + {removeMarkdown(truncate(description ?? '', 200))} + + + + {#if !canWrite} + + Shared globally + + This resource type is from the 'admins' workspace shared with all + workspaces + + + {:else if $userStore?.is_admin || $userStore?.is_super_admin} +
+ + +
+ {:else} + + Non Editable + + Since resource types are shared with the whole workspace, only admins + can edit/delete them + + + {/if} +
+
+ {/each} + {/if} + +
+
{/if} - - + {/if} + {/if} diff --git a/frontend/src/routes/(root)/(logged)/schedules/+page.svelte b/frontend/src/routes/(root)/(logged)/schedules/+page.svelte index 6591b3e210..27f9dd52ef 100644 --- a/frontend/src/routes/(root)/(logged)/schedules/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/schedules/+page.svelte @@ -279,7 +279,7 @@

Page not available for operators

{:else} - + Page not available for operators

{:else} - - - -
- {#if tab == 'contextual' && ($userStore?.is_admin || $userStore?.is_super_admin)} - - {:else} - - {/if} -
-
+ + +
+ {#if tab == 'contextual' && ($userStore?.is_admin || $userStore?.is_super_admin)} + + {:else} + + {/if} +
+
- - - { - loadVariables() - }} - /> + + + { + loadVariables() + }} + /> - - -
- - Workspace -
-
- -
- - Contextual - - Contextual variables are passed as environment variables when running a script and - depends on the execution context. - -
-
-
- {#if tab == 'workspace'} -
- + + +
+ + Workspace
-
- + + +
+ + Contextual + + Contextual variables are passed as environment variables when running a script and + depends on the execution context. +
-
- {#if !filteredItems} - - {#each new Array(3) as _} - - {/each} - {:else if filteredItems.length == 0} -
-
No variables found
-
- Try changing the filters or creating a new variable -
+ + + {#if tab == 'workspace'} +
+ +
+
+ +
+
+ {#if !filteredItems} + + {#each new Array(3) as _} + + {/each} + {:else if filteredItems.length == 0} +
+
No variables found
+
+ Try changing the filters or creating a new variable
- {:else} - - - - - Path - Value - Description - - - - - - {#each filteredItems as { path, value, is_secret, description, extra_perms, canWrite, account, is_refreshed, is_expired, refresh_error, is_linked, marked }} - - - - - - variableEditor.editVariable(path)} - href="#{path}" - > - {#if marked} - {@html marked} +
+ {:else} + + + + + Path + Value + Description + + + + + + {#each filteredItems as { path, value, is_secret, description, extra_perms, canWrite, account, is_refreshed, is_expired, refresh_error, is_linked, marked }} + + + + + + variableEditor.editVariable(path)} + href="#{path}" + > + {#if marked} + {@html marked} + {:else} + {path} + {/if} + + + + +
+ {#if value} + {truncate(value, 20)} {:else} - {path} - {/if} - - - - -
- {#if value} - {truncate(value, 20)} - {:else} - ∗∗∗∗ - {/if} -
- {#if is_secret} - - - This item is secret - - {/if} -
-
- - {truncate(description ?? '', 50)} - - - -
- {#if is_linked} - - -
- This variable is linked with a resource of the same path. They are - deleted and renamed together. -
-
- {/if} - {#if account} - - -
- This OAuth token will be kept up-to-date in the background by Windmill - using its refresh token -
-
- {/if} - - {#if is_refreshed} -
- {#if refresh_error} - -
- - -
- -
- Latest exchange of the refresh token did not succeed. Error: {refresh_error} -
-
- {:else if is_expired} - - -
- The access_token is expired, it will get renewed the next time - this variable is fetched or you can request is to be refreshed in - the dropdown on the right. -
-
- {:else} - - -
- The variable was connected through OAuth and the token is not - expired. -
-
- {/if} -
+ ∗∗∗∗ {/if}
-
- - { - let owner = isOwner(path, $userStore, $workspaceStore) - return [ - { - displayName: 'Edit', - icon: Pen, - action: () => variableEditor.editVariable(path), - disabled: !canWrite - }, - { - displayName: 'Delete', - icon: Trash, - type: 'delete', - action: (event) => { - if (event['shiftKey']) { + {#if is_secret} + + + This item is secret + + {/if} + + + + {truncate(description ?? '', 50)} + + + +
+ {#if is_linked} + + +
+ This variable is linked with a resource of the same path. They are + deleted and renamed together. +
+
+ {/if} + {#if account} + + +
+ This OAuth token will be kept up-to-date in the background by Windmill + using its refresh token +
+
+ {/if} + + {#if is_refreshed} +
+ {#if refresh_error} + +
+ + +
+ +
+ Latest exchange of the refresh token did not succeed. Error: {refresh_error} +
+
+ {:else if is_expired} + + +
+ The access_token is expired, it will get renewed the next time this + variable is fetched or you can request is to be refreshed in the + dropdown on the right. +
+
+ {:else} + + +
+ The variable was connected through OAuth and the token is not + expired. +
+
+ {/if} +
+ {/if} +
+
+ + { + let owner = isOwner(path, $userStore, $workspaceStore) + return [ + { + displayName: 'Edit', + icon: Pen, + action: () => variableEditor.editVariable(path), + disabled: !canWrite + }, + { + displayName: 'Delete', + icon: Trash, + type: 'delete', + action: (event) => { + if (event['shiftKey']) { + deleteVariable(path, account) + } else { + deleteConfirmedCallback = () => { deleteVariable(path, account) - } else { - deleteConfirmedCallback = () => { - deleteVariable(path, account) + } + } + }, + disabled: !owner + }, + ...(isDeployable( + is_secret ? 'secret' : 'variable', + path, + deployUiSettings + ) + ? [ + { + displayName: 'Deploy to prod/staging', + icon: FileUp, + action: () => { + deploymentDrawer.openDrawer(path, 'variable') } } - }, - disabled: !owner + ] + : []), + { + displayName: owner ? 'Share' : 'See Permissions', + action: () => { + shareModal.openDrawer(path, 'variable') }, - ...(isDeployable( - is_secret ? 'secret' : 'variable', - path, - deployUiSettings - ) - ? [ - { - displayName: 'Deploy to prod/staging', - icon: FileUp, - action: () => { - deploymentDrawer.openDrawer(path, 'variable') - } + icon: Share + }, + ...(account != undefined + ? [ + { + displayName: 'Refresh token', + icon: RefreshCw, + action: async () => { + await OauthService.refreshToken({ + workspace: $workspaceStore ?? '', + id: account ?? 0, + requestBody: { + path + } + }) + sendUserToast('Token refreshed') + loadVariables() } - ] - : []), - { - displayName: owner ? 'Share' : 'See Permissions', - action: () => { - shareModal.openDrawer(path, 'variable') - }, - icon: Share - }, - ...(account != undefined - ? [ - { - displayName: 'Refresh token', - icon: RefreshCw, - action: async () => { - await OauthService.refreshToken({ - workspace: $workspaceStore ?? '', - id: account ?? 0, - requestBody: { - path - } - }) - sendUserToast('Token refreshed') - loadVariables() - } - } - ] - : []) - ] - }} - /> - - - {/each} - - - {/if} -
- {:else if tab == 'contextual'} -
- {#if loading.contextual} - - {#each new Array(8) as _} - - {/each} + } + ] + : []) + ] + }} + /> + + + {/each} + + + {/if} +
+ {:else if tab == 'contextual'} +
+ {#if loading.contextual} + + {#each new Array(8) as _} + + {/each} + {:else} + + {#if contextualVariables.filter((x) => x.is_custom).length === 0} +
+
No custom contextual variables found
+
{:else} - - {#if contextualVariables.filter((x) => x.is_custom).length === 0} -
-
No custom contextual variables found
-
- {:else} - x.is_custom)} - keys={['name', 'value']} - getRowActions={$userStore?.is_admin || $userStore?.is_super_admin - ? (row) => { - return [ - { - displayName: 'Edit', - action: () => contextualVariableEditor.editVariable(row.name, row.value) - }, - { - displayName: 'Delete', - type: 'delete', - action: () => { - deleteContextualVariable(row) - } - } - ] - } - : undefined} - /> - {/if} - !x.is_custom)} - keys={['name', 'value', 'description']} + headers={['Name', 'Value']} + data={contextualVariables.filter((x) => x.is_custom)} + keys={['name', 'value']} + getRowActions={$userStore?.is_admin || $userStore?.is_super_admin + ? (row) => { + return [ + { + displayName: 'Edit', + action: () => contextualVariableEditor.editVariable(row.name, row.value) + }, + { + displayName: 'Delete', + type: 'delete', + action: () => { + deleteContextualVariable(row) + } + } + ] + } + : undefined} /> {/if} -
- {/if} - - + + !x.is_custom)} + keys={['name', 'value', 'description']} + /> + {/if} +
+ {/if} + {/if}