Files
huly-platform/plugins/card-resources/src/components/CreateCardPopup.svelte
T
Denis BykhovandGitHub 0762a42922 Fix permissions for mixins/tags (#10294)
* Fix permissions for mixins/tags

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>

* Fix

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>

---------

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
2025-12-12 10:15:56 +07:00

233 lines
7.0 KiB
Svelte

<!-- 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 card, { Card, CardSpace, MasterTag } from '@hcengineering/card'
import presentation, { getClient, getCommunicationClient, SpaceSelector } from '@hcengineering/presentation'
import { createEventDispatcher } from 'svelte'
import core, { Data, generateId, Ref, Markup, notEmpty } from '@hcengineering/core'
import { getResource, translate, getEmbeddedLabel } from '@hcengineering/platform'
import { Label, Modal, ModernEditbox, languageStore, showPopup, Component } from '@hcengineering/ui'
import { AttachmentStyledBox } from '@hcengineering/attachment-resources'
import { EmptyMarkup } from '@hcengineering/text'
import { Employee, getCurrentEmployee } from '@hcengineering/contact'
import { SelectUsersPopup, employeeByIdStore, permissionsStore } from '@hcengineering/contact-resources'
import view from '@hcengineering/view'
import { createCard } from '../utils'
import CardCollaborators from './CardCollaborators.svelte'
import { TypeSelector } from '../index'
import { canCreateObject } from '@hcengineering/view-resources'
export let title: string = ''
export let type: Ref<MasterTag> = card.types.Document
export let space: Ref<CardSpace> | undefined = undefined
export let changeType: boolean = false
export let allowChangeSpace: boolean = true
export let description: Markup = EmptyMarkup
const dispatch = createEventDispatcher()
const client = getClient()
const hierarchy = client.getHierarchy()
const communicationClient = getCommunicationClient()
const me = getCurrentEmployee()
const _id = generateId<Card>()
$: extension =
type != null
? client
.getModel()
.findAllSync(card.mixin.CreateCardExtension, {})
.find((it) => hierarchy.isDerived(type, it._id))
: undefined
let data: Partial<Data<Card>> = { title }
let _space: Ref<CardSpace> | undefined = space
let collaborators: Ref<Employee>[] = [me]
let creating = false
async function addCollaborators (): Promise<void> {
if (type == null) return
const accounts = collaborators
.filter((it) => it !== me)
.map((it) => $employeeByIdStore.get(it)?.personUuid)
.filter(notEmpty)
if (accounts.length > 0) {
await communicationClient.addCollaborators(_id, type, accounts)
}
}
async function okAction (): Promise<void> {
if (_space === undefined || type == null) return
try {
creating = true
if (extension?.canCreate != null) {
const fn = await getResource(extension.canCreate)
const res = await fn(_space, data)
if (res === false) {
dispatch('close')
return
} else if (typeof res === 'string') {
dispatch('close', res)
return
}
}
await createCard(type, _space, data, description, _id)
await addCollaborators()
dispatch('close', _id)
} finally {
creating = false
}
}
function handleCancel (): void {
dispatch('close')
}
let label: string = ''
$: void updateLabel($languageStore)
async function updateLabel (lang: string): Promise<void> {
const _clazz = hierarchy.getClass(type)
const typeString = await translate(_clazz.label, {}, lang)
const createString = await translate(presentation.string.Create, {}, lang)
label = `${createString} ${typeString}`
}
function openSelectUsersPopup (): void {
showPopup(
SelectUsersPopup,
{
okLabel: presentation.string.Ok,
disableDeselectFor: [me],
skipCurrentAccount: false,
skipInactive: true,
selected: collaborators,
showStatus: true
},
'top',
(result?: Ref<Employee>[]) => {
if (result != null) {
collaborators = result
}
}
)
}
function handleChange (event: CustomEvent<{ data: Partial<Data<Card>>, space?: Ref<CardSpace> }>): void {
data = {
...data,
...event.detail.data
}
if (event.detail.space != null) {
_space = event.detail.space
}
}
$: allowed = _space && canCreateObject(type, _space, $permissionsStore)
</script>
<Modal
label={getEmbeddedLabel(label)}
type="type-popup"
width="large"
okLabel={presentation.string.Create}
{okAction}
okLoading={creating}
canSave={data.title != null && data.title.trim().length > 0 && _space != null && allowed}
onCancel={handleCancel}
maxWidth="90vw"
on:close
>
<div class="hulyModal-content__titleGroup" style="padding: 0">
<ModernEditbox
bind:value={data.title}
label={view.string.Title}
size="medium"
kind="ghost"
disabled={extension?.disableTitle ?? false}
autoFocus={!(extension?.disableTitle ?? false)}
/>
<AttachmentStyledBox
objectId={_id}
_class={type}
space={_space}
alwaysEdit
showButtons={false}
bind:content={description}
placeholder={core.string.Description}
kind="indented"
isScrollable={true}
kitOptions={{ reference: true }}
enableAttachments={false}
/>
</div>
<div class="hulyModal-content__settingsSet">
{#if changeType}
<div class="hulyModal-content__settingsSet-line">
<span class="label"><Label label={card.string.MasterTag} /></span>
<TypeSelector bind:value={type} />
</div>
{/if}
{#if (space == null || allowChangeSpace) && !(extension?.hideSpace ?? false)}
<div class="hulyModal-content__settingsSet-line">
<span class="label"><Label label={core.string.Space} /></span>
<SpaceSelector
_class={card.class.CardSpace}
query={{ archived: false }}
label={core.string.Space}
bind:space={_space}
focus={false}
kind={'regular'}
size={'large'}
/>
</div>
{/if}
<CardCollaborators
ids={collaborators}
disableRemoveFor={[me]}
on:add={openSelectUsersPopup}
on:remove={(ev) => {
collaborators = collaborators.filter((id) => id !== ev.detail)
}}
/>
{#if extension?.component}
<Component is={extension.component} props={{ collaborators, data, space: _space }} on:change={handleChange} />
{/if}
</div>
<div slot="afterContent" class="error p-4 flex-row-reverse">
{#if !allowed}
<Label label={view.string.NoCreatePermissionTitle} />
{/if}
</div>
</Modal>
<style lang="scss">
.error {
color: var(--theme-error-color);
}
</style>