From 101449b39c50cc32ee29fa29d05a18186ba362ab Mon Sep 17 00:00:00 2001 From: Andrey Sobolev Date: Thu, 26 Dec 2024 18:31:38 +0700 Subject: [PATCH] UBERF-9032: Fix proper query initializers Signed-off-by: Andrey Sobolev --- packages/presentation/src/utils.ts | 17 +++ plugins/activity-resources/src/activity.ts | 32 ++--- plugins/calendar-resources/src/utils.ts | 34 ++--- .../src/components/chat/utils.ts | 15 +- plugins/contact-resources/src/utils.ts | 52 +++---- plugins/love-resources/src/stores.ts | 132 ++++++++---------- plugins/task-resources/src/index.ts | 56 +++----- plugins/tracker-resources/src/utils.ts | 53 +++---- plugins/view-resources/src/status.ts | 32 ++--- 9 files changed, 182 insertions(+), 241 deletions(-) diff --git a/packages/presentation/src/utils.ts b/packages/presentation/src/utils.ts index 8abd129f4c9..787882bb067 100644 --- a/packages/presentation/src/utils.ts +++ b/packages/presentation/src/utils.ts @@ -21,6 +21,7 @@ import core, { TxProcessor, getCurrentAccount, reduceCalls, + type Account, type AnyAttribute, type ArrOf, type AttachedDoc, @@ -253,6 +254,18 @@ export function getClient (): TxOperations & Client { return clientProxy } +export type OnClientListener = (client: Client, account: Account) => void +const onClientListeners: OnClientListener[] = [] + +export function onClient (l: OnClientListener): void { + onClientListeners.push(l) + if (client !== undefined) { + setTimeout(() => { + l(client, getCurrentAccount()) + }) + } +} + let txQueue: Tx[] = [] export type RefreshListener = () => void @@ -306,6 +319,10 @@ export async function setClient (_client: Client): Promise { if (needRefresh || globalQueries.length > 0) { await refreshClient(true) } + const acc = getCurrentAccount() + onClientListeners.forEach((l) => { + l(_client, acc) + }) } /** * @public diff --git a/plugins/activity-resources/src/activity.ts b/plugins/activity-resources/src/activity.ts index 89125e90b70..47cab72ebe3 100644 --- a/plugins/activity-resources/src/activity.ts +++ b/plugins/activity-resources/src/activity.ts @@ -14,31 +14,21 @@ // import activity, { type ActivityMessage, type SavedMessage } from '@hcengineering/activity' import core, { type Ref, SortingOrder, type WithLookup } from '@hcengineering/core' +import { createQuery, onClient } from '@hcengineering/presentation' import { writable } from 'svelte/store' -import { createQuery, getClient } from '@hcengineering/presentation' export const savedMessagesStore = writable>>([]) export const messageInFocus = writable | undefined>(undefined) const savedMessagesQuery = createQuery(true) -export function loadSavedMessages (): void { - const client = getClient() - - if (client !== undefined) { - savedMessagesQuery.query( - activity.class.SavedMessage, - { space: core.space.Workspace }, - (res) => { - savedMessagesStore.set(res.filter(({ $lookup }) => $lookup?.attachedTo !== undefined)) - }, - { lookup: { attachedTo: activity.class.ActivityMessage }, sort: { modifiedOn: SortingOrder.Descending } } - ) - } else { - setTimeout(() => { - loadSavedMessages() - }, 50) - } -} - -loadSavedMessages() +onClient(() => { + savedMessagesQuery.query( + activity.class.SavedMessage, + { space: core.space.Workspace }, + (res) => { + savedMessagesStore.set(res.filter(({ $lookup }) => $lookup?.attachedTo !== undefined)) + }, + { lookup: { attachedTo: activity.class.ActivityMessage }, sort: { modifiedOn: SortingOrder.Descending } } + ) +}) diff --git a/plugins/calendar-resources/src/utils.ts b/plugins/calendar-resources/src/utils.ts index a4dfa48fe4a..236c7e0a5aa 100644 --- a/plugins/calendar-resources/src/utils.ts +++ b/plugins/calendar-resources/src/utils.ts @@ -5,12 +5,12 @@ import { type ReccuringInstance, generateEventId } from '@hcengineering/calendar' -import { type IdMap, type Timestamp, getCurrentAccount, toIdMap, type DocumentUpdate } from '@hcengineering/core' -import { createQuery, getClient } from '@hcengineering/presentation' -import { showPopup, closePopup, DAY } from '@hcengineering/ui' +import { type DocumentUpdate, type IdMap, type Timestamp, getCurrentAccount, toIdMap } from '@hcengineering/core' +import { createQuery, getClient, onClient } from '@hcengineering/presentation' +import { closePopup, DAY, showPopup } from '@hcengineering/ui' import { writable } from 'svelte/store' -import calendar from './plugin' import UpdateRecInstancePopup from './components/UpdateRecInstancePopup.svelte' +import calendar from './plugin' export function saveUTC (date: Timestamp): Timestamp { const utcdate = new Date(date) @@ -74,24 +74,14 @@ export const calendarByIdStore = writable>(new Map()) export const calendarStore = writable([]) export const visibleCalendarStore = writable([]) -function fillStores (): void { - const client = getClient() - - if (client !== undefined) { - const query = createQuery(true) - query.query(calendar.class.Calendar, {}, (res) => { - calendarStore.set(res) - visibleCalendarStore.set(res.filter((p) => !p.hidden)) - calendarByIdStore.set(toIdMap(res)) - }) - } else { - setTimeout(() => { - fillStores() - }, 50) - } -} - -fillStores() +const query = createQuery(true) +onClient((client, account) => { + query.query(calendar.class.Calendar, {}, (res) => { + calendarStore.set(res) + visibleCalendarStore.set(res.filter((p) => !p.hidden)) + calendarByIdStore.set(toIdMap(res)) + }) +}) export async function updatePast (ops: DocumentUpdate, object: ReccuringInstance): Promise { const client = getClient() diff --git a/plugins/chunter-resources/src/components/chat/utils.ts b/plugins/chunter-resources/src/components/chat/utils.ts index 203b576a066..f843631f72f 100644 --- a/plugins/chunter-resources/src/components/chat/utils.ts +++ b/plugins/chunter-resources/src/components/chat/utils.ts @@ -28,7 +28,7 @@ import core, { } from '@hcengineering/core' import notification, { type DocNotifyContext } from '@hcengineering/notification' import { InboxNotificationsClientImpl } from '@hcengineering/notification-resources' -import { createQuery, getClient, MessageBox } from '@hcengineering/presentation' +import { createQuery, getClient, MessageBox, onClient } from '@hcengineering/presentation' import { type Action, showPopup } from '@hcengineering/ui' import view from '@hcengineering/view' import workbench, { type SpecialNavModel } from '@hcengineering/workbench' @@ -364,12 +364,9 @@ function archiveActivityChannels (contexts: DocNotifyContext[]): void { ) } +const savedAttachmentsQuery = createQuery(true) export function loadSavedAttachments (): void { - const client = getClient() - - if (client !== undefined) { - const savedAttachmentsQuery = createQuery(true) - + onClient(() => { savedAttachmentsQuery.query( attachment.class.SavedAttachments, { space: core.space.Workspace }, @@ -378,11 +375,7 @@ export function loadSavedAttachments (): void { }, { lookup: { attachedTo: attachment.class.Attachment }, sort: { modifiedOn: SortingOrder.Descending } } ) - } else { - setTimeout(() => { - loadSavedAttachments() - }, 50) - } + }) } export async function hideActivityChannels (contexts: DocNotifyContext[]): Promise { diff --git a/plugins/contact-resources/src/utils.ts b/plugins/contact-resources/src/utils.ts index 93700daccce..e7e7a03a747 100644 --- a/plugins/contact-resources/src/utils.ts +++ b/plugins/contact-resources/src/utils.ts @@ -52,7 +52,7 @@ import core, { } from '@hcengineering/core' import notification, { type DocNotifyContext, type InboxNotification } from '@hcengineering/notification' import { type IntlString, getEmbeddedLabel, getResource, translate } from '@hcengineering/platform' -import { createQuery, getClient } from '@hcengineering/presentation' +import { createQuery, getClient, onClient } from '@hcengineering/presentation' import { type TemplateDataProvider } from '@hcengineering/templates' import { getCurrentResolvedLocation, @@ -323,42 +323,32 @@ export const personByIdStore = derived([personAccountPersonByIdStore, employeeBy return new Map([...m1, ...m2]) }) -function fillStores (): void { - const client = getClient() - - if (client !== undefined) { - const accountPersonQuery = createQuery(true) - - const query = createQuery(true) - query.query(contact.mixin.Employee, { active: { $in: [true, false] } }, (res) => { - employeesStore.set(res) - employeeByIdStore.set(toIdMap(res)) - }) +const query = createQuery(true) +const accountQ = createQuery(true) +const accountPersonQuery = createQuery(true) +const providerQuery = createQuery(true) - const accountQ = createQuery(true) - accountQ.query(contact.class.PersonAccount, {}, (res) => { - personAccountByIdStore.set(toIdMap(res)) +onClient(() => { + query.query(contact.mixin.Employee, { active: { $in: [true, false] } }, (res) => { + employeesStore.set(res) + employeeByIdStore.set(toIdMap(res)) + }) - const persons = res.map((it) => it.person) + accountQ.query(contact.class.PersonAccount, {}, (res) => { + personAccountByIdStore.set(toIdMap(res)) - accountPersonQuery.query(contact.class.Person, { _id: { $in: persons } }, (res) => { - const personIn = toIdMap(res) - personAccountPersonByIdStore.set(personIn) - }) - }) + const persons = res.map((it) => it.person) - const providerQuery = createQuery(true) - providerQuery.query(contact.class.ChannelProvider, {}, (res) => { - channelProviders.set(res) + accountPersonQuery.query(contact.class.Person, { _id: { $in: persons } }, (res) => { + const personIn = toIdMap(res) + personAccountPersonByIdStore.set(personIn) }) - } else { - setTimeout(() => { - fillStores() - }, 50) - } -} + }) -fillStores() + providerQuery.query(contact.class.ChannelProvider, {}, (res) => { + channelProviders.set(res) + }) +}) const userStatusesQuery = createQuery(true) diff --git a/plugins/love-resources/src/stores.ts b/plugins/love-resources/src/stores.ts index 1e77d61a97a..af5cf8054f0 100644 --- a/plugins/love-resources/src/stores.ts +++ b/plugins/love-resources/src/stores.ts @@ -11,7 +11,7 @@ import { type Room, type MeetingMinutes } from '@hcengineering/love' -import { createQuery, getClient } from '@hcengineering/presentation' +import { createQuery, onClient } from '@hcengineering/presentation' import { derived, get, writable } from 'svelte/store' import { personIdByAccountId } from '@hcengineering/contact-resources' import aiBot from '@hcengineering/ai-bot' @@ -79,77 +79,69 @@ function filterParticipantInfo (value: ParticipantInfo[]): ParticipantInfo[] { export const storePromise = writable>(new Promise((resolve) => {})) -function fillStores (): void { - const client = getClient() - if (client !== undefined || getCurrentAccount() != null) { - const query = createQuery(true) - const roomPromise = new Promise((resolve) => - query.query(love.class.Room, {}, (res) => { - rooms.set(res) - resolve() - }) - ) - const statusQuery = createQuery(true) - const infoPromise = new Promise((resolve) => - statusQuery.query(love.class.ParticipantInfo, {}, (res) => { - infos.set(filterParticipantInfo(res)) - resolve() - }) - ) - const floorsQuery = createQuery(true) - const floorPromise = new Promise((resolve) => - floorsQuery.query(love.class.Floor, {}, (res) => { - floors.set(res) +const query = createQuery(true) +const statusQuery = createQuery(true) +const floorsQuery = createQuery(true) +const requestsQuery = createQuery(true) +const preferencesQuery = createQuery(true) +const invitesQuery = createQuery(true) + +onClient(() => { + const roomPromise = new Promise((resolve) => + query.query(love.class.Room, {}, (res) => { + rooms.set(res) + resolve() + }) + ) + const infoPromise = new Promise((resolve) => + statusQuery.query(love.class.ParticipantInfo, {}, (res) => { + infos.set(filterParticipantInfo(res)) + resolve() + }) + ) + const floorPromise = new Promise((resolve) => + floorsQuery.query(love.class.Floor, {}, (res) => { + floors.set(res) + resolve() + }) + ) + const requestPromise = new Promise((resolve) => + requestsQuery.query( + love.class.JoinRequest, + { person: (getCurrentAccount() as PersonAccount).person, status: RequestStatus.Pending }, + (res) => { + myRequests.set(res) resolve() - }) - ) - const requestsQuery = createQuery(true) - const requestPromise = new Promise((resolve) => - requestsQuery.query( - love.class.JoinRequest, - { person: (getCurrentAccount() as PersonAccount).person, status: RequestStatus.Pending }, - (res) => { - myRequests.set(res) - resolve() - } - ) + } ) - const preferencesQuery = createQuery(true) - const preferencePromise = new Promise((resolve) => - preferencesQuery.query(love.class.DevicesPreference, {}, (res) => { - myPreferences.set(res[0]) - $myPreferences = res[0] - resolve() - }) - ) - const invitesQuery = createQuery(true) - const invitesPromise = new Promise((resolve) => - invitesQuery.query(love.class.Invite, { status: RequestStatus.Pending }, (res) => { - invites.set(res) + ) + const preferencePromise = new Promise((resolve) => + preferencesQuery.query(love.class.DevicesPreference, {}, (res) => { + myPreferences.set(res[0]) + $myPreferences = res[0] + resolve() + }) + ) + + const invitesPromise = new Promise((resolve) => + invitesQuery.query(love.class.Invite, { status: RequestStatus.Pending }, (res) => { + invites.set(res) + resolve() + }) + ) + storePromise.set( + new Promise((resolve) => { + void Promise.all([ + roomPromise, + infoPromise, + floorPromise, + requestPromise, + preferencePromise, + invitesPromise + ]).then(() => { resolve() }) - ) - storePromise.set( - new Promise((resolve) => { - void Promise.all([ - roomPromise, - infoPromise, - floorPromise, - requestPromise, - preferencePromise, - invitesPromise - ]).then(() => { - resolve() - }) - }) - ) - } else { - setTimeout(() => { - fillStores() - }, 50) - } -} - -fillStores() - + }) + ) +}) export const lockedRoom = writable('') diff --git a/plugins/task-resources/src/index.ts b/plugins/task-resources/src/index.ts index 537d2c9b46f..bf7456c4d6e 100644 --- a/plugins/task-resources/src/index.ts +++ b/plugins/task-resources/src/index.ts @@ -14,8 +14,10 @@ // limitations under the License. // +import activity from '@hcengineering/activity' +import chunter from '@hcengineering/chunter' +import { type Employee, type PersonAccount } from '@hcengineering/contact' import core, { - getCurrentAccount, toIdMap, type Attribute, type Class, @@ -27,7 +29,7 @@ import core, { type TxOperations } from '@hcengineering/core' import { type IntlString, type Resources } from '@hcengineering/platform' -import { createQuery, getClient } from '@hcengineering/presentation' +import { createQuery, getClient, onClient } from '@hcengineering/presentation' import task, { getStatusIndex, makeRank, @@ -41,9 +43,6 @@ import { getCurrentLocation, navigate, showPopup } from '@hcengineering/ui' import { type ViewletDescriptor } from '@hcengineering/view' import { CategoryQuery, groupBy, statusStore } from '@hcengineering/view-resources' import { get, writable } from 'svelte/store' -import { type Employee, type PersonAccount } from '@hcengineering/contact' -import activity from '@hcengineering/activity' -import chunter from '@hcengineering/chunter' import AssignedTasks from './components/AssignedTasks.svelte' import Dashboard from './components/Dashboard.svelte' @@ -69,14 +68,14 @@ import TaskKindSelector from './components/taskTypes/TaskKindSelector.svelte' import TaskTypeClassPresenter from './components/taskTypes/TaskTypeClassPresenter.svelte' import TaskTypePresenter from './components/taskTypes/TaskTypePresenter.svelte' -import ProjectTypeSelector from './components/projectTypes/ProjectTypeSelector.svelte' +import { employeeByIdStore, personAccountByIdStore, personByIdStore } from '@hcengineering/contact-resources' import CreateProjectType from './components/projectTypes/CreateProjectType.svelte' -import ProjectTypeGeneralSectionEditor from './components/projectTypes/ProjectTypeGeneralSectionEditor.svelte' -import ProjectTypeTasksTypeSectionEditor from './components/projectTypes/ProjectTypeTasksTypeSectionEditor.svelte' import ProjectTypeAutomationsSectionEditor from './components/projectTypes/ProjectTypeAutomationsSectionEditor.svelte' import ProjectTypeCollectionsSectionEditor from './components/projectTypes/ProjectTypeCollectionsSectionEditor.svelte' +import ProjectTypeGeneralSectionEditor from './components/projectTypes/ProjectTypeGeneralSectionEditor.svelte' +import ProjectTypeSelector from './components/projectTypes/ProjectTypeSelector.svelte' +import ProjectTypeTasksTypeSectionEditor from './components/projectTypes/ProjectTypeTasksTypeSectionEditor.svelte' import TaskTypeEditor from './components/taskTypes/TaskTypeEditor.svelte' -import { employeeByIdStore, personAccountByIdStore, personByIdStore } from '@hcengineering/contact-resources' export { default as AssigneePresenter } from './components/AssigneePresenter.svelte' export { default as TypeSelector } from './components/TypeSelector.svelte' @@ -364,33 +363,24 @@ export const taskTypeStore = writable>(new Map()) export const typesOfJoinedProjectsStore = writable>>() export const joinedProjectsStore = writable() -function fillStores (): void { - const client = getClient() - - if (client !== undefined && getCurrentAccount() != null) { - const query = createQuery(true) - query.query(task.class.ProjectType, {}, (res) => { - typeStore.set(toIdMap(res)) - }) +const query = createQuery(true) +const taskQuery = createQuery(true) +const projectQuery = createQuery(true) - const taskQuery = createQuery(true) - taskQuery.query(task.class.TaskType, {}, (res) => { - taskTypeStore.set(toIdMap(res)) - }) +onClient((client, user) => { + query.query(task.class.ProjectType, {}, (res) => { + typeStore.set(toIdMap(res)) + }) - const projectQuery = createQuery(true) - projectQuery.query(task.class.Project, { members: getCurrentAccount()._id }, (res) => { - typesOfJoinedProjectsStore.set(res.map((r) => r.type).filter((it, idx, arr) => arr.indexOf(it) === idx)) - joinedProjectsStore.set(res) - }) - } else { - setTimeout(() => { - fillStores() - }, 50) - } -} + taskQuery.query(task.class.TaskType, {}, (res) => { + taskTypeStore.set(toIdMap(res)) + }) -fillStores() + projectQuery.query(task.class.Project, { members: user._id }, (res) => { + typesOfJoinedProjectsStore.set(res.map((r) => r.type).filter((it, idx, arr) => arr.indexOf(it) === idx)) + joinedProjectsStore.set(res) + }) +}) export const selectedTypeStore = writable | undefined>(undefined) export const selectedTaskTypeStore = writable | undefined>(undefined) diff --git a/plugins/tracker-resources/src/utils.ts b/plugins/tracker-resources/src/utils.ts index 1d3e380332c..69bdc5ca37e 100644 --- a/plugins/tracker-resources/src/utils.ts +++ b/plugins/tracker-resources/src/utils.ts @@ -36,7 +36,7 @@ import core, { type TxUpdateDoc } from '@hcengineering/core' import { type IntlString } from '@hcengineering/platform' -import { createQuery, getClient } from '@hcengineering/presentation' +import { createQuery, getClient, onClient } from '@hcengineering/presentation' import task, { getStatusIndex, makeRank, type ProjectType } from '@hcengineering/task' import { activeProjects as taskActiveProjects, taskTypeStore } from '@hcengineering/task-resources' import { @@ -577,36 +577,25 @@ export interface IssueRef { export type IssueReverseRevMap = Map, IssueRef[]> export const relatedIssues = writable(new Map()) -function fillStores (): void { - const client = getClient() - - if (client !== undefined) { - const relatedIssuesQuery = createQuery(true) - - relatedIssuesQuery.query( - tracker.class.Issue, - { 'relations._id': { $exists: true } }, - (res) => { - const nMap: IssueReverseRevMap = new Map() - for (const r of res) { - for (const rr of r.relations ?? []) { - nMap.set(rr._id, [...(nMap.get(rr._id) ?? []), { _id: r._id, status: r.status }]) - } - } - relatedIssues.set(nMap) - }, - { - projection: { - relations: 1, - status: 1 +const relatedIssuesQuery = createQuery(true) +onClient(() => { + relatedIssuesQuery.query( + tracker.class.Issue, + { 'relations._id': { $exists: true } }, + (res) => { + const nMap: IssueReverseRevMap = new Map() + for (const r of res) { + for (const rr of r.relations ?? []) { + nMap.set(rr._id, [...(nMap.get(rr._id) ?? []), { _id: r._id, status: r.status }]) } } - ) - } else { - setTimeout(() => { - fillStores() - }, 50) - } -} - -fillStores() + relatedIssues.set(nMap) + }, + { + projection: { + relations: 1, + status: 1 + } + } + ) +}) diff --git a/plugins/view-resources/src/status.ts b/plugins/view-resources/src/status.ts index a3ed74dac58..127f09787a0 100644 --- a/plugins/view-resources/src/status.ts +++ b/plugins/view-resources/src/status.ts @@ -14,7 +14,7 @@ // import core, { type IdMap, type Status, toIdMap } from '@hcengineering/core' -import { createQuery, getClient } from '@hcengineering/presentation' +import { createQuery, onClient } from '@hcengineering/presentation' import { writable } from 'svelte/store' interface Store { @@ -28,23 +28,13 @@ export const statusStore = writable({ array: [] }) -function fillStores (): void { - const client = getClient() - - if (client !== undefined) { - const query = createQuery(true) - query.query(core.class.Status, {}, (res) => { - const obj = { - byId: toIdMap(res), - array: res - } - statusStore.set(obj) - }) - } else { - setTimeout(() => { - fillStores() - }, 50) - } -} - -fillStores() +const query = createQuery(true) +onClient(() => { + query.query(core.class.Status, {}, (res) => { + const obj = { + byId: toIdMap(res), + array: res + } + statusStore.set(obj) + }) +})