diff --git a/foundations/core/packages/query/src/index.ts b/foundations/core/packages/query/src/index.ts index 464d3870fe..1c9b373b32 100644 --- a/foundations/core/packages/query/src/index.ts +++ b/foundations/core/packages/query/src/index.ts @@ -1122,43 +1122,74 @@ export class LiveQuery implements WithTx, Client { if (q.result instanceof Promise) { q.result = await q.result } - const direct = assoc[1] === 1 - const res = findRelationDoc(q.result.getDocs(), q.options.associations, relation) - if (res === undefined) return - const association = this.getModel().findObject(assoc[0]) - if (association === undefined) return - const nestedAssoc = assoc[2] - const options: FindOptions | undefined = - nestedAssoc !== undefined - ? { - associations: nestedAssoc - } - : undefined - const docToPush = await this.findOne( - direct ? association.classB : association.classA, - { - _id: res.targetId - }, - options - ) - if (docToPush === undefined) return - if (res.doc.$associations === undefined) { - res.doc.$associations = {} + const res = await this.fillRelationDoc(q.result, q.result.getDocs(), q.options.associations, relation) + if (res) { + this.queriesToUpdate.set(q.id, q) } - const key = direct ? 'b' : 'a' - const arr = res.doc.$associations?.[`${assoc[0]}_${key}`] ?? [] - const exists = arr.findIndex((p) => p._id === docToPush._id) - if (exists !== -1) { - arr[exists] = docToPush - } else { - arr.push(docToPush) - } - res.doc.$associations[`${assoc[0]}_${key}`] = arr - q.result.updateDoc(res.doc, false) - this.queriesToUpdate.set(q.id, q) } } + async fillRelationDoc ( + qRes: ResultArray, + docs: WithLookup[], + associations: AssociationQuery[] | undefined, + relation: Relation + ): Promise { + if (associations === undefined) return false + let result = false + for (const assoc of associations) { + if (assoc[0] === relation.association) { + const association = this.getModel().findObject(assoc[0]) + if (association === undefined) continue + const sourceId = assoc[1] === 1 ? relation.docA : relation.docB + const targetId = assoc[1] === 1 ? relation.docB : relation.docA + const direct = assoc[1] === 1 + for (const doc of docs) { + if (doc._id === sourceId) { + const docToPush = await this.findOne(direct ? association.classB : association.classA, { + _id: targetId + }) + if (docToPush === undefined) continue + if (doc.$associations === undefined) { + doc.$associations = {} + } + const key = direct ? 'b' : 'a' + const arr = doc.$associations?.[`${assoc[0]}_${key}`] ?? [] + const exists = arr.findIndex((p) => p._id === docToPush._id) + if (exists !== -1) { + arr[exists] = docToPush + } else { + arr.push(docToPush) + } + doc.$associations[`${assoc[0]}_${key}`] = arr + if (qRes.findDoc(doc._id) !== undefined) { + qRes.updateDoc(doc, false) + } + result = true + } + } + } + } + for (const assoc of associations) { + if (assoc[2] !== undefined) { + const key = assoc[1] === 1 ? 'b' : 'a' + for (const doc of docs) { + const arr = doc.$associations?.[`${assoc[0]}_${key}`] ?? [] + if (arr.length > 0) { + const res = await this.fillRelationDoc(qRes, arr, assoc[2], relation) + if (res) { + result = true + if (qRes.findDoc(doc._id) !== undefined) { + qRes.updateDoc(doc, false) + } + } + } + } + } + } + return result + } + private async handleDocAddLookup (q: Query, doc: Doc): Promise { if (q.options?.lookup === undefined) return const lookup = q.options.lookup @@ -1645,47 +1676,3 @@ function findAssociation ( } } } - -function findRelationDoc ( - result: WithLookup[], - associations: AssociationQuery[] | undefined, - relation: Relation -): - | { - doc: WithLookup - targetId: Ref - } - | undefined { - if (associations === undefined) return - for (const assoc of associations) { - if (assoc[0] === relation.association) { - const sourceId = assoc[1] === 1 ? relation.docA : relation.docB - const targetId = assoc[1] === 1 ? relation.docB : relation.docA - for (const doc of result) { - if (doc._id === sourceId) { - return { - doc, - targetId - } - } - } - } - } - for (const assoc of associations) { - if (assoc[2] !== undefined) { - const key = assoc[1] === 1 ? 'b' : 'a' - for (const doc of result) { - const arr = doc.$associations?.[`${assoc[0]}_${key}`] ?? [] - if (arr.length > 0) { - const res = findRelationDoc(arr, assoc[2], relation) - if (res !== undefined) { - return { - doc, - targetId: res.doc._id - } - } - } - } - } - } -} diff --git a/foundations/server/packages/postgres/src/storage.ts b/foundations/server/packages/postgres/src/storage.ts index 02a8938af4..d649da7753 100644 --- a/foundations/server/packages/postgres/src/storage.ts +++ b/foundations/server/packages/postgres/src/storage.ts @@ -296,7 +296,7 @@ abstract class PostgresAdapterBase implements DbAdapter { async rawFindAll(_domain: Domain, query: DocumentQuery, options?: FindOptions): Promise { const domain = translateDomain(_domain) const vars = new ValuesVariables() - const select = `SELECT ${this.getProjection(vars, domain, options?.projection, [], options?.associations)} FROM ${domain}` + const select = `SELECT ${this.getProjection(vars, domain, options?.projection, [])} FROM ${domain}` const sqlChunks: string[] = [] sqlChunks.push(`WHERE ${this.buildRawQuery(vars, domain, query, options)}`) if (options?.sort !== undefined) { @@ -472,7 +472,7 @@ abstract class PostgresAdapterBase implements DbAdapter { const projection = this.localizeProjection(_class, options?.projection ?? undefined) - const select = `SELECT ${this.getProjection(vars, domain, projection, joins, options?.associations)} FROM ${domain}` + const select = `SELECT ${this.getProjection(vars, domain, projection, joins)} FROM ${domain}` if (joins.length > 0) { sqlChunks.push(this.buildJoinString(vars, joins)) @@ -745,7 +745,7 @@ abstract class PostgresAdapterBase implements DbAdapter { const nextParentMap = new Map>() for (const row of rows) { const parentId = row.parent_id - const parsed = parseDoc(row, getSchema(row._class)) + const parsed = nextParentMap.get(row._id) ?? parseDoc(row, getSchema(row._class)) const parent = parentMap.get(parentId) if (parent === undefined) continue @@ -756,7 +756,9 @@ abstract class PostgresAdapterBase implements DbAdapter { if (parent.$associations[key] === undefined) parent.$associations[key] = [] parent.$associations[key].push(parsed) - nextParentMap.set(parsed._id, parsed) + if (!nextParentMap.has(parsed._id)) { + nextParentMap.set(parsed._id, parsed) + } } if (nested !== undefined && nested.length > 0 && nextParentMap.size > 0) { @@ -1459,10 +1461,9 @@ abstract class PostgresAdapterBase implements DbAdapter { vars: ValuesVariables, baseDomain: string, projection: Projection | undefined, - joins: JoinProps[], - associations: AssociationQuery[] | undefined + joins: JoinProps[] ): string | '*' { - if (projection === undefined && joins.length === 0 && associations === undefined) return `${baseDomain}.*` + if (projection === undefined && joins.length === 0) return `${baseDomain}.*` const res: string[] = [] let dataAdded = false if (projection === undefined) { diff --git a/plugins/process-resources/src/components/ProcessesCardSection.svelte b/plugins/process-resources/src/components/ProcessesCardSection.svelte index 88bdc6e234..d5ec1b6be2 100644 --- a/plugins/process-resources/src/components/ProcessesCardSection.svelte +++ b/plugins/process-resources/src/components/ProcessesCardSection.svelte @@ -18,12 +18,13 @@ import ProcessesExtension from './ProcessesExtension.svelte' export let doc: Card + export let readonly: boolean = false export let hidden: boolean = false {#if !hidden}
- +
{/if} diff --git a/plugins/process-resources/src/components/ProcessesExtension.svelte b/plugins/process-resources/src/components/ProcessesExtension.svelte index 03a5820133..e8f6d0323b 100644 --- a/plugins/process-resources/src/components/ProcessesExtension.svelte +++ b/plugins/process-resources/src/components/ProcessesExtension.svelte @@ -42,6 +42,7 @@ import { PermissionsStore } from '@hcengineering/contact' export let card: Card + export let readonly: boolean = false const viewletId = process.viewlet.CardExecutions const dispatch = createEventDispatcher() @@ -57,6 +58,9 @@ } function add (e: MouseEvent): void { + if (readonly) { + return + } showPopup(RunProcessPopup, { value: card }, eventToHTMLElement(e)) } @@ -120,7 +124,7 @@
- {#if !checkForbiddenPermission($permissionsStore)} + {#if !readonly && !checkForbiddenPermission($permissionsStore)}
diff --git a/plugins/view-assets/lang/en.json b/plugins/view-assets/lang/en.json index 6d4922cc59..8c79b179dd 100644 --- a/plugins/view-assets/lang/en.json +++ b/plugins/view-assets/lang/en.json @@ -154,6 +154,6 @@ "RoleLabel": "Role: {role}", "ForbidAttributeChanges": "Forbid changes: ", "AllowAttributeChanges": "Allow changes: ", - "RelationshipTable": "Relationship table" + "RelationshipTable": "Traceability Matrix" } } diff --git a/plugins/view-assets/lang/fr.json b/plugins/view-assets/lang/fr.json index a9c8f6afa1..8f6b4bed3a 100644 --- a/plugins/view-assets/lang/fr.json +++ b/plugins/view-assets/lang/fr.json @@ -149,6 +149,6 @@ "RoleLabel": "Rôle : {role}", "ForbidAttributeChanges": "Interdire les modifications: ", "AllowAttributeChanges": "Autoriser les modifications: ", - "RelationshipTable": "Table des relations" + "RelationshipTable": "Matrice de traçabilité" } }