From 4ae95a447f443083ce8820840d2e36858c3c4266 Mon Sep 17 00:00:00 2001 From: Alexander Onnikov Date: Tue, 24 Sep 2024 14:54:57 +0700 Subject: [PATCH 1/5] fix: rush fast-format (#6702) Signed-off-by: Alexander Onnikov --- dev/tool/src/index.ts | 76 ++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/dev/tool/src/index.ts b/dev/tool/src/index.ts index e2ae3c88d1..5c54f9f4d9 100644 --- a/dev/tool/src/index.ts +++ b/dev/tool/src/index.ts @@ -1140,49 +1140,51 @@ export function devTool ( .option('-bl, --blobLimit ', 'A blob size limit in megabytes (default 50mb)', '50') .option('-c, --concurrency ', 'Number of files being processed concurrently', '10') .option('--disabled', 'Include disabled workspaces', false) - .action(async (cmd: { workspace: string, move: string, blobLimit: string, concurrency: string, disabled: boolean }) => { - const params = { - blobSizeLimitMb: parseInt(cmd.blobLimit), - concurrency: parseInt(cmd.concurrency), - move: cmd.move === 'true' - } + .action( + async (cmd: { workspace: string, move: string, blobLimit: string, concurrency: string, disabled: boolean }) => { + const params = { + blobSizeLimitMb: parseInt(cmd.blobLimit), + concurrency: parseInt(cmd.concurrency), + move: cmd.move === 'true' + } - const { mongodbUri } = prepareTools() - await withDatabase(mongodbUri, async (db) => { - await withStorage(mongodbUri, async (adapter) => { - try { - const exAdapter = adapter as StorageAdapterEx - if (exAdapter.adapters === undefined || exAdapter.adapters.size < 2) { - throw new Error('bad storage config, at least two storage providers are required') - } - - console.log('moving files to storage provider', exAdapter.defaultAdapter) - - let index = 1 - const workspaces = await listWorkspacesPure(db) - workspaces.sort((a, b) => b.lastVisit - a.lastVisit) - - for (const workspace of workspaces) { - if (cmd.workspace !== '' && workspace.workspace !== cmd.workspace) { - continue - } - if (workspace.disabled === true && !cmd.disabled) { - console.log('ignore disabled workspace', workspace.workspace) - continue + const { mongodbUri } = prepareTools() + await withDatabase(mongodbUri, async (db) => { + await withStorage(mongodbUri, async (adapter) => { + try { + const exAdapter = adapter as StorageAdapterEx + if (exAdapter.adapters === undefined || exAdapter.adapters.size < 2) { + throw new Error('bad storage config, at least two storage providers are required') } - console.log('start', workspace.workspace, index, '/', workspaces.length) - await moveFiles(toolCtx, getWorkspaceId(workspace.workspace), exAdapter, params) - console.log('done', workspace.workspace) + console.log('moving files to storage provider', exAdapter.defaultAdapter) - index += 1 + let index = 1 + const workspaces = await listWorkspacesPure(db) + workspaces.sort((a, b) => b.lastVisit - a.lastVisit) + + for (const workspace of workspaces) { + if (cmd.workspace !== '' && workspace.workspace !== cmd.workspace) { + continue + } + if (workspace.disabled === true && !cmd.disabled) { + console.log('ignore disabled workspace', workspace.workspace) + continue + } + + console.log('start', workspace.workspace, index, '/', workspaces.length) + await moveFiles(toolCtx, getWorkspaceId(workspace.workspace), exAdapter, params) + console.log('done', workspace.workspace) + + index += 1 + } + } catch (err: any) { + console.error(err) } - } catch (err: any) { - console.error(err) - } + }) }) - }) - }) + } + ) program .command('sync-files') From 33e132cb0075fa93360577e32f0824086aecf8dd Mon Sep 17 00:00:00 2001 From: Andrey Sobolev Date: Tue, 24 Sep 2024 16:20:00 +0700 Subject: [PATCH 2/5] UBERF-8251: Fix github re-authenticate (#6704) Signed-off-by: Andrey Sobolev --- services/github/github-resources/src/components/utils.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/github/github-resources/src/components/utils.ts b/services/github/github-resources/src/components/utils.ts index 2a49911c2c..5600ca53c7 100644 --- a/services/github/github-resources/src/components/utils.ts +++ b/services/github/github-resources/src/components/utils.ts @@ -24,10 +24,10 @@ export async function onAuthorize (login?: string): Promise { ) const client = getClient() - const config = await client.findOne(github.class.GithubAuthentication, {}) - - if (config !== undefined) { - await client.remove(config) + // Remove old authorizations. + const config = await client.findAll(github.class.GithubAuthentication, {}) + for (const c of config) { + await client.remove(c) } await client.createDoc(github.class.GithubAuthentication, core.space.Workspace, { attachedTo: meId, From 1ddf1fe4b013b3d7370ea003580864c74940beef Mon Sep 17 00:00:00 2001 From: Alexander Onnikov Date: Tue, 24 Sep 2024 18:01:00 +0700 Subject: [PATCH 3/5] UBERF-8080 Handle errors in ListKeymap extension (#6705) Signed-off-by: Alexander Onnikov --- .../src/components/extension/listkeymap.ts | 88 +++++++++++++++++++ .../src/kits/editor-kit.ts | 4 +- 2 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 plugins/text-editor-resources/src/components/extension/listkeymap.ts diff --git a/plugins/text-editor-resources/src/components/extension/listkeymap.ts b/plugins/text-editor-resources/src/components/extension/listkeymap.ts new file mode 100644 index 0000000000..eb1c9e842e --- /dev/null +++ b/plugins/text-editor-resources/src/components/extension/listkeymap.ts @@ -0,0 +1,88 @@ +// +// 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 Editor } from '@tiptap/core' +import ListKeymap, { type ListKeymapOptions, listHelpers } from '@tiptap/extension-list-keymap' + +/** + * Workaround for the original ListKeymap extension issue that + * https://github.com/ueberdosis/tiptap/issues/4368 + */ +export const ListKeymapExtension = ListKeymap.extend({ + addKeyboardShortcuts () { + const handleBackspace = (editor: Editor): boolean => { + let handled = false + + if (!editor.state.selection.empty) { + return false + } + + this.options.listTypes.forEach(({ itemName, wrapperNames }) => { + if (editor.state.schema.nodes[itemName] === undefined) { + return + } + if (listHelpers.handleBackspace(editor, itemName, wrapperNames)) { + handled = true + } + }) + + return handled + } + + const handleDelete = (editor: Editor): boolean => { + let handled = false + + if (!editor.state.selection.empty) { + return false + } + + this.options.listTypes.forEach(({ itemName }) => { + if (editor.state.schema.nodes[itemName] === undefined) { + return + } + if (listHelpers.handleDelete(editor, itemName)) { + handled = true + } + }) + + return handled + } + + const handleBackspaceSafe = (editor: Editor): boolean => { + try { + return handleBackspace(editor) + } catch (e) { + console.log(e) + return false + } + } + + const handleDeleteSafe = (editor: Editor): boolean => { + try { + return handleDelete(editor) + } catch (e) { + console.log(e) + return false + } + } + + return { + Backspace: ({ editor }) => handleBackspaceSafe(editor), + 'Mod-Backspace': ({ editor }) => handleBackspaceSafe(editor), + Delete: ({ editor }) => handleDeleteSafe(editor), + 'Mod-Delete': ({ editor }) => handleDeleteSafe(editor) + } + } +}) diff --git a/plugins/text-editor-resources/src/kits/editor-kit.ts b/plugins/text-editor-resources/src/kits/editor-kit.ts index 3c986bd86f..f16deb5bf7 100644 --- a/plugins/text-editor-resources/src/kits/editor-kit.ts +++ b/plugins/text-editor-resources/src/kits/editor-kit.ts @@ -19,7 +19,6 @@ import { CodeExtension, codeOptions } from '@hcengineering/text' import textEditor, { type ActionContext, type ExtensionCreator, type TextEditorMode } from '@hcengineering/text-editor' import { type AnyExtension, type Editor, Extension } from '@tiptap/core' import { type Level } from '@tiptap/extension-heading' -import ListKeymap from '@tiptap/extension-list-keymap' import TableHeader from '@tiptap/extension-table-header' import 'prosemirror-codemark/dist/codemark.css' @@ -30,6 +29,7 @@ import { FileExtension, type FileOptions } from '../components/extension/fileExt import { HardBreakExtension } from '../components/extension/hardBreak' import { ImageExtension, type ImageOptions } from '../components/extension/imageExt' import { InlineToolbarExtension } from '../components/extension/inlineToolbar' +import { ListKeymapExtension } from '../components/extension/listkeymap' import { NodeUuidExtension } from '../components/extension/nodeUuid' import { ParagraphExtension } from '../components/extension/paragraph' import { SubmitExtension, type SubmitOptions } from '../components/extension/submit' @@ -195,7 +195,7 @@ async function buildEditorKit (): Promise> { staticKitExtensions.push([ 500, - ListKeymap.configure({ + ListKeymapExtension.configure({ listTypes: [ { itemName: 'listItem', From 3662f1f8ee0d3c73d7492398be7aee6ef8448b5b Mon Sep 17 00:00:00 2001 From: Alexander Platov Date: Tue, 24 Sep 2024 19:31:11 +0700 Subject: [PATCH 4/5] Planner: fixed DateEditor layout (#6696) --- packages/theme/styles/button.scss | 174 ++++++++++ packages/ui/src/components/ButtonBase.svelte | 299 +----------------- .../components/calendar/TimeInputBox.svelte | 2 +- .../src/components/DateEditor.svelte | 57 ++-- .../src/components/Workslots.svelte | 19 +- .../tests/model/planning/planning-page.ts | 39 ++- 6 files changed, 239 insertions(+), 351 deletions(-) diff --git a/packages/theme/styles/button.scss b/packages/theme/styles/button.scss index 53820dbcfa..df341e369a 100644 --- a/packages/theme/styles/button.scss +++ b/packages/theme/styles/button.scss @@ -1,3 +1,177 @@ +.hulyButton { + display: inline-flex; + justify-content: center; + align-items: center; + flex-shrink: 0; + gap: var(--spacing-1); + border: 1px solid transparent; + + &:not(:disabled, .disabled, .loading) { cursor: pointer; } + &.inheritFont { font: inherit; } + + .icon { + display: flex; + align-items: center; + justify-content: center; + width: var(--spacing-2_5); + height: var(--spacing-2_5); + } + span { white-space: nowrap; } + + &:focus { + outline: 2px solid var(--global-focus-BorderColor); + outline-offset: 2px; + } + &.type-button-icon { padding: 0; } + &.large { + height: var(--global-large-Size); + border-radius: var(--medium-BorderRadius); + + &.round { border-radius: var(--large-BorderRadius); } + + &.type-button:not(.iconOnly) { padding: 0 var(--spacing-2); } + &.iconOnly, + &.type-button-icon { width: var(--global-large-Size); } + } + &.medium { + height: var(--global-medium-Size); + border-radius: var(--medium-BorderRadius); + + &.round { border-radius: var(--large-BorderRadius); } + &.type-button:not(.iconOnly) { padding: 0 var(--spacing-2); } + &.iconOnly, + &.type-button-icon { width: var(--global-medium-Size); } + } + &.small { + height: var(--global-small-Size); + gap: var(--spacing-0_5); + border-radius: var(--small-BorderRadius); + + &.round { border-radius: var(--large-BorderRadius); } + &.type-button:not(.iconOnly) { padding: 0 var(--spacing-1); } + &.iconOnly, + &.type-button-icon { width: var(--global-small-Size); } + } + &.extra-small { + height: var(--global-extra-small-Size); + border-radius: var(--extra-small-BorderRadius); + + &.round { border-radius: var(--large-BorderRadius); } + &.type-button:not(.iconOnly) { padding: 0 var(--spacing-1); } + &.iconOnly, + &.type-button-icon { width: var(--global-extra-small-Size); } + } + &.min { + height: var(--global-min-Size); + border: 0; + border-radius: var(--min-BorderRadius); + } + &.type-button-icon .icon, + &.menu .icon { + width: var(--spacing-2); + height: var(--spacing-2); + } + + &:disabled:not(.loading), + &.disabled:not(.loading) { + border-color: transparent; + cursor: not-allowed; + + .icon { color: var(--button-disabled-IconColor); } + span { color: var(--button-disabled-LabelColor); } + } + + &.primary { + border-color: var(--button-primary-BorderColor); + background-color: var(--button-primary-BackgroundColor); + + .icon { color: var(--button-accent-IconColor); } + span { color: var(--button-accent-LabelColor); } + + &:not(.disabled, :disabled):hover { background-color: var(--button-primary-hover-BackgroundColor); } + &:not(.disabled, :disabled):active, + &.pressed:not(.disabled, :disabled) { background-color: var(--button-primary-active-BackgroundColor); } + &.menu:not(.disabled, :disabled):active, + &.pressed:not(.disabled, :disabled) { border-color: var(--button-menu-active-BorderColor); } + &:disabled:not(.loading), + &.disabled:not(.loading) { background-color: var(--button-disabled-BackgroundColor); } + &.loading { + background-color: var(--button-primary-active-BackgroundColor); + + span { color: var(--button-primary-loading-LabelColor); } + } + } + + &.secondary { + border-color: var(--button-secondary-BorderColor); + background-color: var(--button-secondary-BackgroundColor); + + .icon { color: var(--button-subtle-IconColor); } + span { color: var(--button-subtle-LabelColor); } + + &:not(.disabled, :disabled):hover { background-color: var(--button-secondary-hover-BackgroundColor); } + &:not(.disabled, :disabled):active, + &.pressed:not(.disabled, :disabled) { background-color: var(--button-secondary-active-BackgroundColor); } + &.menu:not(.disabled, :disabled):active, + &.pressed:not(.disabled, :disabled) { border-color: var(--button-menu-active-BorderColor); } + &:disabled:not(.loading), + &.disabled:not(.loading) { background-color: var(--button-disabled-BackgroundColor); } + &.loading { + background-color: var(--button-secondary-active-BackgroundColor); + + span { color: var(--button-disabled-LabelColor); } + } + } + + &.tertiary { + border-color: transparent; + background-color: transparent; + + &:not(.inheritColor) .icon { color: var(--button-subtle-IconColor); } + &.inheritColor { + color: inherit; + + .icon { color: currentColor; } + } + span { color: var(--button-subtle-LabelColor); } + + &:not(.disabled, :disabled):hover { background-color: var(--button-tertiary-hover-BackgroundColor); } + &:not(.disabled, :disabled):active, + &.pressed:not(.disabled, :disabled) { background-color: var(--button-tertiary-active-BackgroundColor); } + &.menu:not(.disabled, :disabled):active, + &.pressed:not(.disabled, :disabled) { border-color: var(--button-menu-active-BorderColor); } + &.loading { + background-color: var(--button-tertiary-active-BackgroundColor); + + span { color: var(--button-disabled-LabelColor); } + } + } + + &.negative { + border-color: var(--button-negative-BorderColor); + background-color: var(--button-negative-BackgroundColor); + + .icon { color: var(--button-accent-IconColor); } + span { color: var(--button-accent-LabelColor); } + + &:not(.disabled, :disabled):hover { background-color: var(--button-negative-hover-BackgroundColor); } + &:not(.disabled, :disabled):active, + &.pressed:not(.disabled, :disabled) { background-color: var(--button-negative-active-BackgroundColor); } + &.menu:not(.disabled, :disabled):active, + &.pressed:not(.disabled, :disabled) { border-color: var(--button-menu-active-BorderColor); } + &:disabled:not(.loading), + &.disabled:not(.loading) { background-color: var(--button-disabled-BackgroundColor); } + &.loading { + background-color: var(--button-negative-active-BackgroundColor); + + span { color: var(--button-negative-loading-LabelColor); } + } + } + + & > * { pointer-events: none; } +} + +// Old style Button .antiButton { display: flex; align-items: center; diff --git a/packages/ui/src/components/ButtonBase.svelte b/packages/ui/src/components/ButtonBase.svelte index 487cd96623..1acf7c107b 100644 --- a/packages/ui/src/components/ButtonBase.svelte +++ b/packages/ui/src/components/ButtonBase.svelte @@ -92,7 +92,7 @@ - - diff --git a/packages/ui/src/components/calendar/TimeInputBox.svelte b/packages/ui/src/components/calendar/TimeInputBox.svelte index f3b19b3e8e..dc3cb5466b 100644 --- a/packages/ui/src/components/calendar/TimeInputBox.svelte +++ b/packages/ui/src/components/calendar/TimeInputBox.svelte @@ -153,7 +153,7 @@ } } } - const focused = (ed: TEdits): void => { + export const focused = (ed: TEdits): void => { selected = ed startTyping = true } diff --git a/plugins/calendar-resources/src/components/DateEditor.svelte b/plugins/calendar-resources/src/components/DateEditor.svelte index 1795edd5bf..2ab809b2c4 100644 --- a/plugins/calendar-resources/src/components/DateEditor.svelte +++ b/plugins/calendar-resources/src/components/DateEditor.svelte @@ -31,7 +31,7 @@ export let date: number export let difference: number = 0 - export let direction: 'vertical' | 'horizontal' = 'vertical' + export let direction: 'vertical' | 'horizontal' | 'auto' = 'vertical' export let showDate: boolean = true export let withoutTime: boolean export let kind: ButtonBaseKind = 'tertiary' @@ -44,8 +44,9 @@ const dispatch = createEventDispatcher() $: currentDate = new Date(date) + let tib: TimeInputBox - function timeClick (e: MouseEvent) { + function timeClick (e: MouseEvent & { currentTarget: EventTarget & HTMLElement }) { if (!showDate) { showPopup( DatePopup, @@ -58,7 +59,7 @@ } } ) - } + } else if (!disabled) tib.focused(e.offsetX <= e.currentTarget.clientWidth / 2 ? 'hour' : 'min') } function dateClick (e: MouseEvent) { @@ -85,13 +86,17 @@ {#if fixed === undefined}
- + + +
{:else} - + + + {/if} @@ -103,15 +108,17 @@ {#if !withoutTime} {#if fixed === undefined} - + + +
- +
{:else} - + + +
- +
{/if} {/if} @@ -162,9 +171,15 @@ diff --git a/plugins/chunter-resources/src/components/threads/ThreadView.svelte b/plugins/chunter-resources/src/components/threads/ThreadView.svelte index 9a249b28de..f6c386e228 100644 --- a/plugins/chunter-resources/src/components/threads/ThreadView.svelte +++ b/plugins/chunter-resources/src/components/threads/ThreadView.svelte @@ -15,7 +15,7 @@ {#if showHeader} @@ -153,54 +141,10 @@ {/if} -
- {#if message && dataProvider !== undefined} - - -
- -
- - {#if (message.replies ?? $messagesStore?.length ?? 0) > 0} -
-
-
-
-
- {/if} - - - {/if} -
- - +{#if message} + {#key _id} + + {/key} +{:else if isLoading} + +{/if} diff --git a/plugins/chunter-resources/src/navigation.ts b/plugins/chunter-resources/src/navigation.ts index 6e9cf29e75..9281c98fa2 100644 --- a/plugins/chunter-resources/src/navigation.ts +++ b/plugins/chunter-resources/src/navigation.ts @@ -28,6 +28,7 @@ import { get } from 'svelte/store' import { chatSpecials } from './components/chat/utils' import { getChannelName, isThreadMessage } from './utils' import chunter from './plugin' +import { threadMessagesStore } from './stores' export function openChannel (_id: string, _class: Ref>, thread?: Ref): void { const loc = getCurrentLocation() @@ -168,6 +169,8 @@ export async function replyToThread (message: ActivityMessage, e: Event): Promis const fromSidebar = isElementFromSidebar(e.target as HTMLElement) const loc = getCurrentLocation() + threadMessagesStore.set(message) + if (fromSidebar) { const widget = getClient().getModel().findAllSync(workbench.class.Widget, { _id: chunter.ids.ChatWidget })[0] const widgetState = get(sidebarStore).widgetsState.get(widget._id) @@ -235,7 +238,8 @@ export async function openChannelInSidebar ( _class: Ref>, doc?: Doc, thread?: Ref, - newTab = true + newTab = true, + selectedMessageId?: Ref ): Promise { const client = getClient() @@ -267,6 +271,7 @@ export async function openChannelInSidebar ( _id, _class, thread, + selectedMessageId, channelName: name } } diff --git a/plugins/chunter-resources/src/stores.ts b/plugins/chunter-resources/src/stores.ts index 789c8a702d..03b1b787ad 100644 --- a/plugins/chunter-resources/src/stores.ts +++ b/plugins/chunter-resources/src/stores.ts @@ -17,11 +17,14 @@ import { writable } from 'svelte/store' import { type ChatMessage } from '@hcengineering/chunter' import { type Markup, type Ref } from '@hcengineering/core' import { languageStore } from '@hcengineering/ui' +import { type ActivityMessage } from '@hcengineering/activity' export const translatingMessagesStore = writable>>(new Set()) export const translatedMessagesStore = writable, Markup>>(new Map()) export const shownTranslatedMessagesStore = writable>>(new Set()) +export const threadMessagesStore = writable(undefined) + languageStore.subscribe(() => { translatedMessagesStore.set(new Map()) shownTranslatedMessagesStore.set(new Set()) diff --git a/plugins/chunter/src/index.ts b/plugins/chunter/src/index.ts index 3c814160b9..662ea1e23d 100644 --- a/plugins/chunter/src/index.ts +++ b/plugins/chunter/src/index.ts @@ -100,7 +100,13 @@ export interface InlineButton extends AttachedDoc { } export interface ChatWidgetTab extends WidgetTab { - data: { _id?: Ref, _class?: Ref>, thread?: Ref, channelName: string } + data: { + _id?: Ref + _class?: Ref> + thread?: Ref + channelName: string + selectedMessageId?: Ref + } } /** @@ -234,7 +240,14 @@ export default plugin(chunterId, { CanTranslateMessage: '' as Resource<(doc?: Doc | Doc[]) => Promise>, OpenThreadInSidebar: '' as Resource<(_id: Ref, msg?: ActivityMessage, doc?: Doc) => Promise>, OpenChannelInSidebar: '' as Resource< - (_id: Ref, _class: Ref, doc?: Doc, thread?: Ref) => Promise + ( + _id: Ref, + _class: Ref>, + doc?: Doc, + thread?: Ref, + newTab?: boolean, + selectedMessageId?: Ref + ) => Promise > } }) diff --git a/plugins/notification-resources/src/components/DocNotifyContextCard.svelte b/plugins/notification-resources/src/components/DocNotifyContextCard.svelte index d9c8b7ef75..206e845674 100644 --- a/plugins/notification-resources/src/components/DocNotifyContextCard.svelte +++ b/plugins/notification-resources/src/components/DocNotifyContextCard.svelte @@ -64,6 +64,7 @@ $: if (object !== undefined && object?._id !== value.objectId) { object = undefined + isLoading = true } let isActionMenuOpened = false diff --git a/plugins/notification-resources/src/components/Notification.svelte b/plugins/notification-resources/src/components/Notification.svelte index e76f6c5ae8..0fd5045cee 100644 --- a/plugins/notification-resources/src/components/Notification.svelte +++ b/plugins/notification-resources/src/components/Notification.svelte @@ -1,13 +1,14 @@ @@ -56,7 +77,7 @@