mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-12 11:20:49 +00:00
175 lines
5.3 KiB
Svelte
175 lines
5.3 KiB
Svelte
<!--
|
|
// Copyright © 2022 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 { createEventDispatcher } from 'svelte'
|
|
import core, { AnyAttribute, ArrOf, AttachedDoc, Class, Collection, Doc, Ref, RefTo, Type } from '@hcengineering/core'
|
|
import { IntlString, getResource } from '@hcengineering/platform'
|
|
import presentation, { MessageBox, createQuery, getClient } from '@hcengineering/presentation'
|
|
import {
|
|
Action,
|
|
AnySvelteComponent,
|
|
IconDelete,
|
|
IconEdit,
|
|
Menu,
|
|
getEventPositionElement,
|
|
showPopup
|
|
} from '@hcengineering/ui'
|
|
import { getContextActions } from '@hcengineering/view-resources'
|
|
import settings from '../plugin'
|
|
import ClassAttributeRow from './ClassAttributeRow.svelte'
|
|
import EditAttribute from './EditAttribute.svelte'
|
|
|
|
export let _class: Ref<Class<Doc>>
|
|
export let ofClass: Ref<Class<Doc>> | undefined = undefined
|
|
export let notUseOfClass: boolean = false
|
|
export let selected: AnyAttribute | undefined = undefined
|
|
|
|
export let attributeMapper:
|
|
| {
|
|
component: AnySvelteComponent
|
|
label: IntlString
|
|
props: Record<string, any>
|
|
}
|
|
| undefined = undefined
|
|
|
|
const dispatch = createEventDispatcher()
|
|
|
|
const client = getClient()
|
|
const hierarchy = client.getHierarchy()
|
|
|
|
const classQuery = createQuery()
|
|
|
|
let clazz: Class<Doc> | undefined
|
|
let hovered: number | null = null
|
|
|
|
$: classQuery.query(core.class.Class, { _id: _class }, (res) => {
|
|
clazz = res.shift()
|
|
})
|
|
$: attributes = getCustomAttributes(_class)
|
|
|
|
function getCustomAttributes (_class: Ref<Class<Doc>>): AnyAttribute[] {
|
|
const cl = hierarchy.getClass(_class)
|
|
const attributes = Array.from(
|
|
hierarchy.getAllAttributes(_class, _class === ofClass && !notUseOfClass ? core.class.Doc : cl.extends).values()
|
|
)
|
|
return attributes
|
|
}
|
|
|
|
const attrQuery = createQuery()
|
|
|
|
$: attrQuery.query(core.class.Attribute, { attributeOf: _class }, () => {
|
|
attributes = getCustomAttributes(_class)
|
|
})
|
|
|
|
function update (): void {
|
|
attributes = getCustomAttributes(_class)
|
|
}
|
|
|
|
export async function editAttribute (attribute: AnyAttribute, exist: boolean): Promise<void> {
|
|
showPopup(EditAttribute, { attribute, exist }, 'top', update)
|
|
}
|
|
|
|
export async function removeAttribute (attribute: AnyAttribute, exist: boolean): Promise<void> {
|
|
showPopup(
|
|
MessageBox,
|
|
{
|
|
label: settings.string.DeleteAttribute,
|
|
message: exist ? settings.string.DeleteAttributeExistConfirm : settings.string.DeleteAttributeConfirm
|
|
},
|
|
'top',
|
|
async (result) => {
|
|
if (result != null) {
|
|
await client.remove(attribute)
|
|
update()
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
async function showMenu (ev: MouseEvent, attribute: AnyAttribute, row: number): Promise<void> {
|
|
hovered = row
|
|
const exist = (await client.findOne(attribute.attributeOf, { [attribute.name]: { $exists: true } })) !== undefined
|
|
|
|
const actions: Action[] = [
|
|
{
|
|
label: presentation.string.Edit,
|
|
icon: IconEdit,
|
|
action: async () => {
|
|
dispatch('select', attribute._id)
|
|
}
|
|
}
|
|
]
|
|
if (attribute.isCustom === true) {
|
|
actions.push({
|
|
label: presentation.string.Remove,
|
|
icon: IconDelete,
|
|
action: async () => {
|
|
await removeAttribute(attribute, exist)
|
|
}
|
|
})
|
|
}
|
|
const extra = await getContextActions(client, attribute, { mode: 'context' })
|
|
actions.push(
|
|
...extra.map((it) => ({
|
|
label: it.label,
|
|
icon: it.icon,
|
|
action: async (_: any, evt: Event) => {
|
|
const r = await getResource(it.action)
|
|
await r(attribute, evt, it.actionProps)
|
|
}
|
|
}))
|
|
)
|
|
showPopup(Menu, { actions }, getEventPositionElement(ev), () => {
|
|
hovered = null
|
|
})
|
|
}
|
|
|
|
function getAttrType (type: Type<any>): IntlString | undefined {
|
|
switch (type._class) {
|
|
case core.class.RefTo:
|
|
return client.getHierarchy().getClass((type as RefTo<Doc>).to).label
|
|
case core.class.Collection:
|
|
return client.getHierarchy().getClass((type as Collection<AttachedDoc>).of).label
|
|
case core.class.ArrOf:
|
|
return (type as ArrOf<Doc>).of.label
|
|
default:
|
|
return undefined
|
|
}
|
|
}
|
|
</script>
|
|
|
|
{#each attributes as attr, i}
|
|
{@const attrType = getAttrType(attr.type)}
|
|
<ClassAttributeRow
|
|
attribute={attr}
|
|
attributeType={attrType}
|
|
selected={selected && attr._id === selected._id}
|
|
hovered={hovered === i}
|
|
{attributeMapper}
|
|
clickMore={async (event) => {
|
|
event.preventDefault()
|
|
void showMenu(event, attr, i)
|
|
}}
|
|
on:contextmenu={async (event) => {
|
|
event.preventDefault()
|
|
void showMenu(event, attr, i)
|
|
}}
|
|
on:click={async () => {
|
|
if (selected && selected._id === attr._id) dispatch('deselect')
|
|
else dispatch('select', attr)
|
|
}}
|
|
/>
|
|
{/each}
|