mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-09 19:27:44 +02:00
164 lines
5.4 KiB
Svelte
164 lines
5.4 KiB
Svelte
<!--
|
|
//
|
|
// Copyright © 2023 Hardcore Engineering Inc.
|
|
//
|
|
-->
|
|
<script lang="ts">
|
|
import { Employee } from '@hcengineering/contact'
|
|
import { UserBoxItems, getPermittedPersons, permissionsStore } from '@hcengineering/contact-resources'
|
|
import documents, {
|
|
ControlledDocument,
|
|
ControlledDocumentState,
|
|
DocumentRequest
|
|
} from '@hcengineering/controlled-documents'
|
|
import { Class, Ref, TxOperations } from '@hcengineering/core'
|
|
import { getClient } from '@hcengineering/presentation'
|
|
import { RequestStatus } from '@hcengineering/request'
|
|
import { Label, ModernDialog, showPopup } from '@hcengineering/ui'
|
|
import { createEventDispatcher } from 'svelte'
|
|
|
|
import documentsRes from '../plugin'
|
|
import { sendApprovalRequest, sendReviewRequest } from '../utils'
|
|
import SignatureDialog from './SignatureDialog.svelte'
|
|
|
|
type SendRequestFunc = (
|
|
client: TxOperations,
|
|
controlledDoc: ControlledDocument,
|
|
users: Array<Ref<Employee>>,
|
|
externalUsers: Array<Ref<Employee>>,
|
|
oldExternalUsers: Array<Ref<Employee>>
|
|
) => Promise<void>
|
|
|
|
export let controlledDoc: ControlledDocument
|
|
export let requestClass: Ref<Class<DocumentRequest>>
|
|
export let readonly: boolean = false
|
|
export let requireSignature: boolean = false
|
|
|
|
const client = getClient()
|
|
const hierarchy = client.getHierarchy()
|
|
const dispatch = createEventDispatcher()
|
|
|
|
const isReviewRequest = hierarchy.isDerived(requestClass, documentsRes.class.DocumentReviewRequest)
|
|
|
|
const docField: keyof ControlledDocument = isReviewRequest ? 'reviewers' : 'approvers'
|
|
const label = isReviewRequest ? documentsRes.string.SelectReviewers : documentsRes.string.SelectApprovers
|
|
const sendRequestFunc: SendRequestFunc = isReviewRequest ? sendReviewRequest : sendApprovalRequest
|
|
const permissionId = isReviewRequest ? documents.permission.ReviewDocument : documents.permission.ApproveDocument
|
|
$: permissionsSpace =
|
|
controlledDoc.space === documents.space.UnsortedTemplates ? documents.space.QualityDocuments : controlledDoc.space
|
|
$: permittedPeople = new Set(getPermittedPersons(permissionId, permissionsSpace, $permissionsStore))
|
|
$: permittedEmployees = Array.from(permittedPeople) as Ref<Employee>[]
|
|
|
|
let docRequest: DocumentRequest | undefined
|
|
let loading = true
|
|
void client
|
|
.findOne(requestClass, {
|
|
attachedTo: controlledDoc._id,
|
|
status: RequestStatus.Active
|
|
})
|
|
.then((res) => {
|
|
loading = false
|
|
docRequest = res
|
|
})
|
|
|
|
let users: Ref<Employee>[] = controlledDoc[docField] ?? []
|
|
let externalUsers: Ref<Employee>[] = isReviewRequest ? [] : (controlledDoc.externalApprovers ?? [])
|
|
const existingExternalUsers = externalUsers
|
|
|
|
async function submit (): Promise<void> {
|
|
const complete = async (): Promise<void> => {
|
|
loading = true
|
|
|
|
await sendRequestFunc?.(client, controlledDoc, users, isReviewRequest ? [] : externalUsers, existingExternalUsers)
|
|
|
|
loading = false
|
|
|
|
dispatch('close')
|
|
}
|
|
|
|
if (requireSignature) {
|
|
showPopup(
|
|
SignatureDialog,
|
|
{
|
|
confirmationTitle: isReviewRequest
|
|
? documentsRes.string.ConfirmReviewSubmission
|
|
: documentsRes.string.ConfirmApprovalSubmission
|
|
},
|
|
'center',
|
|
async (res) => {
|
|
if (!res) return
|
|
|
|
await complete()
|
|
}
|
|
)
|
|
} else {
|
|
await complete()
|
|
}
|
|
}
|
|
|
|
$: canSubmit = docRequest === undefined && (users.length > 0 || externalUsers.length > 0)
|
|
</script>
|
|
|
|
<ModernDialog {loading} {label} {canSubmit} on:submit={submit} on:close>
|
|
<div class="flex-col pt-2 flex-gap-4">
|
|
<div class="flex">
|
|
<div class="flex labelContainer">
|
|
<div class="label mr-1">
|
|
<Label label={isReviewRequest ? documentsRes.string.Reviewers : documentsRes.string.Approvers} />
|
|
</div>
|
|
{users?.length}
|
|
</div>
|
|
<div class="flex-col">
|
|
<UserBoxItems
|
|
items={users}
|
|
label={isReviewRequest ? documentsRes.string.Reviewers : documentsRes.string.Approvers}
|
|
readonly={controlledDoc.controlledState === ControlledDocumentState.InReview ||
|
|
controlledDoc.controlledState === ControlledDocumentState.InApproval ||
|
|
readonly}
|
|
docQuery={{
|
|
active: true,
|
|
_id: { $in: permittedEmployees }
|
|
}}
|
|
on:update={({ detail }) => (users = detail)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
{#if !isReviewRequest}
|
|
<div class="flex">
|
|
<div class="flex labelContainer">
|
|
<div class="label mr-1">
|
|
<Label label={documentsRes.string.ExternalApprovers} />
|
|
</div>
|
|
{externalUsers?.length}
|
|
</div>
|
|
<div class="flex-col">
|
|
<UserBoxItems
|
|
items={externalUsers}
|
|
label={documentsRes.string.ExternalApprovers}
|
|
readonly={controlledDoc.controlledState === ControlledDocumentState.InReview ||
|
|
controlledDoc.controlledState === ControlledDocumentState.InApproval ||
|
|
readonly}
|
|
docQuery={{
|
|
active: true,
|
|
role: 'GUEST',
|
|
_id: { $nin: permittedEmployees }
|
|
}}
|
|
on:update={({ detail }) => (externalUsers = detail)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
</ModernDialog>
|
|
|
|
<style lang="scss">
|
|
.labelContainer {
|
|
min-width: 11rem;
|
|
}
|
|
|
|
.label {
|
|
color: var(--theme-qms-form-row-label-color);
|
|
font-weight: 500;
|
|
}
|
|
</style>
|