diff --git a/common/scripts/docker_tag.sh b/common/scripts/docker_tag.sh index b6dd465b22..ffbb926f54 100755 --- a/common/scripts/docker_tag.sh +++ b/common/scripts/docker_tag.sh @@ -9,12 +9,19 @@ then c=( ${a[2]//[^0-9]*/ } ) ((c++)) version="${a[0]}.${a[1]}.${c}-staging" - echo "Tagging stating $1 with version ${version}" + echo "Tagging staging $1 with version ${version}" docker tag "$1:$rev_version" "$1:$version" for n in {1..5}; do docker push "$1:$version" && break - echo 'Docker failed to push, wait 5 seconds' - sleep 5 + + if (( $n < 5 )) + then + echo 'Docker failed to push, wait 5 second' + sleep 5 + else + echo '5 push attempts failed, exiting with failure' + exit 1 + fi done else echo "Tagging release $1 with version ${version}" @@ -22,12 +29,26 @@ else docker tag "$1:$rev_version" "$1:latest" for n in {1..5}; do docker push "$1:$version" && break - echo 'Docker failed to push, wait 5 seconds' - sleep 5 + + if (( $n < 5 )) + then + echo 'Docker failed to push, wait 5 second' + sleep 5 + else + echo '5 push attempts failed, exiting with failure' + exit 1 + fi done for n in {1..5}; do docker push "$1:latest" && break - echo 'Docker failed to push, wait 5 seconds' - sleep 5 + + if (( $n < 5 )) + then + echo 'Docker failed to push, wait 5 second' + sleep 5 + else + echo '5 push attempts failed, exiting with failure' + exit 1 + fi done fi diff --git a/dev/tool/src/db.ts b/dev/tool/src/db.ts index 7bd1d69e33..34f376ae3d 100644 --- a/dev/tool/src/db.ts +++ b/dev/tool/src/db.ts @@ -140,6 +140,7 @@ export async function moveAccountDbFromMongoToPG ( mongoDb: AccountDB, pgDb: AccountDB ): Promise { + // [accountId, workspaceId] const workspaceAssignments: [ObjectId, ObjectId][] = [] const accounts = await listAccounts(mongoDb) const workspaces = await listWorkspacesPure(mongoDb) @@ -153,14 +154,26 @@ export async function moveAccountDbFromMongoToPG ( delete (pgAccount as any).workspaces + if (pgAccount.createdOn == null) { + pgAccount.createdOn = Date.now() + } + + if (pgAccount.first == null) { + pgAccount.first = 'NotSet' + } + + if (pgAccount.last == null) { + pgAccount.last = 'NotSet' + } + + for (const workspaceString of new Set(mongoAccount.workspaces.map((w) => w.toString()))) { + workspaceAssignments.push([pgAccount._id, workspaceString]) + } + const exists = await getAccount(pgDb, pgAccount.email) if (exists === null) { await pgDb.account.insertOne(pgAccount) ctx.info('Moved account', { email: pgAccount.email }) - - for (const workspace of mongoAccount.workspaces) { - workspaceAssignments.push([pgAccount._id, workspace.toString()]) - } } } @@ -170,6 +183,10 @@ export async function moveAccountDbFromMongoToPG ( _id: mongoWorkspace._id.toString() } + if (pgWorkspace.createdOn == null) { + pgWorkspace.createdOn = Date.now() + } + // delete deprecated fields delete (pgWorkspace as any).createProgress delete (pgWorkspace as any).creating @@ -202,9 +219,19 @@ export async function moveAccountDbFromMongoToPG ( } } - if (workspaceAssignments.length > 0) { - for (const [accountId, workspaceId] of workspaceAssignments) { - await pgDb.assignWorkspace(accountId, workspaceId) - } + const pgAssignments = (await listAccounts(pgDb)).reduce>((assignments, acc) => { + assignments[acc._id] = acc.workspaces + + return assignments + }, {}) + const assignmentsToInsert = workspaceAssignments.filter( + ([accountId, workspaceId]) => + pgAssignments[accountId] === undefined || !pgAssignments[accountId].includes(workspaceId) + ) + + for (const [accountId, workspaceId] of assignmentsToInsert) { + await pgDb.assignWorkspace(accountId, workspaceId) } + + ctx.info('Assignments made', { count: assignmentsToInsert.length }) } diff --git a/models/all/src/migration.ts b/models/all/src/migration.ts index c919fd5334..4366401105 100644 --- a/models/all/src/migration.ts +++ b/models/all/src/migration.ts @@ -51,6 +51,7 @@ import { documentsOperation } from '@hcengineering/model-controlled-documents' import { productsOperation } from '@hcengineering/model-products' import { requestOperation } from '@hcengineering/model-request' import { analyticsCollectorOperation } from '@hcengineering/model-analytics-collector' +import { workbenchOperation } from '@hcengineering/model-workbench' export const migrateOperations: [string, MigrateOperation][] = [ ['core', coreOperation], @@ -90,5 +91,6 @@ export const migrateOperations: [string, MigrateOperation][] = [ ['textEditorOperation', textEditorOperation], // We should call notification migration after activityServer and chunter ['notification', notificationOperation], - ['analyticsCollector', analyticsCollectorOperation] + ['analyticsCollector', analyticsCollectorOperation], + ['workbench', workbenchOperation] ] diff --git a/models/attachment/package.json b/models/attachment/package.json index 7d94445a8d..ec30d84bfa 100644 --- a/models/attachment/package.json +++ b/models/attachment/package.json @@ -40,6 +40,7 @@ "@hcengineering/ui": "^0.6.15", "@hcengineering/view": "^0.6.13", "@hcengineering/model-presentation": "^0.6.0", - "@hcengineering/model-uploader": "^0.6.0" + "@hcengineering/model-uploader": "^0.6.0", + "@hcengineering/workbench": "^0.6.16" } } diff --git a/models/attachment/src/index.ts b/models/attachment/src/index.ts index fa062aeb06..f7bf8cf1a4 100644 --- a/models/attachment/src/index.ts +++ b/models/attachment/src/index.ts @@ -31,6 +31,8 @@ import { import core, { TAttachedDoc } from '@hcengineering/model-core' import preference, { TPreference } from '@hcengineering/model-preference' import view, { createAction } from '@hcengineering/model-view' +import workbench, { WidgetType } from '@hcengineering/workbench' +import presentation from '@hcengineering/model-presentation' import attachment from './plugin' @@ -97,6 +99,24 @@ export function createModel (builder: Builder): void { editor: attachment.component.Photos }) + builder.createDoc( + workbench.class.Widget, + core.space.Model, + { + label: attachment.string.Files, + type: WidgetType.Flexible, + icon: attachment.icon.Attachment, + component: attachment.component.PreviewWidget, + closeIfNoTabs: true + }, + attachment.ids.PreviewWidget + ) + + builder.createDoc(presentation.class.ComponentPointExtension, core.space.Model, { + extension: presentation.extension.FilePreviewPopupActions, + component: attachment.component.PreviewPopupActions + }) + builder.createDoc( activity.class.DocUpdateMessageViewlet, core.space.Model, diff --git a/models/attachment/src/plugin.ts b/models/attachment/src/plugin.ts index f62c50a8ab..d8bcdad4f9 100644 --- a/models/attachment/src/plugin.ts +++ b/models/attachment/src/plugin.ts @@ -24,7 +24,9 @@ import type { ActionCategory } from '@hcengineering/view' export default mergeIds(attachmentId, attachment, { component: { - AttachmentPresenter: '' as AnyComponent + AttachmentPresenter: '' as AnyComponent, + PreviewWidget: '' as AnyComponent, + PreviewPopupActions: '' as AnyComponent }, string: { AddAttachment: '' as IntlString, diff --git a/models/notification/src/index.ts b/models/notification/src/index.ts index 90a018a7aa..7a7026d5b4 100644 --- a/models/notification/src/index.ts +++ b/models/notification/src/index.ts @@ -388,7 +388,7 @@ export function createModel (builder: Builder): void { core.space.Model, { label: notification.string.Inbox, - icon: notification.icon.Inbox, + icon: notification.icon.Notifications, alias: notificationId, hidden: true, locationResolver: notification.resolver.Location, diff --git a/models/workbench/package.json b/models/workbench/package.json index 1270cc94d9..eaf30fbe28 100644 --- a/models/workbench/package.json +++ b/models/workbench/package.json @@ -35,6 +35,7 @@ "@hcengineering/model-presentation": "^0.6.0", "@hcengineering/model-view": "^0.6.0", "@hcengineering/platform": "^0.6.11", + "@hcengineering/preference": "^0.6.13", "@hcengineering/ui": "^0.6.15", "@hcengineering/view": "^0.6.13", "@hcengineering/workbench": "^0.6.16", diff --git a/models/workbench/src/index.ts b/models/workbench/src/index.ts index d7810e554a..765e7e5d9c 100644 --- a/models/workbench/src/index.ts +++ b/models/workbench/src/index.ts @@ -40,6 +40,7 @@ import presentation from '@hcengineering/model-presentation' import workbench from './plugin' export { workbenchId } from '@hcengineering/workbench' +export { workbenchOperation } from './migration' export type { Application } @Model(workbench.class.Application, core.class.Doc, DOMAIN_MODEL) diff --git a/models/workbench/src/migration.ts b/models/workbench/src/migration.ts new file mode 100644 index 0000000000..d4fb8fdaf3 --- /dev/null +++ b/models/workbench/src/migration.ts @@ -0,0 +1,40 @@ +// +// Copyright © 2024 Hardcore Engineering Inc. +// +// Licensed under the Eclipse Public License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// +import { + type MigrateOperation, + type MigrationClient, + type MigrationUpgradeClient, + tryMigrate +} from '@hcengineering/model' +import { DOMAIN_PREFERENCE } from '@hcengineering/preference' +import workbench from '@hcengineering/workbench' + +import { workbenchId } from '.' + +async function removeTabs (client: MigrationClient): Promise { + await client.deleteMany(DOMAIN_PREFERENCE, { _class: workbench.class.WorkbenchTab }) +} + +export const workbenchOperation: MigrateOperation = { + async migrate (client: MigrationClient): Promise { + await tryMigrate(client, workbenchId, [ + { + state: 'remove-wrong-tabs-v1', + func: removeTabs + } + ]) + }, + async upgrade (state: Map>, client: () => Promise): Promise {} +} diff --git a/packages/presentation/src/components/DownloadFileButton.svelte b/packages/presentation/src/components/DownloadFileButton.svelte new file mode 100644 index 0000000000..9275126a08 --- /dev/null +++ b/packages/presentation/src/components/DownloadFileButton.svelte @@ -0,0 +1,43 @@ + + + +{#await srcRef then src} + {#if src !== ''} + +