UBERF-5770 (#4803)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2024-02-28 14:16:11 +06:00 committed by GitHub
parent 3e7e3cab66
commit 5d54728777
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 53 additions and 15 deletions

View File

@ -75,7 +75,7 @@ export default async () => {
return connect(url.href, upgradeHandler, onUpgrade, onUnauthorized, onConnect) return connect(url.href, upgradeHandler, onUpgrade, onUnauthorized, onConnect)
}, },
filterModel ? [...getPlugins(), ...(getMetadata(clientPlugin.metadata.ExtraPlugins) ?? [])] : undefined, filterModel ? [...getPlugins(), ...(getMetadata(clientPlugin.metadata.ExtraPlugins) ?? [])] : undefined,
createModelPersistence(token) createModelPersistence(getWSFromToken(token))
) )
// Check if we had dev hook for client. // Check if we had dev hook for client.
client = hookClient(client) client = hookClient(client)
@ -84,7 +84,7 @@ export default async () => {
} }
} }
} }
function createModelPersistence (token: string): TxPersistenceStore | undefined { function createModelPersistence (workspace: string): TxPersistenceStore | undefined {
let dbRequest: IDBOpenDBRequest | undefined let dbRequest: IDBOpenDBRequest | undefined
let dbPromise: Promise<IDBDatabase | undefined> = Promise.resolve(undefined) let dbPromise: Promise<IDBDatabase | undefined> = Promise.resolve(undefined)
@ -111,7 +111,7 @@ function createModelPersistence (token: string): TxPersistenceStore | undefined
const transaction = db.transaction('model', 'readwrite') // (1) const transaction = db.transaction('model', 'readwrite') // (1)
const models = transaction.objectStore('model') // (2) const models = transaction.objectStore('model') // (2)
const model = await new Promise<{ id: string, model: LoadModelResponse } | undefined>((resolve) => { const model = await new Promise<{ id: string, model: LoadModelResponse } | undefined>((resolve) => {
const storedValue: IDBRequest<{ id: string, model: LoadModelResponse }> = models.get(token) const storedValue: IDBRequest<{ id: string, model: LoadModelResponse }> = models.get(workspace)
storedValue.onsuccess = function () { storedValue.onsuccess = function () {
resolve(storedValue.result) resolve(storedValue.result)
} }
@ -140,7 +140,7 @@ function createModelPersistence (token: string): TxPersistenceStore | undefined
if (db !== undefined) { if (db !== undefined) {
const transaction = db.transaction('model', 'readwrite') // (1) const transaction = db.transaction('model', 'readwrite') // (1)
const models = transaction.objectStore('model') // (2) const models = transaction.objectStore('model') // (2)
models.put({ id: token, model }) models.put({ id: workspace, model })
} }
} }
} }
@ -163,3 +163,15 @@ async function hookClient (client: Promise<AccountClient>): Promise<AccountClien
} }
return await client return await client
} }
function getWSFromToken (token: string): string {
const parts = token.split('.')
const payload = parts[1]
const decodedPayload = atob(payload)
const parsedPayload = JSON.parse(decodedPayload)
return parsedPayload.workspace
}

View File

@ -4,6 +4,8 @@
"PublicLink": "Public link", "PublicLink": "Public link",
"Revoke": "Revoke", "Revoke": "Revoke",
"RevokeConfirmation": "This will cause previously shared link to stop working. Are you sure you want to revoke this public link?", "RevokeConfirmation": "This will cause previously shared link to stop working. Are you sure you want to revoke this public link?",
"LinkWasRevoked": "Public link was revoked" "LinkWasRevoked": "Public link was revoked",
"Copy": "Copy",
"Copied": "Copied"
} }
} }

View File

@ -4,6 +4,8 @@
"PublicLink": "Публичная ссылка", "PublicLink": "Публичная ссылка",
"Revoke": "Отозвать", "Revoke": "Отозвать",
"RevokeConfirmation": "Это приведет к тому, что ранее созданная ссылка перестанет работать. Вы уверены, что хотите отозвать эту публичную ссылку?", "RevokeConfirmation": "Это приведет к тому, что ранее созданная ссылка перестанет работать. Вы уверены, что хотите отозвать эту публичную ссылку?",
"LinkWasRevoked": "Ссылка была отозвана" "LinkWasRevoked": "Ссылка была отозвана",
"Copy": "Копировать",
"Copied": "Скопировано"
} }
} }

View File

