Emoji for types (#8240)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2025-03-15 21:32:53 +05:00 committed by GitHub
parent 21eaf38daa
commit 54be660e9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 65 additions and 60 deletions

View File

@ -60,11 +60,14 @@ export { cardId } from '@hcengineering/card'
@Model(card.class.MasterTag, core.class.Class)
export class TMasterTag extends TClass implements MasterTag {
color?: number
removed?: boolean
}
@Model(card.class.Tag, core.class.Mixin)
export class TTag extends TMixin implements Tag {}
export class TTag extends TMixin implements Tag {
color?: number
}
@Model(card.class.Card, core.class.Doc, DOMAIN_CARD)
@UX(card.string.Card, card.icon.Card)
@ -155,8 +158,14 @@ export function createModel (builder: Builder): void {
},
config: [
{ key: '', props: { showParent: true } },
'_class',
{ key: '', presenter: view.component.RolePresenter, label: card.string.Tags, props: { fullSize: true } },
{ key: '_class', displayProps: { fixed: 'left' } },
{
key: '',
presenter: view.component.RolePresenter,
label: card.string.Tags,
props: { fullSize: true },
displayProps: { fixed: 'left' }
},
{ key: '', displayProps: { grow: true } },
{
key: 'modifiedOn',

View File

@ -26,12 +26,10 @@
const client = getClient()
const hierarchy = client.getHierarchy()
$: hasDescription = !hierarchy.isDerived(doc._class, card.types.File)
$: isFile = hierarchy.isDerived(doc._class, card.types.File)
</script>
{#if hasDescription}
<Description {doc} {readonly} bind:content />
{:else if Object.keys(doc.blobs ?? {}).length === 0 && !readonly}
{#if isFile && Object.keys(doc.blobs ?? {}).length === 0 && !readonly}
<FilePlaceholder {doc} />
{/if}
@ -44,3 +42,5 @@
fit={blob.type !== 'application/pdf'}
/>
{/each}
<Description {doc} {readonly} bind:content minHeight={isFile ? '15vh' : '25vh'} />

View File

@ -28,6 +28,7 @@
export let doc: Card
export let readonly: boolean = false
export let content: HTMLElement
export let minHeight: '15vh' | '25vh' = '25vh'
const client = getClient()
@ -89,7 +90,7 @@
{readonly}
boundary={content}
overflow={'none'}
editorAttributes={{ style: 'padding: 0 2em 2em; margin: 0 -2em; min-height: 30vh' }}
editorAttributes={{ style: `padding: 0 2em 2em; margin: 0 -2em; min-height: ${minHeight}` }}
attachFile={async (file) => {
return await createEmbedding(file)
}}

View File

@ -16,6 +16,7 @@
-->
<script lang="ts">
import { Analytics } from '@hcengineering/analytics'
import { Attachments } from '@hcengineering/attachment-resources'
import { Card, CardEvents } from '@hcengineering/card'
import { Doc, Mixin, Ref, WithLookup } from '@hcengineering/core'
import notification from '@hcengineering/notification'
@ -165,6 +166,8 @@
<Childs object={doc} {readonly} />
<RelationsEditor object={doc} {readonly} />
<Attachments objectId={doc._id} _class={doc._class} space={doc.space} attachments={doc.attachments ?? 0} />
<svelte:fragment slot="utils">
{#if !readonly}
<Button

View File

@ -13,7 +13,7 @@
// limitations under the License.
-->
<script lang="ts">
import { Card } from '@hcengineering/card'
import { Card, MasterTag } from '@hcengineering/card'
import { getClient } from '@hcengineering/presentation'
import setting, { settingId } from '@hcengineering/setting'
import {
@ -23,12 +23,14 @@
getCurrentResolvedLocation,
Icon,
IconAdd,
IconWithEmoji,
Label,
navigate,
showPopup
} from '@hcengineering/ui'
import card from '../plugin'
import CardAttributes from './CardAttributes.svelte'
import view from '@hcengineering/view'
export let value: Card
export let readonly: boolean = false
@ -36,7 +38,8 @@
const client = getClient()
const hierarchy = client.getHierarchy()
$: label = hierarchy.getClass(value._class).label
$: clazz = hierarchy.getClass(value._class) as MasterTag
$: label = clazz.label
let isCollapsed = false
@ -51,7 +54,11 @@
<div class="header flex flex-gap-2">
<div class="label flex flex-gap-2" on:click={isCollapsed ? expand : collapse}>
<Icon icon={card.icon.MasterTag} size="large" />
<Icon
icon={clazz.icon === view.ids.IconWithEmoji ? IconWithEmoji : clazz.icon ?? card.icon.MasterTag}
iconProps={clazz.icon === view.ids.IconWithEmoji ? { icon: clazz.color } : {}}
size="large"
/>
<Label {label} />
<Chevron expanded={!isCollapsed} outline fill={'var(--content-color)'} />
</div>

View File

@ -13,57 +13,24 @@
// limitations under the License.
-->
<script lang="ts">
import { Card, MasterTag } from '@hcengineering/card'
import { fillDefaults } from '@hcengineering/core'
import { createQuery, getClient } from '@hcengineering/presentation'
import { DropdownLabelsIntl, Label } from '@hcengineering/ui'
import card from '../plugin'
import { Card } from '@hcengineering/card'
import { getClient } from '@hcengineering/presentation'
import { Label } from '@hcengineering/ui'
export let value: Card
let selected = value._class
$: selected = value._class
const clQuery = createQuery()
const client = getClient()
const hierarchy = client.getHierarchy()
let masterTags: MasterTag[] = []
$: items = masterTags.map((x) => ({
id: x._id,
label: x.label
}))
clQuery.query(card.class.MasterTag, { _class: card.class.MasterTag }, (res) => {
masterTags = res
})
async function select (event: CustomEvent): Promise<void> {
const _class = event.detail
const update = { _class } as any
selected = event.detail
await client.update(value, update)
const updated = fillDefaults(hierarchy, hierarchy.clone(value), _class)
await client.diffUpdate(value, updated)
}
$: label = hierarchy.getClass(selected).label
</script>
<div class="flex flex-gap-2 items-center item caption-color">
{#if value._class === card.class.Card}
<DropdownLabelsIntl
{items}
{selected}
disabled={value._class !== card.class.Card}
label={card.string.MasterTag}
on:selected={select}
/>
{:else}
<div class="tag">
<Label {label} />
</div>
{/if}
<div class="tag">
<Label {label} />
</div>
</div>
<style lang="scss">

View File

@ -16,10 +16,11 @@
import { MasterTag } from '@hcengineering/card'
import { Class, Doc, Ref } from '@hcengineering/core'
import { getClient } from '@hcengineering/presentation'
import { NavItem } from '@hcengineering/ui'
import { IconWithEmoji, NavItem } from '@hcengineering/ui'
import { NavLink } from '@hcengineering/view-resources'
import { createEventDispatcher } from 'svelte'
import card from '../plugin'
import view from '@hcengineering/view'
export let classes: MasterTag[] = []
export let allClasses: MasterTag[] = []
@ -59,7 +60,8 @@
<NavItem
_id={clazz._id}
label={clazz.label}
icon={clazz.icon}
icon={clazz.icon === view.ids.IconWithEmoji ? IconWithEmoji : clazz.icon}
iconProps={clazz.icon === view.ids.IconWithEmoji ? { icon: clazz.color } : {}}
isFold
empty
{level}

View File

@ -20,6 +20,7 @@
ButtonIcon,
getCurrentLocation,
IconDelete,
IconWithEmoji,
ModernEditbox,
navigate,
showPopup,
@ -29,6 +30,7 @@
import setting from '@hcengineering/setting'
import card from '../../plugin'
import { deleteMasterTag } from '../../utils'
import view from '@hcengineering/view'
export let masterTag: MasterTag
@ -61,12 +63,18 @@
}
function setIcon (): void {
showPopup(IconPicker, { icon: masterTag.icon, showEmoji: false, showColor: false }, 'top', async (res) => {
if (res !== undefined) {
await attributeUpdated('icon', res.icon)
masterTag.icon = res.icon
showPopup(
IconPicker,
{ icon: masterTag.icon, color: masterTag.color, showEmoji: true, showColor: false },
'top',
async (res) => {
if (res !== undefined) {
await client.update(masterTag, { icon: res.icon, color: res.color })
masterTag.icon = res.icon
masterTag.color = res.color
}
}
})
)
}
const h = client.getHierarchy()
@ -77,7 +85,8 @@
<div class="hulyComponent-content__header items-center">
<div class="flex items-center">
<ButtonIcon
icon={masterTag.icon ?? card.icon.MasterTag}
icon={masterTag.icon === view.ids.IconWithEmoji ? IconWithEmoji : masterTag.icon ?? card.icon.MasterTag}
iconProps={masterTag.icon === view.ids.IconWithEmoji ? { icon: masterTag.color, size: 'large' } : {}}
size={'large'}
iconSize={'large'}
kind={'tertiary'}

View File

@ -18,6 +18,7 @@ import type { AnyComponent } from '@hcengineering/ui'
export * from './analytics'
export interface MasterTag extends Class<Card> {
color?: number
removed?: boolean
}
@ -29,6 +30,7 @@ export interface Card extends Doc {
content: MarkupBlobRef
blobs: Blobs
children?: number
attachments?: number
parentInfo: ParentInfo[]
parent?: Ref<Card> | null
rank: Rank

View File

@ -24,7 +24,7 @@
</script>
{#if _class}
<div>
<div class="whitespace-nowrap">
<Label label={_class.label} />
</div>
{/if}

View File

@ -104,11 +104,16 @@
}
$: allowToCreate = isAllowedToCreate(association, docs, direction)
$: classLabel = client.getHierarchy().getClass(_class).label
</script>
<Section {label}>
<svelte:fragment slot="header">
<div class="buttons-group xsmall-gap">
{#if classLabel}
<Label label={classLabel} />
{/if}
{#if !readonly && allowToCreate}
<Button id={core.string.AddRelation} icon={IconAdd} kind={'ghost'} on:click={add} />
{/if}