mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-12 20:57:45 +02:00
EZQMS-1393: implemented folders in controlled documents (#7803)
* EZQMS-1393: implemented folders in controlled documents Signed-off-by: Victor Ilyushchenko <alt13ri@gmail.com> * formatting Signed-off-by: Victor Ilyushchenko <alt13ri@gmail.com> --------- Signed-off-by: Victor Ilyushchenko <alt13ri@gmail.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
<!--
|
||||
//
|
||||
// Copyright © 2025 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
-->
|
||||
<script lang="ts">
|
||||
import documents, {
|
||||
createNewFolder,
|
||||
DocumentMeta,
|
||||
type DocumentSpace,
|
||||
type Project,
|
||||
type ProjectDocument
|
||||
} from '@hcengineering/controlled-documents'
|
||||
import core, { Ref } from '@hcengineering/core'
|
||||
import { Card, getClient } from '@hcengineering/presentation'
|
||||
import { EditBox, FocusHandler, createFocusManager } from '@hcengineering/ui'
|
||||
import view from '@hcengineering/view'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
export function canClose (): boolean {
|
||||
return name === ''
|
||||
}
|
||||
|
||||
export let folder: DocumentMeta | undefined
|
||||
export let name: string = ''
|
||||
|
||||
export let space: Ref<DocumentSpace> | undefined
|
||||
export let project: Ref<Project<DocumentSpace>> | undefined
|
||||
export let parent: Ref<ProjectDocument> | undefined
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const client = getClient()
|
||||
|
||||
$: canSave = getTitle(name).length > 0 && (folder !== undefined || space !== undefined)
|
||||
|
||||
function getTitle (value: string): string {
|
||||
return value.trim()
|
||||
}
|
||||
|
||||
async function create (): Promise<void> {
|
||||
const title = getTitle(name)
|
||||
if (title.length < 1) {
|
||||
return
|
||||
}
|
||||
|
||||
if (folder !== undefined) {
|
||||
await client.update(folder, { title })
|
||||
} else if (space !== undefined) {
|
||||
await createNewFolder(client, space, project ?? documents.ids.NoProject, parent, title)
|
||||
}
|
||||
dispatch('close')
|
||||
}
|
||||
|
||||
const manager = createFocusManager()
|
||||
</script>
|
||||
|
||||
<FocusHandler {manager} />
|
||||
|
||||
<Card
|
||||
label={folder ? documents.string.RenameFolder : documents.string.CreateFolder}
|
||||
okAction={create}
|
||||
accentHeader
|
||||
{canSave}
|
||||
on:close={() => {
|
||||
dispatch('close')
|
||||
}}
|
||||
on:changeContent
|
||||
>
|
||||
<div class="flex-row-center clear-mins">
|
||||
<EditBox placeholder={core.string.Name} bind:value={name} autoFocus focusIndex={1} />
|
||||
</div>
|
||||
</Card>
|
||||
+33
-12
@@ -14,7 +14,7 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { type Ref, type Doc, SortingOrder, getCurrentAccount, WithLookup } from '@hcengineering/core'
|
||||
import { type Ref, type Doc, SortingOrder, getCurrentAccount, WithLookup, toIdMap } from '@hcengineering/core'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import type { PersonAccount } from '@hcengineering/contact'
|
||||
import { type Action } from '@hcengineering/ui'
|
||||
@@ -80,6 +80,11 @@
|
||||
let lastSeqNumber = -1
|
||||
|
||||
for (const prjdoc of result) {
|
||||
if (prjdoc.document === documents.ids.Folder) {
|
||||
docs.push(prjdoc)
|
||||
continue
|
||||
}
|
||||
|
||||
const doc = prjdoc.$lookup?.document as ControlledDocument | undefined
|
||||
if (doc === undefined) continue
|
||||
if (doc.state === DocumentState.Deleted) continue
|
||||
@@ -120,29 +125,45 @@
|
||||
}
|
||||
)
|
||||
|
||||
let docsMeta: DocumentMeta[] = []
|
||||
|
||||
const metaQuery = createQuery()
|
||||
$: metaQuery.query(documents.class.DocumentMeta, { _id: { $in: projectMeta.map((p) => p.meta) } }, (result) => {
|
||||
docsMeta = result
|
||||
})
|
||||
|
||||
async function getDocMoreActions (obj: Doc): Promise<Action[]> {
|
||||
return getMoreActions !== undefined ? await getMoreActions(obj) : []
|
||||
}
|
||||
|
||||
$: projectMetaById = toIdMap(projectMeta)
|
||||
$: docsMetaById = toIdMap(docsMeta)
|
||||
</script>
|
||||
|
||||
{#each docs as prjdoc}
|
||||
{@const pjmeta = projectMetaById.get(prjdoc.attachedTo)}
|
||||
{@const doc = prjdoc.$lookup?.document}
|
||||
{@const metaid = pjmeta?.meta}
|
||||
{@const meta = metaid ? docsMetaById.get(metaid) : undefined}
|
||||
{@const title = doc ? getDocumentName(doc) : meta?.title ?? ''}
|
||||
{@const docid = doc?._id ?? prjdoc._id}
|
||||
{@const isFolder = prjdoc.document === documents.ids.Folder}
|
||||
|
||||
{#if doc}
|
||||
{@const children = childrenByParent[doc.attachedTo] ?? []}
|
||||
{@const isDraggedOver = draggedOver === doc.attachedTo}
|
||||
{#if metaid}
|
||||
{@const children = childrenByParent[metaid] ?? []}
|
||||
{@const isDraggedOver = draggedOver === metaid}
|
||||
<div class="flex-col relative">
|
||||
{#if isDraggedOver}
|
||||
<DropArea />
|
||||
{/if}
|
||||
<TreeItem
|
||||
_id={doc._id}
|
||||
icon={documents.icon.Document}
|
||||
_id={docid}
|
||||
icon={isFolder ? documents.icon.Folder : documents.icon.Document}
|
||||
iconProps={{
|
||||
fill: 'currentColor'
|
||||
}}
|
||||
title={getDocumentName(doc)}
|
||||
selected={selected === doc._id || selected === prjdoc._id}
|
||||
{title}
|
||||
selected={selected === docid || selected === prjdoc._id}
|
||||
isFold
|
||||
empty={children.length === 0 || children === undefined}
|
||||
actions={getMoreActions !== undefined ? () => getDocMoreActions(prjdoc) : undefined}
|
||||
@@ -154,16 +175,16 @@
|
||||
}}
|
||||
draggable={onDragStart !== undefined}
|
||||
on:dragstart={(evt) => {
|
||||
onDragStart?.(evt, doc.attachedTo)
|
||||
onDragStart?.(evt, metaid)
|
||||
}}
|
||||
on:dragover={(evt) => {
|
||||
onDragOver?.(evt, doc.attachedTo)
|
||||
onDragOver?.(evt, metaid)
|
||||
}}
|
||||
on:dragend={(evt) => {
|
||||
onDragEnd?.(evt, doc.attachedTo)
|
||||
onDragEnd?.(evt, metaid)
|
||||
}}
|
||||
on:drop={(evt) => {
|
||||
onDrop?.(evt, doc.attachedTo)
|
||||
onDrop?.(evt, metaid)
|
||||
}}
|
||||
>
|
||||
<svelte:fragment slot="dropbox">
|
||||
|
||||
+18
-1
@@ -51,7 +51,9 @@
|
||||
canCreateChildDocument,
|
||||
moveDocument,
|
||||
moveDocumentBefore,
|
||||
moveDocumentAfter
|
||||
moveDocumentAfter,
|
||||
canCreateChildFolder,
|
||||
createFolder
|
||||
} from '../../utils'
|
||||
|
||||
import documents from '../../plugin'
|
||||
@@ -178,6 +180,21 @@
|
||||
})
|
||||
}
|
||||
|
||||
if (
|
||||
spaceType?.projects === true &&
|
||||
(await isEditableProject(project)) &&
|
||||
(await canCreateChildFolder(space, true))
|
||||
) {
|
||||
actions.push({
|
||||
icon: documents.icon.Folder,
|
||||
label: documents.string.CreateFolder,
|
||||
group: 'create',
|
||||
action: async () => {
|
||||
await createFolder(space)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return orderActions(actions)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,54 +12,54 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
import { type PersonAccount } from '@hcengineering/contact'
|
||||
import {
|
||||
type Document,
|
||||
type DocumentMeta,
|
||||
type DocumentSpace,
|
||||
DocumentState,
|
||||
type Project,
|
||||
type ProjectDocument
|
||||
} from '@hcengineering/controlled-documents'
|
||||
import {
|
||||
checkPermission,
|
||||
type Class,
|
||||
type Client,
|
||||
type Doc,
|
||||
type DocumentQuery,
|
||||
getCurrentAccount,
|
||||
type Ref,
|
||||
type RelatedDocument,
|
||||
SortingOrder,
|
||||
type WithLookup,
|
||||
type Doc,
|
||||
getCurrentAccount,
|
||||
checkPermission
|
||||
type WithLookup
|
||||
} from '@hcengineering/core'
|
||||
import {
|
||||
type Document,
|
||||
type DocumentSpace,
|
||||
DocumentState,
|
||||
type DocumentMeta,
|
||||
type ProjectDocument,
|
||||
type Project
|
||||
} from '@hcengineering/controlled-documents'
|
||||
import { type Resources } from '@hcengineering/platform'
|
||||
import { type ObjectSearchResult, getClient, MessageBox } from '@hcengineering/presentation'
|
||||
import { getClient, MessageBox, type ObjectSearchResult } from '@hcengineering/presentation'
|
||||
import { showPopup } from '@hcengineering/ui'
|
||||
import { type PersonAccount } from '@hcengineering/contact'
|
||||
|
||||
import CreateDocument from './components/CreateDocument.svelte'
|
||||
import DeleteCategoryPopup from './components/category/popups/DeleteCategoryPopup.svelte'
|
||||
import QmsDocumentWizard from './components/create-doc/QmsDocumentWizard.svelte'
|
||||
import QmsTemplateWizard from './components/create-doc/QmsTemplateWizard.svelte'
|
||||
import DocumentStatusTag from './components/document/common/DocumentStatusTag.svelte'
|
||||
import DocumentSpacePresenter from './components/hierarchy/DocumentSpacePresenter.svelte'
|
||||
import DocumentPresenter from './components/document/presenters/DocumentPresenter.svelte'
|
||||
import StatePresenter from './components/document/presenters/StatePresenter.svelte'
|
||||
import StateFilterValuePresenter from './components/document/presenters/StateFilterValuePresenter.svelte'
|
||||
import TitlePresenter from './components/document/presenters/TitlePresenter.svelte'
|
||||
import OwnerPresenter from './components/document/presenters/OwnerPresenter.svelte'
|
||||
import AddCommentPopup from './components/document/popups/AddCommentPopup.svelte'
|
||||
import DocumentCommentsPopup from './components/document/popups/DocumentCommentsPopup.svelte'
|
||||
import ChangeOwnerPopup from './components/document/popups/ChangeOwnerPopup.svelte'
|
||||
import DeleteCategoryPopup from './components/category/popups/DeleteCategoryPopup.svelte'
|
||||
import DocumentCommentsPopup from './components/document/popups/DocumentCommentsPopup.svelte'
|
||||
import DocumentPresenter from './components/document/presenters/DocumentPresenter.svelte'
|
||||
import OwnerPresenter from './components/document/presenters/OwnerPresenter.svelte'
|
||||
import StateFilterValuePresenter from './components/document/presenters/StateFilterValuePresenter.svelte'
|
||||
import StatePresenter from './components/document/presenters/StatePresenter.svelte'
|
||||
import TitlePresenter from './components/document/presenters/TitlePresenter.svelte'
|
||||
import DocumentSpacePresenter from './components/hierarchy/DocumentSpacePresenter.svelte'
|
||||
|
||||
import CategoryPresenter from './components/category/presenters/CategoryPresenter.svelte'
|
||||
import DocumentItem from './components/DocumentItem.svelte'
|
||||
import Documents from './components/Documents.svelte'
|
||||
import DocumentsContainer from './components/DocumentsContainer.svelte'
|
||||
import MyDocuments from './components/MyDocuments.svelte'
|
||||
import EditDoc from './components/EditDoc.svelte'
|
||||
import EditProjectDoc from './components/EditProjectDoc.svelte'
|
||||
import DocumentItem from './components/DocumentItem.svelte'
|
||||
import MyDocuments from './components/MyDocuments.svelte'
|
||||
import NewDocumentHeader from './components/NewDocumentHeader.svelte'
|
||||
import CategoryPresenter from './components/category/presenters/CategoryPresenter.svelte'
|
||||
import DocumentIcon from './components/icons/DocumentIcon.svelte'
|
||||
|
||||
import DocumentTemplates from './components/DocumentTemplates.svelte'
|
||||
@@ -67,43 +67,53 @@ import DocumentTemplates from './components/DocumentTemplates.svelte'
|
||||
import Categories from './components/Categories.svelte'
|
||||
import EditDocumentCategory from './components/EditDocumentCategory.svelte'
|
||||
|
||||
import DocumentMetaPresenter from './components/DocumentMetaPresenter.svelte'
|
||||
import CreateDocumentSpaceType from './components/docspace/CreateDocumentSpaceType.svelte'
|
||||
import CreateDocumentsSpace from './components/docspace/CreateDocumentsSpace.svelte'
|
||||
import DocumentTitle from './components/document/DocumentTitle.svelte'
|
||||
import EditDocContent from './components/document/EditDocContent.svelte'
|
||||
import ControlledStateFilterValuePresenter from './components/document/presenters/ControlledStateFilterValuePresenter.svelte'
|
||||
import DocumentVersionPresenter from './components/document/presenters/DocumentVersionPresenter.svelte'
|
||||
import DocumentReviewRequest from './components/requests/DocumentReviewRequest.svelte'
|
||||
import DocumentReviewRequestPresenter from './components/requests/DocumentReviewRequestPresenter.svelte'
|
||||
import DocumentApprovalRequest from './components/requests/DocumentApprovalRequest.svelte'
|
||||
import DocumentApprovalRequestPresenter from './components/requests/DocumentApprovalRequestPresenter.svelte'
|
||||
import ControlledStateFilterValuePresenter from './components/document/presenters/ControlledStateFilterValuePresenter.svelte'
|
||||
import DocumentMetaPresenter from './components/DocumentMetaPresenter.svelte'
|
||||
import CreateDocumentsSpace from './components/docspace/CreateDocumentsSpace.svelte'
|
||||
import CreateDocumentSpaceType from './components/docspace/CreateDocumentSpaceType.svelte'
|
||||
import DocumentReviewRequest from './components/requests/DocumentReviewRequest.svelte'
|
||||
import DocumentReviewRequestPresenter from './components/requests/DocumentReviewRequestPresenter.svelte'
|
||||
|
||||
import Projects from './components/project/Projects.svelte'
|
||||
import ProjectPresenter from './components/project/ProjectPresenter.svelte'
|
||||
import ProjectRefPresenter from './components/project/ProjectRefPresenter.svelte'
|
||||
import Projects from './components/project/Projects.svelte'
|
||||
|
||||
import { getPrintBaseURL } from '@hcengineering/print'
|
||||
import CreateFolder from './components/create-doc/CreateFolder.svelte'
|
||||
import TransferDocumentPopup from './components/document/popups/TransferDocumentPopup.svelte'
|
||||
import { resolveLocation } from './navigation'
|
||||
import documents from './plugin'
|
||||
import './styles/_colors.scss'
|
||||
import { resolveLocation } from './navigation'
|
||||
import { comment, isCommentVisible } from './text'
|
||||
import {
|
||||
getVisibleFilters,
|
||||
sortDocumentStates,
|
||||
getAllDocumentStates,
|
||||
canChangeDocumentOwner,
|
||||
canDeleteDocumentCategory,
|
||||
canCreateChildTemplate,
|
||||
canCreateChildDocument,
|
||||
documentIdentifierProvider,
|
||||
getControlledDocumentTitle,
|
||||
getDocumentMetaLinkFragment,
|
||||
canCreateChildFolder,
|
||||
canCreateChildTemplate,
|
||||
canDeleteDocumentCategory,
|
||||
canDeleteFolder,
|
||||
canRenameFolder,
|
||||
createChildDocument,
|
||||
createChildFolder,
|
||||
createChildTemplate,
|
||||
createDocument,
|
||||
createTemplate
|
||||
createFolder,
|
||||
createTemplate,
|
||||
deleteFolder,
|
||||
documentIdentifierProvider,
|
||||
getAllDocumentStates,
|
||||
getControlledDocumentTitle,
|
||||
getDocumentMetaLinkFragment,
|
||||
getVisibleFilters,
|
||||
isFolder,
|
||||
renameFolder,
|
||||
sortDocumentStates
|
||||
} from './utils'
|
||||
import { comment, isCommentVisible } from './text'
|
||||
import TransferDocumentPopup from './components/document/popups/TransferDocumentPopup.svelte'
|
||||
|
||||
export { DocumentStatusTag, DocumentTitle, DocumentVersionPresenter, StatePresenter }
|
||||
|
||||
@@ -210,6 +220,37 @@ async function canArchiveDocument (obj?: Doc | Doc[]): Promise<boolean> {
|
||||
).then((res) => res.every((r) => r))
|
||||
}
|
||||
|
||||
async function canOpenDocument (obj?: ProjectDocument | ProjectDocument[]): Promise<boolean> {
|
||||
if (obj == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
const h = getClient().getHierarchy()
|
||||
|
||||
const objs = Array.isArray(obj) ? obj : [obj]
|
||||
return !objs.some((d) => isFolder(h, d))
|
||||
}
|
||||
|
||||
async function canPrintDocument (obj?: Document | Document[] | ProjectDocument | ProjectDocument[]): Promise<boolean> {
|
||||
if (obj == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
const h = getClient().getHierarchy()
|
||||
|
||||
const objs = Array.isArray(obj) ? obj : [obj]
|
||||
if (objs.some((d) => isFolder(h, d))) return false
|
||||
|
||||
let printURL = ''
|
||||
try {
|
||||
printURL = getPrintBaseURL()
|
||||
} catch (err) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
return printURL?.length > 0
|
||||
}
|
||||
|
||||
async function canTransferDocument (obj?: Doc | Doc[]): Promise<boolean> {
|
||||
if (obj == null) {
|
||||
return false
|
||||
@@ -339,7 +380,8 @@ export default async (): Promise<Resources> => ({
|
||||
Projects,
|
||||
ProjectPresenter,
|
||||
ProjectRefPresenter,
|
||||
DocumentIcon
|
||||
DocumentIcon,
|
||||
CreateFolder
|
||||
},
|
||||
completion: {
|
||||
DocumentMetaQuery: async (
|
||||
@@ -356,8 +398,12 @@ export default async (): Promise<Resources> => ({
|
||||
CanChangeDocumentOwner: canChangeDocumentOwner,
|
||||
CanCreateTemplate: canCreateChildTemplate,
|
||||
CanCreateDocument: canCreateChildDocument,
|
||||
CanCreateFolder: canCreateChildFolder,
|
||||
CanCreateChildTemplate: canCreateChildTemplate,
|
||||
CanCreateChildDocument: canCreateChildDocument,
|
||||
CanCreateChildFolder: canCreateChildFolder,
|
||||
CanRenameFolder: canRenameFolder,
|
||||
CanDeleteFolder: canDeleteFolder,
|
||||
CanDeleteDocumentCategory: canDeleteDocumentCategory,
|
||||
GetVisibleFilters: getVisibleFilters,
|
||||
DocumentStateSort: sortDocumentStates,
|
||||
@@ -366,6 +412,8 @@ export default async (): Promise<Resources> => ({
|
||||
CanDeleteDocument: canDeleteDocument,
|
||||
CanArchiveDocument: canArchiveDocument,
|
||||
CanTransferDocument: canTransferDocument,
|
||||
CanOpenDocument: canOpenDocument,
|
||||
CanPrintDocument: canPrintDocument,
|
||||
DocumentIdentifierProvider: documentIdentifierProvider,
|
||||
ControlledDocumentTitleProvider: getControlledDocumentTitle,
|
||||
Comment: comment,
|
||||
@@ -374,8 +422,12 @@ export default async (): Promise<Resources> => ({
|
||||
actionImpl: {
|
||||
CreateChildDocument: createChildDocument,
|
||||
CreateChildTemplate: createChildTemplate,
|
||||
CreateChildFolder: createChildFolder,
|
||||
RenameFolder: renameFolder,
|
||||
DeleteFolder: deleteFolder,
|
||||
CreateDocument: createDocument,
|
||||
CreateTemplate: createTemplate,
|
||||
CreateFolder: createFolder,
|
||||
DeleteDocument: deleteDocuments,
|
||||
ArchiveDocument: archiveDocuments,
|
||||
TransferDocument: transferDocuments,
|
||||
|
||||
@@ -226,8 +226,12 @@ export default mergeIds(documentsId, documents, {
|
||||
function: {
|
||||
CanCreateTemplate: '' as Resource<ViewActionAvailabilityFunction<DocumentSpace>>,
|
||||
CanCreateDocument: '' as Resource<ViewActionAvailabilityFunction<DocumentSpace>>,
|
||||
CanCreateFolder: '' as Resource<ViewActionAvailabilityFunction<DocumentSpace>>,
|
||||
CanCreateChildTemplate: '' as Resource<ViewActionAvailabilityFunction<Document>>,
|
||||
CanCreateChildDocument: '' as Resource<ViewActionAvailabilityFunction<Document>>,
|
||||
CanCreateChildFolder: '' as Resource<ViewActionAvailabilityFunction<Document>>,
|
||||
CanRenameFolder: '' as Resource<ViewActionAvailabilityFunction<Document>>,
|
||||
CanDeleteFolder: '' as Resource<ViewActionAvailabilityFunction<Document>>,
|
||||
CheckIsDocumentCreationDisabled: '' as Resource<() => Promise<boolean>>,
|
||||
CheckAreTemplatesDisabled: '' as Resource<() => Promise<boolean>>,
|
||||
CheckAreDomainsDisabled: '' as Resource<() => Promise<boolean>>,
|
||||
@@ -238,6 +242,8 @@ 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>>,
|
||||
CanOpenDocument: '' as Resource<(doc?: Doc | Doc[]) => Promise<boolean>>,
|
||||
CanPrintDocument: '' as Resource<(doc?: Doc | Doc[]) => Promise<boolean>>,
|
||||
CanTransferDocument: '' as Resource<(doc?: Doc | Doc[]) => Promise<boolean>>,
|
||||
ControlledDocumentTitleProvider: '' as Resource<(client: Client, ref: Ref<Doc>, doc?: Doc) => Promise<string>>
|
||||
}
|
||||
|
||||
@@ -119,6 +119,11 @@ export function isProjectDocument (hierarchy: Hierarchy, doc: Doc): doc is Proje
|
||||
return hierarchy.isDerived(doc._class, documents.class.ProjectDocument)
|
||||
}
|
||||
|
||||
export function isFolder (hierarchy: Hierarchy, doc: Doc): doc is ProjectDocument {
|
||||
if (!isProjectDocument(hierarchy, doc)) return false
|
||||
return doc.document === documents.ids.Folder
|
||||
}
|
||||
|
||||
export async function getVisibleFilters (filters: KeyFilter[], space?: Ref<Space>): Promise<KeyFilter[]> {
|
||||
// Removes the "Space" filter if a specific space is provided
|
||||
return space === undefined ? filters : filters.filter((f) => f.key !== 'space')
|
||||
@@ -461,6 +466,112 @@ export async function canCreateChildDocument (
|
||||
return true
|
||||
}
|
||||
|
||||
export async function canCreateChildFolder (
|
||||
doc?: Document | Document[] | DocumentSpace | DocumentSpace[] | ProjectDocument | ProjectDocument[],
|
||||
includeProjects = false
|
||||
): Promise<boolean> {
|
||||
if (doc === null || doc === undefined) {
|
||||
return false
|
||||
}
|
||||
if (Array.isArray(doc)) {
|
||||
return false
|
||||
}
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
const spaceId: Ref<DocumentSpace> = isSpace(hierarchy, doc) ? doc._id : doc.space
|
||||
|
||||
const canCreateDocument = await checkPermission(client, documents.permission.CreateDocument, spaceId)
|
||||
if (!canCreateDocument) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (isSpace(hierarchy, doc)) {
|
||||
const spaceType = await client.findOne(documents.class.DocumentSpaceType, { _id: doc.type })
|
||||
return includeProjects || spaceType?.projects !== true
|
||||
}
|
||||
|
||||
if (isProjectDocument(hierarchy, doc)) {
|
||||
return await isEditableProject(doc.project)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
export async function canRenameFolder (
|
||||
doc?: Document | Document[] | DocumentSpace | DocumentSpace[] | ProjectDocument | ProjectDocument[],
|
||||
includeProjects = false
|
||||
): Promise<boolean> {
|
||||
if (doc === null || doc === undefined) {
|
||||
return false
|
||||
}
|
||||
if (Array.isArray(doc)) {
|
||||
return false
|
||||
}
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
const spaceId: Ref<DocumentSpace> = isSpace(hierarchy, doc) ? doc._id : doc.space
|
||||
|
||||
const canCreateDocument = await checkPermission(client, documents.permission.CreateDocument, spaceId)
|
||||
if (!canCreateDocument) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (isSpace(hierarchy, doc)) {
|
||||
const spaceType = await client.findOne(documents.class.DocumentSpaceType, { _id: doc.type })
|
||||
return includeProjects || spaceType?.projects !== true
|
||||
}
|
||||
|
||||
if (!isFolder(hierarchy, doc)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return await isEditableProject(doc.project)
|
||||
}
|
||||
|
||||
export async function canDeleteFolder (obj?: Doc | Doc[]): Promise<boolean> {
|
||||
if (obj == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
|
||||
const objs = (Array.isArray(obj) ? obj : [obj]) as Document[]
|
||||
|
||||
const isFolders = objs.every((doc) => isFolder(hierarchy, doc))
|
||||
if (!isFolders) {
|
||||
return false
|
||||
}
|
||||
|
||||
const folders = objs as unknown as ProjectDocument[]
|
||||
|
||||
const pjMeta = await client.findAll(documents.class.ProjectMeta, { _id: { $in: folders.map((f) => f.attachedTo) } })
|
||||
const directChildren = await client.findAll(documents.class.ProjectMeta, {
|
||||
parent: { $in: pjMeta.map((p) => p.meta) }
|
||||
})
|
||||
|
||||
if (directChildren.length > 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
export async function canDeleteDocumentCategory (doc?: Doc | Doc[]): Promise<boolean> {
|
||||
if (doc === null || doc === undefined) {
|
||||
return false
|
||||
@@ -627,6 +738,54 @@ export async function createChildTemplate (doc: ProjectDocument): Promise<void>
|
||||
showPopup(documents.component.QmsTemplateWizard, {})
|
||||
}
|
||||
|
||||
export async function createChildFolder (doc: ProjectDocument): Promise<void> {
|
||||
const props = {
|
||||
space: doc.space,
|
||||
project: doc.project,
|
||||
parent: doc._id
|
||||
}
|
||||
|
||||
showPopup(documents.component.CreateFolder, props)
|
||||
}
|
||||
|
||||
export async function renameFolder (doc: ProjectDocument): Promise<void> {
|
||||
const client = getClient()
|
||||
|
||||
const pjmeta = await client.findOne(documents.class.ProjectMeta, { _id: doc.attachedTo })
|
||||
if (pjmeta === undefined) return
|
||||
|
||||
const meta = await client.findOne(documents.class.DocumentMeta, { _id: pjmeta.meta })
|
||||
if (meta === undefined) return
|
||||
|
||||
const props = {
|
||||
folder: meta,
|
||||
name: meta.title
|
||||
}
|
||||
|
||||
showPopup(documents.component.CreateFolder, props)
|
||||
}
|
||||
|
||||
export async function deleteFolder (obj: ProjectDocument | ProjectDocument[]): Promise<void> {
|
||||
const client = getClient()
|
||||
|
||||
if (!(await canDeleteFolder(obj))) {
|
||||
return
|
||||
}
|
||||
|
||||
const objs = Array.isArray(obj) ? obj : [obj]
|
||||
|
||||
const pjmeta = await client.findAll(documents.class.ProjectMeta, { _id: { $in: objs.map((p) => p.attachedTo) } })
|
||||
const meta = await client.findAll(documents.class.DocumentMeta, { _id: { $in: pjmeta.map((p) => p.meta) } })
|
||||
|
||||
const docsToRemove = [...objs, ...pjmeta, ...meta]
|
||||
const ops = client.apply()
|
||||
for (const doc of docsToRemove) {
|
||||
await ops.remove(doc)
|
||||
}
|
||||
|
||||
await ops.commit()
|
||||
}
|
||||
|
||||
export async function createDocument (space: DocumentSpace): Promise<void> {
|
||||
const project = await getLatestProjectId(space._id)
|
||||
wizardOpened({
|
||||
@@ -642,6 +801,15 @@ export async function createTemplate (space: OrgSpace): Promise<void> {
|
||||
showPopup(documents.component.QmsTemplateWizard, {})
|
||||
}
|
||||
|
||||
export async function createFolder (space: DocumentSpace): Promise<void> {
|
||||
const project = await getLatestProjectId(space._id)
|
||||
const props = {
|
||||
space: space._id,
|
||||
project: project ?? documents.ids.NoProject
|
||||
}
|
||||
showPopup(documents.component.CreateFolder, props)
|
||||
}
|
||||
|
||||
export function formatSignatureDate (date: number): string {
|
||||
const timeZone: string = getUserTimezone()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user