|
| 1 | +<script lang="ts"> |
| 2 | + import { Class, Mixin, Ref } from '@hcengineering/core' |
| 3 | + import { Task } from '@hcengineering/task' |
| 4 | + import { ButtonMenu, Label } from '@hcengineering/ui' |
| 5 | + import { createEventDispatcher } from 'svelte' |
| 6 | + import { getClient } from '@hcengineering/presentation' |
| 7 | + import plugin from '../../plugin' |
| 8 | +
|
| 9 | + export let baseClass: Ref<Class<Task>> |
| 10 | + export let value: Ref<Mixin<Task>> | undefined = undefined |
| 11 | + export let readonly = false |
| 12 | + export let buttonKind: 'primary' | 'secondary' | 'tertiary' | 'negative' = 'secondary' |
| 13 | + export let buttonSize: 'large' | 'medium' | 'small' = 'large' |
| 14 | +
|
| 15 | + const dispatch = createEventDispatcher() |
| 16 | + const client = getClient() |
| 17 | + const hierarchy = client.getHierarchy() |
| 18 | +
|
| 19 | + // Find all mixins that derive from baseClass |
| 20 | + function getAvailableMixins (): Array<{ id: string; label: string }> { |
| 21 | + const result: Array<{ id: string; label: string }> = [ |
| 22 | + { id: '', label: 'None (create new)' } |
| 23 | + ] |
| 24 | +
|
| 25 | + try { |
| 26 | + const descendants = hierarchy.getDescendants(baseClass) |
| 27 | + for (const descendant of descendants) { |
| 28 | + const cls = hierarchy.getClass(descendant) |
| 29 | + if (cls.kind === 'mixin' && descendant !== baseClass) { |
| 30 | + result.push({ |
| 31 | + id: descendant as string, |
| 32 | + label: cls.label ?? descendant |
| 33 | + }) |
| 34 | + } |
| 35 | + } |
| 36 | + } catch (e) { |
| 37 | + console.error('Error getting available mixins:', e) |
| 38 | + } |
| 39 | +
|
| 40 | + return result |
| 41 | + } |
| 42 | +
|
| 43 | + function handleSelect (evt: CustomEvent<string>): void { |
| 44 | + if (evt.detail !== undefined) { |
| 45 | + value = evt.detail === '' ? undefined : (evt.detail as Ref<Mixin<Task>>) |
| 46 | + dispatch('change', value) |
| 47 | + } |
| 48 | + } |
| 49 | +
|
| 50 | + $: items = getAvailableMixins() |
| 51 | + $: selected = items.find((it) => it.id === (value ?? '')) |
| 52 | +</script> |
| 53 | + |
| 54 | +<div class="mixin-selector"> |
| 55 | + <Label label={plugin.string.BaseMixin} /> |
| 56 | + {#if readonly} |
| 57 | + {#if selected} |
| 58 | + <span class="selected-value">{selected.label}</span> |
| 59 | + {/if} |
| 60 | + {:else} |
| 61 | + <ButtonMenu |
| 62 | + selected={value ?? ''} |
| 63 | + {items} |
| 64 | + label={selected?.label ?? plugin.string.NoBaseMixin} |
| 65 | + kind={buttonKind} |
| 66 | + size={buttonSize} |
| 67 | + on:selected={handleSelect} |
| 68 | + /> |
| 69 | + {/if} |
| 70 | +</div> |
| 71 | + |
| 72 | +<style lang="scss"> |
| 73 | + .mixin-selector { |
| 74 | + display: flex; |
| 75 | + flex-direction: column; |
| 76 | + gap: 0.5rem; |
| 77 | + } |
| 78 | +
|
| 79 | + .selected-value { |
| 80 | + color: var(--theme-content-color); |
| 81 | + } |
| 82 | +</style> |
0 commit comments