diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 526f6f1aae..1f4a4e4207 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -1734,6 +1734,31 @@ paths: items: $ref: "#/components/schemas/User" + /w/{workspace}/users/list_usage: + get: + summary: list users usage + operationId: listUsersUsage + tags: + - user + parameters: + - $ref: "#/components/parameters/WorkspaceId" + responses: + "200": + description: user + content: + application/json: + schema: + type: array + items: + type: object + properties: + email: + type: string + executions: + type: number + required: + email + /w/{workspace}/users/list_usernames: get: summary: list usernames @@ -8399,8 +8424,6 @@ components: type: array items: type: string - usage: - $ref: "#/components/schemas/Usage" required: - email - username @@ -8412,12 +8435,6 @@ components: - folders - folders_owners - Usage: - type: object - properties: - executions: - type: number - Login: type: object properties: diff --git a/frontend/src/lib/components/settings/WorkspaceUserSettings.svelte b/frontend/src/lib/components/settings/WorkspaceUserSettings.svelte index 09edb8a087..e874a928f6 100644 --- a/frontend/src/lib/components/settings/WorkspaceUserSettings.svelte +++ b/frontend/src/lib/components/settings/WorkspaceUserSettings.svelte @@ -11,16 +11,18 @@ import Head from '$lib/components/table/Head.svelte' import Toggle from '$lib/components/Toggle.svelte' import Tooltip from '$lib/components/Tooltip.svelte' - import type { User } from '$lib/gen' + import type { CancelablePromise, User } from '$lib/gen' import { UserService, WorkspaceService, type WorkspaceInvite } from '$lib/gen' import { userStore, workspaceStore } from '$lib/stores' import { sendUserToast } from '$lib/toast' - import { Mails, Search } from 'lucide-svelte' + import { Loader2, Mails, Search } from 'lucide-svelte' import SearchItems from '../SearchItems.svelte' import Cell from '../table/Cell.svelte' import Row from '../table/Row.svelte' import ConfirmationModal from '../common/confirmationModal/ConfirmationModal.svelte' import { isCloudHosted } from '$lib/cloud' + import { truncate } from '$lib/utils' + import { onDestroy } from 'svelte' let users: User[] | undefined = undefined let invites: WorkspaceInvite[] = [] @@ -38,6 +40,22 @@ autoAdd = settings.auto_add } + let getUsagePromise: CancelablePromise> | undefined = undefined + + let usage: Record | undefined = undefined + + async function getUsage() { + getUsagePromise = UserService.listUsersUsage({ workspace: $workspaceStore! }) + const res = await getUsagePromise + usage = res.reduce((acc, { email, executions }) => { + acc[email] = executions ?? 0 + return acc + }, {} as Record) + } + async function listUsers(): Promise { users = await UserService.listUsers({ workspace: $workspaceStore! }) } @@ -58,11 +76,16 @@ if ($workspaceStore) { getDisallowedAutoDomain() listUsers() + getUsage() listInvites() loadSettings() } } + onDestroy(() => { + getUsagePromise?.cancel() + }) + let deleteConfirmedCallback: (() => void) | undefined = undefined async function removeAllInvitesFromDomain() { @@ -145,11 +168,11 @@ {#if filteredUsers} - {#each filteredUsers.slice(0, nbDisplayed) as { email, username, is_admin, operator, usage, disabled } (email)} + {#each filteredUsers.slice(0, nbDisplayed) as { email, username, is_admin, operator, disabled } (email)} - {email} - {username} - {usage?.executions} + {truncate(email, 20)} + {truncate(username, 30)} + {#if usage?.[email] != undefined}{usage?.[email]}{:else}{/if}
{#if disabled}