diff --git a/packages/account-client/src/client.ts b/packages/account-client/src/client.ts index 1f0fbfb14e..268dd4dc52 100644 --- a/packages/account-client/src/client.ts +++ b/packages/account-client/src/client.ts @@ -97,6 +97,14 @@ export interface AccountClient { ) => Promise join: (email: string, password: string, inviteId: string, workspaceUrl: string) => Promise createInvite: (exp: number, emailMask: string, limit: number, role: AccountRole) => Promise + /** + * @param options.personalized + * If true, will generate a link with a personalized token for one person access + * If false, will generate a link with an open-ended account in the token. Every token use will generate a new account. + * When false, notBefore and expiration parameters are mandatory. + * @param options.notBefore - not valid before; timestamp in seconds + * @param options.expiration - expires after; timestamp in seconds + */ createAccessLink: ( role: AccountRole, options?: { @@ -105,6 +113,9 @@ export interface AccountClient { navigateUrl?: string extra?: Record spaces?: string[] + notBefore?: number + expiration?: number + personalized?: boolean } ) => Promise checkJoin: (inviteId: string) => Promise @@ -435,6 +446,9 @@ class AccountClientImpl implements AccountClient { navigateUrl?: string extra?: Record spaces?: string[] + notBefore?: number + expiration?: number + personalized?: boolean } ): Promise { const params: any = { ...(options ?? {}), role } diff --git a/packages/platform/src/platform.ts b/packages/platform/src/platform.ts index c4e9116aa6..93a7d3abfa 100644 --- a/packages/platform/src/platform.ts +++ b/packages/platform/src/platform.ts @@ -141,6 +141,8 @@ export default plugin(platformId, { BadRequest: '' as StatusCode, Forbidden: '' as StatusCode, // 403 Unauthorized: '' as StatusCode, // 401 + TokenExpired: '' as StatusCode, // 401 + TokenNotActive: '' as StatusCode<{ notBefore: number }>, // 401 Conflict: '' as StatusCode, // 409 ExpiredLink: '' as StatusCode, UnknownMethod: '' as StatusCode<{ method: string }>, diff --git a/packages/ui/src/components/TimeLeft.svelte b/packages/ui/src/components/TimeLeft.svelte index 1ca3d3e14c..813fbfcb44 100644 --- a/packages/ui/src/components/TimeLeft.svelte +++ b/packages/ui/src/components/TimeLeft.svelte @@ -17,13 +17,18 @@ import { createEventDispatcher, onDestroy } from 'svelte' import { Timestamp } from '@hcengineering/core' + import { Label } from '..' + import ui from '../plugin' + export let time: Timestamp + export let showHours = false const dispatch = createEventDispatcher() let displayTime = time let notified = false let intervalId: any | undefined = undefined + const dayMs = 1000 * 60 * 60 * 24 function applyTimer (time: number): void { if (intervalId !== undefined) { @@ -56,11 +61,19 @@ function getDisplayTime (time: number): string { const options: Intl.DateTimeFormatOptions = { minute: 'numeric', second: 'numeric' } + if (showHours) { + options.timeZone = 'UTC' + options.hour = 'numeric' + } return new Date(time).toLocaleString('default', options) } {#if displayTime > 0} - {getDisplayTime(displayTime)} + {#if displayTime < dayMs} + {getDisplayTime(displayTime)} + {:else} +