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,14 +2,13 @@
<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" />
<path d="M20.5 11.0004C20.0055 11.0004 19.5222 11.147 19.1111 11.4217C18.6999 11.6964 18.3795 12.0868 18.1903 12.5437C18.0011 13.0005 17.9516 13.5031 18.048 13.9881C18.1445 14.473 18.3826 14.9185 18.7322 15.2681C19.0819 15.6178 19.5273 15.8559 20.0123 15.9523C20.4972 16.0488 20.9999 15.9993 21.4567 15.8101C21.9135 15.6208 22.304 15.3004 22.5787 14.8893C22.8534 14.4782 23 13.9948 23 13.5004C23.0027 13.1713 22.9398 12.845 22.8151 12.5405C22.6904 12.236 22.5064 11.9593 22.2737 11.7267C22.041 11.494 21.7644 11.3099 21.4599 11.1852C21.1553 11.0605 20.829 10.9977 20.5 11.0004Z" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.3431 20.243C10.7337 19.8525 11.3668 19.8525 11.7574 20.243C12.3145 20.8002 12.9759 21.2421 13.7039 21.5436C14.4319 21.8452 15.2121 22.0004 16 22.0004C16.7879 22.0004 17.5681 21.8452 18.2961 21.5436C19.0241 21.2421 19.6855 20.8002 20.2426 20.243C20.6332 19.8525 21.2663 19.8525 21.6569 20.243C22.0474 20.6335 22.0474 21.2667 21.6569 21.6572C20.914 22.4001 20.0321 22.9894 19.0615 23.3914C18.0909 23.7934 17.0506 24.0004 16 24.0004C14.9494 24.0004 13.9091 23.7934 12.9385 23.3914C11.9679 22.9894 11.086 22.4001 10.3431 21.6572C9.95262 21.2667 9.95262 20.6335 10.3431 20.243Z" />
</symbol>
<symbol id="bookmark" viewBox="0 0 20 28">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 4.00012C0 1.79098 1.79086 0.00012207 4 0.00012207H16C18.2091 0.00012207 20 1.79098 20 4.00012V27.0001C20 27.3689 19.797 27.7078 19.4719 27.8818C19.1467 28.0558 18.7522 28.0367 18.4453 27.8322L10 22.202L1.5547 27.8322C1.24784 28.0367 0.8533 28.0558 0.528142 27.8818C0.202985 27.7078 0 27.3689 0 27.0001V4.00012ZM4 2.00012C2.89543 2.00012 2 2.89555 2 4.00012V25.1316L9.4453 20.1681C9.7812 19.9441 10.2188 19.9441 10.5547 20.1681L18 25.1316V4.00012C18 2.89555 17.1046 2.00012 16 2.00012H4Z" />
</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" />
<path d="M20.5 11.0004C20.0055 11.0004 19.5222 11.147 19.1111 11.4217C18.6999 11.6964 18.3795 12.0868 18.1903 12.5437C18.0011 13.0005 17.9516 13.5031 18.048 13.9881C18.1445 14.473 18.3826 14.9185 18.7322 15.2681C19.0819 15.6178 19.5273 15.8559 20.0123 15.9523C20.4972 16.0488 20.9999 15.9993 21.4567 15.8101C21.9135 15.6208 22.304 15.3004 22.5787 14.8893C22.8534 14.4782 23 13.9948 23 13.5004C23.0027 13.1713 22.9398 12.845 22.8151 12.5405C22.6904 12.236 22.5064 11.9593 22.2737 11.7267C22.041 11.494 21.7644 11.3099 21.4599 11.1852C21.1553 11.0605 20.829 10.9977 20.5 11.0004Z" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.3431 20.243C10.7337 19.8525 11.3668 19.8525 11.7574 20.243C12.3145 20.8002 12.9759 21.2421 13.7039 21.5436C14.4319 21.8452 15.2121 22.0004 16 22.0004C16.7879 22.0004 17.5681 21.8452 18.2961 21.5436C19.0241 21.2421 19.6855 20.8002 20.2426 20.243C20.6332 19.8525 21.2663 19.8525 21.6569 20.243C22.0474 20.6335 22.0474 21.2667 21.6569 21.6572C20.914 22.4001 20.0321 22.9894 19.0615 23.3914C18.0909 23.7934 17.0506 24.0004 16 24.0004C14.9494 24.0004 13.9091 23.7934 12.9385 23.3914C11.9679 22.9894 11.086 22.4001 10.3431 21.6572C9.95262 21.2667 9.95262 20.6335 10.3431 20.243Z" />
</symbol>
<symbol id="bookmark" viewBox="0 0 20 28">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 4.00012C0 1.79098 1.79086 0.00012207 4 0.00012207H16C18.2091 0.00012207 20 1.79098 20 4.00012V27.0001C20 27.3689 19.797 27.7078 19.4719 27.8818C19.1467 28.0558 18.7522 28.0367 18.4453 27.8322L10 22.202L1.5547 27.8322C1.24784 28.0367 0.8533 28.0558 0.528142 27.8818C0.202985 27.7078 0 27.3689 0 27.0001V4.00012ZM4 2.00012C2.89543 2.00012 2 2.89555 2 4.00012V25.1316L9.4453 20.1681C9.7812 19.9441 10.2188 19.9441 10.5547 20.1681L18 25.1316V4.00012C18 2.89555 17.1046 2.00012 16 2.00012H4Z" />
</symbol>
</svg>

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)
$: if (srcDoc !== undefined) {
void getObjectPresenter(client, srcDoc._class, { key: '' }).then((result) => {
presenter = result
$: isActivityMessage(value) &&
client.findOne(value.attachedToClass, { _id: value.attachedTo }).then((res) => {
parentObject = res
})
}
</script>
{#if presenter}
<span class="labels-row">
<svelte:component this={presenter.presenter} value={srcDoc} {inline} embedded shouldShowAvatar={false} />
</span>
{/if}
<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,33 +42,40 @@
{#if inline && value}
<ObjectMention object={value} {disabled} {noUnderline} {onClick} component={tracker.component.EditIssue} />
{:else if value}
<div class="flex-row-center">
<DocNavLink
object={value}
{onClick}
{disabled}
{noUnderline}
{inline}
component={tracker.component.EditIssue}
shrink={0}
>
<span class="issuePresenterRoot" class:list={kind === 'list'} class:cursor-pointer={!disabled}>
{#if shouldShowAvatar}
<div class="icon" use:tooltip={{ label: tracker.string.Issue }}>
{#if taskType !== undefined}
<TaskTypeIcon value={taskType} />
{:else}
<Icon icon={icon ?? tracker.icon.Issues} size={'small'} />
{/if}
</div>
{/if}
<span class="overflow-label" class:select-text={!noSelect} title={value?.title}>
{value.identifier}
<slot name="details" />
{#if type === 'link'}
<div class="flex-row-center">
<DocNavLink
object={value}
{onClick}
{disabled}
{noUnderline}
{inline}
{colorInherit}
component={tracker.component.EditIssue}
shrink={0}
>
<span class="issuePresenterRoot" class:list={kind === 'list'} class:cursor-pointer={!disabled}>
{#if shouldShowAvatar}
<div class="icon" use:tooltip={{ label: tracker.string.Issue }}>
{#if taskType !== undefined}
<TaskTypeIcon value={taskType} />
{:else}
<Icon icon={icon ?? tracker.icon.Issues} size={'small'} />
{/if}
</div>
{/if}
<span class="overflow-label" class:select-text={!noSelect} title={value?.title}>
{value.identifier}
<slot name="details" />
</span>
</span>
</span>
</DocNavLink>
</div>
</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

@ -115,6 +115,9 @@
<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" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.7071 9.29326C21.0976 9.68378 21.0976 10.3169 20.7071 10.7075L12.7071 18.7075C12.3166 19.098 11.6834 19.098 11.2929 18.7075L7.29289 14.7075C6.90237 14.3169 6.90237 13.6838 7.29289 13.2933C7.68342 12.9027 8.31658 12.9027 8.70711 13.2933L12 16.5862L19.2929 9.29326C19.6834 8.90274 20.3166 8.90274 20.7071 9.29326Z" />

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'