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
-
+ {
+ 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 _}
-
{#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.
-
+ 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]}
+