UBERF-6464: update activity mentions display (#5339)

This commit is contained in:
Kristina 2024-04-16 18:13:18 +04:00 committed by GitHub
parent fb0194af3e
commit de6e0739c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 300 additions and 194 deletions

View File

@ -315,10 +315,6 @@ export function createModel (builder: Builder): void {
presenter: activity.component.ActivityReferencePreview
})
builder.mixin(activity.class.DocUpdateMessage, core.class.Class, view.mixin.LinkProvider, {
encode: activity.function.GetFragment
})
builder.createDoc(
activity.class.ActivityMessagesFilter,
core.space.Model,

View File

@ -16,7 +16,6 @@ import { activityId, type ActivityMessage, type DocUpdateMessageViewlet } from '
import activity from '@hcengineering/activity-resources/src/plugin'
import { type IntlString, mergeIds, type Resource } from '@hcengineering/platform'
import { type Doc, type Ref } from '@hcengineering/core'
import type { Location } from '@hcengineering/ui'
import { type ActionCategory } from '@hcengineering/view'
import { type NotificationGroup, type NotificationType } from '@hcengineering/notification'
@ -38,9 +37,6 @@ export default mergeIds(activityId, activity, {
ActivityNotificationGroup: '' as Ref<NotificationGroup>,
AddReactionNotification: '' as Ref<NotificationType>
},
function: {
GetFragment: '' as Resource<(doc: Doc, props: Record<string, any>) => Promise<Location>>
},
category: {
Activity: '' as Ref<ActionCategory>
}

View File

@ -398,6 +398,10 @@ export function createModel (builder: Builder, options = { addApplication: true
)
}
builder.mixin(activity.class.ActivityMessage, core.class.Class, view.mixin.LinkProvider, {
encode: chunter.function.GetMessageLink
})
builder.mixin(chunter.class.ThreadMessage, core.class.Class, view.mixin.LinkProvider, {
encode: chunter.function.GetThreadLink
})

View File

@ -100,6 +100,7 @@ export default mergeIds(chunterId, chunter, {
CanCopyMessageLink: '' as Resource<(doc?: Doc | Doc[]) => Promise<boolean>>,
GetChunterSpaceLinkFragment: '' as Resource<(doc: Doc, props: Record<string, any>) => Promise<Location>>,
GetThreadLink: '' as Resource<(doc: Doc, props: Record<string, any>) => Promise<Location>>,
GetMessageLink: '' as Resource<(doc: Doc, props: Record<string, any>) => Promise<Location>>,
ReplyToThread: '' as Resource<(doc: ActivityMessage) => Promise<void>>
},
filter: {

View File

@ -257,6 +257,10 @@ function defineDocument (builder: Builder): void {
encode: document.function.GetObjectLinkFragment
})
builder.mixin(document.class.Document, core.class.Class, view.mixin.ObjectIcon, {
component: document.component.DocumentIcon
})
// Actions
createAction(builder, {

View File

@ -30,7 +30,8 @@ export default mergeIds(documentId, document, {
NotificationDocumentPresenter: '' as AnyComponent,
TeamspaceSpacePresenter: '' as AnyComponent,
Move: '' as AnyComponent,
DocumentToDoPresenter: '' as AnyComponent
DocumentToDoPresenter: '' as AnyComponent,
DocumentIcon: '' as AnyComponent
},
completion: {
DocumentQuery: '' as Resource<ObjectSearchFactory>,

View File

@ -658,16 +658,6 @@
height: var(--global-extra-small-Size);
}
}
.hulyToDoLine-reference {
padding: 0 var(--spacing-1) 0 var(--spacing-0_75);
box-shadow: inset 0 0 0 1px var(--global-subtle-ui-BorderColor);
border-radius: var(--extra-small-BorderRadius);
background-color: var(--tag-nuance-SkyBackground);
&:hover {
box-shadow: inset 0 0 0 1px var(--global-ui-BorderColor);
}
}
&.hovered,
&:hover {

View File

@ -2,7 +2,6 @@
<symbol id="activity" viewBox="0 0 16 16">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13 2C12.4477 2 12 2.44772 12 3C12 3.55228 12.4477 4 13 4C13.5523 4 14 3.55228 14 3C14 2.44772 13.5523 2 13 2ZM11 3C11 1.89543 11.8954 1 13 1C14.1046 1 15 1.89543 15 3C15 4.10457 14.1046 5 13 5C11.8954 5 11 4.10457 11 3ZM2 4C2 2.89543 2.89543 2 4 2H9.5C9.77614 2 10 2.22386 10 2.5C10 2.77614 9.77614 3 9.5 3H4C3.44772 3 3 3.44772 3 4V12C3 12.5523 3.44772 13 4 13H12C12.5523 13 13 12.5523 13 12V6.5C13 6.22386 13.2239 6 13.5 6C13.7761 6 14 6.22386 14 6.5V12C14 13.1046 13.1046 14 12 14H4C2.89543 14 2 13.1046 2 12V4ZM6.64645 6.64645C6.84171 6.45118 7.15829 6.45118 7.35355 6.64645L9 8.29289L10.1464 7.14645C10.3417 6.95118 10.6583 6.95118 10.8536 7.14645C11.0488 7.34171 11.0488 7.65829 10.8536 7.85355L9.35355 9.35355C9.15829 9.54882 8.84171 9.54882 8.64645 9.35355L7 7.70711L5.85355 8.85355C5.65829 9.04882 5.34171 9.04882 5.14645 8.85355C4.95118 8.65829 4.95118 8.34171 5.14645 8.14645L6.64645 6.64645Z"/>
</symbol>
<symbol id="emoji" viewBox="0 0 32 32">
<path d="M16 2.00037C13.2311 2.00037 10.5243 2.82145 8.22201 4.35979C5.91973 5.89813 4.12531 8.08463 3.06569 10.6428C2.00606 13.201 1.72881 16.0159 2.269 18.7316C2.8092 21.4474 4.14257 23.9419 6.1005 25.8999C8.05844 27.8578 10.553 29.1912 13.2687 29.7314C15.9845 30.2716 18.7994 29.9943 21.3576 28.9347C23.9157 27.8751 26.1022 26.0806 27.6406 23.7783C29.1789 21.4761 30 18.7693 30 16.0004C30 12.2873 28.525 8.72638 25.8995 6.10087C23.274 3.47536 19.713 2.00037 16 2.00037ZM16 28.0004C13.6266 28.0004 11.3065 27.2966 9.33316 25.978C7.35977 24.6594 5.8217 22.7853 4.91344 20.5926C4.00519 18.3999 3.76755 15.9871 4.23058 13.6593C4.6936 11.3315 5.83649 9.19332 7.51472 7.51508C9.19295 5.83685 11.3311 4.69397 13.6589 4.23094C15.9867 3.76792 18.3995 4.00556 20.5922 4.91381C22.7849 5.82206 24.6591 7.36013 25.9776 9.33352C27.2962 11.3069 28 13.627 28 16.0004C28 19.183 26.7357 22.2352 24.4853 24.4856C22.2348 26.7361 19.1826 28.0004 16 28.0004Z" />
<path d="M11.5 11.0004C11.0055 11.0004 10.5222 11.147 10.1111 11.4217C9.69995 11.6964 9.37952 12.0868 9.1903 12.5437C9.00108 13.0005 8.95157 13.5031 9.04804 13.9881C9.1445 14.473 9.3826 14.9185 9.73223 15.2681C10.0819 15.6178 10.5273 15.8559 11.0123 15.9523C11.4972 16.0488 11.9999 15.9993 12.4567 15.8101C12.9135 15.6208 13.304 15.3004 13.5787 14.8893C13.8534 14.4782 14 13.9948 14 13.5004C14.0027 13.1713 13.9398 12.845 13.8151 12.5405C13.6904 12.236 13.5064 11.9593 13.2737 11.7267C13.041 11.494 12.7644 11.3099 12.4599 11.1852C12.1553 11.0605 11.829 10.9977 11.5 11.0004Z" />

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -562,19 +562,6 @@ export async function getLinkData (
}
}
export async function getMessageFragment (doc: Doc): Promise<string> {
const client = getClient()
const hierarchy = client.getHierarchy()
let clazz = hierarchy.getClass(doc._class)
let label = clazz.shortLabel
while (label === undefined && clazz.extends !== undefined) {
clazz = hierarchy.getClass(clazz.extends)
label = clazz.shortLabel
}
label = label ?? doc._class
return `${label}-${doc._id}`
}
function isDocUpdateMessage (message?: ActivityMessage): message is DocUpdateMessage {
if (message === undefined) {
return false
@ -583,6 +570,14 @@ function isDocUpdateMessage (message?: ActivityMessage): message is DocUpdateMes
return message._class === activity.class.DocUpdateMessage
}
export function isActivityMessage (message?: Doc): message is ActivityMessage {
if (message === undefined) {
return false
}
return getClient().getHierarchy().isDerived(message._class, activity.class.ActivityMessage)
}
export function isReactionMessage (message?: ActivityMessage): boolean {
if (message === undefined) {
return false

View File

@ -110,6 +110,7 @@
{skipLabel}
{hoverable}
{hoverStyles}
showDatePreposition
{onClick}
{onReply}
>
@ -131,13 +132,8 @@
{/if}
{#if srcDoc}
<span class="text-sm lower"><Label label={activity.string.In} /></span>
<DocNavLink object={srcDoc} component={srcDocPanel?.component ?? view.component.EditDoc} shrink={0}>
<span class="text-sm">
<ReferenceSrcPresenter
{value}
inline={hierarchy.isDerived(srcDoc._class, activity.class.ActivityMessage)}
/>
</span>
<DocNavLink object={srcDoc} component={srcDocPanel?.component ?? view.component.EditDoc} shrink={0} noUnderline>
<ReferenceSrcPresenter value={srcDoc} />
</DocNavLink>
{/if}
</span>
@ -151,6 +147,8 @@
<style lang="scss">
.header {
gap: var(--global-spacing-1);
display: flex;
align-items: center;
gap: var(--spacing-0_5);
}
</style>

View File

@ -14,33 +14,36 @@
-->
<script lang="ts">
import type { Doc } from '@hcengineering/core'
import { createQuery, getClient } from '@hcengineering/presentation'
import { AttributeModel } from '@hcengineering/view'
import { getObjectPresenter } from '@hcengineering/view-resources'
import { ActivityReference } from '@hcengineering/activity'
import { getClient } from '@hcengineering/presentation'
import { DocReferencePresenter } from '@hcengineering/view-resources'
import activity from '../../plugin'
export let value: ActivityReference
export let inline = true
import { isActivityMessage } from '../../activityMessagesUtils'
import view from '@hcengineering/view'
import { Icon, Label } from '@hcengineering/ui'
export let value: Doc | undefined
const client = getClient()
const srcDocQuery = createQuery()
let srcDoc: Doc | undefined
let presenter: AttributeModel | undefined
let parentObject: Doc | undefined
$: srcDocQuery.query(value.srcDocClass, { _id: value.srcDocId }, (r) => {
srcDoc = r.shift()
$: showParent = isActivityMessage(value)
$: isActivityMessage(value) &&
client.findOne(value.attachedToClass, { _id: value.attachedTo }).then((res) => {
parentObject = res
})
$: if (srcDoc !== undefined) {
void getObjectPresenter(client, srcDoc._class, { key: '' }).then((result) => {
presenter = result
})
}
</script>
{#if presenter}
<span class="labels-row">
<svelte:component this={presenter.presenter} value={srcDoc} {inline} embedded shouldShowAvatar={false} />
<DocReferencePresenter value={showParent ? parentObject : value} compact={showParent}>
<svelte:fragment slot="prefix">
{#if showParent}
<span class="nowrap flex-presenter flex-gap-1 lower ml-2">
<Icon icon={view.icon.Bubble} size="x-small" />
<Label label={activity.string.Thread} />
<Label label={activity.string.In} />
</span>
{/if}
</svelte:fragment>
</DocReferencePresenter>

View File

@ -26,13 +26,7 @@ import DocUpdateMessagePreview from './components/doc-update-message/DocUpdateMe
import ActivityReferencePreview from './components/activity-reference/ActivityReferencePreview.svelte'
import ActivityInfoMessagePreview from './components/activity-info-message/ActivityInfoMessagePreview.svelte'
import {
getMessageFragment,
attributesFilter,
pinnedFilter,
allFilter,
referencesFilter
} from './activityMessagesUtils'
import { attributesFilter, pinnedFilter, allFilter, referencesFilter } from './activityMessagesUtils'
import { updateReferences } from './references'
export * from './activity'
@ -76,9 +70,6 @@ export default async (): Promise<Resources> => ({
AllFilter: allFilter,
ReferencesFilter: referencesFilter
},
function: {
GetFragment: getMessageFragment
},
backreference: {
Update: updateReferences
}

View File

@ -15,19 +15,22 @@
<script lang="ts">
import { Channel, chunterId } from '@hcengineering/chunter'
import { getClient } from '@hcengineering/presentation'
import { Icon } from '@hcengineering/ui'
import { Icon, tooltip } from '@hcengineering/ui'
import { NavLink } from '@hcengineering/view-resources'
import { getEmbeddedLabel } from '@hcengineering/platform'
import { ObjectPresenterType } from '@hcengineering/view'
export let value: Channel
export let inline: boolean = false
export let shouldShowAvatar = true
export let type: ObjectPresenterType = 'link'
const client = getClient()
$: icon = client.getHierarchy().getClass(value._class).icon
</script>
{#if value}
{#if value && type === 'link'}
<NavLink app={chunterId} space={value._id}>
<div class="flex-presenter">
{#if !inline && shouldShowAvatar}
@ -41,3 +44,7 @@
</div>
</NavLink>
{/if}
{#if value && type === 'text'}
<span class="overflow-label" use:tooltip={{ label: getEmbeddedLabel(value.name) }}>{value.name}</span>
{/if}

View File

@ -64,7 +64,13 @@ import {
leaveChannelAction,
removeChannelAction
} from './utils'
import { chunterSpaceLinkFragmentProvider, getThreadLink, getMessageLink, replyToThread } from './navigation'
import {
chunterSpaceLinkFragmentProvider,
getThreadLink,
getMessageLink,
replyToThread,
getMessageLocation
} from './navigation'
export { default as ChatMessagesPresenter } from './components/chat-message/ChatMessagesPresenter.svelte'
export { default as ChatMessagePopup } from './components/chat-message/ChatMessagePopup.svelte'
@ -191,6 +197,7 @@ export default async (): Promise<Resources> => ({
GetChunterSpaceLinkFragment: chunterSpaceLinkFragmentProvider,
GetUnreadThreadsCount: getUnreadThreadsCount,
GetThreadLink: getThreadLink,
GetMessageLink: getMessageLocation,
ReplyToThread: replyToThread
},
actionImpl: {

View File

@ -137,3 +137,9 @@ export async function replyToThread (message: ActivityMessage): Promise<void> {
navigate(buildThreadLink(loc, message.attachedTo, message.attachedToClass, message._id))
}
export async function getMessageLocation (doc: ActivityMessage): Promise<Location> {
const loc = getCurrentResolvedLocation()
return buildThreadLink(loc, doc.attachedTo, doc.attachedToClass, doc._id)
}

View File

@ -18,6 +18,7 @@
import { getEmbeddedLabel } from '@hcengineering/platform'
import { tooltip } from '@hcengineering/ui'
import { DocNavLink, ObjectMention } from '@hcengineering/view-resources'
import { ObjectPresenterType } from '@hcengineering/view'
import contact from '../plugin'
import Company from './icons/Company.svelte'
@ -28,6 +29,7 @@
export let accent: boolean = false
export let noUnderline: boolean = false
export let maxWidth = ''
export let type: ObjectPresenterType = 'link'
</script>
{#if value}
@ -39,7 +41,7 @@
{noUnderline}
component={contact.component.EditOrganizationPanel}
/>
{:else}
{:else if type === 'link'}
<DocNavLink {disabled} object={value} {accent} {noUnderline} component={contact.component.EditOrganizationPanel}>
<div class="flex-presenter" style:max-width={maxWidth} use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
<div class="icon circle">
@ -50,5 +52,7 @@
>
</div>
</DocNavLink>
{:else if type === 'text'}
<span class="overflow-label" use:tooltip={{ label: getEmbeddedLabel(value.name) }}>{value.name}</span>
{/if}
{/if}

View File

@ -26,6 +26,7 @@
tooltip
} from '@hcengineering/ui'
import { createEventDispatcher, onMount } from 'svelte'
import { ObjectPresenterType } from '@hcengineering/view'
import Avatar from './Avatar.svelte'
import PersonElement from './PersonElement.svelte'
@ -47,6 +48,7 @@
export let accent: boolean = false
export let maxWidth = ''
export let compact = false
export let type: ObjectPresenterType = 'link'
const client = getClient()
@ -87,6 +89,7 @@
{enlargedText}
{colorInherit}
{accent}
{type}
{maxWidth}
/>
<span class="status">
@ -108,6 +111,7 @@
{enlargedText}
{colorInherit}
{accent}
{type}
{maxWidth}
/>
{/if}

View File

@ -16,6 +16,7 @@
import { Employee, Person } from '@hcengineering/contact'
import { IconSize, LabelAndProps, tooltip } from '@hcengineering/ui'
import { DocNavLink, ObjectMention } from '@hcengineering/view-resources'
import { ObjectPresenterType } from '@hcengineering/view'
import Avatar from './Avatar.svelte'
export let value: Person | Employee | undefined | null
@ -32,12 +33,13 @@
export let colorInherit: boolean = false
export let accent: boolean = false
export let maxWidth: string = ''
export let type: ObjectPresenterType = 'link'
</script>
{#if value}
{#if inline}
<ObjectMention object={value} {disabled} {accent} {noUnderline} {colorInherit} onClick={onEdit} />
{:else}
{:else if type === 'link'}
<DocNavLink object={value} onClick={onEdit} {disabled} {noUnderline} {colorInherit} {accent} noOverflow>
<span
use:tooltip={disabled ? undefined : showTooltip}
@ -61,5 +63,9 @@
{/if}
</span>
</DocNavLink>
{:else if type === 'text'}
<span class="overflow-label" use:tooltip={disabled ? undefined : showTooltip}>
{name}
</span>
{/if}
{/if}

View File

@ -21,6 +21,7 @@
import { getClient } from '@hcengineering/presentation'
import { Ref } from '@hcengineering/core'
import ui from '@hcengineering/ui'
import { ObjectPresenterType } from '@hcengineering/view'
export let value: Ref<Person> | Person | null | undefined
export let inline = false
@ -40,6 +41,7 @@
export let accent: boolean = false
export let maxWidth = ''
export let compact = false
export let type: ObjectPresenterType = 'link'
const client = getClient()
$: personValue = typeof value === 'string' ? $personByIdStore.get(value) : value
@ -94,6 +96,7 @@
{accent}
{maxWidth}
{compact}
{type}
on:accent-color
/>
{/if}

View File

@ -19,6 +19,7 @@
import { Document } from '@hcengineering/document'
import { tooltip } from '@hcengineering/ui'
import { DocNavLink, ObjectMention } from '@hcengineering/view-resources'
import { ObjectPresenterType } from '@hcengineering/view'
import document from '../plugin'
import DocumentIcon from './DocumentIcon.svelte'
@ -31,12 +32,13 @@
export let breadcrumb: boolean = false
export let maxWidth = ''
export let shouldShowAvatar = true
export let type: ObjectPresenterType = 'link'
</script>
{#if value}
{#if inline}
<ObjectMention object={value} {disabled} {accent} {noUnderline} component={document.component.EditDoc} />
{:else}
{:else if type === 'link'}
<DocNavLink {disabled} object={value} {accent} {noUnderline} component={document.component.EditDoc}>
<div
class="flex-presenter"
@ -54,5 +56,9 @@
</span>
</div>
</DocNavLink>
{:else if type === 'text'}
<span class="overflow-label" use:tooltip={{ label: document.string.Document }}>
{value.name}
</span>
{/if}
{/if}

View File

@ -43,6 +43,7 @@ import DocumentSearchIcon from './components/DocumentSearchIcon.svelte'
import NotificationDocumentPresenter from './components/NotificationDocumentPresenter.svelte'
import Move from './components/Move.svelte'
import DocumentToDoPresenter from './components/DocumentToDoPresenter.svelte'
import DocumentIcon from './components/DocumentIcon.svelte'
import document from './plugin'
import { createEmptyDocument, documentTitleProvider, getDocumentLink, getDocumentUrl, resolveLocation } from './utils'
@ -135,7 +136,8 @@ export default async (): Promise<Resources> => ({
DocumentSearchIcon,
NotificationDocumentPresenter,
Move,
DocumentToDoPresenter
DocumentToDoPresenter,
DocumentIcon
},
completion: {
DocumentQuery: async (

View File

@ -15,9 +15,11 @@
-->
<script lang="ts">
import type { Lead } from '@hcengineering/lead'
import { Icon } from '@hcengineering/ui'
import { Icon, tooltip } from '@hcengineering/ui'
import { DocNavLink, ObjectMention } from '@hcengineering/view-resources'
import lead from '@hcengineering/lead'
import { getEmbeddedLabel } from '@hcengineering/platform'
import { ObjectPresenterType } from '@hcengineering/view'
export let value: Lead
export let inline: boolean = false
@ -25,12 +27,13 @@
export let accent: boolean = false
export let noUnderline: boolean = false
export let shouldShowAvatar: boolean = true
export let type: ObjectPresenterType = 'link'
</script>
{#if value}
{#if inline}
<ObjectMention object={value} {disabled} {noUnderline} {accent} />
{:else}
{:else if type === 'link'}
<DocNavLink object={value} {disabled} {noUnderline} {accent}>
<div class="flex-presenter">
{#if shouldShowAvatar}
@ -41,5 +44,7 @@
>
</div>
</DocNavLink>
{:else if type === 'text'}
<span class="overflow-label" use:tooltip={{ label: getEmbeddedLabel(value.title) }}>{value.identifier}</span>
{/if}
{/if}

View File

@ -15,9 +15,9 @@
-->
<script lang="ts">
import { getClient } from '@hcengineering/presentation'
import type { Applicant } from '@hcengineering/recruit'
import recruit from '@hcengineering/recruit'
import { Icon } from '@hcengineering/ui'
import recruit, { Applicant } from '@hcengineering/recruit'
import { Icon, tooltip } from '@hcengineering/ui'
import { ObjectPresenterType } from '@hcengineering/view'
import { DocNavLink, ObjectMention } from '@hcengineering/view-resources'
export let value: Applicant
@ -26,15 +26,17 @@
export let noUnderline: boolean = false
export let accent: boolean = false
export let shouldShowAvatar: boolean = true
export let type: ObjectPresenterType = 'link'
const client = getClient()
const shortLabel = value && client.getHierarchy().getClass(value._class).shortLabel
const clazz = value && client.getHierarchy().getClass(value._class)
const shortLabel = clazz?.shortLabel
</script>
{#if value && shortLabel}
{#if inline}
<ObjectMention object={value} {disabled} {noUnderline} {accent} />
{:else}
{:else if type === 'link'}
<DocNavLink object={value} {disabled} {noUnderline} {accent}>
<div class="flex-presenter">
{#if shouldShowAvatar}
@ -47,5 +49,9 @@
</span>
</div>
</DocNavLink>
{:else if type === 'text'}
<span class="overflow-label" use:tooltip={{ label: clazz.label }}>
{#if shortLabel}{shortLabel}-{/if}{value.number}
</span>
{/if}
{/if}

View File

@ -19,6 +19,7 @@
import { Icon, getPlatformAvatarColorForTextDef, themeStore, tooltip } from '@hcengineering/ui'
import { DocNavLink, ObjectMention } from '@hcengineering/view-resources'
import { createEventDispatcher, onMount } from 'svelte'
import { ObjectPresenterType } from '@hcengineering/view'
import recruit from '../plugin'
@ -27,6 +28,7 @@
export let disabled: boolean = false
export let accent: boolean = false
export let noUnderline: boolean = false
export let type: ObjectPresenterType = 'link'
const dispatch = createEventDispatcher()
$: accentColor = getPlatformAvatarColorForTextDef(value.name, $themeStore.dark)
@ -40,7 +42,7 @@
{#if value}
{#if inline}
<ObjectMention object={value} {disabled} {accent} {noUnderline} component={recruit.component.EditVacancy} />
{:else}
{:else if type === 'link'}
<DocNavLink {disabled} object={value} {accent} {noUnderline} component={recruit.component.EditVacancy}>
<div class="flex-presenter" use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
<div class="icon"><Icon icon={recruit.icon.Vacancy} size={'small'} /></div>
@ -49,5 +51,9 @@
</span>
</div>
</DocNavLink>
{:else if type === 'text'}
<span class="overflow-label" use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
{value.name}
</span>
{/if}
{/if}

View File

@ -1,37 +0,0 @@
<!--
// Copyright © 2024 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">
export let label: string
</script>
<button class="hulyToDoLine-reference flex-row-top flex-no-shrink flex-gap-2" on:click>
<div class="hulyToDoLine-icon">
<slot name="icon" />
</div>
<span class="hulyToDoLine-label overflow-label font-medium-12 text-left max-w-20 secondary-textColor">
{label}
</span>
<slot />
</button>
<style lang="scss">
button {
margin: 0;
padding: 0;
text-align: left;
border: none;
outline: none;
}
</style>

View File

@ -14,28 +14,11 @@
-->
<script lang="ts">
import type { Document } from '@hcengineering/document'
import { Icon, IconWithEmoji, getPlatformColorDef, themeStore } from '@hcengineering/ui'
import document from '@hcengineering/document'
import view from '@hcengineering/view'
import ToDoReference from '../ToDoReference.svelte'
import { DocReferencePresenter } from '@hcengineering/view-resources'
export let value: Document
export let inline: boolean = false
export let disabled: boolean = false
export let withoutSpace: boolean = true
$: icon = value.icon === view.ids.IconWithEmoji ? IconWithEmoji : value.icon ?? document.icon.Document
$: iconProps =
value.icon === view.ids.IconWithEmoji
? { icon: value.color }
: {
fill: value.color !== undefined ? getPlatformColorDef(value.color, $themeStore.dark).icon : 'currentColor'
}
</script>
<ToDoReference label={value.name} on:click>
<svelte:fragment slot="icon">
<Icon size="small" {icon} {iconProps} />
</svelte:fragment>
<DocReferencePresenter {value} on:click>
<slot />
</ToDoReference>
</DocReferencePresenter>

View File

@ -1,20 +1,10 @@
<script lang="ts">
import { Issue } from '@hcengineering/tracker'
import { IssueStatusIcon } from '@hcengineering/tracker-resources'
import { statusStore } from '@hcengineering/view-resources'
import ToDoReference from '../ToDoReference.svelte'
import { DocReferencePresenter } from '@hcengineering/view-resources'
export let value: Issue
export let inline: boolean = false
export let disabled: boolean = false
export let withoutSpace: boolean = true
$: status = $statusStore.byId.get(value.status)
</script>
<ToDoReference label={value.identifier} on:click>
<svelte:fragment slot="icon">
<IssueStatusIcon size="small" value={status} space={value.space} />
</svelte:fragment>
<DocReferencePresenter {value} on:click>
<slot />
</ToDoReference>
</DocReferencePresenter>

View File

@ -14,12 +14,13 @@
-->
<script lang="ts">
import { WithLookup } from '@hcengineering/core'
import { Asset } from '@hcengineering/platform'
import { Asset, getEmbeddedLabel } from '@hcengineering/platform'
import { taskTypeStore } from '@hcengineering/task-resources'
import TaskTypeIcon from '@hcengineering/task-resources/src/components/taskTypes/TaskTypeIcon.svelte'
import type { Issue } from '@hcengineering/tracker'
import { AnySvelteComponent, Icon, tooltip } from '@hcengineering/ui'
import { DocNavLink, ObjectMention } from '@hcengineering/view-resources'
import { ObjectPresenterType } from '@hcengineering/view'
import tracker from '../../plugin'
@ -28,9 +29,11 @@
export let onClick: (() => void) | undefined = undefined
export let shouldShowAvatar: boolean = false
export let noUnderline: boolean = disabled
export let colorInherit: boolean = false
export let noSelect: boolean = false
export let inline = false
export let kind: 'list' | undefined = undefined
export let type: ObjectPresenterType = 'link'
export let icon: Asset | AnySvelteComponent | undefined = undefined
$: taskType = value !== undefined ? $taskTypeStore.get(value.kind) : undefined
@ -39,6 +42,7 @@
{#if inline && value}
<ObjectMention object={value} {disabled} {noUnderline} {onClick} component={tracker.component.EditIssue} />
{:else if value}
{#if type === 'link'}
<div class="flex-row-center">
<DocNavLink
object={value}
@ -46,6 +50,7 @@
{disabled}
{noUnderline}
{inline}
{colorInherit}
component={tracker.component.EditIssue}
shrink={0}
>
@ -66,6 +71,11 @@
</span>
</DocNavLink>
</div>
{:else if value && type === 'text'}
<span class="overflow-label" class:select-text={!noSelect} use:tooltip={{ label: getEmbeddedLabel(value.title) }}>
{value.identifier}
</span>
{/if}
{/if}
<style lang="scss">

View File

@ -114,6 +114,9 @@
<path fill-rule="evenodd" clip-rule="evenodd" d="M28.2929 2.29277C28.6834 1.90225 29.3166 1.90225 29.7071 2.29277C30.0976 2.6833 30.0976 3.31646 29.7071 3.70698L25.2001 8.21985C27.7981 10.0869 29.7934 12.6731 30.9401 15.6598C31.0195 15.8796 31.0195 16.1201 30.9401 16.3398C29.7639 19.3822 27.722 22.0132 25.0669 23.9078C22.4117 25.8023 19.2595 26.8773 16.0001 26.9998C13.3641 26.9573 10.7839 26.2339 8.51006 24.8998L3.70724 29.707C3.31672 30.0975 2.68355 30.0975 2.29303 29.707C1.90251 29.3164 1.90251 28.6833 2.29303 28.2928L28.2929 2.29277ZM20.0001 15.9998C19.9959 16.7 19.808 17.3867 19.4552 17.9914C19.1024 18.5961 18.597 19.0977 17.9897 19.4459C17.3823 19.7941 16.6942 19.9768 15.9941 19.9758C15.2939 19.9747 14.6064 19.7899 14.0001 19.4398L19.4401 13.9998C19.7996 14.6056 19.9927 15.2955 20.0001 15.9998ZM16.0001 24.9998C13.9021 24.9632 11.844 24.4212 10.0001 23.4198L12.5401 20.8798C13.6954 21.6815 15.0956 22.0519 16.4962 21.9263C17.8968 21.8008 19.2088 21.1873 20.2031 20.1929C21.1975 19.1986 21.811 17.8866 21.9365 16.486C22.0621 15.0854 21.6917 13.6852 20.8901 12.5298L23.7601 9.65985C26.0547 11.2348 27.849 13.4353 28.9301 15.9998C26.9001 21.0698 21.3001 24.9998 16.0001 24.9998Z"/>
<path d="M6.67006 21.0898L5.24006 22.5098C3.38049 20.8109 1.94831 18.6969 1.06006 16.3398C0.98063 16.1201 0.98063 15.8796 1.06006 15.6598C2.23622 12.6175 4.27808 9.98646 6.93326 8.09193C9.58845 6.1974 12.7406 5.12242 16.0001 4.99985C17.9078 5.0232 19.7927 5.41717 21.5501 6.15985L20.0001 7.71985C18.7155 7.26113 17.364 7.01785 16.0001 6.99985C10.7001 6.99985 5.10006 10.9298 3.07006 15.9998C3.87404 17.9445 5.10428 19.684 6.67006 21.0898Z" />
<path d="M13.1611 13.1909C12.4818 13.8703 12.0696 14.7716 12.0001 15.7298L10.1801 17.5399C9.91301 16.5256 9.91648 15.4591 10.1901 14.4466C10.4638 13.4341 10.998 12.5111 11.7397 11.7694C12.4813 11.0278 13.4043 10.4936 14.4168 10.2199C15.4293 9.94626 16.4958 9.94279 17.5101 10.2098L15.7001 12.0299C14.7418 12.0994 13.8405 12.5115 13.1611 13.1909Z" />
</symbol>
<symbol id="bubble" viewBox="0 0 28 24">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14 2.00012C7.20948 2.00012 2 6.62735 2 12.0001C2 14.1621 2.82539 16.1784 4.25857 17.8354C4.48585 18.0982 4.56044 18.4602 4.45559 18.7914C4.11025 19.8823 3.59859 20.905 2.96437 21.8563C4.36749 21.6498 5.72455 21.2237 6.98685 20.5983C7.26684 20.4596 7.59558 20.4598 7.87546 20.5987C9.66322 21.4863 11.7558 22.0001 14 22.0001C20.7905 22.0001 26 17.3729 26 12.0001C26 6.62735 20.7905 2.00012 14 2.00012ZM1.55557e-06 12.0001C1.55557e-06 5.22263 6.43112 0.00012207 14 0.00012207C21.5689 0.00012207 28 5.22263 28 12.0001C28 18.7776 21.5689 24.0001 14 24.0001C11.6319 24.0001 9.39442 23.4964 7.43078 22.6017C5.4311 23.5145 3.24057 24.0001 1 24.0001C0.631206 24.0001 0.292346 23.7971 0.118327 23.472C-0.0556921 23.1468 -0.0366195 22.7523 0.167951 22.4454L1.37487 20.635C1.78033 20.0268 2.11535 19.375 2.37375 18.6921C0.884016 16.7926 1.55557e-06 14.4912 1.55557e-06 12.0001Z" />
</symbol>
<symbol id="check-circle" viewBox="0 0 32 32">
<path d="M14 0.00012207C11.2311 0.00012207 8.52431 0.821208 6.22202 2.35955C3.91973 3.89789 2.12532 6.08439 1.06569 8.64255C0.00606596 11.2007 -0.271181 14.0157 0.269012 16.7314C0.809205 19.4471 2.14258 21.9417 4.10051 23.8996C6.05845 25.8576 8.55301 27.1909 11.2687 27.7311C13.9845 28.2713 16.7994 27.9941 19.3576 26.9344C21.9157 25.8748 24.1022 24.0804 25.6406 21.7781C27.1789 19.4758 28 16.7691 28 14.0001C28 10.2871 26.525 6.72614 23.8995 4.10063C21.274 1.47512 17.713 0.00012207 14 0.00012207ZM14 26.0001C11.6266 26.0001 9.30655 25.2963 7.33316 23.9778C5.35977 22.6592 3.8217 20.785 2.91345 18.5923C2.0052 16.3996 1.76756 13.9868 2.23058 11.659C2.69361 9.33127 3.83649 7.19307 5.51472 5.51484C7.19296 3.83661 9.33115 2.69372 11.6589 2.2307C13.9867 1.76768 16.3995 2.00532 18.5922 2.91357C20.7849 3.82182 22.6591 5.35989 23.9776 7.33328C25.2962 9.30667 26 11.6267 26 14.0001C26 17.1827 24.7357 20.235 22.4853 22.4854C20.2348 24.7358 17.1826 26.0001 14 26.0001Z" />

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -44,6 +44,7 @@ loadMetadata(view.icon, {
Star: `${icons}#star`,
Eye: `${icons}#eye`,
EyeCrossed: `${icons}#eye-crossed`,
Bubble: `${icons}#bubble`,
CheckCircle: `${icons}#check-circle`,
Add: `${icons}#add`,
Image: `${icons}#image`,

View File

@ -0,0 +1,111 @@
<!--
// Copyright © 2024 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 type { Doc } from '@hcengineering/core'
import { getClient } from '@hcengineering/presentation'
import view, { AttributeModel } from '@hcengineering/view'
import { Component, Icon, IconSize } from '@hcengineering/ui'
import contact from '@hcengineering/contact'
import { classIcon, getObjectPresenter } from '../utils'
export let value: Doc | undefined
export let compact = false
const client = getClient()
const hierarchy = client.getHierarchy()
let presenter: AttributeModel | undefined
let size: IconSize = 'small'
$: if (value !== undefined) {
void getObjectPresenter(client, value._class, { key: '' }).then((result) => {
presenter = result
})
}
$: iconMixin = value && hierarchy.classHierarchyMixin(value._class, view.mixin.ObjectIcon)
$: if (value && hierarchy.isDerived(value._class, contact.class.Person)) {
size = 'tiny'
} else {
size = 'small'
}
</script>
<button class="reference flex-row-top flex-no-shrink flex-gap-2" class:compact on:click>
<span class="label overflow-label font-medium-12 text-left secondary-textColor">
<slot name="prefix" />
</span>
<div class="icon">
{#if iconMixin && value}
<Component is={iconMixin.component} props={{ value, size }} />
{:else if !iconMixin && value}
<Icon icon={classIcon(client, value._class) ?? view.icon.Views} {size} />
{/if}
</div>
<span class="label overflow-label font-medium-12 text-left max-w-20 secondary-textColor">
{#if presenter && value}
<svelte:component
this={presenter.presenter}
{value}
embedded
shouldShowAvatar={false}
noUnderline
disabled
colorInherit
type="text"
/>
{/if}
</span>
<slot />
</button>
<style lang="scss">
.reference {
padding: 0 var(--spacing-1) 0 0;
box-shadow: inset 0 0 0 1px var(--global-subtle-ui-BorderColor);
border-radius: var(--extra-small-BorderRadius);
background-color: var(--tag-nuance-SkyBackground);
&.compact {
gap: var(--spacing-0_5);
}
&:hover {
box-shadow: inset 0 0 0 1px var(--global-ui-BorderColor);
}
}
.icon {
display: flex;
justify-content: center;
align-items: center;
flex-shrink: 0;
width: var(--global-min-Size);
height: var(--global-extra-small-Size);
}
.label {
flex-grow: 1;
flex-shrink: 1;
padding-top: var(--spacing-0_5);
color: var(--global-secondary-TextColor);
&:not(.large) {
height: var(--global-extra-small-Size);
}
}
</style>

View File

@ -91,6 +91,7 @@ import UpDownNavigator from './components/UpDownNavigator.svelte'
import ValueSelector from './components/ValueSelector.svelte'
import ViewletContentView from './components/ViewletContentView.svelte'
import ViewletSettingButton from './components/ViewletSettingButton.svelte'
import DocReferencePresenter from './components/DocReferencePresenter.svelte'
import {
afterResult,
@ -201,7 +202,8 @@ export {
TreeNode,
UpDownNavigator,
ViewletContentView,
ViewletSettingButton
ViewletSettingButton,
DocReferencePresenter
}
function PositionElementAlignment (e?: Event): PopupAlignment | undefined {

View File

@ -223,6 +223,7 @@ const view = plugin(viewId, {
Star: '' as Asset,
Eye: '' as Asset,
EyeCrossed: '' as Asset,
Bubble: '' as Asset,
CheckCircle: '' as Asset,
Add: '' as Asset,
Image: '' as Asset,

View File

@ -778,3 +778,5 @@ export interface IconProps {
icon?: Asset
color?: number
}
export type ObjectPresenterType = 'link' | 'text'