mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-22 11:42:30 +03:00
UBERF-5527: add context menu for activity and inbox (#5373)
Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
parent
577c948d29
commit
7405b01d04
@ -21,8 +21,6 @@ import {
|
|||||||
type ActivityInfoMessage,
|
type ActivityInfoMessage,
|
||||||
type ActivityMessage,
|
type ActivityMessage,
|
||||||
type ActivityMessageControl,
|
type ActivityMessageControl,
|
||||||
type ActivityMessageExtension,
|
|
||||||
type ActivityMessageExtensionKind,
|
|
||||||
type ActivityMessagePreview,
|
type ActivityMessagePreview,
|
||||||
type ActivityMessagesFilter,
|
type ActivityMessagesFilter,
|
||||||
type ActivityReference,
|
type ActivityReference,
|
||||||
@ -70,7 +68,7 @@ import {
|
|||||||
} from '@hcengineering/model'
|
} from '@hcengineering/model'
|
||||||
import { TAttachedDoc, TClass, TDoc } from '@hcengineering/model-core'
|
import { TAttachedDoc, TClass, TDoc } from '@hcengineering/model-core'
|
||||||
import preference, { TPreference } from '@hcengineering/model-preference'
|
import preference, { TPreference } from '@hcengineering/model-preference'
|
||||||
import view from '@hcengineering/model-view'
|
import view, { createAction } from '@hcengineering/model-view'
|
||||||
import notification from '@hcengineering/notification'
|
import notification from '@hcengineering/notification'
|
||||||
import type { Asset, IntlString, Resource } from '@hcengineering/platform'
|
import type { Asset, IntlString, Resource } from '@hcengineering/platform'
|
||||||
import { type AnyComponent } from '@hcengineering/ui/src/types'
|
import { type AnyComponent } from '@hcengineering/ui/src/types'
|
||||||
@ -210,15 +208,6 @@ export class TDocUpdateMessageViewlet extends TDoc implements DocUpdateMessageVi
|
|||||||
onlyWithParent?: boolean
|
onlyWithParent?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@Model(activity.class.ActivityMessageExtension, core.class.Doc, DOMAIN_MODEL)
|
|
||||||
export class TActivityMessageExtension extends TDoc implements ActivityMessageExtension {
|
|
||||||
@Prop(TypeRef(activity.class.ActivityMessage), core.string.Class)
|
|
||||||
@Index(IndexKind.Indexed)
|
|
||||||
ofMessage!: Ref<Class<ActivityMessage>>
|
|
||||||
|
|
||||||
components!: { kind: ActivityMessageExtensionKind, component: AnyComponent }[]
|
|
||||||
}
|
|
||||||
|
|
||||||
@Model(activity.class.ActivityExtension, core.class.Doc, DOMAIN_MODEL)
|
@Model(activity.class.ActivityExtension, core.class.Doc, DOMAIN_MODEL)
|
||||||
export class TActivityExtension extends TDoc implements ActivityExtension {
|
export class TActivityExtension extends TDoc implements ActivityExtension {
|
||||||
@Prop(TypeRef(core.class.Class), core.string.Class)
|
@Prop(TypeRef(core.class.Class), core.string.Class)
|
||||||
@ -275,7 +264,6 @@ export function createModel (builder: Builder): void {
|
|||||||
TTxViewlet,
|
TTxViewlet,
|
||||||
TActivityDoc,
|
TActivityDoc,
|
||||||
TActivityMessagesFilter,
|
TActivityMessagesFilter,
|
||||||
TActivityMessageExtension,
|
|
||||||
TActivityMessage,
|
TActivityMessage,
|
||||||
TDocUpdateMessage,
|
TDocUpdateMessage,
|
||||||
TDocUpdateMessageViewlet,
|
TDocUpdateMessageViewlet,
|
||||||
@ -426,6 +414,113 @@ export function createModel (builder: Builder): void {
|
|||||||
{ attachedToClass: 1 }
|
{ attachedToClass: 1 }
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
createAction(
|
||||||
|
builder,
|
||||||
|
{
|
||||||
|
action: activity.actionImpl.AddReaction,
|
||||||
|
label: activity.string.AddReaction,
|
||||||
|
icon: activity.icon.Emoji,
|
||||||
|
input: 'focus',
|
||||||
|
category: activity.category.Activity,
|
||||||
|
target: activity.class.ActivityMessage,
|
||||||
|
inline: true,
|
||||||
|
context: {
|
||||||
|
mode: 'context',
|
||||||
|
group: 'edit'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
activity.ids.AddReactionAction
|
||||||
|
)
|
||||||
|
|
||||||
|
createAction(
|
||||||
|
builder,
|
||||||
|
{
|
||||||
|
action: activity.actionImpl.SaveForLater,
|
||||||
|
label: activity.string.SaveForLater,
|
||||||
|
icon: activity.icon.Bookmark,
|
||||||
|
input: 'focus',
|
||||||
|
inline: true,
|
||||||
|
actionProps: {
|
||||||
|
size: 'x-small'
|
||||||
|
},
|
||||||
|
category: activity.category.Activity,
|
||||||
|
target: activity.class.ActivityMessage,
|
||||||
|
visibilityTester: activity.function.CanSaveForLater,
|
||||||
|
context: {
|
||||||
|
mode: 'context',
|
||||||
|
group: 'edit'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
activity.ids.SaveForLaterAction
|
||||||
|
)
|
||||||
|
|
||||||
|
createAction(
|
||||||
|
builder,
|
||||||
|
{
|
||||||
|
action: activity.actionImpl.RemoveFromSaved,
|
||||||
|
label: activity.string.RemoveFromLater,
|
||||||
|
icon: activity.icon.BookmarkFilled,
|
||||||
|
input: 'focus',
|
||||||
|
inline: true,
|
||||||
|
actionProps: {
|
||||||
|
iconProps: {
|
||||||
|
fill: 'var(--global-accent-TextColor)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
category: activity.category.Activity,
|
||||||
|
target: activity.class.ActivityMessage,
|
||||||
|
visibilityTester: activity.function.CanRemoveFromSaved,
|
||||||
|
context: {
|
||||||
|
mode: 'context',
|
||||||
|
group: 'edit'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
activity.ids.RemoveFromLaterAction
|
||||||
|
)
|
||||||
|
|
||||||
|
createAction(
|
||||||
|
builder,
|
||||||
|
{
|
||||||
|
action: activity.actionImpl.PinMessage,
|
||||||
|
label: view.string.Pin,
|
||||||
|
icon: view.icon.Pin,
|
||||||
|
input: 'focus',
|
||||||
|
inline: true,
|
||||||
|
category: activity.category.Activity,
|
||||||
|
target: activity.class.ActivityMessage,
|
||||||
|
visibilityTester: activity.function.CanPinMessage,
|
||||||
|
context: {
|
||||||
|
mode: 'context',
|
||||||
|
group: 'edit'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
activity.ids.PinMessageAction
|
||||||
|
)
|
||||||
|
|
||||||
|
createAction(
|
||||||
|
builder,
|
||||||
|
{
|
||||||
|
action: activity.actionImpl.UnpinMessage,
|
||||||
|
label: view.string.Unpin,
|
||||||
|
icon: view.icon.Pin,
|
||||||
|
input: 'focus',
|
||||||
|
inline: true,
|
||||||
|
actionProps: {
|
||||||
|
iconProps: {
|
||||||
|
fill: 'var(--global-accent-TextColor)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
category: activity.category.Activity,
|
||||||
|
target: activity.class.ActivityMessage,
|
||||||
|
visibilityTester: activity.function.CanUnpinMessage,
|
||||||
|
context: {
|
||||||
|
mode: 'context',
|
||||||
|
group: 'edit'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
activity.ids.UnpinMessageAction
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default activity
|
export default activity
|
||||||
|
@ -16,7 +16,13 @@ import { activityId, type ActivityMessage, type DocUpdateMessageViewlet } from '
|
|||||||
import activity from '@hcengineering/activity-resources/src/plugin'
|
import activity from '@hcengineering/activity-resources/src/plugin'
|
||||||
import { type IntlString, mergeIds, type Resource } from '@hcengineering/platform'
|
import { type IntlString, mergeIds, type Resource } from '@hcengineering/platform'
|
||||||
import { type Doc, type Ref } from '@hcengineering/core'
|
import { type Doc, type Ref } from '@hcengineering/core'
|
||||||
import { type ActionCategory } from '@hcengineering/view'
|
import type { Location } from '@hcengineering/ui'
|
||||||
|
import {
|
||||||
|
type Action,
|
||||||
|
type ActionCategory,
|
||||||
|
type ViewAction,
|
||||||
|
type ViewActionAvailabilityFunction
|
||||||
|
} from '@hcengineering/view'
|
||||||
import { type NotificationGroup, type NotificationType } from '@hcengineering/notification'
|
import { type NotificationGroup, type NotificationType } from '@hcengineering/notification'
|
||||||
|
|
||||||
export default mergeIds(activityId, activity, {
|
export default mergeIds(activityId, activity, {
|
||||||
@ -24,7 +30,10 @@ export default mergeIds(activityId, activity, {
|
|||||||
Attributes: '' as IntlString,
|
Attributes: '' as IntlString,
|
||||||
Pinned: '' as IntlString,
|
Pinned: '' as IntlString,
|
||||||
Emoji: '' as IntlString,
|
Emoji: '' as IntlString,
|
||||||
Replies: '' as IntlString
|
Replies: '' as IntlString,
|
||||||
|
AddReaction: '' as IntlString,
|
||||||
|
SaveForLater: '' as IntlString,
|
||||||
|
RemoveFromLater: '' as IntlString
|
||||||
},
|
},
|
||||||
filter: {
|
filter: {
|
||||||
AttributesFilter: '' as Resource<(message: ActivityMessage, _class?: Ref<Doc>) => boolean>,
|
AttributesFilter: '' as Resource<(message: ActivityMessage, _class?: Ref<Doc>) => boolean>,
|
||||||
@ -35,9 +44,28 @@ export default mergeIds(activityId, activity, {
|
|||||||
ids: {
|
ids: {
|
||||||
ReactionAddedActivityViewlet: '' as Ref<DocUpdateMessageViewlet>,
|
ReactionAddedActivityViewlet: '' as Ref<DocUpdateMessageViewlet>,
|
||||||
ActivityNotificationGroup: '' as Ref<NotificationGroup>,
|
ActivityNotificationGroup: '' as Ref<NotificationGroup>,
|
||||||
AddReactionNotification: '' as Ref<NotificationType>
|
AddReactionNotification: '' as Ref<NotificationType>,
|
||||||
|
AddReactionAction: '' as Ref<Action>,
|
||||||
|
SaveForLaterAction: '' as Ref<Action>,
|
||||||
|
RemoveFromLaterAction: '' as Ref<Action>,
|
||||||
|
PinMessageAction: '' as Ref<Action>,
|
||||||
|
UnpinMessageAction: '' as Ref<Action>
|
||||||
|
},
|
||||||
|
function: {
|
||||||
|
GetFragment: '' as Resource<(doc: Doc, props: Record<string, any>) => Promise<Location>>,
|
||||||
|
CanSaveForLater: '' as Resource<ViewActionAvailabilityFunction>,
|
||||||
|
CanRemoveFromSaved: '' as Resource<ViewActionAvailabilityFunction>,
|
||||||
|
CanPinMessage: '' as Resource<ViewActionAvailabilityFunction>,
|
||||||
|
CanUnpinMessage: '' as Resource<ViewActionAvailabilityFunction>
|
||||||
},
|
},
|
||||||
category: {
|
category: {
|
||||||
Activity: '' as Ref<ActionCategory>
|
Activity: '' as Ref<ActionCategory>
|
||||||
|
},
|
||||||
|
actionImpl: {
|
||||||
|
AddReaction: '' as ViewAction,
|
||||||
|
SaveForLater: '' as ViewAction,
|
||||||
|
RemoveFromSaved: '' as ViewAction,
|
||||||
|
PinMessage: '' as ViewAction,
|
||||||
|
UnpinMessage: '' as ViewAction
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -677,46 +677,6 @@ export function createModel (builder: Builder, options = { addApplication: true
|
|||||||
components: { input: chunter.component.ChatMessageInput }
|
components: { input: chunter.component.ChatMessageInput }
|
||||||
})
|
})
|
||||||
|
|
||||||
builder.createDoc(activity.class.ActivityMessageExtension, core.space.Model, {
|
|
||||||
ofMessage: chunter.class.ChatMessage,
|
|
||||||
components: [{ kind: 'footer', component: chunter.component.Replies }]
|
|
||||||
})
|
|
||||||
|
|
||||||
builder.createDoc(activity.class.ActivityMessageExtension, core.space.Model, {
|
|
||||||
ofMessage: activity.class.DocUpdateMessage,
|
|
||||||
components: [{ kind: 'footer', component: chunter.component.Replies }]
|
|
||||||
})
|
|
||||||
|
|
||||||
builder.createDoc(activity.class.ActivityMessageExtension, core.space.Model, {
|
|
||||||
ofMessage: activity.class.ActivityInfoMessage,
|
|
||||||
components: [{ kind: 'footer', component: chunter.component.Replies }]
|
|
||||||
})
|
|
||||||
|
|
||||||
builder.createDoc(activity.class.ActivityMessageExtension, core.space.Model, {
|
|
||||||
ofMessage: activity.class.ActivityReference,
|
|
||||||
components: [{ kind: 'footer', component: chunter.component.Replies }]
|
|
||||||
})
|
|
||||||
|
|
||||||
builder.createDoc(activity.class.ActivityMessageExtension, core.space.Model, {
|
|
||||||
ofMessage: chunter.class.ChatMessage,
|
|
||||||
components: [{ kind: 'action', component: chunter.component.ReplyToThreadAction }]
|
|
||||||
})
|
|
||||||
|
|
||||||
builder.createDoc(activity.class.ActivityMessageExtension, core.space.Model, {
|
|
||||||
ofMessage: activity.class.DocUpdateMessage,
|
|
||||||
components: [{ kind: 'action', component: chunter.component.ReplyToThreadAction }]
|
|
||||||
})
|
|
||||||
|
|
||||||
builder.createDoc(activity.class.ActivityMessageExtension, core.space.Model, {
|
|
||||||
ofMessage: activity.class.ActivityInfoMessage,
|
|
||||||
components: [{ kind: 'action', component: chunter.component.ReplyToThreadAction }]
|
|
||||||
})
|
|
||||||
|
|
||||||
builder.createDoc(activity.class.ActivityMessageExtension, core.space.Model, {
|
|
||||||
ofMessage: activity.class.ActivityReference,
|
|
||||||
components: [{ kind: 'action', component: chunter.component.ReplyToThreadAction }]
|
|
||||||
})
|
|
||||||
|
|
||||||
builder.mixin(chunter.class.Channel, core.class.Class, chunter.mixin.ObjectChatPanel, {
|
builder.mixin(chunter.class.Channel, core.class.Class, chunter.mixin.ObjectChatPanel, {
|
||||||
ignoreKeys: ['archived', 'collaborators', 'lastMessage', 'pinned', 'topic', 'description']
|
ignoreKeys: ['archived', 'collaborators', 'lastMessage', 'pinned', 'topic', 'description']
|
||||||
})
|
})
|
||||||
@ -741,6 +701,25 @@ export function createModel (builder: Builder, options = { addApplication: true
|
|||||||
builder.createDoc(activity.class.ReplyProvider, core.space.Model, {
|
builder.createDoc(activity.class.ReplyProvider, core.space.Model, {
|
||||||
function: chunter.function.ReplyToThread
|
function: chunter.function.ReplyToThread
|
||||||
})
|
})
|
||||||
|
|
||||||
|
createAction(
|
||||||
|
builder,
|
||||||
|
{
|
||||||
|
action: chunter.actionImpl.ReplyToThread,
|
||||||
|
label: chunter.string.ReplyToThread,
|
||||||
|
icon: chunter.icon.Thread,
|
||||||
|
input: 'focus',
|
||||||
|
category: chunter.category.Chunter,
|
||||||
|
target: activity.class.ActivityMessage,
|
||||||
|
visibilityTester: chunter.function.CanReplyToThread,
|
||||||
|
inline: true,
|
||||||
|
context: {
|
||||||
|
mode: 'context',
|
||||||
|
group: 'edit'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
chunter.action.ReplyToThreadAction
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default chunter
|
export default chunter
|
||||||
|
@ -40,13 +40,15 @@ export default mergeIds(chunterId, chunter, {
|
|||||||
ArchiveChannel: '' as Ref<Action>,
|
ArchiveChannel: '' as Ref<Action>,
|
||||||
UnarchiveChannel: '' as Ref<Action>,
|
UnarchiveChannel: '' as Ref<Action>,
|
||||||
ConvertToPrivate: '' as Ref<Action>,
|
ConvertToPrivate: '' as Ref<Action>,
|
||||||
CopyChatMessageLink: '' as Ref<Action<Doc, any>>
|
CopyChatMessageLink: '' as Ref<Action<Doc, any>>,
|
||||||
|
ReplyToThreadAction: '' as Ref<Action>
|
||||||
},
|
},
|
||||||
actionImpl: {
|
actionImpl: {
|
||||||
ArchiveChannel: '' as ViewAction,
|
ArchiveChannel: '' as ViewAction,
|
||||||
UnarchiveChannel: '' as ViewAction,
|
UnarchiveChannel: '' as ViewAction,
|
||||||
ConvertDmToPrivateChannel: '' as ViewAction,
|
ConvertDmToPrivateChannel: '' as ViewAction,
|
||||||
DeleteChatMessage: '' as ViewAction
|
DeleteChatMessage: '' as ViewAction,
|
||||||
|
ReplyToThread: '' as ViewAction
|
||||||
},
|
},
|
||||||
category: {
|
category: {
|
||||||
Chunter: '' as Ref<ActionCategory>
|
Chunter: '' as Ref<ActionCategory>
|
||||||
@ -100,8 +102,9 @@ export default mergeIds(chunterId, chunter, {
|
|||||||
CanCopyMessageLink: '' as Resource<(doc?: Doc | Doc[]) => Promise<boolean>>,
|
CanCopyMessageLink: '' as Resource<(doc?: Doc | Doc[]) => Promise<boolean>>,
|
||||||
GetChunterSpaceLinkFragment: '' as Resource<(doc: Doc, props: Record<string, any>) => Promise<Location>>,
|
GetChunterSpaceLinkFragment: '' as Resource<(doc: Doc, props: Record<string, any>) => Promise<Location>>,
|
||||||
GetThreadLink: '' 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>>,
|
||||||
ReplyToThread: '' as Resource<(doc: ActivityMessage) => Promise<void>>
|
CanReplyToThread: '' as Resource<(doc?: Doc | Doc[]) => Promise<boolean>>,
|
||||||
|
GetMessageLink: '' as Resource<(doc: Doc, props: Record<string, any>) => Promise<Location>>
|
||||||
},
|
},
|
||||||
filter: {
|
filter: {
|
||||||
ChatMessagesFilter: '' as Resource<(message: ActivityMessage, _class?: Ref<Doc>) => boolean>
|
ChatMessagesFilter: '' as Resource<(message: ActivityMessage, _class?: Ref<Doc>) => boolean>
|
||||||
|
@ -111,6 +111,7 @@ export function closePopup (category?: string): void {
|
|||||||
} else {
|
} else {
|
||||||
for (let i = popups.length - 1; i >= 0; i--) {
|
for (let i = popups.length - 1; i >= 0; i--) {
|
||||||
if (popups[i].options.fixed !== true) {
|
if (popups[i].options.fixed !== true) {
|
||||||
|
popups[i].onClose?.(undefined)
|
||||||
popups.splice(i, 1)
|
popups.splice(i, 1)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -239,6 +239,7 @@ export type IconSize =
|
|||||||
| 'inline'
|
| 'inline'
|
||||||
| 'tiny'
|
| 'tiny'
|
||||||
| 'card'
|
| 'card'
|
||||||
|
| 'xx-small'
|
||||||
| 'x-small'
|
| 'x-small'
|
||||||
| 'smaller'
|
| 'smaller'
|
||||||
| 'small'
|
| 'small'
|
||||||
@ -258,6 +259,7 @@ export function getIconSize2x (size: IconSize): IconSize {
|
|||||||
switch (size) {
|
switch (size) {
|
||||||
case 'inline':
|
case 'inline':
|
||||||
case 'tiny':
|
case 'tiny':
|
||||||
|
case 'xx-small':
|
||||||
case 'x-small':
|
case 'x-small':
|
||||||
case 'small':
|
case 'small':
|
||||||
case 'card':
|
case 'card':
|
||||||
|
@ -11,4 +11,7 @@
|
|||||||
<symbol id="bookmark" viewBox="0 0 20 28">
|
<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" />
|
<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>
|
||||||
|
<symbol id="bookmark-filled" viewBox="0 0 32 32">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M6 6.00012C6 3.79098 7.79086 2.00012 10 2.00012H22C24.2091 2.00012 26 3.79098 26 6.00012V29.0001C26 29.3689 25.797 29.7078 25.4719 29.8818C25.1467 30.0558 24.7522 30.0367 24.4453 29.8322L16 24.202L7.5547 29.8322C7.24784 30.0367 6.8533 30.0558 6.52814 29.8818C6.20298 29.7078 6 29.3689 6 29.0001V6.00012Z" />
|
||||||
|
</symbol>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.8 KiB |
@ -40,6 +40,9 @@
|
|||||||
"Mentions": "Mentions",
|
"Mentions": "Mentions",
|
||||||
"MentionedYouIn": "Mentioned you in {title}",
|
"MentionedYouIn": "Mentioned you in {title}",
|
||||||
"Messages": "Messages",
|
"Messages": "Messages",
|
||||||
"Thread": "Thread"
|
"Thread": "Thread",
|
||||||
|
"AddReaction": "Add reaction",
|
||||||
|
"SaveForLater": "Save for later",
|
||||||
|
"RemoveFromLater": "Remove from saved"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -40,6 +40,9 @@
|
|||||||
"Mentions": "Упоминания",
|
"Mentions": "Упоминания",
|
||||||
"MentionedYouIn": "Упомянул(а) вас в {title}",
|
"MentionedYouIn": "Упомянул(а) вас в {title}",
|
||||||
"Messages": "Cообщения",
|
"Messages": "Cообщения",
|
||||||
"Thread": "Обсуждение"
|
"Thread": "Обсуждение",
|
||||||
|
"AddReaction": "Добавить реакцию",
|
||||||
|
"SaveForLater": "Cохранить",
|
||||||
|
"RemoveFromLater": "Удалить из сохраненных"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,5 +20,6 @@ const icons = require('../assets/icons.svg') as string // eslint-disable-line
|
|||||||
loadMetadata(activity.icon, {
|
loadMetadata(activity.icon, {
|
||||||
Activity: `${icons}#activity`,
|
Activity: `${icons}#activity`,
|
||||||
Emoji: `${icons}#emoji`,
|
Emoji: `${icons}#emoji`,
|
||||||
Bookmark: `${icons}#bookmark`
|
Bookmark: `${icons}#bookmark`,
|
||||||
|
BookmarkFilled: `${icons}#bookmark-filled`
|
||||||
})
|
})
|
||||||
|
@ -14,9 +14,10 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { type AnySvelteComponent, ButtonIcon, IconSize } from '@hcengineering/ui'
|
import { type AnySvelteComponent, ButtonIcon, IconSize } from '@hcengineering/ui'
|
||||||
import { Asset } from '@hcengineering/platform'
|
import { Asset, IntlString } from '@hcengineering/platform'
|
||||||
import { ComponentType } from 'svelte'
|
import { ComponentType } from 'svelte'
|
||||||
|
|
||||||
|
export let label: IntlString
|
||||||
export let icon: Asset | AnySvelteComponent | ComponentType
|
export let icon: Asset | AnySvelteComponent | ComponentType
|
||||||
export let iconProps: any | undefined = undefined
|
export let iconProps: any | undefined = undefined
|
||||||
export let size: IconSize = 'small'
|
export let size: IconSize = 'small'
|
||||||
@ -30,4 +31,13 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ButtonIcon {icon} {iconProps} iconSize={size} size="small" kind="tertiary" pressed={opened} on:click={onClick} />
|
<ButtonIcon
|
||||||
|
{icon}
|
||||||
|
{iconProps}
|
||||||
|
iconSize={size}
|
||||||
|
size="small"
|
||||||
|
kind="tertiary"
|
||||||
|
pressed={opened}
|
||||||
|
on:click={onClick}
|
||||||
|
tooltip={{ label }}
|
||||||
|
/>
|
||||||
|
@ -13,60 +13,95 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import activity, { ActivityMessage, ActivityMessageExtension } from '@hcengineering/activity'
|
import activity, { ActivityMessage } from '@hcengineering/activity'
|
||||||
import { Action, IconMoreV, showPopup } from '@hcengineering/ui'
|
import { Action, IconMoreV, showPopup } from '@hcengineering/ui'
|
||||||
import { Menu } from '@hcengineering/view-resources'
|
import { getActions, Menu } from '@hcengineering/view-resources'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { getClient } from '@hcengineering/presentation'
|
||||||
|
import { getResource } from '@hcengineering/platform'
|
||||||
|
import view, { Action as ViewAction } from '@hcengineering/view'
|
||||||
|
|
||||||
import ActivityMessageAction from './ActivityMessageAction.svelte'
|
import ActivityMessageAction from './ActivityMessageAction.svelte'
|
||||||
import PinMessageAction from './PinMessageAction.svelte'
|
import { savedMessagesStore } from '../activity'
|
||||||
import SaveMessageAction from './SaveMessageAction.svelte'
|
|
||||||
import ActivityMessageExtensionComponent from './activity-message/ActivityMessageExtension.svelte'
|
|
||||||
import AddReactionAction from './reactions/AddReactionAction.svelte'
|
|
||||||
|
|
||||||
export let message: ActivityMessage | undefined
|
export let message: ActivityMessage | undefined
|
||||||
export let extensions: ActivityMessageExtension[] = []
|
|
||||||
export let actions: Action[] = []
|
export let actions: Action[] = []
|
||||||
export let withActionMenu = true
|
export let withActionMenu = true
|
||||||
|
export let onOpen: () => void
|
||||||
|
export let onClose: () => void
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const client = getClient()
|
||||||
|
|
||||||
|
let inlineActions: ViewAction[] = []
|
||||||
let isActionMenuOpened = false
|
let isActionMenuOpened = false
|
||||||
|
|
||||||
|
$: void updateInlineActions(message)
|
||||||
|
|
||||||
|
savedMessagesStore.subscribe(() => {
|
||||||
|
void updateInlineActions(message)
|
||||||
|
})
|
||||||
|
|
||||||
function handleActionMenuOpened (): void {
|
function handleActionMenuOpened (): void {
|
||||||
isActionMenuOpened = true
|
isActionMenuOpened = true
|
||||||
dispatch('open')
|
onOpen()
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleActionMenuClosed (): void {
|
function handleActionMenuClosed (): void {
|
||||||
isActionMenuOpened = false
|
isActionMenuOpened = false
|
||||||
dispatch('close')
|
onClose()
|
||||||
}
|
}
|
||||||
|
|
||||||
function showMenu (ev: MouseEvent): void {
|
function showMenu (ev: MouseEvent): void {
|
||||||
|
const excludedActions = inlineActions.map(({ _id }) => _id)
|
||||||
|
|
||||||
showPopup(
|
showPopup(
|
||||||
Menu,
|
Menu,
|
||||||
{
|
{
|
||||||
object: message,
|
object: message,
|
||||||
actions,
|
actions,
|
||||||
baseMenuClass: activity.class.ActivityMessage
|
baseMenuClass: activity.class.ActivityMessage,
|
||||||
|
excludedActions
|
||||||
},
|
},
|
||||||
ev.target as HTMLElement,
|
ev.target as HTMLElement,
|
||||||
handleActionMenuClosed
|
handleActionMenuClosed
|
||||||
)
|
)
|
||||||
handleActionMenuOpened()
|
handleActionMenuOpened()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function updateInlineActions (message?: ActivityMessage): Promise<void> {
|
||||||
|
if (message === undefined) {
|
||||||
|
inlineActions = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
inlineActions = (await getActions(client, message, activity.class.ActivityMessage)).filter(
|
||||||
|
(action) => action.inline
|
||||||
|
)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if message}
|
{#if message}
|
||||||
<div class="root">
|
<div class="root">
|
||||||
<AddReactionAction object={message} on:open on:close />
|
{#each inlineActions as inline}
|
||||||
<ActivityMessageExtensionComponent kind="action" {extensions} props={{ object: message }} on:close on:open />
|
{#if inline.icon}
|
||||||
<PinMessageAction object={message} />
|
{#await getResource(inline.action) then action}
|
||||||
<SaveMessageAction object={message} />
|
<ActivityMessageAction
|
||||||
|
label={inline.label}
|
||||||
|
size={inline.actionProps?.size ?? 'small'}
|
||||||
|
icon={inline.icon}
|
||||||
|
iconProps={inline.actionProps?.iconProps}
|
||||||
|
action={(ev) => action(message, ev, { onOpen, onClose })}
|
||||||
|
/>
|
||||||
|
{/await}
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
|
||||||
{#if withActionMenu}
|
{#if withActionMenu}
|
||||||
<ActivityMessageAction size="small" icon={IconMoreV} opened={isActionMenuOpened} action={showMenu} />
|
<ActivityMessageAction
|
||||||
|
size="small"
|
||||||
|
icon={IconMoreV}
|
||||||
|
opened={isActionMenuOpened}
|
||||||
|
action={showMenu}
|
||||||
|
label={view.string.MoreActions}
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -26,9 +26,10 @@
|
|||||||
import core, { Account, Doc, Ref, Timestamp } from '@hcengineering/core'
|
import core, { Account, Doc, Ref, Timestamp } from '@hcengineering/core'
|
||||||
import { Icon, Label, resizeObserver, TimeSince, tooltip } from '@hcengineering/ui'
|
import { Icon, Label, resizeObserver, TimeSince, tooltip } from '@hcengineering/ui'
|
||||||
import { Asset, getEmbeddedLabel, IntlString } from '@hcengineering/platform'
|
import { Asset, getEmbeddedLabel, IntlString } from '@hcengineering/platform'
|
||||||
import activity, { ActivityMessagePreviewType } from '@hcengineering/activity'
|
import activity, { ActivityMessage, ActivityMessagePreviewType } from '@hcengineering/activity'
|
||||||
import { classIcon, DocNavLink } from '@hcengineering/view-resources'
|
import { classIcon, DocNavLink, showMenu } from '@hcengineering/view-resources'
|
||||||
|
|
||||||
|
export let message: ActivityMessage | undefined = undefined
|
||||||
export let text: string | undefined = undefined
|
export let text: string | undefined = undefined
|
||||||
export let intlLabel: IntlString | undefined = undefined
|
export let intlLabel: IntlString | undefined = undefined
|
||||||
export let readonly = false
|
export let readonly = false
|
||||||
@ -99,6 +100,12 @@
|
|||||||
width = element.clientWidth
|
width = element.clientWidth
|
||||||
}}
|
}}
|
||||||
on:click
|
on:click
|
||||||
|
on:contextmenu={(evt) => {
|
||||||
|
showMenu(evt, { object: message, baseMenuClass: activity.class.ActivityMessage }, () => {
|
||||||
|
isActionsOpened = false
|
||||||
|
})
|
||||||
|
isActionsOpened = true
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<span class="left overflow-label">
|
<span class="left overflow-label">
|
||||||
{#if type === 'full'}
|
{#if type === 'full'}
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
<!--
|
|
||||||
// Copyright © 2023 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 { getClient } from '@hcengineering/presentation'
|
|
||||||
import view from '@hcengineering/view'
|
|
||||||
import { ActivityMessage } from '@hcengineering/activity'
|
|
||||||
import ActivityMessageAction from './ActivityMessageAction.svelte'
|
|
||||||
|
|
||||||
export let object: ActivityMessage
|
|
||||||
|
|
||||||
const client = getClient()
|
|
||||||
|
|
||||||
async function toggleMessagePinning (): Promise<void> {
|
|
||||||
await client.update(object, { isPinned: !object.isPinned })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<ActivityMessageAction
|
|
||||||
icon={view.icon.Pin}
|
|
||||||
iconProps={{ fill: object.isPinned ? '#3265cb' : 'currentColor' }}
|
|
||||||
action={toggleMessagePinning}
|
|
||||||
/>
|
|
@ -29,7 +29,6 @@
|
|||||||
|
|
||||||
export let object: ActivityMessage
|
export let object: ActivityMessage
|
||||||
export let embedded = false
|
export let embedded = false
|
||||||
export let onReply: (() => void) | undefined = undefined
|
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
const maxDisplayPersons = 5
|
const maxDisplayPersons = 5
|
||||||
@ -83,11 +82,6 @@
|
|||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
if (onReply) {
|
|
||||||
onReply()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (replyProvider) {
|
if (replyProvider) {
|
||||||
const fn = await getResource(replyProvider.function)
|
const fn = await getResource(replyProvider.function)
|
||||||
fn(object)
|
fn(object)
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
<!--
|
|
||||||
// Copyright © 2023 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 { createQuery, getClient } from '@hcengineering/presentation'
|
|
||||||
import activity, { ActivityMessage, SavedMessage } from '@hcengineering/activity'
|
|
||||||
import preference from '@hcengineering/preference'
|
|
||||||
|
|
||||||
import BookmarkBorder from './icons/BookmarkBorder.svelte'
|
|
||||||
import ActivityMessageAction from './ActivityMessageAction.svelte'
|
|
||||||
import Bookmark from './icons/Bookmark.svelte'
|
|
||||||
import { savedMessagesStore } from '../activity'
|
|
||||||
|
|
||||||
export let object: ActivityMessage
|
|
||||||
|
|
||||||
const client = getClient()
|
|
||||||
|
|
||||||
let savedMessage: SavedMessage | undefined = undefined
|
|
||||||
|
|
||||||
savedMessagesStore.subscribe((saved) => {
|
|
||||||
savedMessage = saved.find(({ attachedTo }) => attachedTo === object._id)
|
|
||||||
})
|
|
||||||
|
|
||||||
async function toggleSaveMessage (): Promise<void> {
|
|
||||||
if (savedMessage !== undefined) {
|
|
||||||
await client.remove(savedMessage)
|
|
||||||
savedMessage = undefined
|
|
||||||
} else {
|
|
||||||
await client.createDoc(activity.class.SavedMessage, preference.space.Preference, {
|
|
||||||
attachedTo: object._id
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<ActivityMessageAction
|
|
||||||
icon={savedMessage ? Bookmark : BookmarkBorder}
|
|
||||||
size={savedMessage ? 'small' : 'x-small'}
|
|
||||||
iconProps={{ fill: savedMessage ? 'var(--global-accent-TextColor)' : 'currentColor' }}
|
|
||||||
action={toggleSaveMessage}
|
|
||||||
/>
|
|
@ -1,30 +0,0 @@
|
|||||||
<!--
|
|
||||||
// Copyright © 2023 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 { ActivityMessageExtension, ActivityMessageExtensionKind } from '@hcengineering/activity'
|
|
||||||
import { Component } from '@hcengineering/ui'
|
|
||||||
|
|
||||||
export let kind: ActivityMessageExtensionKind
|
|
||||||
export let extensions: ActivityMessageExtension[] = []
|
|
||||||
export let props: Record<string, any> = {}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#each extensions as extension}
|
|
||||||
{#each extension.components as component}
|
|
||||||
{#if component.kind === kind}
|
|
||||||
<Component is={component.component} {props} showLoading={false} on:close on:open />
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
{/each}
|
|
@ -39,7 +39,6 @@
|
|||||||
export let hideLink = false
|
export let hideLink = false
|
||||||
export let compact = false
|
export let compact = false
|
||||||
export let onClick: (() => void) | undefined = undefined
|
export let onClick: (() => void) | undefined = undefined
|
||||||
export let onReply: (() => void) | undefined = undefined
|
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
const hierarchy = client.getHierarchy()
|
const hierarchy = client.getHierarchy()
|
||||||
@ -70,8 +69,7 @@
|
|||||||
videoPreload,
|
videoPreload,
|
||||||
hideLink,
|
hideLink,
|
||||||
compact,
|
compact,
|
||||||
onClick,
|
onClick
|
||||||
onReply
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -13,23 +13,18 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import activity, {
|
import activity, { ActivityMessageViewlet, DisplayActivityMessage } from '@hcengineering/activity'
|
||||||
ActivityMessageExtension,
|
|
||||||
ActivityMessageViewlet,
|
|
||||||
DisplayActivityMessage
|
|
||||||
} from '@hcengineering/activity'
|
|
||||||
import { Person } from '@hcengineering/contact'
|
import { Person } from '@hcengineering/contact'
|
||||||
import { Avatar, EmployeePresenter, SystemAvatar } from '@hcengineering/contact-resources'
|
import { Avatar, EmployeePresenter, SystemAvatar } from '@hcengineering/contact-resources'
|
||||||
import core from '@hcengineering/core'
|
import core from '@hcengineering/core'
|
||||||
import { getClient } from '@hcengineering/presentation'
|
import { getClient } from '@hcengineering/presentation'
|
||||||
import { Action, Label } from '@hcengineering/ui'
|
import { Action, Icon, Label } from '@hcengineering/ui'
|
||||||
import { getActions, restrictionStore } from '@hcengineering/view-resources'
|
import { getActions, restrictionStore, showMenu } from '@hcengineering/view-resources'
|
||||||
|
|
||||||
import ReactionsPresenter from '../reactions/ReactionsPresenter.svelte'
|
import ReactionsPresenter from '../reactions/ReactionsPresenter.svelte'
|
||||||
import ActivityMessagePresenter from './ActivityMessagePresenter.svelte'
|
import ActivityMessagePresenter from './ActivityMessagePresenter.svelte'
|
||||||
import ActivityMessageActions from '../ActivityMessageActions.svelte'
|
import ActivityMessageActions from '../ActivityMessageActions.svelte'
|
||||||
import { isReactionMessage } from '../../activityMessagesUtils'
|
import { isReactionMessage } from '../../activityMessagesUtils'
|
||||||
import Bookmark from '../icons/Bookmark.svelte'
|
|
||||||
import { savedMessagesStore } from '../../activity'
|
import { savedMessagesStore } from '../../activity'
|
||||||
import MessageTimestamp from '../MessageTimestamp.svelte'
|
import MessageTimestamp from '../MessageTimestamp.svelte'
|
||||||
import Replies from '../Replies.svelte'
|
import Replies from '../Replies.svelte'
|
||||||
@ -53,14 +48,12 @@
|
|||||||
export let hoverStyles: 'borderedHover' | 'filledHover' = 'borderedHover'
|
export let hoverStyles: 'borderedHover' | 'filledHover' = 'borderedHover'
|
||||||
export let showDatePreposition = false
|
export let showDatePreposition = false
|
||||||
export let onClick: (() => void) | undefined = undefined
|
export let onClick: (() => void) | undefined = undefined
|
||||||
export let onReply: (() => void) | undefined = undefined
|
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
|
||||||
let menuActionIds: string[] = []
|
let menuActionIds: string[] = []
|
||||||
|
|
||||||
let element: HTMLDivElement | undefined = undefined
|
let element: HTMLDivElement | undefined = undefined
|
||||||
let extensions: ActivityMessageExtension[] = []
|
|
||||||
let isActionsOpened = false
|
let isActionsOpened = false
|
||||||
|
|
||||||
let isSaved = false
|
let isSaved = false
|
||||||
@ -85,8 +78,6 @@
|
|||||||
setTimeout(scrollToMessage, 100)
|
setTimeout(scrollToMessage, 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
$: extensions = client.getModel().findAllSync(activity.class.ActivityMessageExtension, { ofMessage: message._class })
|
|
||||||
|
|
||||||
function handleActionsOpened (): void {
|
function handleActionsOpened (): void {
|
||||||
isActionsOpened = true
|
isActionsOpened = true
|
||||||
}
|
}
|
||||||
@ -121,6 +112,12 @@
|
|||||||
class:borderedHover={hoverStyles === 'borderedHover'}
|
class:borderedHover={hoverStyles === 'borderedHover'}
|
||||||
class:filledHover={hoverStyles === 'filledHover'}
|
class:filledHover={hoverStyles === 'filledHover'}
|
||||||
on:click={onClick}
|
on:click={onClick}
|
||||||
|
on:contextmenu={(evt) => {
|
||||||
|
showMenu(evt, { object: message, baseMenuClass: activity.class.ActivityMessage }, () => {
|
||||||
|
isActionsOpened = false
|
||||||
|
})
|
||||||
|
isActionsOpened = true
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{#if showNotify && !embedded}
|
{#if showNotify && !embedded}
|
||||||
<div class="notify" />
|
<div class="notify" />
|
||||||
@ -136,7 +133,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{#if isSaved}
|
{#if isSaved}
|
||||||
<div class="saveMarker">
|
<div class="saveMarker">
|
||||||
<Bookmark size="xx-small" />
|
<Icon icon={activity.icon.BookmarkFilled} size="xx-small" />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
@ -171,7 +168,7 @@
|
|||||||
<slot name="content" />
|
<slot name="content" />
|
||||||
|
|
||||||
{#if !hideFooter}
|
{#if !hideFooter}
|
||||||
<Replies {embedded} object={message} {onReply} />
|
<Replies {embedded} object={message} />
|
||||||
{/if}
|
{/if}
|
||||||
<ReactionsPresenter object={message} {readonly} />
|
<ReactionsPresenter object={message} {readonly} />
|
||||||
{#if parentMessage && showEmbedded}
|
{#if parentMessage && showEmbedded}
|
||||||
@ -184,11 +181,10 @@
|
|||||||
<div class="actions" class:opened={isActionsOpened}>
|
<div class="actions" class:opened={isActionsOpened}>
|
||||||
<ActivityMessageActions
|
<ActivityMessageActions
|
||||||
message={isReactionMessage(message) ? parentMessage : message}
|
message={isReactionMessage(message) ? parentMessage : message}
|
||||||
{extensions}
|
|
||||||
{actions}
|
{actions}
|
||||||
{withActionMenu}
|
{withActionMenu}
|
||||||
on:open={handleActionsOpened}
|
onOpen={handleActionsOpened}
|
||||||
on:close={handleActionsClosed}
|
onClose={handleActionsClosed}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getClient } from '@hcengineering/presentation'
|
|
||||||
import { IntlString } from '@hcengineering/platform'
|
import { IntlString } from '@hcengineering/platform'
|
||||||
import activity, { ActivityMessage, ActivityMessagePreviewType } from '@hcengineering/activity'
|
import activity, { ActivityMessage, ActivityMessagePreviewType } from '@hcengineering/activity'
|
||||||
|
|
||||||
@ -30,17 +29,14 @@
|
|||||||
export let message: ActivityMessage
|
export let message: ActivityMessage
|
||||||
export let actions: Action[] = []
|
export let actions: Action[] = []
|
||||||
|
|
||||||
const client = getClient()
|
|
||||||
|
|
||||||
let previewElement: BasePreview
|
let previewElement: BasePreview
|
||||||
let isCompact = false
|
let isCompact = false
|
||||||
|
|
||||||
$: extensions = client.getModel().findAllSync(activity.class.ActivityMessageExtension, { ofMessage: message._class })
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<BasePreview
|
<BasePreview
|
||||||
bind:this={previewElement}
|
bind:this={previewElement}
|
||||||
bind:isCompact
|
bind:isCompact
|
||||||
|
{message}
|
||||||
{text}
|
{text}
|
||||||
{intlLabel}
|
{intlLabel}
|
||||||
{readonly}
|
{readonly}
|
||||||
@ -58,13 +54,14 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
<svelte:fragment slot="actions">
|
<svelte:fragment slot="actions">
|
||||||
|
{#if previewElement}
|
||||||
<ActivityMessageActions
|
<ActivityMessageActions
|
||||||
{message}
|
{message}
|
||||||
{extensions}
|
|
||||||
{actions}
|
{actions}
|
||||||
withActionMenu={false}
|
withActionMenu={false}
|
||||||
on:open={previewElement.onActionsOpened}
|
onOpen={previewElement.onActionsOpened}
|
||||||
on:close={previewElement.onActionsClosed}
|
onClose={previewElement.onActionsClosed}
|
||||||
/>
|
/>
|
||||||
|
{/if}
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</BasePreview>
|
</BasePreview>
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
export let hideLink = false
|
export let hideLink = false
|
||||||
export let compact = false
|
export let compact = false
|
||||||
export let onClick: (() => void) | undefined = undefined
|
export let onClick: (() => void) | undefined = undefined
|
||||||
export let onReply: (() => void) | undefined = undefined
|
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
const hierarchy = client.getHierarchy()
|
const hierarchy = client.getHierarchy()
|
||||||
@ -112,7 +111,6 @@
|
|||||||
{hoverStyles}
|
{hoverStyles}
|
||||||
showDatePreposition
|
showDatePreposition
|
||||||
{onClick}
|
{onClick}
|
||||||
{onReply}
|
|
||||||
>
|
>
|
||||||
<svelte:fragment slot="header">
|
<svelte:fragment slot="header">
|
||||||
<span class="header">
|
<span class="header">
|
||||||
|
@ -51,7 +51,6 @@
|
|||||||
export let hoverStyles: 'borderedHover' | 'filledHover' = 'borderedHover'
|
export let hoverStyles: 'borderedHover' | 'filledHover' = 'borderedHover'
|
||||||
export let hideLink = false
|
export let hideLink = false
|
||||||
export let onClick: (() => void) | undefined = undefined
|
export let onClick: (() => void) | undefined = undefined
|
||||||
export let onReply: (() => void) | undefined = undefined
|
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
const hierarchy = client.getHierarchy()
|
const hierarchy = client.getHierarchy()
|
||||||
@ -172,7 +171,6 @@
|
|||||||
{hoverStyles}
|
{hoverStyles}
|
||||||
showDatePreposition={hideLink}
|
showDatePreposition={hideLink}
|
||||||
{onClick}
|
{onClick}
|
||||||
{onReply}
|
|
||||||
>
|
>
|
||||||
<svelte:fragment slot="header">
|
<svelte:fragment slot="header">
|
||||||
<DocUpdateMessageHeader
|
<DocUpdateMessageHeader
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
<!--
|
|
||||||
// Copyright © 2023 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 size: 'tiny' | 'xx-small' | 'x-small' | 'small' | 'medium' | 'large' = 'small'
|
|
||||||
export let fill: string = 'currentColor'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<svg class="svg-{size}" {fill} viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path
|
|
||||||
fill-rule="evenodd"
|
|
||||||
clip-rule="evenodd"
|
|
||||||
d="M6 6.00012C6 3.79098 7.79086 2.00012 10 2.00012H22C24.2091 2.00012 26 3.79098 26 6.00012V29.0001C26 29.3689 25.797 29.7078 25.4719 29.8818C25.1467 30.0558 24.7522 30.0367 24.4453 29.8322L16 24.202L7.5547 29.8322C7.24784 30.0367 6.8533 30.0558 6.52814 29.8818C6.20298 29.7078 6 29.3689 6 29.0001V6.00012Z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
@ -1,26 +0,0 @@
|
|||||||
<!--
|
|
||||||
// Copyright © 2023 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 size: 'small' | 'medium' | 'large'
|
|
||||||
export let fill: string = 'currentColor'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<svg class="svg-{size}" {fill} viewBox="0 0 20 28" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<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"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
@ -1,52 +0,0 @@
|
|||||||
<!--
|
|
||||||
// Copyright © 2023 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 { createEventDispatcher } from 'svelte'
|
|
||||||
import { EmojiPopup, showPopup } from '@hcengineering/ui'
|
|
||||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
|
||||||
import activity, { ActivityMessage, Reaction } from '@hcengineering/activity'
|
|
||||||
|
|
||||||
import { updateDocReactions } from '../../utils'
|
|
||||||
import ActivityMessageAction from '../ActivityMessageAction.svelte'
|
|
||||||
|
|
||||||
export let object: ActivityMessage | undefined = undefined
|
|
||||||
|
|
||||||
const client = getClient()
|
|
||||||
|
|
||||||
const reactionsQuery = createQuery()
|
|
||||||
const dispatch = createEventDispatcher()
|
|
||||||
|
|
||||||
let reactions: Reaction[] = []
|
|
||||||
let isOpened = false
|
|
||||||
|
|
||||||
$: if (object?.reactions && object.reactions > 0) {
|
|
||||||
reactionsQuery.query(activity.class.Reaction, { attachedTo: object._id }, (res?: Reaction[]) => {
|
|
||||||
reactions = res || []
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function openEmojiPalette (ev: Event) {
|
|
||||||
dispatch('open')
|
|
||||||
showPopup(EmojiPopup, {}, ev.target as HTMLElement, (emoji: string) => {
|
|
||||||
updateDocReactions(client, reactions, object, emoji)
|
|
||||||
isOpened = false
|
|
||||||
dispatch('close')
|
|
||||||
})
|
|
||||||
|
|
||||||
isOpened = true
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<ActivityMessageAction icon={activity.icon.Emoji} action={openEmojiPalette} opened={isOpened} />
|
|
@ -28,6 +28,17 @@ import ActivityInfoMessagePreview from './components/activity-info-message/Activ
|
|||||||
|
|
||||||
import { attributesFilter, pinnedFilter, allFilter, referencesFilter } from './activityMessagesUtils'
|
import { attributesFilter, pinnedFilter, allFilter, referencesFilter } from './activityMessagesUtils'
|
||||||
import { updateReferences } from './references'
|
import { updateReferences } from './references'
|
||||||
|
import {
|
||||||
|
addReactionAction,
|
||||||
|
canPinMessage,
|
||||||
|
canRemoveFromSaved,
|
||||||
|
saveForLater,
|
||||||
|
unpinMessage,
|
||||||
|
pinMessage,
|
||||||
|
canSaveForLater,
|
||||||
|
canUnpinMessage,
|
||||||
|
removeFromSaved
|
||||||
|
} from './utils'
|
||||||
|
|
||||||
export * from './activity'
|
export * from './activity'
|
||||||
export * from './utils'
|
export * from './utils'
|
||||||
@ -42,7 +53,6 @@ export { default as ActivityDocLink } from './components/ActivityDocLink.svelte'
|
|||||||
export { default as ReactionPresenter } from './components/reactions/ReactionPresenter.svelte'
|
export { default as ReactionPresenter } from './components/reactions/ReactionPresenter.svelte'
|
||||||
export { default as ActivityMessageNotificationLabel } from './components/activity-message/ActivityMessageNotificationLabel.svelte'
|
export { default as ActivityMessageNotificationLabel } from './components/activity-message/ActivityMessageNotificationLabel.svelte'
|
||||||
export { default as ActivityMessageHeader } from './components/activity-message/ActivityMessageHeader.svelte'
|
export { default as ActivityMessageHeader } from './components/activity-message/ActivityMessageHeader.svelte'
|
||||||
export { default as AddReactionAction } from './components/reactions/AddReactionAction.svelte'
|
|
||||||
export { default as ActivityMessageAction } from './components/ActivityMessageAction.svelte'
|
export { default as ActivityMessageAction } from './components/ActivityMessageAction.svelte'
|
||||||
export { default as ActivityMessagesFilterPopup } from './components/FilterPopup.svelte'
|
export { default as ActivityMessagesFilterPopup } from './components/FilterPopup.svelte'
|
||||||
export { default as ActivityReferencePresenter } from './components/activity-reference/ActivityReferencePresenter.svelte'
|
export { default as ActivityReferencePresenter } from './components/activity-reference/ActivityReferencePresenter.svelte'
|
||||||
@ -70,7 +80,20 @@ export default async (): Promise<Resources> => ({
|
|||||||
AllFilter: allFilter,
|
AllFilter: allFilter,
|
||||||
ReferencesFilter: referencesFilter
|
ReferencesFilter: referencesFilter
|
||||||
},
|
},
|
||||||
|
function: {
|
||||||
|
CanSaveForLater: canSaveForLater,
|
||||||
|
CanRemoveFromSaved: canRemoveFromSaved,
|
||||||
|
CanPinMessage: canPinMessage,
|
||||||
|
CanUnpinMessage: canUnpinMessage
|
||||||
|
},
|
||||||
backreference: {
|
backreference: {
|
||||||
Update: updateReferences
|
Update: updateReferences
|
||||||
|
},
|
||||||
|
actionImpl: {
|
||||||
|
AddReaction: addReactionAction,
|
||||||
|
SaveForLater: saveForLater,
|
||||||
|
RemoveFromSaved: removeFromSaved,
|
||||||
|
PinMessage: pinMessage,
|
||||||
|
UnpinMessage: unpinMessage
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -20,18 +20,23 @@ import core, {
|
|||||||
getCurrentAccount
|
getCurrentAccount
|
||||||
} from '@hcengineering/core'
|
} from '@hcengineering/core'
|
||||||
import { type Asset, type IntlString, getResource, translate } from '@hcengineering/platform'
|
import { type Asset, type IntlString, getResource, translate } from '@hcengineering/platform'
|
||||||
import { getAttributePresenterClass } from '@hcengineering/presentation'
|
import { getAttributePresenterClass, getClient } from '@hcengineering/presentation'
|
||||||
import {
|
import {
|
||||||
type AnyComponent,
|
type AnyComponent,
|
||||||
type AnySvelteComponent,
|
type AnySvelteComponent,
|
||||||
ErrorPresenter,
|
ErrorPresenter,
|
||||||
themeStore,
|
themeStore,
|
||||||
type Location
|
type Location,
|
||||||
|
getEventPositionElement,
|
||||||
|
closePopup,
|
||||||
|
showPopup,
|
||||||
|
EmojiPopup
|
||||||
} from '@hcengineering/ui'
|
} from '@hcengineering/ui'
|
||||||
import view, { type AttributeModel, type BuildModelKey, type BuildModelOptions } from '@hcengineering/view'
|
import view, { type AttributeModel, type BuildModelKey, type BuildModelOptions } from '@hcengineering/view'
|
||||||
import { getObjectPresenter } from '@hcengineering/view-resources'
|
import { getObjectPresenter } from '@hcengineering/view-resources'
|
||||||
|
import preference from '@hcengineering/preference'
|
||||||
|
|
||||||
import { type ActivityKey, activityKey } from './activity'
|
import { type ActivityKey, activityKey, savedMessagesStore } from './activity'
|
||||||
import activity from './plugin'
|
import activity from './plugin'
|
||||||
|
|
||||||
const valueTypes: ReadonlyArray<Ref<Class<Doc>>> = [
|
const valueTypes: ReadonlyArray<Ref<Class<Doc>>> = [
|
||||||
@ -427,3 +432,90 @@ export async function updateDocReactions (
|
|||||||
export function getMessageFromLoc (loc: Location): Ref<ActivityMessage> | undefined {
|
export function getMessageFromLoc (loc: Location): Ref<ActivityMessage> | undefined {
|
||||||
return (loc.query?.message ?? undefined) as Ref<ActivityMessage> | undefined
|
return (loc.query?.message ?? undefined) as Ref<ActivityMessage> | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ActivityMessageActionParams {
|
||||||
|
onClose?: () => void
|
||||||
|
onOpen?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function addReactionAction (
|
||||||
|
message?: ActivityMessage,
|
||||||
|
ev?: MouseEvent,
|
||||||
|
params?: ActivityMessageActionParams
|
||||||
|
): Promise<void> {
|
||||||
|
if (message === undefined || ev === undefined) return
|
||||||
|
|
||||||
|
const client = getClient()
|
||||||
|
const reactions: Reaction[] =
|
||||||
|
(message.reactions ?? 0) > 0
|
||||||
|
? await client.findAll<Reaction>(activity.class.Reaction, { attachedTo: message._id })
|
||||||
|
: []
|
||||||
|
const element = getEventPositionElement(ev)
|
||||||
|
|
||||||
|
closePopup()
|
||||||
|
|
||||||
|
showPopup(EmojiPopup, {}, element, (emoji: string) => {
|
||||||
|
void updateDocReactions(client, reactions, message, emoji)
|
||||||
|
params?.onClose?.()
|
||||||
|
})
|
||||||
|
params?.onOpen?.()
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function saveForLater (message?: ActivityMessage): Promise<void> {
|
||||||
|
if (message === undefined) return
|
||||||
|
closePopup()
|
||||||
|
const client = getClient()
|
||||||
|
|
||||||
|
await client.createDoc(activity.class.SavedMessage, preference.space.Preference, {
|
||||||
|
attachedTo: message._id
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function removeFromSaved (message?: ActivityMessage): Promise<void> {
|
||||||
|
if (message === undefined) return
|
||||||
|
closePopup()
|
||||||
|
const client = getClient()
|
||||||
|
const saved = get(savedMessagesStore).find((saved) => saved.attachedTo === message._id)
|
||||||
|
|
||||||
|
if (saved !== undefined) {
|
||||||
|
await client.removeDoc(saved._class, saved.space, saved._id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function canSaveForLater (message?: ActivityMessage): Promise<boolean> {
|
||||||
|
if (message === undefined) return false
|
||||||
|
|
||||||
|
const saved = get(savedMessagesStore).find((saved) => saved.attachedTo === message._id)
|
||||||
|
|
||||||
|
return saved === undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function canRemoveFromSaved (message?: ActivityMessage): Promise<boolean> {
|
||||||
|
if (message === undefined) return false
|
||||||
|
|
||||||
|
return !(await canSaveForLater(message))
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function canPinMessage (message?: ActivityMessage): Promise<boolean> {
|
||||||
|
return message !== undefined && message.isPinned !== true
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function canUnpinMessage (message?: ActivityMessage): Promise<boolean> {
|
||||||
|
return message !== undefined && message.isPinned === true
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function pinMessage (message?: ActivityMessage): Promise<void> {
|
||||||
|
if (message === undefined) return
|
||||||
|
closePopup()
|
||||||
|
const client = getClient()
|
||||||
|
|
||||||
|
await client.update(message, { isPinned: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function unpinMessage (message?: ActivityMessage): Promise<void> {
|
||||||
|
if (message === undefined) return
|
||||||
|
closePopup()
|
||||||
|
const client = getClient()
|
||||||
|
|
||||||
|
await client.update(message, { isPinned: false })
|
||||||
|
}
|
||||||
|
@ -157,16 +157,6 @@ export interface ActivityInfoMessage extends ActivityMessage {
|
|||||||
links?: { _class: Ref<Class<Doc>>, _id: Ref<Doc> }[]
|
links?: { _class: Ref<Class<Doc>>, _id: Ref<Doc> }[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ActivityMessageExtensionKind = 'action' | 'footer'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
export interface ActivityMessageExtension extends Doc {
|
|
||||||
ofMessage: Ref<Class<ActivityMessage>>
|
|
||||||
components: { kind: ActivityMessageExtensionKind, component: AnyComponent }[]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@ -333,7 +323,6 @@ export default plugin(activityId, {
|
|||||||
ActivityInfoMessage: '' as Ref<Class<ActivityInfoMessage>>,
|
ActivityInfoMessage: '' as Ref<Class<ActivityInfoMessage>>,
|
||||||
ActivityMessageControl: '' as Ref<Class<ActivityMessageControl>>,
|
ActivityMessageControl: '' as Ref<Class<ActivityMessageControl>>,
|
||||||
DocUpdateMessageViewlet: '' as Ref<Class<DocUpdateMessageViewlet>>,
|
DocUpdateMessageViewlet: '' as Ref<Class<DocUpdateMessageViewlet>>,
|
||||||
ActivityMessageExtension: '' as Ref<Class<ActivityMessageExtension>>,
|
|
||||||
ActivityMessagesFilter: '' as Ref<Class<ActivityMessagesFilter>>,
|
ActivityMessagesFilter: '' as Ref<Class<ActivityMessagesFilter>>,
|
||||||
ActivityExtension: '' as Ref<Class<ActivityExtension>>,
|
ActivityExtension: '' as Ref<Class<ActivityExtension>>,
|
||||||
Reaction: '' as Ref<Class<Reaction>>,
|
Reaction: '' as Ref<Class<Reaction>>,
|
||||||
@ -344,7 +333,8 @@ export default plugin(activityId, {
|
|||||||
icon: {
|
icon: {
|
||||||
Activity: '' as Asset,
|
Activity: '' as Asset,
|
||||||
Emoji: '' as Asset,
|
Emoji: '' as Asset,
|
||||||
Bookmark: '' as Asset
|
Bookmark: '' as Asset,
|
||||||
|
BookmarkFilled: '' as Asset
|
||||||
},
|
},
|
||||||
string: {
|
string: {
|
||||||
Activity: '' as IntlString,
|
Activity: '' as IntlString,
|
||||||
|
@ -1,32 +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">
|
|
||||||
import { ActivityMessage } from '@hcengineering/activity'
|
|
||||||
import { ActivityMessageAction } from '@hcengineering/activity-resources'
|
|
||||||
|
|
||||||
import chunter from './../plugin'
|
|
||||||
import { replyToThread } from '../index'
|
|
||||||
import { canReplyToThread } from '../utils'
|
|
||||||
|
|
||||||
export let object: ActivityMessage
|
|
||||||
|
|
||||||
function onReply (): void {
|
|
||||||
replyToThread(object)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#if canReplyToThread(object)}
|
|
||||||
<ActivityMessageAction size="small" icon={chunter.icon.Thread} action={onReply} />
|
|
||||||
{/if}
|
|
@ -50,7 +50,6 @@
|
|||||||
export let hideLink = false
|
export let hideLink = false
|
||||||
export let compact = false
|
export let compact = false
|
||||||
export let onClick: (() => void) | undefined = undefined
|
export let onClick: (() => void) | undefined = undefined
|
||||||
export let onReply: (() => void) | undefined = undefined
|
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
const hierarchy = client.getHierarchy()
|
const hierarchy = client.getHierarchy()
|
||||||
@ -183,7 +182,6 @@
|
|||||||
{skipLabel}
|
{skipLabel}
|
||||||
showDatePreposition={hideLink}
|
showDatePreposition={hideLink}
|
||||||
{onClick}
|
{onClick}
|
||||||
{onReply}
|
|
||||||
>
|
>
|
||||||
<svelte:fragment slot="header">
|
<svelte:fragment slot="header">
|
||||||
<ChatMessageHeader {object} {parentObject} message={value} {viewlet} {person} {skipLabel} {hideLink} />
|
<ChatMessageHeader {object} {parentObject} message={value} {viewlet} {person} {skipLabel} {hideLink} />
|
||||||
|
@ -40,7 +40,6 @@
|
|||||||
export let attachmentImageSize: AttachmentImageSize = 'x-large'
|
export let attachmentImageSize: AttachmentImageSize = 'x-large'
|
||||||
export let videoPreload = true
|
export let videoPreload = true
|
||||||
export let onClick: (() => void) | undefined = undefined
|
export let onClick: (() => void) | undefined = undefined
|
||||||
export let onReply: (() => void) | undefined = undefined
|
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
</script>
|
</script>
|
||||||
@ -76,6 +75,5 @@
|
|||||||
{videoPreload}
|
{videoPreload}
|
||||||
showLinksPreview={false}
|
showLinksPreview={false}
|
||||||
{onClick}
|
{onClick}
|
||||||
{onReply}
|
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -48,7 +48,6 @@ import ChannelIcon from './components/ChannelIcon.svelte'
|
|||||||
import ThreadNotificationPresenter from './components/notification/ThreadNotificationPresenter.svelte'
|
import ThreadNotificationPresenter from './components/notification/ThreadNotificationPresenter.svelte'
|
||||||
import ChatMessageNotificationLabel from './components/notification/ChatMessageNotificationLabel.svelte'
|
import ChatMessageNotificationLabel from './components/notification/ChatMessageNotificationLabel.svelte'
|
||||||
import ChatAside from './components/chat/ChatAside.svelte'
|
import ChatAside from './components/chat/ChatAside.svelte'
|
||||||
import ReplyToThreadAction from './components/ReplyToThreadAction.svelte'
|
|
||||||
import ThreadMessagePreview from './components/threads/ThreadMessagePreview.svelte'
|
import ThreadMessagePreview from './components/threads/ThreadMessagePreview.svelte'
|
||||||
import ChatMessagePreview from './components/chat-message/ChatMessagePreview.svelte'
|
import ChatMessagePreview from './components/chat-message/ChatMessagePreview.svelte'
|
||||||
|
|
||||||
@ -62,7 +61,8 @@ import {
|
|||||||
getUnreadThreadsCount,
|
getUnreadThreadsCount,
|
||||||
canCopyMessageLink,
|
canCopyMessageLink,
|
||||||
leaveChannelAction,
|
leaveChannelAction,
|
||||||
removeChannelAction
|
removeChannelAction,
|
||||||
|
canReplyToThread
|
||||||
} from './utils'
|
} from './utils'
|
||||||
import {
|
import {
|
||||||
chunterSpaceLinkFragmentProvider,
|
chunterSpaceLinkFragmentProvider,
|
||||||
@ -180,7 +180,6 @@ export default async (): Promise<Resources> => ({
|
|||||||
ChatMessageNotificationLabel,
|
ChatMessageNotificationLabel,
|
||||||
ThreadNotificationPresenter,
|
ThreadNotificationPresenter,
|
||||||
ChatAside,
|
ChatAside,
|
||||||
ReplyToThreadAction,
|
|
||||||
ThreadMessagePreview,
|
ThreadMessagePreview,
|
||||||
ChatMessagePreview
|
ChatMessagePreview
|
||||||
},
|
},
|
||||||
@ -197,8 +196,9 @@ export default async (): Promise<Resources> => ({
|
|||||||
GetChunterSpaceLinkFragment: chunterSpaceLinkFragmentProvider,
|
GetChunterSpaceLinkFragment: chunterSpaceLinkFragmentProvider,
|
||||||
GetUnreadThreadsCount: getUnreadThreadsCount,
|
GetUnreadThreadsCount: getUnreadThreadsCount,
|
||||||
GetThreadLink: getThreadLink,
|
GetThreadLink: getThreadLink,
|
||||||
GetMessageLink: getMessageLocation,
|
ReplyToThread: replyToThread,
|
||||||
ReplyToThread: replyToThread
|
CanReplyToThread: canReplyToThread,
|
||||||
|
GetMessageLink: getMessageLocation
|
||||||
},
|
},
|
||||||
actionImpl: {
|
actionImpl: {
|
||||||
ArchiveChannel,
|
ArchiveChannel,
|
||||||
@ -206,6 +206,7 @@ export default async (): Promise<Resources> => ({
|
|||||||
ConvertDmToPrivateChannel,
|
ConvertDmToPrivateChannel,
|
||||||
DeleteChatMessage: deleteChatMessage,
|
DeleteChatMessage: deleteChatMessage,
|
||||||
LeaveChannel: leaveChannelAction,
|
LeaveChannel: leaveChannelAction,
|
||||||
RemoveChannel: removeChannelAction
|
RemoveChannel: removeChannelAction,
|
||||||
|
ReplyToThread: replyToThread
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -138,8 +138,6 @@ export default plugin(chunterId, {
|
|||||||
ChatMessagePresenter: '' as AnyComponent,
|
ChatMessagePresenter: '' as AnyComponent,
|
||||||
ThreadMessagePresenter: '' as AnyComponent,
|
ThreadMessagePresenter: '' as AnyComponent,
|
||||||
ChatAside: '' as AnyComponent,
|
ChatAside: '' as AnyComponent,
|
||||||
Replies: '' as AnyComponent,
|
|
||||||
ReplyToThreadAction: '' as AnyComponent,
|
|
||||||
ChatMessagePreview: '' as AnyComponent,
|
ChatMessagePreview: '' as AnyComponent,
|
||||||
ThreadMessagePreview: '' as AnyComponent
|
ThreadMessagePreview: '' as AnyComponent
|
||||||
},
|
},
|
||||||
|
@ -119,6 +119,7 @@
|
|||||||
"ToViewCommands": "to view available commands",
|
"ToViewCommands": "to view available commands",
|
||||||
"UnArchive": "Unarchive",
|
"UnArchive": "Unarchive",
|
||||||
"Pin": "Pin",
|
"Pin": "Pin",
|
||||||
"Unpin": "Unpin"
|
"Unpin": "Unpin",
|
||||||
|
"MoreActions": "More actions"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,7 @@
|
|||||||
"ToViewCommands": "чтобы увидеть команды",
|
"ToViewCommands": "чтобы увидеть команды",
|
||||||
"UnArchive": "Разархивировать",
|
"UnArchive": "Разархивировать",
|
||||||
"Pin": "Закрепить",
|
"Pin": "Закрепить",
|
||||||
"Unpin": "Открепить"
|
"Unpin": "Открепить",
|
||||||
|
"MoreActions": "Больше действий"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,8 @@ const view = plugin(viewId, {
|
|||||||
Type: '' as IntlString,
|
Type: '' as IntlString,
|
||||||
UnArchive: '' as IntlString,
|
UnArchive: '' as IntlString,
|
||||||
Save: '' as IntlString,
|
Save: '' as IntlString,
|
||||||
PublicView: '' as IntlString
|
PublicView: '' as IntlString,
|
||||||
|
MoreActions: '' as IntlString
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
Table: '' as Asset,
|
Table: '' as Asset,
|
||||||
|
Loading…
Reference in New Issue
Block a user