EQMS-1451/1453/1455: reference tweaks for QMS documents (#8083)

* EQMS-1451/1453/1455: reference tweaks for QMS documents

Signed-off-by: Victor Ilyushchenko <alt13ri@gmail.com>

* fmt

Signed-off-by: Victor Ilyushchenko <alt13ri@gmail.com>

---------

Signed-off-by: Victor Ilyushchenko <alt13ri@gmail.com>
This commit is contained in:
Victor Ilyushchenko
2025-02-24 17:13:35 +03:00
committed by GitHub
parent f98152986c
commit c6e752c7aa
22 changed files with 195 additions and 40 deletions
@@ -49,10 +49,12 @@
$documentComments as documentComments,
documentCommentsDisplayRequested,
documentCommentsHighlightUpdated,
documentCommentsLocationNavigateRequested
documentCommentsLocationNavigateRequested,
$documentReleasedVersions as documentReleasedVersions
} from '../../stores/editors/document'
import DocumentTitle from './DocumentTitle.svelte'
import DocumentPrintTitlePage from '../print/DocumentPrintTitlePage.svelte'
import { syncDocumentMetaTitle } from '../../utils'
const client = getClient()
const hierarchy = client.getHierarchy()
@@ -111,14 +113,17 @@
unsubscribeNavigateToLocation()
})
const handleUpdateTitle = () => {
const handleUpdateTitle = async () => {
if (!$controlledDocument || !title) {
return
}
const titleTrimmed = title.trim()
if (titleTrimmed.length > 0 && titleTrimmed !== $controlledDocument.title) {
client.update($controlledDocument, { title: titleTrimmed })
await client.update($controlledDocument, { title: titleTrimmed })
if ($documentReleasedVersions.length === 0 && $controlledDocument.state === DocumentState.Draft) {
await syncDocumentMetaTitle(client, $controlledDocument.attachedTo, $controlledDocument.code, titleTrimmed)
}
}
}
@@ -15,14 +15,15 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte'
import documents, { Document } from '@hcengineering/controlled-documents'
import documents, { ControlledDocument } from '@hcengineering/controlled-documents'
import presentation, { createQuery, getClient } from '@hcengineering/presentation'
import { Button, EditBox, Label } from '@hcengineering/ui'
import IconWarning from '../../icons/IconWarning.svelte'
import documentsRes from '../../../plugin'
import { syncDocumentMetaTitle } from '../../../utils'
export let object: Document
export let object: ControlledDocument
const client = getClient()
const dispatch = createEventDispatcher()
@@ -59,6 +60,7 @@
}
await client.update(object, { code })
await syncDocumentMetaTitle(client, object.attachedTo, code, object.title)
dispatch('close')
}
</script>
@@ -106,7 +106,10 @@ import {
createTemplate,
deleteFolder,
documentIdentifierProvider,
controlledDocumentReferenceObjectProvider,
projectDocumentReferenceObjectProvider,
getAllDocumentStates,
getControlledDocumentLinkFragment,
getControlledDocumentTitle,
getDocumentMetaLinkFragment,
getDocumentMetaTitle,
@@ -450,6 +453,7 @@ export default async (): Promise<Resources> => ({
DocumentStateSort: sortDocumentStates,
GetAllDocumentStates: getAllDocumentStates,
GetDocumentMetaLinkFragment: getDocumentMetaLinkFragment,
GetControlledDocumentLinkFragment: getControlledDocumentLinkFragment,
CanDeleteDocument: canDeleteDocument,
CanArchiveDocument: canArchiveDocument,
CanMakeDocumentObsolete: canMakeDocumentObsolete,
@@ -457,6 +461,8 @@ export default async (): Promise<Resources> => ({
CanOpenDocument: canOpenDocument,
CanPrintDocument: canPrintDocument,
DocumentIdentifierProvider: documentIdentifierProvider,
ControlledDocumentReferenceObjectProvider: controlledDocumentReferenceObjectProvider,
ProjectDocumentReferenceObjectProvider: projectDocumentReferenceObjectProvider,
ControlledDocumentTitleProvider: getControlledDocumentTitle,
DocumentMetaTitleProvider: getDocumentMetaTitle,
Comment: comment,
@@ -212,7 +212,9 @@ export default mergeIds(documentsId, documents, {
CreateDocumentFailed: '' as IntlString,
CreateDocumentTemplateFailed: '' as IntlString,
TryAgain: '' as IntlString
TryAgain: '' as IntlString,
LatestVersionHint: '' as IntlString
},
controlledDocStates: {
Empty: '' as IntlString,
@@ -240,6 +242,7 @@ export default mergeIds(documentsId, documents, {
GetAllDocumentStates: '' as Resource<() => Promise<DocumentState[]>>,
GetVisibleFilters: '' as Resource<(filters: KeyFilter[], space?: Ref<Space>) => Promise<KeyFilter[]>>,
GetDocumentMetaLinkFragment: '' as Resource<(doc: Doc, props: Record<string, any>) => Promise<Location>>,
GetControlledDocumentLinkFragment: '' as Resource<(doc: Doc, props: Record<string, any>) => Promise<Location>>,
CanDeleteDocument: '' as Resource<(doc?: Doc | Doc[]) => Promise<boolean>>,
CanArchiveDocument: '' as Resource<(doc?: Doc | Doc[]) => Promise<boolean>>,
CanMakeDocumentObsolete: '' as Resource<(doc?: Doc | Doc[]) => Promise<boolean>>,
@@ -16,6 +16,7 @@ import { type Employee, type Person, type PersonAccount } from '@hcengineering/c
import documents, {
type ControlledDocument,
type Document,
type DocumentBundle,
type DocumentCategory,
type DocumentComment,
type DocumentMeta,
@@ -27,12 +28,12 @@ import documents, {
type ProjectDocument,
type ProjectMeta,
ControlledDocumentState,
type DocumentBundle,
DocumentState,
ProjectDocumentTree,
compareDocumentVersions,
emptyBundle,
getDocumentName,
getFirstRank,
ProjectDocumentTree
getFirstRank
} from '@hcengineering/controlled-documents'
import core, {
type Class,
@@ -195,6 +196,18 @@ export async function getDocumentMetaLinkFragment (document: Doc): Promise<Locat
return getProjectDocumentLink(targetDocument, project)
}
export async function getControlledDocumentLinkFragment (document: ControlledDocument): Promise<Location> {
const client = getClient()
const targetDocument = await client.findOne(documents.class.ProjectDocument, { document: document._id })
if (targetDocument === undefined) {
throw new Error('Cannot resolve a ProjectDocument for document ' + document._id)
}
const project = targetDocument.project ?? documents.ids.NoProject
return getProjectDocumentLink(document, project)
}
export interface TeamPopupData {
controlledDoc: ControlledDocument
requestClass: Ref<Class<DocumentRequest>>
@@ -707,6 +720,41 @@ export async function documentIdentifierProvider (client: Client, ref: Ref<Docum
return document.code
}
export async function controlledDocumentReferenceObjectProvider (
client: Client,
ref: Ref<ControlledDocument>,
doc?: ControlledDocument
): Promise<Doc | undefined> {
const document = doc ?? (await client.findOne(documents.class.ControlledDocument, { _id: ref }))
if (document === undefined) return
const meta = await client.findOne(documents.class.DocumentMeta, { _id: document.attachedTo })
if (meta === undefined) return
let documentSeq: ControlledDocument[] = await client.findAll(documents.class.ControlledDocument, {
attachedTo: meta._id
})
const allowStates = [DocumentState.Draft, DocumentState.Effective]
documentSeq = documentSeq.filter((d) => allowStates.includes(d.state)).sort(compareDocumentVersions)
const effIndex = documentSeq.findIndex((d) => d.state === DocumentState.Effective)
const docIndex = documentSeq.findIndex((d) => d._id === document._id)
return docIndex >= 0 && (docIndex <= effIndex || effIndex < 0) ? meta : document
}
export async function projectDocumentReferenceObjectProvider (
client: Client,
ref: Ref<ProjectDocument>,
doc?: ProjectDocument
): Promise<Doc | undefined> {
const prjdoc = doc ?? (await client.findOne(documents.class.ProjectDocument, { _id: ref }))
if (prjdoc === undefined) return
return await controlledDocumentReferenceObjectProvider(client, prjdoc.document as Ref<ControlledDocument>)
}
export function documentCompareFn (doc1: Document, doc2: Document): number {
return doc1.major - doc2.major !== 0 ? doc1.major - doc2.major : doc1.minor - doc2.minor
}
@@ -724,7 +772,7 @@ export async function getControlledDocumentTitle (
if (object === undefined) return ''
return object.title
return object.title + ` (${getDocumentVersionString(object)})`
}
export async function getDocumentMetaTitle (
@@ -736,7 +784,9 @@ export async function getDocumentMetaTitle (
if (object === undefined) return ''
return object.title
const hint = await translate(documentsResources.string.LatestVersionHint, {})
return object.title + ` (${hint})`
}
export const getCurrentEmployee = (): Ref<Employee> | undefined => {
@@ -932,3 +982,15 @@ export class DocumentHiearchyQuery {
export function createDocumentHierarchyQuery (): DocumentHiearchyQuery {
return new DocumentHiearchyQuery()
}
export async function syncDocumentMetaTitle (
client: Client & TxOperations,
_id: Ref<DocumentMeta>,
code: string,
title: string
): Promise<void> {
const meta = await client.findOne(documents.class.DocumentMeta, { _id })
if (meta !== undefined) {
await client.update(meta, { title: `${code} ${title}` })
}
}