@ -13,7 +13,8 @@
// limitations under the License. // limitations under the License.
--> -->
<script lang="ts"> <script lang="ts">
import { Doc } from '@hcengineering/core' import { Doc, Timestamp } from '@hcengineering/core'
import { PublicLink } from '@hcengineering/guest'
import presentaion, { import presentaion, {
Card, Card,
MessageBox, MessageBox,
@ -21,12 +22,11 @@
createQuery, createQuery,
getClient getClient
} from '@hcengineering/presentation' } from '@hcengineering/presentation'
import guest from '../plugin' import { Button, Loading, Location, showPopup, ticker } from '@hcengineering/ui'
import { Button, Loading, Location, showPopup } from '@hcengineering/ui'
import { getObjectLinkFragment } from '@hcengineering/view-resources'
import view from '@hcengineering/view' import view from '@hcengineering/view'
import { PublicLink } from '@hcengineering/guest' import { getObjectLinkFragment } from '@hcengineering/view-resources'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import guest from '../plugin'
export let value: Doc export let value: Doc
@ -82,6 +82,8 @@
function copy (): void { function copy (): void {
if (link?.url === undefined || link.url === '') return if (link?.url === undefined || link.url === '') return
copyTextToClipboard(link.url) copyTextToClipboard(link.url)
copied = true
copiedTime = Date.now()
} }
async function revoke (): Promise<void> { async function revoke (): Promise<void> {
@ -103,6 +105,19 @@
} }
$: revokable = link?.revokable ?? false $: revokable = link?.revokable ?? false
let copiedTime: Timestamp | undefined
let copied = false
$: checkLabel($ticker)
function checkLabel (now: number) {
if (copiedTime) {
if (copied && now - copiedTime > 1000) {
copied = false
copiedTime = undefined
}
}
}
</script> </script>
<Card label={guest.string.PublicLink} canSave={true} okLabel={presentaion.string.Close} on:close okAction={close}> <Card label={guest.string.PublicLink} canSave={true} okLabel={presentaion.string.Close} on:close okAction={close}>
@ -115,5 +130,8 @@
{#if revokable} {#if revokable}
<Button label={guest.string.Revoke} kind={'dangerous'} size={'large'} on:click={revoke} /> <Button label={guest.string.Revoke} kind={'dangerous'} size={'large'} on:click={revoke} />
{/if} {/if}
{#if link?.url !== undefined && link.url !== ''}
<Button label={copied ? guest.string.Copied : guest.string.Copy} size={'medium'} on:click={copy} />
{/if}
</svelte:fragment> </svelte:fragment>
</Card> </Card>

View File

@ -6,6 +6,8 @@ export default mergeIds(guestId, guest, {
CreatePublicLink: '' as IntlString, CreatePublicLink: '' as IntlString,
PublicLink: '' as IntlString, PublicLink: '' as IntlString,
Revoke: '' as IntlString, Revoke: '' as IntlString,
Copy: '' as IntlString,
Copied: '' as IntlString,
RevokeConfirmation: '' as IntlString, RevokeConfirmation: '' as IntlString,
LinkWasRevoked: '' as IntlString LinkWasRevoked: '' as IntlString
} }

View File

@ -27,7 +27,7 @@
} from '@hcengineering/presentation' } from '@hcengineering/presentation'
import setting, { settingId } from '@hcengineering/setting' import setting, { settingId } from '@hcengineering/setting'
import { taskTypeStore, typeStore } from '@hcengineering/task-resources' import { taskTypeStore, typeStore } from '@hcengineering/task-resources'
import { Issue, Project } from '@hcengineering/tracker' import { Issue } from '@hcengineering/tracker'
import { import {
AnyComponent, AnyComponent,
Button, Button,
@ -37,7 +37,6 @@
IconMixin, IconMixin,
IconMoreH, IconMoreH,
Label, Label,
Spinner,
createFocusManager, createFocusManager,
getCurrentResolvedLocation, getCurrentResolvedLocation,
navigate navigate
@ -205,12 +204,15 @@
{#if (projectType?.tasks.length ?? 0) > 1 && taskType !== undefined} {#if (projectType?.tasks.length ?? 0) > 1 && taskType !== undefined}
({taskType.name}) ({taskType.name})
{/if} {/if}
<ComponentExtensions extension={tracker.extensions.EditIssueTitle} props={{ size: 'medium', value: issue }} /> <ComponentExtensions
extension={tracker.extensions.EditIssueTitle}
props={{ size: 'medium', value: issue, readonly }}
/>
</svelte:fragment> </svelte:fragment>
<svelte:fragment slot="pre-utils"> <svelte:fragment slot="pre-utils">
<ComponentExtensions <ComponentExtensions
extension={tracker.extensions.EditIssueHeader} extension={tracker.extensions.EditIssueHeader}
props={{ size: 'medium', kind: 'ghost', space: issue.space }} props={{ size: 'medium', kind: 'ghost', space: issue.space, readonly }}
/> />
{#if saved} {#if saved}
<Label label={presentation.string.Saved} /> <Label label={presentation.string.Saved} />