mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-09 11:17:43 +02:00
Fix inbox ui (#9688)
This commit is contained in:
+1
-1
Submodule communication updated: 5a3d9e7076...f7d1b98df4
@@ -28,7 +28,8 @@ export function buildApplets (builder: Builder): void {
|
||||
createLabel: communication.string.CreatePoll,
|
||||
createComponent: communication.poll.CreatePoll,
|
||||
previewComponent: communication.poll.PollPreview,
|
||||
createFn: communication.poll.CreatePollFn
|
||||
createFn: communication.poll.CreatePollFn,
|
||||
getTitleFn: communication.poll.GetPollTitleFn
|
||||
},
|
||||
communication.ids.PollApplet
|
||||
)
|
||||
|
||||
@@ -24,7 +24,8 @@ import {
|
||||
type PollAnswer,
|
||||
type Poll,
|
||||
type CustomActivityPresenter,
|
||||
type GuestCommunicationSettings
|
||||
type GuestCommunicationSettings,
|
||||
type AppletGetTitleFnResource
|
||||
} from '@hcengineering/communication'
|
||||
import { PaletteColorIndexes } from '@hcengineering/ui/src/colors'
|
||||
import { type AppletType } from '@hcengineering/communication-types'
|
||||
@@ -58,6 +59,7 @@ class TApplet extends TDoc implements Applet {
|
||||
createLabel!: IntlString
|
||||
createComponent!: AnyComponent
|
||||
previewComponent!: AnyComponent
|
||||
getTitleFn!: AppletGetTitleFnResource
|
||||
createFn?: AppletCreateFnResource
|
||||
}
|
||||
|
||||
|
||||
@@ -424,8 +424,9 @@
|
||||
style:transform={options.transform}
|
||||
style:visibility={options.visibility}
|
||||
style:z-index={($modals.findIndex((t) => t.type === 'tooltip') ?? 1) + 10000}
|
||||
style:text-align={$tooltip.textAlign}
|
||||
>
|
||||
<span class="label">
|
||||
<span class="label l1">
|
||||
<Label label={$tooltip.label} params={$tooltip.props ?? {}} />
|
||||
</span>
|
||||
{#if $tooltip.keys !== undefined}
|
||||
|
||||
@@ -14,7 +14,8 @@ const emptyTooltip: LabelAndProps = {
|
||||
keys: undefined,
|
||||
kind: 'tooltip',
|
||||
style: undefined,
|
||||
noArrow: false
|
||||
noArrow: false,
|
||||
textAlign: undefined
|
||||
}
|
||||
let storedValue: LabelAndProps = emptyTooltip
|
||||
export const tooltipstore = derived(modalStore, (modals) => {
|
||||
@@ -50,7 +51,8 @@ export function tooltip (node: HTMLElement, options?: LabelAndProps): any {
|
||||
opt.kind,
|
||||
opt.keys,
|
||||
opt.style,
|
||||
opt.noArrow
|
||||
opt.noArrow,
|
||||
opt.textAlign
|
||||
)
|
||||
}, opt.timeout ?? 10)
|
||||
} else {
|
||||
@@ -65,7 +67,8 @@ export function tooltip (node: HTMLElement, options?: LabelAndProps): any {
|
||||
opt.kind,
|
||||
opt.keys,
|
||||
opt.style,
|
||||
opt.noArrow
|
||||
opt.noArrow,
|
||||
opt.textAlign
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -92,7 +95,8 @@ export function tooltip (node: HTMLElement, options?: LabelAndProps): any {
|
||||
opt.kind,
|
||||
opt.keys,
|
||||
opt.style,
|
||||
opt.noArrow
|
||||
opt.noArrow,
|
||||
opt.textAlign
|
||||
)
|
||||
}
|
||||
},
|
||||
@@ -119,7 +123,8 @@ export function showTooltip (
|
||||
kind?: 'tooltip' | 'submenu' | 'popup',
|
||||
keys?: string[],
|
||||
style?: 'default' | 'modern',
|
||||
noArrow?: boolean
|
||||
noArrow?: boolean,
|
||||
textAlign?: 'left' | 'center' | 'right'
|
||||
): void {
|
||||
storedValue = {
|
||||
label,
|
||||
@@ -133,7 +138,8 @@ export function showTooltip (
|
||||
keys,
|
||||
type: 'tooltip',
|
||||
style,
|
||||
noArrow
|
||||
noArrow,
|
||||
textAlign
|
||||
}
|
||||
modalStore.update((old) => {
|
||||
const tooltip = old.find((m) => m?.type === 'tooltip') as LabelAndProps | undefined
|
||||
|
||||
@@ -312,6 +312,7 @@ export interface LabelAndProps {
|
||||
timeout?: number
|
||||
style?: 'default' | 'modern'
|
||||
noArrow?: boolean
|
||||
textAlign?: 'left' | 'center' | 'right'
|
||||
}
|
||||
|
||||
export interface ListItem {
|
||||
|
||||
@@ -38,7 +38,7 @@ import {
|
||||
showOriginalMessage,
|
||||
translateMessage
|
||||
} from './actions'
|
||||
import { createPoll } from './poll'
|
||||
import { createPoll, getPollTitle } from './poll'
|
||||
|
||||
export { isActivityMessage } from './activity'
|
||||
export * from './stores'
|
||||
@@ -56,6 +56,7 @@ export default async (): Promise<Resources> => ({
|
||||
CreatePoll,
|
||||
PollPreview,
|
||||
CreatePollFn: createPoll,
|
||||
GetPollTitleFn: getPollTitle,
|
||||
UserVoteActivityPresenter,
|
||||
UserVotesPresenter
|
||||
},
|
||||
|
||||
@@ -17,7 +17,8 @@ import communication, {
|
||||
type MessageAction,
|
||||
type MessageActionFunctionResource,
|
||||
type MessageActionVisibilityTesterResource,
|
||||
type AppletCreateFnResource
|
||||
type AppletCreateFnResource,
|
||||
type AppletGetTitleFnResource
|
||||
} from '@hcengineering/communication'
|
||||
import { type AnyComponent } from '@hcengineering/ui'
|
||||
import { type Ref } from '@hcengineering/core'
|
||||
@@ -31,6 +32,7 @@ export default mergeIds(communicationId, communication, {
|
||||
CreatePoll: '' as AnyComponent,
|
||||
PollPreview: '' as AnyComponent,
|
||||
CreatePollFn: '' as AppletCreateFnResource,
|
||||
GetPollTitleFn: '' as AppletGetTitleFnResource,
|
||||
UserVoteActivityPresenter: '' as AnyComponent,
|
||||
UserVotesPresenter: '' as AnyComponent
|
||||
},
|
||||
|
||||
@@ -25,7 +25,7 @@ import { type Poll, type PollAnswer } from '@hcengineering/communication'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import card, { type Card } from '@hcengineering/card'
|
||||
import { makeRank } from '@hcengineering/rank'
|
||||
import { type MessageID } from '@hcengineering/communication-types'
|
||||
import { type AppletAttachment, type MessageID } from '@hcengineering/communication-types'
|
||||
|
||||
import communication from './plugin'
|
||||
|
||||
@@ -87,6 +87,11 @@ export async function createPoll (parent: Card, message: MessageID, params: Poll
|
||||
await client.createDoc(communication.type.Poll, parent.space, filledData, params.id)
|
||||
}
|
||||
|
||||
export function getPollTitle (attachment: AppletAttachment): string {
|
||||
const params = attachment.params as PollConfig
|
||||
return params.question
|
||||
}
|
||||
|
||||
export function isVotedByMe (result: Poll | undefined, anonymous: boolean = false, answers: PollAnswer[] = []): boolean {
|
||||
if (result == null) return false
|
||||
if (anonymous) {
|
||||
|
||||
@@ -11,7 +11,14 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { AccountID, AppletParams, AppletType, Message, MessageID } from '@hcengineering/communication-types'
|
||||
import {
|
||||
AccountID,
|
||||
AppletAttachment,
|
||||
AppletParams,
|
||||
AppletType,
|
||||
Message,
|
||||
MessageID
|
||||
} from '@hcengineering/communication-types'
|
||||
import { AttachedDoc, Configuration, Doc, Ref } from '@hcengineering/core'
|
||||
import { Asset, IntlString, Resource } from '@hcengineering/platform'
|
||||
import { Card, MasterTag } from '@hcengineering/card'
|
||||
@@ -59,12 +66,16 @@ export interface Applet extends Doc {
|
||||
createLabel: IntlString
|
||||
createComponent: AnyComponent
|
||||
previewComponent: AnyComponent
|
||||
getTitleFn: AppletGetTitleFnResource
|
||||
createFn?: AppletCreateFnResource
|
||||
}
|
||||
|
||||
export type AppletCreateFn = (parent: Card, message: MessageID, params: AppletParams) => Promise<void>
|
||||
export type AppletCreateFnResource = Resource<AppletCreateFn>
|
||||
|
||||
export type AppletGetTitleFn = (attachment: AppletAttachment) => string
|
||||
export type AppletGetTitleFnResource = Resource<AppletGetTitleFn>
|
||||
|
||||
export interface PollAnswer extends AttachedDoc<Poll> {
|
||||
options: string[]
|
||||
space: Ref<PersonSpace>
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
gap: 0.5rem;
|
||||
margin-left: var(--spacing-0_5);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,10 @@
|
||||
{#if notification.message}
|
||||
<div class="reaction-notification">
|
||||
<PreviewTemplate socialId={content.creator} date={notification.created} color="secondary" showSeparator={false}>
|
||||
<Label label={inbox.string.ReactedToYourMessage} />
|
||||
<svelte:fragment slot="content">
|
||||
<span class="ml-1-5" />
|
||||
<Label label={inbox.string.ReactedToYourMessage} />
|
||||
</svelte:fragment>
|
||||
</PreviewTemplate>
|
||||
|
||||
<div class="reaction-notification__body">
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
<!-- Copyright © 2025 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 { Attachment } from '@hcengineering/communication-types'
|
||||
import { Label } from '@hcengineering/ui'
|
||||
import { isAppletAttachment, isBlobAttachment } from '@hcengineering/communication-shared'
|
||||
import { getResource } from '@hcengineering/platform'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import communication from '@hcengineering/communication'
|
||||
|
||||
export let attachment: Attachment
|
||||
export let lower: boolean = false
|
||||
|
||||
const client = getClient()
|
||||
const applets = client.getModel().findAllSync(communication.class.Applet, {})
|
||||
</script>
|
||||
|
||||
{#if isBlobAttachment(attachment)}
|
||||
{attachment.params.fileName}
|
||||
{/if}
|
||||
|
||||
{#if isAppletAttachment(attachment)}
|
||||
{@const applet = applets.find((it) => it.type === attachment.type)}
|
||||
{#if applet}
|
||||
<span class:lower>
|
||||
<Label label={applet.label} />:
|
||||
</span>
|
||||
{#await getResource(applet.getTitleFn) then fn}
|
||||
{fn(attachment)}
|
||||
{/await}
|
||||
{/if}
|
||||
{/if}
|
||||
+16
-9
@@ -15,27 +15,33 @@
|
||||
import { Message } from '@hcengineering/communication-types'
|
||||
import { Icon, Label, tooltip } from '@hcengineering/ui'
|
||||
import communication from '@hcengineering/communication'
|
||||
import { isBlobAttachment } from '@hcengineering/communication-shared'
|
||||
import { isAppletAttachment, isBlobAttachment } from '@hcengineering/communication-shared'
|
||||
import { getEmbeddedLabel } from '@hcengineering/platform'
|
||||
|
||||
import AttachmentsTooltip from './AttachmentsTooltip.svelte'
|
||||
import AttachmentName from './AttachmentName.svelte'
|
||||
|
||||
export let message: Message
|
||||
|
||||
$: blobs = message.attachments.filter(isBlobAttachment) ?? []
|
||||
$: showFiles = blobs.length > 0
|
||||
$: attachments = message.attachments.filter((it) => isBlobAttachment(it) || isAppletAttachment(it)) ?? []
|
||||
</script>
|
||||
|
||||
{#if showFiles}
|
||||
{#if attachments.length > 0}
|
||||
{#if message.content.trim().length > 0}
|
||||
<span class="attachments" use:tooltip={{ component: AttachmentsTooltip, props: { attachments: blobs } }}>
|
||||
{blobs.length}
|
||||
<span class="attachments" use:tooltip={{ component: AttachmentsTooltip, props: { attachments } }}>
|
||||
{attachments.length}
|
||||
<Icon icon={communication.icon.File} size="small" />
|
||||
</span>
|
||||
{:else}
|
||||
<span class="attachments-text font-normal overflow-label">
|
||||
<Label label={communication.string.Files} />:
|
||||
<span class="ml-1 overflow-label" use:tooltip={{ component: AttachmentsTooltip, props: { attachments: blobs } }}>
|
||||
{blobs.map((it) => it.params.fileName).join(', ')}
|
||||
<Label label={getEmbeddedLabel('Attachments')} />:
|
||||
<span class="ml-1 overflow-label" use:tooltip={{ component: AttachmentsTooltip, props: { attachments } }}>
|
||||
{#each attachments as att, i}
|
||||
<AttachmentName attachment={att} lower={i > 0} />
|
||||
{#if i < attachments.length - 1}
|
||||
,
|
||||
{/if}
|
||||
{/each}
|
||||
</span>
|
||||
</span>
|
||||
{/if}
|
||||
@@ -61,5 +67,6 @@
|
||||
white-space: nowrap;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
margin-left: -0.25rem;
|
||||
}
|
||||
</style>
|
||||
@@ -13,17 +13,16 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { Attachment } from '@hcengineering/communication-types'
|
||||
import { isBlobAttachment } from '@hcengineering/communication-shared'
|
||||
|
||||
import AttachmentName from './AttachmentName.svelte'
|
||||
|
||||
export let attachments: Attachment[] = []
|
||||
|
||||
$: blobs = attachments.filter(isBlobAttachment)
|
||||
</script>
|
||||
|
||||
<div class="tooltip">
|
||||
{#each blobs as blob}
|
||||
{#each attachments as attachment, i}
|
||||
<div>
|
||||
{blob.params.fileName}
|
||||
<AttachmentName {attachment} lower={i > 0} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
import { jsonToMarkup, markupToText } from '@hcengineering/text'
|
||||
import { ActivityMessageViewer, isActivityMessage } from '@hcengineering/communication-resources'
|
||||
|
||||
import AttachmentPreview from './AttachmentPreview.svelte'
|
||||
import AttachmentsPreview from './AttachmentsPreview.svelte'
|
||||
import PreviewTemplate from './PreviewTemplate.svelte'
|
||||
|
||||
export let card: Card
|
||||
@@ -62,13 +62,15 @@
|
||||
fixHeight={message.type !== MessageType.Activity}
|
||||
tooltipLabel={getTooltipLabel(message)}
|
||||
>
|
||||
{#if isActivityMessage(message)}
|
||||
<ActivityMessageViewer {message} {card} author={person} />
|
||||
{:else}
|
||||
<LiteMessageViewer message={markdownToMarkup(message.content)} />
|
||||
{/if}
|
||||
<svelte:fragment slot="content">
|
||||
{#if isActivityMessage(message)}
|
||||
<ActivityMessageViewer {message} {card} author={person} />
|
||||
{:else}
|
||||
<LiteMessageViewer message={markdownToMarkup(message.content)} />
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="after">
|
||||
<AttachmentPreview {message} />
|
||||
<AttachmentsPreview {message} />
|
||||
</svelte:fragment>
|
||||
</PreviewTemplate>
|
||||
|
||||
@@ -100,18 +100,24 @@
|
||||
<span class="message-preview-template__name overflow-label {color}">{formatName(_person?.name ?? '')}</span>
|
||||
{/if}
|
||||
{#if showSeparator}
|
||||
<span class="message-preview-template__separator"> • </span>
|
||||
{#if showPersonName}
|
||||
<span class="message-preview-template__separator"> • </span>
|
||||
{:else}
|
||||
<span class="mr-0-5" />
|
||||
{/if}
|
||||
{/if}
|
||||
</span>
|
||||
</PersonPreviewProvider>
|
||||
|
||||
<span
|
||||
class="message-preview-template__content overflow-label {color}"
|
||||
class:fixHeight
|
||||
use:tooltip={tooltipLabel ? { label: tooltipLabel } : undefined}
|
||||
>
|
||||
<slot />
|
||||
</span>
|
||||
{#if $$slots.content}
|
||||
<span
|
||||
class="message-preview-template__content overflow-label {color}"
|
||||
class:fixHeight
|
||||
use:tooltip={tooltipLabel ? { label: tooltipLabel, textAlign: 'left' } : undefined}
|
||||
>
|
||||
<slot name="content" />
|
||||
</span>
|
||||
{/if}
|
||||
<slot name="after" />
|
||||
</span>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user