EZQMS-1392: Obsolete documents (#7833)

Signed-off-by: Victor Ilyushchenko <alt13ri@gmail.com>
This commit is contained in:
Victor Ilyushchenko
2025-01-29 17:18:46 +03:00
committed by GitHub
parent 7ae937461f
commit 984c7d90ab
20 changed files with 143 additions and 23 deletions
@@ -57,9 +57,10 @@
$: inProgress = { state: { $in: [DocumentState.Draft] }, space: { $in: spaces } }
$: effective = { state: { $in: [DocumentState.Effective] }, space: { $in: spaces } }
$: archived = { state: { $in: [DocumentState.Archived, DocumentState.Deleted] }, space: { $in: spaces } }
$: obsolete = { state: { $in: [DocumentState.Obsolete] }, space: { $in: spaces } }
$: all = { space: { $in: spaces } }
$: queries = { inProgress, effective, archived, all }
$: queries = { inProgress, effective, archived, obsolete, all }
$: mode = $resolvedLocationStore.query?.mode ?? undefined
$: if (mode === undefined || (queries as any)[mode] === undefined) {
@@ -118,6 +118,7 @@
DocumentState.Archived,
DocumentState.Deleted,
DocumentState.Effective,
DocumentState.Obsolete,
ControlledDocumentState.InApproval,
ControlledDocumentState.Approved,
ControlledDocumentState.ToReview
@@ -37,11 +37,11 @@
}
&.obsolete {
background: var(--theme-state-ghost-background-color);
border-color: var(--theme-state-ghost-border-color);
background: var(--theme-state-negative-background-color);
border-color: var(--theme-state-negative-border-color);
.label {
color: var(--theme-state-ghost-color);
color: var(--theme-state-negative-color);
}
}
@@ -148,9 +148,10 @@
{@const title = doc ? getDocumentName(doc) : meta?.title ?? ''}
{@const docid = doc?._id ?? prjdoc._id}
{@const isFolder = prjdoc.document === documents.ids.Folder}
{@const isObsolete = doc ? doc.state === DocumentState.Obsolete : false}
{@const children = metaid ? childrenByParent[metaid] ?? [] : []}
{#if metaid}
{@const children = childrenByParent[metaid] ?? []}
{#if metaid && (!isObsolete || children.length > 0)}
{@const isDraggedOver = draggedOver === metaid}
<div class="flex-col relative">
{#if isDraggedOver}
@@ -160,12 +161,12 @@
_id={docid}
icon={isFolder ? documents.icon.Folder : documents.icon.Document}
iconProps={{
fill: 'currentColor'
fill: isObsolete ? 'var(--dangerous-bg-color)' : 'currentColor'
}}
{title}
selected={selected === docid || selected === prjdoc._id}
isFold
empty={children.length === 0 || children === undefined}
empty={children.length === 0}
actions={getMoreActions !== undefined ? () => getDocMoreActions(prjdoc) : undefined}
{level}
{collapsedPrefix}
@@ -38,6 +38,9 @@
case DocumentState.Archived:
statusWMLabel = plugin.string.Archived
break
case DocumentState.Obsolete:
statusWMLabel = plugin.string.Obsolete
break
}
}
@@ -51,7 +54,7 @@
$controlledDocument != null &&
(isOrgSpace
? $controlledDocument.state !== DocumentState.Effective
: ![DocumentState.Effective, DocumentState.Archived].includes($controlledDocument.state))
: ![DocumentState.Effective, DocumentState.Obsolete, DocumentState.Archived].includes($controlledDocument.state))
</script>
{#if $controlledDocument !== null}
@@ -182,6 +182,24 @@ async function archiveDocuments (obj: Document | Document[]): Promise<void> {
})
}
async function makeDocumentObsolete (obj: Document | Document[]): Promise<void> {
const docs = Array.isArray(obj) ? obj : [obj]
const docNames = docs.map((d) => `${d.title} (${d.prefix}-${d.seqNumber})`).join(', ')
showPopup(MessageBox, {
label: documents.string.MakeDocumentObsoleteDialog,
labelProps: { count: docs.length },
message: documents.string.MakeDocumentObsoleteConfirm,
params: { titles: docNames },
action: async () => {
const client = getClient()
for (const doc of docs) {
await client.update(doc, { state: DocumentState.Obsolete })
}
}
})
}
async function canDeleteDocument (obj?: Doc | Doc[]): Promise<boolean> {
if (obj == null) {
return false
@@ -220,6 +238,28 @@ async function canArchiveDocument (obj?: Doc | Doc[]): Promise<boolean> {
).then((res) => res.every((r) => r))
}
async function canMakeDocumentObsolete (obj?: Doc | Doc[]): Promise<boolean> {
if (obj == null) {
return false
}
const objs = (Array.isArray(obj) ? obj : [obj]) as Document[]
const currentUser = getCurrentAccount() as PersonAccount
const isOwner = objs.every((doc) => doc.owner === currentUser.person)
if (isOwner) {
return true
}
const spaces = new Set(objs.map((doc) => doc.space))
return await Promise.all(
Array.from(spaces).map(
async (space) => await checkPermission(getClient(), documents.permission.ArchiveDocument, space)
)
).then((res) => res.every((r) => r))
}
async function canOpenDocument (obj?: ProjectDocument | ProjectDocument[]): Promise<boolean> {
if (obj == null) {
return false
@@ -411,6 +451,7 @@ export default async (): Promise<Resources> => ({
GetDocumentMetaLinkFragment: getDocumentMetaLinkFragment,
CanDeleteDocument: canDeleteDocument,
CanArchiveDocument: canArchiveDocument,
CanMakeDocumentObsolete: canMakeDocumentObsolete,
CanTransferDocument: canTransferDocument,
CanOpenDocument: canOpenDocument,
CanPrintDocument: canPrintDocument,
@@ -430,6 +471,7 @@ export default async (): Promise<Resources> => ({
CreateFolder: createFolder,
DeleteDocument: deleteDocuments,
ArchiveDocument: archiveDocuments,
MakeDocumentObsolete: makeDocumentObsolete,
TransferDocument: transferDocuments,
EditDocSpace: editDocSpace
},
@@ -242,6 +242,7 @@ export default mergeIds(documentsId, documents, {
GetDocumentMetaLinkFragment: '' 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>>,
CanOpenDocument: '' as Resource<(doc?: Doc | Doc[]) => Promise<boolean>>,
CanPrintDocument: '' as Resource<(doc?: Doc | Doc[]) => Promise<boolean>>,
CanTransferDocument: '' as Resource<(doc?: Doc | Doc[]) => Promise<boolean>>,
@@ -21,9 +21,10 @@ export const $canCreateNewDraft = combine($controlledDocument, $documentAllVersi
if (document == null) return false
const currentIndex = versions.findIndex((p) => p._id === document._id)
const forbiddenStates = [DocumentState.Draft, DocumentState.Obsolete]
return (
versions.slice(0, currentIndex).every((p) => p.state === DocumentState.Deleted) &&
document.state !== DocumentState.Draft
!forbiddenStates.includes(document.state)
)
})
@@ -82,7 +82,8 @@ export async function getTranslatedDocumentStates (lang: string): Promise<Transl
[DocumentState.Draft]: await translate(documents.string.Draft, {}, lang),
[DocumentState.Deleted]: await translate(documents.string.Deleted, {}, lang),
[DocumentState.Effective]: await translate(documents.string.Effective, {}, lang),
[DocumentState.Archived]: await translate(documents.string.Archived, {}, lang)
[DocumentState.Archived]: await translate(documents.string.Archived, {}, lang),
[DocumentState.Obsolete]: await translate(documents.string.Obsolete, {}, lang)
}
}
@@ -159,6 +160,8 @@ export async function getDocumentMetaLinkFragment (document: Doc): Promise<Locat
break
} else if (doc.state === DocumentState.Deleted && targetDocument === undefined) {
targetDocument = doc
} else if (doc.state === DocumentState.Obsolete && targetDocument === undefined) {
targetDocument = doc
} else if (doc.state === DocumentState.Draft) {
targetDocument = doc
} else if (doc.state === DocumentState.Archived) {
@@ -363,13 +366,15 @@ export const statesTags: StatesTags = {
[DocumentState.Draft]: 'draft',
[DocumentState.Effective]: 'effective',
[DocumentState.Archived]: 'obsolete',
[DocumentState.Deleted]: 'obsolete'
[DocumentState.Deleted]: 'obsolete',
[DocumentState.Obsolete]: 'obsolete'
}
export const documentStatesOrder = [
DocumentState.Draft,
DocumentState.Effective,
DocumentState.Archived,
DocumentState.Obsolete,
DocumentState.Deleted
]