From 960c7d9963f7d5e0a9059bbafcc99fded43061c3 Mon Sep 17 00:00:00 2001 From: Andrey Sobolev Date: Mon, 15 Jan 2024 23:10:30 +0700 Subject: [PATCH] UBERF-4928: Indexing fixes (#4357) Signed-off-by: Andrey Sobolev --- models/board/src/index.ts | 18 - models/task/src/index.ts | 88 +---- models/task/src/plugin.ts | 4 - models/tracker/src/types.ts | 4 - packages/core/src/classes.ts | 4 +- packages/core/src/utils.ts | 2 +- .../src/components/EditCard.svelte | 31 +- .../src/components/KanbanCard.svelte | 16 +- .../components/editor/CardChecklist.svelte | 315 ------------------ .../src/components/popups/AddChecklist.svelte | 137 -------- .../presenters/ChecklistsPresenter.svelte | 42 --- plugins/board-resources/src/index.ts | 25 -- plugins/board-resources/src/plugin.ts | 9 +- .../board-resources/src/utils/BoardUtils.ts | 15 +- .../board-resources/src/utils/CardUtils.ts | 13 +- plugins/task-assets/lang/en.json | 2 - plugins/task-assets/lang/ru.json | 2 - .../src/components/todos/CreateTodo.svelte | 88 ----- .../src/components/todos/EditTodo.svelte | 85 ----- .../components/todos/TodoItemPresenter.svelte | 46 --- .../components/todos/TodoItemsPopup.svelte | 40 --- .../todos/TodoStatePresenter.svelte | 44 --- .../src/components/todos/Todos.svelte | 93 ------ plugins/task-resources/src/index.ts | 8 - plugins/task-resources/src/plugin.ts | 1 - plugins/task/src/index.ts | 18 +- server/backup/src/index.ts | 2 + server/core/src/indexer/indexer.ts | 5 +- server/middleware/src/spaceSecurity.ts | 40 ++- server/mongo/src/storage.ts | 25 +- server/tool/src/index.ts | 9 +- server/ws/src/server.ts | 22 +- 32 files changed, 91 insertions(+), 1162 deletions(-) delete mode 100644 plugins/board-resources/src/components/editor/CardChecklist.svelte delete mode 100644 plugins/board-resources/src/components/popups/AddChecklist.svelte delete mode 100644 plugins/board-resources/src/components/presenters/ChecklistsPresenter.svelte delete mode 100644 plugins/task-resources/src/components/todos/CreateTodo.svelte delete mode 100644 plugins/task-resources/src/components/todos/EditTodo.svelte delete mode 100644 plugins/task-resources/src/components/todos/TodoItemPresenter.svelte delete mode 100644 plugins/task-resources/src/components/todos/TodoItemsPopup.svelte delete mode 100644 plugins/task-resources/src/components/todos/TodoStatePresenter.svelte delete mode 100644 plugins/task-resources/src/components/todos/Todos.svelte diff --git a/models/board/src/index.ts b/models/board/src/index.ts index ba96534648..cbe821fb8e 100644 --- a/models/board/src/index.ts +++ b/models/board/src/index.ts @@ -484,24 +484,6 @@ export function createModel (builder: Builder): void { actions: [view.action.Delete, task.action.Move] }) - // TODO: update query when nested query is available - createAction( - builder, - { - action: board.actionImpl.ConvertToCard, - label: board.string.ConvertToCard, - icon: board.icon.Card, - category: board.category.Card, - query: { - attachedToClass: task.class.TodoItem - }, - input: 'any', - target: task.class.TodoItem, - context: { mode: ['context', 'browser'] } - }, - board.action.ConvertToCard - ) - createAction(builder, { ...viewTemplates.open, target: board.class.Board, diff --git a/models/task/src/index.ts b/models/task/src/index.ts index 81b9d5bf24..734e57f6f0 100644 --- a/models/task/src/index.ts +++ b/models/task/src/index.ts @@ -13,7 +13,7 @@ // limitations under the License. // -import type { Employee, Person } from '@hcengineering/contact' +import type { Person } from '@hcengineering/contact' import contact from '@hcengineering/contact' import { ClassifierKind, @@ -41,16 +41,15 @@ import { Mixin, Model, Prop, + ReadOnly, TypeBoolean, TypeDate, - TypeMarkup, TypeRecord, TypeRef, TypeString, UX, type Builder, - type MigrationClient, - ReadOnly + type MigrationClient } from '@hcengineering/model' import attachment from '@hcengineering/model-attachment' import chunter from '@hcengineering/model-chunter' @@ -65,7 +64,6 @@ import { getEmbeddedLabel, type Asset, type IntlString, type Resource } from '@h import setting from '@hcengineering/setting' import tags from '@hcengineering/tags' import { - type TaskStatusFactory, calculateStatuses, findStatusAttr, type KanbanCard, @@ -76,11 +74,11 @@ import { type ProjectTypeDescriptor, type Sequence, type Task, + type TaskStatusFactory, type TaskType, type TaskTypeClass, type TaskTypeDescriptor, - type TaskTypeKind, - type TodoItem + type TaskTypeKind } from '@hcengineering/task' import type { AnyComponent } from '@hcengineering/ui' import { PaletteColorIndexes } from '@hcengineering/ui/src/colors' @@ -121,7 +119,10 @@ export class TTask extends TAttachedDoc implements Task { @Prop(TypeDate(), task.string.DueDate, { editor: task.component.DueDateEditor }) dueDate!: Timestamp | null - declare rank: string + @Prop(TypeString(), task.string.Rank) + @Index(IndexKind.IndexedDsc) + @Hidden() + rank!: string @Prop(Collection(tags.class.TagReference, task.string.TaskLabels), task.string.TaskLabels) labels?: number @@ -135,28 +136,6 @@ export class TTask extends TAttachedDoc implements Task { isDone?: boolean } -@Model(task.class.TodoItem, core.class.AttachedDoc, DOMAIN_TASK) -@UX(task.string.Todo) -export class TTodoItem extends TAttachedDoc implements TodoItem { - @Prop(TypeMarkup(), task.string.TodoName, task.icon.Task) - @Index(IndexKind.FullText) - name!: string - - @Prop(TypeRef(contact.mixin.Employee), task.string.TaskAssignee) - assignee!: Ref | null - - @Prop(TypeBoolean(), task.string.TaskDone) - done!: boolean - - @Prop(TypeDate(), task.string.TaskDueTo) - dueTo!: Timestamp | null - - @Prop(Collection(task.class.TodoItem), task.string.Todos) - items!: number - - declare rank: string -} - @Mixin(task.mixin.KanbanCard, core.class.Class) export class TKanbanCard extends TClass implements KanbanCard { card!: AnyComponent @@ -320,7 +299,6 @@ export function createModel (builder: Builder): void { TKanbanCard, TSequence, TTask, - TTodoItem, TProject, TProjectType, TTaskType, @@ -418,14 +396,6 @@ export function createModel (builder: Builder): void { task.viewlet.Dashboard ) - builder.mixin(task.class.TodoItem, core.class.Class, view.mixin.CollectionEditor, { - editor: task.component.Todos - }) - - builder.mixin(task.class.TodoItem, core.class.Class, view.mixin.ObjectPresenter, { - presenter: task.component.TodoItemPresenter - }) - builder.mixin(task.class.TaskType, core.class.Class, view.mixin.ObjectPresenter, { presenter: task.component.TaskTypePresenter }) @@ -436,46 +406,6 @@ export function createModel (builder: Builder): void { classPresenter(builder, task.class.TaskType, task.component.TaskTypePresenter, task.component.TaskTypePresenter) - createAction(builder, { - label: task.string.MarkAsDone, - icon: task.icon.TodoCheck, - action: view.actionImpl.UpdateDocument, - actionProps: { - key: 'done', - value: true - }, - input: 'focus', - category: task.category.Task, - query: { - done: false - }, - target: task.class.TodoItem, - context: { - mode: ['context', 'browser'], - group: 'edit' - } - }) - - createAction(builder, { - label: task.string.MarkAsUndone, - icon: task.icon.TodoUnCheck, - action: view.actionImpl.UpdateDocument, - actionProps: { - key: 'done', - value: false - }, - input: 'focus', - category: task.category.Task, - query: { - done: true - }, - context: { - mode: ['context', 'browser'], - group: 'edit' - }, - target: task.class.TodoItem - }) - createAction( builder, { diff --git a/models/task/src/plugin.ts b/models/task/src/plugin.ts index 250db11bfb..be6a9c0cc5 100644 --- a/models/task/src/plugin.ts +++ b/models/task/src/plugin.ts @@ -32,8 +32,6 @@ export default mergeIds(taskId, task, { }, actionImpl: { EditStatuses: '' as ViewAction, - TodoItemMarkDone: '' as ViewAction, - TodoItemMarkUnDone: '' as ViewAction, ArchiveSpace: '' as ViewAction, UnarchiveSpace: '' as ViewAction, SelectStatus: '' as ViewAction @@ -51,8 +49,6 @@ export default mergeIds(taskId, task, { StatePresenter: '' as AnyComponent, StateEditor: '' as AnyComponent, KanbanView: '' as AnyComponent, - Todos: '' as AnyComponent, - TodoItemPresenter: '' as AnyComponent, StatusTableView: '' as AnyComponent, TaskHeader: '' as AnyComponent, Dashboard: '' as AnyComponent, diff --git a/models/tracker/src/types.ts b/models/tracker/src/types.ts index 71f1feb48c..6b412575b7 100644 --- a/models/tracker/src/types.ts +++ b/models/tracker/src/types.ts @@ -224,10 +224,6 @@ export class TIssue extends TTask implements Issue { @Prop(TypeDate(DateRangeMode.DATETIME), tracker.string.DueDate) declare dueDate: Timestamp | null - @Prop(TypeString(), tracker.string.Rank) - @Hidden() - declare rank: string - @Prop(TypeRef(tracker.class.Milestone), tracker.string.Milestone, { icon: tracker.icon.Milestone }) @Index(IndexKind.Indexed) milestone!: Ref | null diff --git a/packages/core/src/classes.ts b/packages/core/src/classes.ts index 3f0578151b..20e3a234e3 100644 --- a/packages/core/src/classes.ts +++ b/packages/core/src/classes.ts @@ -114,7 +114,9 @@ export enum IndexKind { * * Also mean to include into Elastic search. */ - Indexed + Indexed, + // Same as indexed but for descending + IndexedDsc } /** diff --git a/packages/core/src/utils.ts b/packages/core/src/utils.ts index ca38a30261..afb4650d3f 100644 --- a/packages/core/src/utils.ts +++ b/packages/core/src/utils.ts @@ -184,7 +184,7 @@ export function isFullTextAttribute (attr: AnyAttribute): boolean { * @public */ export function isIndexedAttribute (attr: AnyAttribute): boolean { - return attr.index === IndexKind.Indexed + return attr.index === IndexKind.Indexed || attr.index === IndexKind.IndexedDsc } /** diff --git a/plugins/board-resources/src/components/EditCard.svelte b/plugins/board-resources/src/components/EditCard.svelte index 078e6a940d..bf11e4f5b2 100644 --- a/plugins/board-resources/src/components/EditCard.svelte +++ b/plugins/board-resources/src/components/EditCard.svelte @@ -19,27 +19,23 @@ import core, { Class, Doc, Mixin, Ref, Space } from '@hcengineering/core' import { Panel } from '@hcengineering/panel' import { createQuery, getClient } from '@hcengineering/presentation' - import type { State, TodoItem } from '@hcengineering/task' - import task from '@hcengineering/task' import { StyledTextBox } from '@hcengineering/text-editor' import { Button, CircleButton, EditBox, - getEventPopupPositionElement, IconAdd, IconMoreH, Label, + getEventPopupPositionElement, showPopup } from '@hcengineering/ui' - import { ContextMenu, DocAttributeBar, invokeAction, ParentsNavigator } from '@hcengineering/view-resources' + import { ContextMenu, DocAttributeBar, ParentsNavigator, invokeAction } from '@hcengineering/view-resources' import { createEventDispatcher, onMount } from 'svelte' import board from '../plugin' import { getCardActions } from '../utils/CardActionUtils' import { updateCard } from '../utils/CardUtils' import CardActions from './editor/CardActions.svelte' - import CardChecklist from './editor/CardChecklist.svelte' - import AddChecklist from './popups/AddChecklist.svelte' export let _id: Ref export let _class: Ref> @@ -48,13 +44,12 @@ const cardQuery = createQuery() const stateQuery = createQuery() const spaceQuery = createQuery() - const checklistsQuery = createQuery() let object: Card | undefined let state: State | undefined let space: Space | undefined let handleMove: (e: Event) => void - let checklists: TodoItem[] = [] + const mixins: Mixin[] = [] const allowedCollections = ['labels'] const ignoreKeys = ['isArchived', 'location', 'title', 'description', 'status', 'number', 'assignee'] @@ -65,16 +60,12 @@ } } - function addChecklist (e: Event) { - showPopup(AddChecklist, { value: object }, getEventPopupPositionElement(e)) - } - $: cardQuery.query(_class, { _id }, (result) => { object = result[0] }) $: object?.status && - stateQuery.query(task.class.State, { _id: object.status }, (result) => { + stateQuery.query(core.class.Status, { _id: object.status }, (result) => { state = result[0] }) @@ -83,11 +74,6 @@ space = result[0] }) - $: object && - checklistsQuery.query(task.class.TodoItem, { space: object.space, attachedTo: object._id }, (result) => { - checklists = result - }) - getCardActions(client, { _id: board.action.Move }).then(async (result) => { if (result[0]) { handleMove = (e) => { @@ -157,15 +143,6 @@
-
- - -
-
- {#each checklists as checklist} - - {/each} -
{#if direction === 'column'} diff --git a/plugins/board-resources/src/components/KanbanCard.svelte b/plugins/board-resources/src/components/KanbanCard.svelte index 7a2305d8ae..893d98a676 100644 --- a/plugins/board-resources/src/components/KanbanCard.svelte +++ b/plugins/board-resources/src/components/KanbanCard.svelte @@ -19,27 +19,26 @@ import contact, { Employee } from '@hcengineering/contact' import type { Ref, WithLookup } from '@hcengineering/core' import notification from '@hcengineering/notification' - import view from '@hcengineering/view' - import tags from '@hcengineering/tags' + import { ChatMessagesPresenter } from '@hcengineering/notification-resources' import { getClient } from '@hcengineering/presentation' + import tags from '@hcengineering/tags' import { Button, Component, EditBox, - getPopupPositionElement, Icon, IconMoreV, Label, + getPopupPositionElement, numberToHexColor, showPopup } from '@hcengineering/ui' + import view from '@hcengineering/view' import { ContextMenu } from '@hcengineering/view-resources' import board from '../plugin' - import DatePresenter from './presenters/DatePresenter.svelte' import { hasDate, openCardPanel, updateCard, updateCardMembers } from '../utils/CardUtils' - import CheckListsPresenter from './presenters/ChecklistsPresenter.svelte' + import DatePresenter from './presenters/DatePresenter.svelte' import NotificationPresenter from './presenters/NotificationPresenter.svelte' - import { ChatMessagesPresenter } from '@hcengineering/notification-resources' export let object: WithLookup @@ -198,11 +197,6 @@ {/if} - {#if (object.todoItems ?? 0) > 0} -
- -
- {/if} {#if (object.labels ?? 0) > 0}
- - -{#if value !== undefined} -
{ - itemDrop() - }} - on:dragover|preventDefault - on:dragleave - > -
- {#if isEditingName} -
- { - isEditingName = false - }} - /> -
- {:else} -
{ - isEditingName = true - }} - > - {value.name} -
- {#if done > 0} -
-
-
- {checklistItems.length > 0 ? Math.round((done / checklistItems.length) * 100) : 0}% -
-
- -
-
- {#each checklistItems.filter((item) => !hideDoneItems || !item.done) as item} -
{ - dragItem = item - }} - on:dragend={() => { - dragItem = undefined - dragOverItem = undefined - }} - on:dragover={() => { - dragOverItem = item - }} - on:mouseover={() => { - hovered = item._id - }} - on:focus={() => { - hovered = item._id - }} - on:mouseout={() => { - hovered = undefined - }} - on:blur={() => { - hovered = undefined - }} - > -
- setDoneToChecklistItem(item, event)} /> -
- {#if editingItemId === item._id} -
- { - editingItemId = undefined - updateItemName(item, event.detail) - }} - on:cancel={() => { - editingItemId = undefined - }} - /> -
- {:else} -
{ - editingItemId = item._id - }} - > - -
-
- { - updateDueDate(item, e.detail) - }} - noShift - /> - { - updateItemAssignee(item, e.detail) - }} - /> -
- {/if} -
- {/each} -
-
- {#if isAddingItem} -
- { - newItemName = '' - isAddingItem = false - }} - /> -
- {/if} -
-
-{/if} diff --git a/plugins/board-resources/src/components/popups/AddChecklist.svelte b/plugins/board-resources/src/components/popups/AddChecklist.svelte deleted file mode 100644 index 202150ce24..0000000000 --- a/plugins/board-resources/src/components/popups/AddChecklist.svelte +++ /dev/null @@ -1,137 +0,0 @@ - - - 0} - on:close={() => { - dispatch('close') - }} -> -
-
- -
-
-
diff --git a/plugins/board-resources/src/components/presenters/ChecklistsPresenter.svelte b/plugins/board-resources/src/components/presenters/ChecklistsPresenter.svelte deleted file mode 100644 index 610ed618d7..0000000000 --- a/plugins/board-resources/src/components/presenters/ChecklistsPresenter.svelte +++ /dev/null @@ -1,42 +0,0 @@ - - -{#if value && (total ?? 0) > 0} -
- -  {done}/{total} - {#if item.dueTo !== null} -   - {/if} -
-{/if} diff --git a/plugins/board-resources/src/index.ts b/plugins/board-resources/src/index.ts index 68909ae20c..fa0627fcd8 100644 --- a/plugins/board-resources/src/index.ts +++ b/plugins/board-resources/src/index.ts @@ -14,10 +14,7 @@ // limitations under the License. // import { type Resources } from '@hcengineering/platform' -import { getClient } from '@hcengineering/presentation' -import task, { type Project, type TodoItem } from '@hcengineering/task' -import { type Ref } from '@hcengineering/core' import Archive from './components/Archive.svelte' import BoardHeader from './components/BoardHeader.svelte' import BoardMenu from './components/BoardMenu.svelte' @@ -39,25 +36,6 @@ import CopyCard from './components/popups/CopyCard.svelte' import DateRangePicker from './components/popups/DateRangePicker.svelte' import MoveCard from './components/popups/MoveCard.svelte' import CardCoverPresenter from './components/presenters/CardCoverPresenter.svelte' -import { createCard, getCardFromTodoItem } from './utils/CardUtils' - -async function ConvertToCard (object: TodoItem): Promise { - const client = getClient() - const todoItemCard = await getCardFromTodoItem(client, object) - if (todoItemCard === undefined) return - - // TODO: Add filtering if requierd, or pass a type from UI - const project = await client.findOne(task.class.Project, { _id: object.space as Ref }) - const taskTypes = await client.findAll(task.class.TaskType, { parent: project?.type }) - await createCard(client, todoItemCard.space, todoItemCard.status, { - title: object.name, - assignee: object.assignee, - dueDate: object.dueTo, - kind: taskTypes[0]._id - }) - - await client.remove(object) -} export default async (): Promise => ({ component: { @@ -83,8 +61,5 @@ export default async (): Promise => ({ CoverActionPopup: CardCoverPicker, MoveActionPopup: MoveCard, CopyActionPopup: CopyCard - }, - actionImpl: { - ConvertToCard } }) diff --git a/plugins/board-resources/src/plugin.ts b/plugins/board-resources/src/plugin.ts index edfa9edc9e..40fa6ec7f6 100644 --- a/plugins/board-resources/src/plugin.ts +++ b/plugins/board-resources/src/plugin.ts @@ -56,11 +56,6 @@ export default mergeIds(boardId, board, { SelectColor: '' as IntlString, NoColor: '' as IntlString, NoColorInfo: '' as IntlString, - Checklists: '' as IntlString, - ChecklistDropdownNone: '' as IntlString, - ShowDoneChecklistItems: '' as IntlString, - HideDoneChecklistItems: '' as IntlString, - CopyChecklistFrom: '' as IntlString, Dates: '' as IntlString, Attachments: '' as IntlString, AddAttachment: '' as IntlString, @@ -119,9 +114,7 @@ export default mergeIds(boardId, board, { SwitchToCards: '' as IntlString, SearchArchive: '' as IntlString, Size: '' as IntlString, - RemoveCover: '' as IntlString, - DeleteChecklist: '' as IntlString, - DeleteChecklistConfirm: '' as IntlString + RemoveCover: '' as IntlString }, statusCategory: { Completed: '' as Ref diff --git a/plugins/board-resources/src/utils/BoardUtils.ts b/plugins/board-resources/src/utils/BoardUtils.ts index 82dc0030b6..cf1a397722 100644 --- a/plugins/board-resources/src/utils/BoardUtils.ts +++ b/plugins/board-resources/src/utils/BoardUtils.ts @@ -1,8 +1,8 @@ import board, { type Board, type CommonBoardPreference } from '@hcengineering/board' -import core, { type Ref, type TxOperations, getCurrentAccount } from '@hcengineering/core' +import core, { getCurrentAccount, type Ref, type TxOperations } from '@hcengineering/core' import preference from '@hcengineering/preference' import { createQuery, getClient } from '@hcengineering/presentation' -import type { ProjectType, TodoItem } from '@hcengineering/task' +import type { ProjectType } from '@hcengineering/task' import { EastSideColor, FeijoaColor, @@ -13,8 +13,7 @@ import { MoodyBlueColor, SalmonColor, SeaBuckthornColor, - SeagullColor, - areDatesEqual + SeagullColor } from '@hcengineering/ui' import { readable } from 'svelte/store' @@ -50,14 +49,6 @@ export function getBoardAvailableColors (): string[] { SeagullColor ] } - -export function getDateIcon (item: TodoItem): 'normal' | 'warning' | 'overdue' { - if (item.dueTo === null) return 'normal' - const date = new Date() - const dueDate = new Date(item.dueTo) - return areDatesEqual(date, dueDate) ? 'warning' : dueDate < date ? 'overdue' : 'normal' -} - export const commonBoardPreference = readable(undefined, (set) => { createQuery().query(board.class.CommonBoardPreference, { attachedTo: board.app.Board }, (result) => { if (result.length > 0) { diff --git a/plugins/board-resources/src/utils/CardUtils.ts b/plugins/board-resources/src/utils/CardUtils.ts index ae9ca07f5d..a223517fc6 100644 --- a/plugins/board-resources/src/utils/CardUtils.ts +++ b/plugins/board-resources/src/utils/CardUtils.ts @@ -11,7 +11,7 @@ import { type Status } from '@hcengineering/core' import { showPanel } from '@hcengineering/ui' -import task, { calcRank, type TodoItem } from '@hcengineering/task' +import task, { calcRank } from '@hcengineering/task' import board from '../plugin' export async function createCard ( @@ -43,17 +43,6 @@ export async function createCard ( return await client.addCollection(board.class.Card, space, space, board.class.Board, 'cards', value) } -export async function getCardFromTodoItem (client: Client, todoItem: TodoItem | undefined): Promise { - if (todoItem === undefined) return - if (todoItem.attachedToClass === todoItem._class) { - return await getCardFromTodoItem( - client, - await client.findOne(todoItem._class, { _id: todoItem.attachedTo as Ref }) - ) - } - return await client.findOne(board.class.Card, { _id: todoItem.attachedTo as Ref }) -} - export function updateCard (client: Client, card: Card, field: string, value: any): Promise | undefined { if (card === undefined) { return diff --git a/plugins/task-assets/lang/en.json b/plugins/task-assets/lang/en.json index eaad83e976..7823ef3148 100644 --- a/plugins/task-assets/lang/en.json +++ b/plugins/task-assets/lang/en.json @@ -41,7 +41,6 @@ "TaskUnAssign": "Unassign", "NoTaskForObject": "No tasks defined", "Delete": "Delete", - "NoTodoItems": "No to do's defined", "TodoName": "Name", "TodoState": "State", "DoneState": "Done State", @@ -70,7 +69,6 @@ "CantStatusDeleteError": "There are objects in the given state. Move or delete them first.", "Tasks": "Tasks", "AssignedToMe": "Assigned to me", - "TodoItems": "Todos", "Dashboard": "Dashboard", "AllTime": "All time", "RelatedIssues": "Related processes", diff --git a/plugins/task-assets/lang/ru.json b/plugins/task-assets/lang/ru.json index 683b683261..f45d50c978 100644 --- a/plugins/task-assets/lang/ru.json +++ b/plugins/task-assets/lang/ru.json @@ -41,7 +41,6 @@ "TaskUnAssign": "Сбросить назначение", "NoTaskForObject": "Задачи не определены", "Delete": "Удалить", - "NoTodoItems": "Нет to do", "TodoName": "Название", "TodoState": "Статус", "DoneState": "Статус Завершен", @@ -70,7 +69,6 @@ "CantStatusDeleteError": "Есть объекты с данным статусом. Сначала переместите или удалите их. ", "Tasks": "Задачи", "AssignedToMe": "Назначено на меня", - "TodoItems": "Todos", "Dashboard": "Дашборд", "AllTime": "Все время", "RelatedIssues": "Связанные процессы", diff --git a/plugins/task-resources/src/components/todos/CreateTodo.svelte b/plugins/task-resources/src/components/todos/CreateTodo.svelte deleted file mode 100644 index 82d0c1ab8b..0000000000 --- a/plugins/task-resources/src/components/todos/CreateTodo.svelte +++ /dev/null @@ -1,88 +0,0 @@ - - - - 0} - on:close={() => { - dispatch('close') - }} - okLabel={plugin.string.TodoSave} - on:changeContent -> - - - - - diff --git a/plugins/task-resources/src/components/todos/EditTodo.svelte b/plugins/task-resources/src/components/todos/EditTodo.svelte deleted file mode 100644 index d3dd93a46b..0000000000 --- a/plugins/task-resources/src/components/todos/EditTodo.svelte +++ /dev/null @@ -1,85 +0,0 @@ - - - - 0} - on:close={() => { - dispatch('close') - }} - okLabel={plugin.string.TodoSave} - on:changeContent -> - - - - - diff --git a/plugins/task-resources/src/components/todos/TodoItemPresenter.svelte b/plugins/task-resources/src/components/todos/TodoItemPresenter.svelte deleted file mode 100644 index e309455dd9..0000000000 --- a/plugins/task-resources/src/components/todos/TodoItemPresenter.svelte +++ /dev/null @@ -1,46 +0,0 @@ - - - -{#if value} - - -
{ - show(ev.target) - }} - > -
- -
- {value.name} -
-{/if} diff --git a/plugins/task-resources/src/components/todos/TodoItemsPopup.svelte b/plugins/task-resources/src/components/todos/TodoItemsPopup.svelte deleted file mode 100644 index a920a11061..0000000000 --- a/plugins/task-resources/src/components/todos/TodoItemsPopup.svelte +++ /dev/null @@ -1,40 +0,0 @@ - - - -
- {#if todos.length > 0} - - {/if} - diff --git a/plugins/task-resources/src/components/todos/TodoStatePresenter.svelte b/plugins/task-resources/src/components/todos/TodoStatePresenter.svelte deleted file mode 100644 index cf7a43e90e..0000000000 --- a/plugins/task-resources/src/components/todos/TodoStatePresenter.svelte +++ /dev/null @@ -1,44 +0,0 @@ - - - -{#if value !== undefined} -
-
-{/if} - - diff --git a/plugins/task-resources/src/components/todos/Todos.svelte b/plugins/task-resources/src/components/todos/Todos.svelte deleted file mode 100644 index 2a182e75b5..0000000000 --- a/plugins/task-resources/src/components/todos/Todos.svelte +++ /dev/null @@ -1,93 +0,0 @@ - - - -
(wSection = element.clientWidth)}> -
- - -
- {#if todos.length > 0} - {#if wSection < 640} - -
- - {:else} -
- {/if} - {:else} -
- - - - -
- {/if} - diff --git a/plugins/task-resources/src/index.ts b/plugins/task-resources/src/index.ts index 0b87032718..320cf606f7 100644 --- a/plugins/task-resources/src/index.ts +++ b/plugins/task-resources/src/index.ts @@ -63,10 +63,6 @@ import TaskTypeClassPresenter from './components/taskTypes/TaskTypeClassPresente import ProjectTypeClassPresenter from './components/taskTypes/ProjectTypeClassPresenter.svelte' import TaskTypePresenter from './components/taskTypes/TaskTypePresenter.svelte' import ProjectTypePresenter from './components/projectTypes/ProjectTypePresenter.svelte' -import TodoItemPresenter from './components/todos/TodoItemPresenter.svelte' -import TodoItemsPopup from './components/todos/TodoItemsPopup.svelte' -import TodoStatePresenter from './components/todos/TodoStatePresenter.svelte' -import Todos from './components/todos/Todos.svelte' import StateIconPresenter from './components/state/StateIconPresenter.svelte' import TaskKindSelector from './components/taskTypes/TaskKindSelector.svelte' @@ -124,16 +120,12 @@ export default async (): Promise => ({ KanbanView, StatePresenter, StateEditor, - Todos, - TodoItemPresenter, - TodoStatePresenter, StatusTableView, TaskHeader, ProjectEditor, ProjectTypeSelector, AssignedTasks, StateRefPresenter, - TodoItemsPopup, DueDateEditor, CreateStatePopup, StatusSelector, diff --git a/plugins/task-resources/src/plugin.ts b/plugins/task-resources/src/plugin.ts index e46a41c3f8..1eeb1a2ff4 100644 --- a/plugins/task-resources/src/plugin.ts +++ b/plugins/task-resources/src/plugin.ts @@ -44,7 +44,6 @@ export default mergeIds(taskId, task, { UploadDropFilesHere: '' as IntlString, NoTaskForObject: '' as IntlString, Delete: '' as IntlString, - NoTodoItems: '' as IntlString, TodoState: '' as IntlString, DoneState: '' as IntlString, UndoneState: '' as IntlString, diff --git a/plugins/task/src/index.ts b/plugins/task/src/index.ts index c55f3e61d6..dc4c911bb9 100644 --- a/plugins/task/src/index.ts +++ b/plugins/task/src/index.ts @@ -19,7 +19,6 @@ import { Attribute, Class, Doc, - Markup, Mixin, Ref, Space, @@ -27,11 +26,11 @@ import { StatusCategory, Timestamp } from '@hcengineering/core' +import { NotificationType } from '@hcengineering/notification' import type { Asset, IntlString, Plugin, Resource } from '@hcengineering/platform' import { plugin } from '@hcengineering/platform' import type { AnyComponent, ComponentExtensionId } from '@hcengineering/ui' import { Action, IconProps, ViewletDescriptor } from '@hcengineering/view' -import { NotificationType } from '@hcengineering/notification' /** * @public @@ -56,21 +55,9 @@ export interface Task extends AttachedDoc, DocWithRank { dueDate: Timestamp | null comments?: number attachments?: number - todoItems?: number labels?: number } -/** - * @public - */ -export interface TodoItem extends AttachedDoc, DocWithRank { - name: Markup - assignee: Ref | null - done: boolean - dueTo: Timestamp | null - items?: number -} - /** * @public */ @@ -252,7 +239,6 @@ const task = plugin(taskId, { MarkAsUndone: '' as IntlString, Kanban: '' as IntlString, ApplicationLabelTask: '' as IntlString, - TodoItems: '' as IntlString, AssignedToMe: '' as IntlString, Dashboard: '' as IntlString, ProjectTypes: '' as IntlString, @@ -261,7 +247,6 @@ const task = plugin(taskId, { }, class: { Sequence: '' as Ref>, - TodoItem: '' as Ref>, ProjectTypeDescriptor: '' as Ref>, ProjectType: '' as Ref>, Project: '' as Ref>, @@ -302,7 +287,6 @@ const task = plugin(taskId, { component: { ProjectEditor: '' as AnyComponent, ProjectTypeSelector: '' as AnyComponent, - TodoItemsPopup: '' as AnyComponent, CreateStatePopup: '' as AnyComponent }, ids: { diff --git a/server/backup/src/index.ts b/server/backup/src/index.ts index b8acada019..8e5f32741d 100644 --- a/server/backup/src/index.ts +++ b/server/backup/src/index.ts @@ -627,10 +627,12 @@ export async function restore ( Object.keys(s.domains).forEach((it) => domains.add(it as Domain)) } + console.log('connecting:', transactorUrl, workspaceId.name) const connection = (await connect(transactorUrl, workspaceId, undefined, { mode: 'backup', model: 'upgrade' })) as unknown as CoreClient & BackupClient + console.log('connected') // We need to find empty domains and clean them. const allDomains = connection.getHierarchy().domains() diff --git a/server/core/src/indexer/indexer.ts b/server/core/src/indexer/indexer.ts index 4531020964..643da06deb 100644 --- a/server/core/src/indexer/indexer.ts +++ b/server/core/src/indexer/indexer.ts @@ -399,10 +399,7 @@ export class FullTextIndexPipeline implements FullTextPipeline { removed: false }, { - limit: globalIndexer.processingSize, - sort: { - _id: 1 - } + limit: globalIndexer.processingSize } ) ) diff --git a/server/middleware/src/spaceSecurity.ts b/server/middleware/src/spaceSecurity.ts index 7eb0a17580..d56692d144 100644 --- a/server/middleware/src/spaceSecurity.ts +++ b/server/middleware/src/spaceSecurity.ts @@ -20,27 +20,27 @@ import core, { DocumentQuery, FindOptions, FindResult, - generateId, LookupData, MeasureContext, ObjQueryType, Position, PullArray, Ref, + SearchOptions, + SearchQuery, + SearchResult, ServerStorage, Space, - systemAccountEmail, Tx, - TxCreateDoc, TxCUD, + TxCreateDoc, TxProcessor, TxRemoveDoc, TxUpdateDoc, TxWorkspaceEvent, WorkspaceEvent, - SearchResult, - SearchQuery, - SearchOptions + generateId, + systemAccountEmail } from '@hcengineering/core' import platform, { PlatformError, Severity, Status } from '@hcengineering/platform' import { BroadcastFunc, Middleware, SessionContext, TxMiddlewareResult } from '@hcengineering/server-core' @@ -117,16 +117,26 @@ export class SpaceSecurityMiddleware extends BaseMiddleware implements Middlewar for (const domain in classesPerDomain) { for (const _class of classesPerDomain[domain]) { const field = this.getKey(_class) - const spaces = await this.storage.findAll( - ctx, - _class, - {}, - { - projection: { [field]: 1 } + const map = this.domainSpaces[domain] ?? new Set() + this.domainSpaces[domain] = map + + while (true) { + const spaces = await this.storage.findAll( + ctx, + _class, + { + [field]: { $nin: Array.from(map.values()) } + }, + { + projection: { [field]: 1 }, + limit: 1000 + } + ) + if (spaces.length === 0) { + break } - ) - this.domainSpaces[domain] = this.domainSpaces[domain] ?? new Set() - spaces.forEach((p) => this.domainSpaces[domain].add((p as any)[field] as Ref)) + spaces.forEach((p) => map.add((p as any)[field] as Ref)) + } } } } diff --git a/server/mongo/src/storage.ts b/server/mongo/src/storage.ts index 5b0ea52e44..38ba574ae7 100644 --- a/server/mongo/src/storage.ts +++ b/server/mongo/src/storage.ts @@ -594,7 +594,24 @@ abstract class MongoAdapterBase implements DbAdapter { find (domain: Domain): StorageIterator { const coll = this.db.collection(domain) - const iterator = coll.find({}, { sort: { _id: -1 } }) + const iterator = coll.find({}, {}) + + const bulkUpdate = new Map, string>() + const flush = async (flush = false): Promise => { + if (bulkUpdate.size > 1000 || flush) { + if (bulkUpdate.size > 0) { + await coll.bulkWrite( + Array.from(bulkUpdate.entries()).map((it) => ({ + updateOne: { + filter: { _id: it[0] }, + update: { $set: { '%hash%': it[1] } } + } + })) + ) + } + bulkUpdate.clear() + } + } return { next: async () => { @@ -611,7 +628,10 @@ abstract class MongoAdapterBase implements DbAdapter { const hash = createHash('sha256') hash.update(doc) digest = hash.digest('base64') - await coll.updateOne({ _id: d._id }, { $set: { '%hash%': digest } }) + + bulkUpdate.set(d._id, digest) + // await coll.updateOne({ _id: d._id }, { $set: { '%hash%': digest } }) + await flush() } return { id: d._id, @@ -620,6 +640,7 @@ abstract class MongoAdapterBase implements DbAdapter { } }, close: async () => { + await flush(true) await iterator.close() } } diff --git a/server/tool/src/index.ts b/server/tool/src/index.ts index 82e4d807b7..deef43a26e 100644 --- a/server/tool/src/index.ts +++ b/server/tool/src/index.ts @@ -24,6 +24,7 @@ import core, { FieldIndex, Hierarchy, IndexKind, + IndexOrder, ModelDb, Tx, WorkspaceId @@ -250,8 +251,12 @@ async function createUpdateIndexes (connection: CoreClient, db: Db, logger: Mode const attrs = hierarchy.getAllAttributes(c._id) const domainAttrs = domains.get(domain) ?? new Set>() for (const a of attrs.values()) { - if (a.index !== undefined && a.index === IndexKind.Indexed) { - domainAttrs.add(a.name) + if (a.index !== undefined && (a.index === IndexKind.Indexed || a.index === IndexKind.IndexedDsc)) { + if (a.index === IndexKind.Indexed) { + domainAttrs.add(a.name) + } else { + domainAttrs.add({ [a.name]: IndexOrder.Descending }) + } } } diff --git a/server/ws/src/server.ts b/server/ws/src/server.ts index e63347fe25..ec436dafa4 100644 --- a/server/ws/src/server.ts +++ b/server/ws/src/server.ts @@ -154,8 +154,6 @@ class TSessionManager implements SessionManager { return this.sessionFactory(token, pipeline, this.broadcast.bind(this)) } - upgradeIdMap = new Map() - async addSession ( ctx: MeasureContext, ws: ConnectionSocket, @@ -176,18 +174,14 @@ class TSessionManager implements SessionManager { } let pipeline: Pipeline - const upgradeId = this.upgradeIdMap.get(token.workspace.name) if (token.extra?.model === 'upgrade') { - if (upgradeId !== undefined && sessionId !== upgradeId) { - ws.close() - throw new Error('Another Upgrade in progress....') + if (workspace.upgrade) { + pipeline = await ctx.with('pipeline', {}, async () => await (workspace as Workspace).pipeline) + } else { + pipeline = await this.createUpgradeSession(token, sessionId, ctx, wsString, workspace, pipelineFactory, ws) } - if (sessionId !== undefined) { - this.upgradeIdMap.set(token.workspace.name, sessionId) - } - pipeline = await this.createUpgradeSession(token, sessionId, ctx, wsString, workspace, pipelineFactory, ws) } else { - if (workspace.upgrade && sessionId !== upgradeId) { + if (workspace.upgrade) { ws.close() throw new Error('Upgrade in progress....') } @@ -331,10 +325,6 @@ class TSessionManager implements SessionManager { } const sessionRef = this.sessions.get(ws.id) if (sessionRef !== undefined) { - const upgradeId = this.upgradeIdMap.get(workspaceId.name) - if (upgradeId === sessionRef.session.sessionId) { - this.upgradeIdMap.delete(workspaceId.name) - } this.sessions.delete(ws.id) workspace.sessions.delete(sessionRef.session.sessionId) this.reconnectIds.add(sessionRef.session.sessionId) @@ -441,14 +431,12 @@ class TSessionManager implements SessionManager { if (this.workspaces.get(wsid)?.id === wsUID) { this.workspaces.delete(wsid) - this.upgradeIdMap.delete(workspaceId.name) } if (LOGGING_ENABLED) { console.timeLog(workspaceId.name, 'Closed workspace', wsUID) } } catch (err: any) { this.workspaces.delete(wsid) - this.upgradeIdMap.delete(workspaceId.name) if (LOGGING_ENABLED) { console.error(workspaceId.name, err) }