From 85bbb79d22d346bcf079d7744d0f9e94d069b656 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Fri, 20 Jan 2023 11:47:24 +0100 Subject: [PATCH] progress --- frontend/src/lib/utils.ts | 2 +- .../(logged)/workspace_settings/+page.svelte | 722 ++++++++++-------- ...vite.config.js.timestamp-1674159088568.mjs | 0 ...vite.config.js.timestamp-1674159119132.mjs | 0 ...vite.config.js.timestamp-1674159133038.mjs | 0 5 files changed, 415 insertions(+), 309 deletions(-) create mode 100644 frontend/vite.config.js.timestamp-1674159088568.mjs create mode 100644 frontend/vite.config.js.timestamp-1674159119132.mjs create mode 100644 frontend/vite.config.js.timestamp-1674159133038.mjs diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts index b719f7cabb..cc19358761 100644 --- a/frontend/src/lib/utils.ts +++ b/frontend/src/lib/utils.ts @@ -655,7 +655,7 @@ export function addWhitespaceBeforeCapitals(word?: string): string { } export function isCloudHosted(): boolean { - return get(page).url.hostname == 'app.windmill.dev' + return get(page).url.hostname == 'app.windmill.dev' || true } export function isObject(obj: any) { diff --git a/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte b/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte index 68ab1cc33b..04519dcf9a 100644 --- a/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte @@ -16,14 +16,15 @@ import { goto } from '$app/navigation' import InviteUser from '$lib/components/InviteUser.svelte' import ScriptPicker from '$lib/components/ScriptPicker.svelte' - import { Badge, Button, Skeleton } from '$lib/components/common' + import { Alert, Badge, Button, Skeleton, Tab, Tabs } from '$lib/components/common' import Tooltip from '$lib/components/Tooltip.svelte' - import { faScroll, faBarsStaggered } from '@fortawesome/free-solid-svg-icons' + import { faScroll, faBarsStaggered, faExternalLink } from '@fortawesome/free-solid-svg-icons' import SearchItems from '$lib/components/SearchItems.svelte' import Toggle from '$lib/components/Toggle.svelte' import ToggleButtonGroup from '$lib/components/common/toggleButton/ToggleButtonGroup.svelte' import ToggleButton from '$lib/components/common/toggleButton/ToggleButton.svelte' import AddUser from '$lib/components/AddUser.svelte' + import { page } from '$app/stores' let users: User[] | undefined = undefined let invites: WorkspaceInvite[] = [] @@ -37,6 +38,11 @@ let operatorOnly: boolean | undefined = undefined let premium_info: { premium: boolean; usage?: number } | undefined = undefined let nbDisplayed = 30 + let plan: string | undefined = undefined + let customer_id: string | undefined = undefined + let tab: 'users' | 'slack' | 'premium' | 'export_delete' = + ($page.url.searchParams.get('tab') as 'users' | 'slack' | 'premium' | 'export_delete') ?? + 'users' // function getDropDownItems(username: string): DropdownItem[] { // return [ @@ -77,6 +83,8 @@ auto_invite_domain = settings.auto_invite_domain operatorOnly = settings.auto_invite_operator scriptPath = (settings.slack_command_script ?? '').split('/').slice(1).join('/') + plan = settings.plan + customer_id = settings.customer_id initialPath = scriptPath } @@ -127,6 +135,30 @@ ) ) } + + const plans = { + Free: [ + 'Users use their individual global free-tier quotas when doing executions in this workspace', + '1 000 free global executions per-user per month' + ], + Team: [ + `$10/mo per user in the workspace.`, + `Executions are not accounted for in the global user's + quotas but are accounted for in the workspace's quota.`, + `Every user in the workspace increases the pooled workspace quota by 50k executions.`, + `1 000 executions above the pooled workspace quota is charged 1$.` + ], + Enterprise: [ + `$50/month per user in the workspace.`, + `Executions are not accounted for in the global user's + quotas but are accounted for in the workspace's quota.`, + `Every user in the workspace increases the pooled workspace quota by 50k executions.`, + `1 000 executions above the pooled workspace quota is charged 1$.`, + `Dedicated workers and database`, + `SAML support`, + `Priority support including an automation engineer` + ] + } - + + +
Users & Invites
+
+ +
Slack Command
+
+ {#if isCloudHosted()} + +
Premium Plans
+
+ {/if} + +
Export & Delete Workspace
+
+
+ {#if tab == 'users'} + - + -
- -
-
- - - email - username - executions (5w) An execution is calculated as 1 for any runs of scripts + 1 for each seconds above - the first one - - - - - - - {#if filteredUsers} - {#each filteredUsers.slice(0, nbDisplayed) as { email, username, is_admin, operator, usage, disabled } (email)} +
+ +
+
+ + + email + username + executions (5w) An execution is calculated as 1 for any runs of scripts + 1 for each seconds above + the first one + + + + + + + {#if filteredUsers} + {#each filteredUsers.slice(0, nbDisplayed) as { email, username, is_admin, operator, usage, disabled } (email)} + + {email} + {username} + {usage?.executions} +
{#if disabled} + disabled + {/if}
+ +
+ { + const body = + e.detail == 'admin' + ? { is_admin: true, operator: false } + : e.detail == 'operator' + ? { is_admin: false, operator: true } + : { is_admin: false, operator: false } + await UserService.updateUser({ + workspace: $workspaceStore ?? '', + username, + requestBody: body + }) + listUsers() + }} + > + Operator An operator can only execute and view scripts/flows/apps from your + workspace, and only those that he has visibility on + Author An Author can execute and view scripts/flows/apps, but he can also + create new ones + Admin + +
+ + +
+ + | + +
+ + + {/each} + {#if filteredUsers?.length > 50} + {nbDisplayed} items out of {filteredUsers.length} + + {/if} + {:else} + {#each new Array(6) as _} + + {#each new Array(4) as _} + + + + {/each} + + {/each} + {/if} + +
+
+ + + + +
+ + + email + role + + + + {#each invites as { email, is_admin, operator }} {email} - {username} - {usage?.executions}
{#if disabled} - disabled - {/if}
{#if operator}operator{:else if is_admin}admin{/if} + + + - -
- { - const body = - e.detail == 'admin' - ? { is_admin: true, operator: false } - : e.detail == 'operator' - ? { is_admin: false, operator: true } - : { is_admin: false, operator: false } - await UserService.updateUser({ - workspace: $workspaceStore ?? '', - username, - requestBody: body - }) - listUsers() - }} - > - Operator An operator can only execute and view scripts/flows/apps from your - workspace, and only those that he has visibility on - Author An Author can execute and view scripts/flows/apps, but he can also create - new ones - Admin - -
- - -
- - | - -
- {/each} - {#if filteredUsers?.length > 50} - {nbDisplayed} items out of {filteredUsers.length} - - {/if} - {:else} - {#each new Array(6) as _} - - {#each new Array(4) as _} - - - - {/each} - - {/each} - {/if} - -
-
- - - + +
+
-
- - - email - role - - - - {#each invites as { email, is_admin, operator }} - - {email} - {#if operator}operator{:else if is_admin}admin{/if} - - - - - {/each} - - -
- - {#if isCloudHosted()}
- - {#if premium_info?.premium}This workspace is on a team plan. The number of executions is - tracked globally. Current number of executions in this workspace since it was switched to - the team Plan for this month: {premium_info.usage ?? 0} - {:else} - This workspace is NOT on a team plan. Users use their global free-tier quotas when - doing executions in this workspace. Upgrade to a Team plan to unlock unlimited execution in - this workspace. -
- -
- {/if} - {/if} - -
- -
- {#if auto_invite_domain != domain} -
- -
- {/if} - {#if auto_invite_domain} -
- { - await removeAllInvitesFromDomain() - await WorkspaceService.editAutoInvite({ - workspace: $workspaceStore ?? '', - requestBody: { operator: e.detail } - }) - loadSettings() - listInvites() - }} - /> + +
+ {#if auto_invite_domain != domain}
Set auto-invite to {domain}
+ {/if} + {#if auto_invite_domain} +
+ { + await removeAllInvitesFromDomain() + await WorkspaceService.editAutoInvite({ + workspace: $workspaceStore ?? '', + requestBody: { operator: e.detail } + }) + loadSettings() + listInvites() + }} + /> +
+ +
+
+ {/if} +
+ {#if !allowedAutoDomain} +
{domain} domain not allowed for auto-invite
+ {/if} + {:else if tab == 'premium'} + {#if isCloudHosted()} +
+ + + {#if customer_id || true} +
+ +

+ See invoices, change billing information or subscription details

+
+ {/if} + +
+ {#if premium_info?.premium}Number of executions in this workspace this month:
{premium_info.usage ?? 0}
+ {:else} + This workspace is NOT on a team plan. Users use their global free-tier quotas when + doing executions in this workspace. Upgrade to a Team or Enterprise plan to unlock unlimited + execution in this workspace. + {/if} +
+ +
+ + The single credit-unit is called an "execution". An execution corresponds to a single + job whose duration is less than 1s. For any additional seconds of execution, an + additional execution is accounted for. Jobs are executed on powerful cpus. Most jobs + will take less than 200ms to execute. + +
+ +
+ {#each Object.entries(plans) as [planTitle, planDesc]} +
+

{planTitle}

+
    + {#each planDesc as item} +
  • {@html item}
  • + {/each} +
+ +
+ {#if planTitle == 'Team'} + {#if plan != 'team'} +
+ +
+ {:else} +
You are on this plan
+ {/if} + {:else if planTitle == 'Enterprise'} + {#if plan != 'enterprise'} +
+ +
+ {:else} +
You are on this plan
+ {/if} + {:else if !plan} +
You are on the free-tier plan
+ {:else} +
+ +
+ {/if} +
+ {/each}
{/if} -
- {#if !allowedAutoDomain} -
{domain} domain not allowed for auto-invite
- {/if} -
- -

- Status: {#if team_name}Connected to slack workspace {team_name}{:else}Not - connected{/if} -

- - {#if team_name} -
- + + +
+ {:else} + - -
- {:else} - - {/if} -

Script or flow to run on /windmill command - The script or flow to be triggered when the `/windmill` command is invoked. The script or - flow chosen is passed the parameters
response_url: string, text: string
- respectively the url to reply directly to the trigger and the text of the command.
-

- -
- -
- -
- -
- -

- The workspace will be archived for a short period of time and then permanently deleted -

- {#if $workspaceStore === 'admins' || $workspaceStore === 'starter'} +
+

- This workspace cannot be deleted as it has a special function. Consult the documentation for - more information. + The workspace will be archived for a short period of time and then permanently deleted

- {/if} -
- - - {#if $superadmin} + {#if $workspaceStore === 'admins' || $workspaceStore === 'starter'} +

+ This workspace cannot be deleted as it has a special function. Consult the documentation + for more information. +

+ {/if} +
- {/if} -
+ + {#if $superadmin} + + {/if} +
+ {/if} {:else}