mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-26 11:34:58 +02:00
Fixes for document hierarchy presentation in QMS (#7938)
* Fixes for document hierarchy presentation in QMS Signed-off-by: Victor Ilyushchenko <alt13ri@gmail.com> * fixed test Signed-off-by: Victor Ilyushchenko <alt13ri@gmail.com> * styling fix Signed-off-by: Victor Ilyushchenko <alt13ri@gmail.com> * cooler names Signed-off-by: Victor Ilyushchenko <alt13ri@gmail.com> --------- Signed-off-by: Victor Ilyushchenko <alt13ri@gmail.com>
This commit is contained in:
+36
-147
@@ -14,184 +14,70 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { type Ref, SortingOrder, getCurrentAccount } from '@hcengineering/core'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import { type PersonAccount } from '@hcengineering/contact'
|
||||
import documents, {
|
||||
type ControlledDocument,
|
||||
type DocumentMeta,
|
||||
import {
|
||||
DocumentBundle,
|
||||
ProjectDocumentTree,
|
||||
type HierarchyDocument,
|
||||
type Project,
|
||||
type ProjectMeta
|
||||
type Project
|
||||
} from '@hcengineering/controlled-documents'
|
||||
import { type Ref } from '@hcengineering/core'
|
||||
|
||||
import { compareDocs, notEmpty } from '../../../../utils'
|
||||
import { createDocumentHierarchyQuery } from '../../../../utils'
|
||||
import DocumentFlatTreeElement from './DocumentFlatTreeElement.svelte'
|
||||
|
||||
export let document: HierarchyDocument | undefined
|
||||
export let project: Ref<Project>
|
||||
|
||||
const currentUser = getCurrentAccount() as PersonAccount
|
||||
const currentPerson = currentUser.person
|
||||
let tree = new ProjectDocumentTree()
|
||||
|
||||
let meta: ProjectMeta | undefined
|
||||
const projectMetaQuery = createQuery()
|
||||
const query = createDocumentHierarchyQuery()
|
||||
$: if (document !== undefined && project !== undefined) {
|
||||
projectMetaQuery.query(
|
||||
documents.class.ProjectMeta,
|
||||
{
|
||||
project,
|
||||
meta: document.attachedTo
|
||||
},
|
||||
(result) => {
|
||||
;[meta] = result
|
||||
}
|
||||
)
|
||||
query.query(document.space, project, (data) => {
|
||||
tree = data
|
||||
})
|
||||
}
|
||||
|
||||
let parentMetas: ProjectMeta[] | undefined
|
||||
const parentMetasQuery = createQuery()
|
||||
$: if (meta !== undefined) {
|
||||
parentMetasQuery.query(
|
||||
documents.class.ProjectMeta,
|
||||
{
|
||||
meta: { $in: meta.path },
|
||||
project: meta.project
|
||||
},
|
||||
(result) => {
|
||||
parentMetas = result
|
||||
}
|
||||
)
|
||||
} else {
|
||||
parentMetasQuery.unsubscribe()
|
||||
}
|
||||
$: docmetaid = tree.metaOf(document?._id)
|
||||
|
||||
let directChildrenMetas: ProjectMeta[] | undefined
|
||||
const childrenMetasQuery = createQuery()
|
||||
$: if (meta !== undefined) {
|
||||
childrenMetasQuery.query(
|
||||
documents.class.ProjectMeta,
|
||||
{
|
||||
parent: meta?.meta,
|
||||
project: meta.project
|
||||
},
|
||||
(result) => {
|
||||
if (meta === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
directChildrenMetas = result
|
||||
}
|
||||
)
|
||||
} else {
|
||||
childrenMetasQuery.unsubscribe()
|
||||
}
|
||||
|
||||
let docs: Record<Ref<DocumentMeta>, ControlledDocument> = {}
|
||||
const docsQuery = createQuery()
|
||||
$: if (parentMetas !== undefined && directChildrenMetas !== undefined) {
|
||||
docsQuery.query(
|
||||
documents.class.ProjectDocument,
|
||||
{
|
||||
attachedTo: { $in: [...parentMetas.map((p) => p._id), ...directChildrenMetas.map((p) => p._id)] }
|
||||
},
|
||||
(result) => {
|
||||
docs = {}
|
||||
let lastTemplate: string | undefined = '###'
|
||||
let lastSeqNumber = -1
|
||||
|
||||
for (const prjdoc of result) {
|
||||
const doc = prjdoc.$lookup?.document as ControlledDocument | undefined
|
||||
if (doc === undefined) continue
|
||||
|
||||
// TODO add proper fix, when document with no template copied, saved value is null
|
||||
const template = doc.template ?? undefined
|
||||
|
||||
if (template === lastTemplate && doc.seqNumber === lastSeqNumber) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (
|
||||
doc.owner === currentPerson ||
|
||||
doc.coAuthors.findIndex((emp) => emp === currentPerson) >= 0 ||
|
||||
doc.approvers.findIndex((emp) => emp === currentPerson) >= 0 ||
|
||||
doc.reviewers.findIndex((emp) => emp === currentPerson) >= 0
|
||||
) {
|
||||
docs[doc.attachedTo] = doc
|
||||
|
||||
lastTemplate = template
|
||||
lastSeqNumber = doc.seqNumber
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
lookup: {
|
||||
document: documents.class.ControlledDocument
|
||||
},
|
||||
sort: {
|
||||
'$lookup.document.template': SortingOrder.Ascending,
|
||||
'$lookup.document.seqNumber': SortingOrder.Ascending,
|
||||
'$lookup.document.major': SortingOrder.Descending,
|
||||
'$lookup.document.minor': SortingOrder.Descending,
|
||||
'$lookup.document.patch': SortingOrder.Descending
|
||||
}
|
||||
}
|
||||
)
|
||||
} else {
|
||||
docsQuery.unsubscribe()
|
||||
}
|
||||
|
||||
let directChildrenDocs: ControlledDocument[] = []
|
||||
$: if (directChildrenMetas !== undefined) {
|
||||
directChildrenDocs = Object.values(docs).filter(
|
||||
(d) => directChildrenMetas !== undefined && directChildrenMetas.findIndex((m) => m.meta === d.attachedTo) >= 0
|
||||
)
|
||||
directChildrenDocs.sort(compareDocs)
|
||||
}
|
||||
|
||||
let parentDocs: ControlledDocument[] = []
|
||||
$: if (meta !== undefined) {
|
||||
parentDocs = [...meta.path]
|
||||
.reverse()
|
||||
.map((mId) => docs[mId])
|
||||
.filter(notEmpty)
|
||||
}
|
||||
|
||||
let levels: Array<[HierarchyDocument[], boolean]> = []
|
||||
let levels: Array<[DocumentBundle[], boolean]> = []
|
||||
$: {
|
||||
levels = []
|
||||
const parents = tree
|
||||
.parentChainOf(docmetaid)
|
||||
.reverse()
|
||||
.map((ref) => tree.bundleOf(ref))
|
||||
.filter((r) => r !== undefined)
|
||||
const me = tree.bundleOf(docmetaid)
|
||||
const children = tree
|
||||
.childrenOf(docmetaid)
|
||||
.map((ref) => tree.bundleOf(ref))
|
||||
.filter((r) => r !== undefined)
|
||||
|
||||
if (parentDocs?.length > 0) {
|
||||
levels.push([parentDocs, false])
|
||||
}
|
||||
|
||||
if (document !== undefined) {
|
||||
levels.push([[document], true])
|
||||
}
|
||||
|
||||
if (directChildrenDocs?.length > 0) {
|
||||
levels.push([directChildrenDocs, false])
|
||||
if (parents.length > 0) levels.push([parents as DocumentBundle[], false])
|
||||
if (me) {
|
||||
levels.push([[me], true])
|
||||
}
|
||||
if (children.length > 0) levels.push([children as DocumentBundle[], false])
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if levels.length > 0}
|
||||
{@const [firstDocs, firstHltd] = levels[0]}
|
||||
<div class="root">
|
||||
{#each firstDocs as doc}
|
||||
<DocumentFlatTreeElement {doc} {project} highlighted={firstHltd} />
|
||||
{#each firstDocs as bundle}
|
||||
<DocumentFlatTreeElement {bundle} {project} highlighted={firstHltd} />
|
||||
{/each}
|
||||
{#if levels.length > 1}
|
||||
{@const [secondDocs, secondHltd] = levels[1]}
|
||||
<div class="container">
|
||||
{#each secondDocs as doc}
|
||||
<DocumentFlatTreeElement {doc} {project} highlighted={secondHltd} />
|
||||
{#each secondDocs as bundle}
|
||||
<DocumentFlatTreeElement {bundle} {project} highlighted={secondHltd} />
|
||||
{/each}
|
||||
{#if levels.length > 2}
|
||||
{@const [thirdDocs, thirdHltd] = levels[2]}
|
||||
<div class="container">
|
||||
{#each thirdDocs as doc}
|
||||
<DocumentFlatTreeElement {doc} {project} highlighted={thirdHltd} />
|
||||
{#each thirdDocs as bundle}
|
||||
<DocumentFlatTreeElement {bundle} {project} highlighted={thirdHltd} />
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
@@ -215,5 +101,8 @@
|
||||
padding: 0 1rem;
|
||||
border-left: 2px solid var(--theme-navpanel-border);
|
||||
gap: 0.25rem;
|
||||
|
||||
padding-left: 0.25rem;
|
||||
margin-left: 0.75rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
+14
-5
@@ -14,17 +14,25 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import documents, { getDocumentName, type Document, type Project } from '@hcengineering/controlled-documents'
|
||||
import documents, {
|
||||
DocumentBundle,
|
||||
getDocumentName,
|
||||
isFolder,
|
||||
type Project
|
||||
} from '@hcengineering/controlled-documents'
|
||||
import { type Ref } from '@hcengineering/core'
|
||||
import { Icon, navigate } from '@hcengineering/ui'
|
||||
|
||||
import { getProjectDocumentLink } from '../../../../navigation'
|
||||
|
||||
export let doc: Document
|
||||
export let bundle: DocumentBundle
|
||||
export let project: Ref<Project>
|
||||
export let highlighted: boolean = false
|
||||
|
||||
const icon = documents.icon.Document
|
||||
$: meta = bundle?.DocumentMeta[0]
|
||||
$: prjdoc = bundle?.ProjectDocument[0]
|
||||
$: document = bundle?.ControlledDocument[0]
|
||||
$: icon = isFolder(prjdoc) ? documents.icon.Folder : documents.icon.Document
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
@@ -32,7 +40,8 @@
|
||||
<div
|
||||
class="antiNav-element root"
|
||||
on:click={() => {
|
||||
const loc = getProjectDocumentLink(doc, project)
|
||||
if (!document) return
|
||||
const loc = getProjectDocumentLink(document, project)
|
||||
navigate(loc)
|
||||
}}
|
||||
>
|
||||
@@ -48,7 +57,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
<span class="an-element__label" class:font-medium={highlighted}>
|
||||
{getDocumentName(doc)}
|
||||
{document ? getDocumentName(document) : meta.title}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user