feat(core): add CLI management for tenant system stores
Signed-off-by: Sebastian <krupinski01@gmail.com>
This commit is contained in:
@@ -80,8 +80,8 @@ final class CompositionController extends ControllerAbstract {
|
||||
if (!isset($data['action']) || !is_string($data['action'])) {
|
||||
throw new InvalidArgumentException('Invalid parameter: action must be a string');
|
||||
}
|
||||
if (!in_array($data['action'], ['fresh', 'reply', 'forward'], true)) {
|
||||
throw new InvalidArgumentException('Invalid parameter: action must be one of fresh, reply, forward');
|
||||
if (!in_array($data['action'], ['fresh', 'reply', 'replyAll', 'forward'], true)) {
|
||||
throw new InvalidArgumentException('Invalid parameter: action must be one of fresh, reply, replyAll, forward');
|
||||
}
|
||||
if (!isset($data['sender']) || !is_array($data['sender'])) {
|
||||
throw new InvalidArgumentException('Invalid parameter: sender must be an array');
|
||||
@@ -89,8 +89,8 @@ final class CompositionController extends ControllerAbstract {
|
||||
if (!isset($data['message']) || !is_array($data['message'])) {
|
||||
throw new InvalidArgumentException('Invalid parameter: message must be an array');
|
||||
}
|
||||
if (($data['action'] === 'reply' || $data['action'] === 'forward') && (!isset($data['source']) || !is_string($data['source']) || $data['source'] === '')) {
|
||||
throw new InvalidArgumentException('Invalid parameter: source must be a non-empty string for reply or forward action');
|
||||
if (($data['action'] === 'reply' || $data['action'] === 'replyAll' || $data['action'] === 'forward') && (!isset($data['source']) || !is_string($data['source']) || $data['source'] === '')) {
|
||||
throw new InvalidArgumentException('Invalid parameter: source must be a non-empty string for reply, replyAll, or forward action');
|
||||
}
|
||||
|
||||
return $this->compositionManager->stage($tenantId, $userId, $data['identifier'], $data['action'], $data['sender'], $data['message'], $data['source'] ?? null);
|
||||
|
||||
@@ -19,6 +19,7 @@ const props = defineProps<{
|
||||
// Emits
|
||||
const emit = defineEmits<{
|
||||
reply: [entity: EntityObject]
|
||||
replyAll: [entity: EntityObject]
|
||||
forward: [entity: EntityObject]
|
||||
move: [entity: EntityObject]
|
||||
delete: [entity: EntityObject]
|
||||
@@ -107,6 +108,12 @@ const handleReply = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleReplyAll = () => {
|
||||
if (props.entity) {
|
||||
emit('replyAll', props.entity)
|
||||
}
|
||||
}
|
||||
|
||||
const handleForward = () => {
|
||||
if (props.entity) {
|
||||
emit('forward', props.entity)
|
||||
@@ -176,6 +183,7 @@ const handleViewerDownload = (item: MediaViewerItem) => {
|
||||
:security-level="effectiveSecurityLevel"
|
||||
:is-security-overridden="overrideSecurityLevel !== null"
|
||||
@reply="handleReply"
|
||||
@reply-all="handleReplyAll"
|
||||
@forward="handleForward"
|
||||
@move="handleMove"
|
||||
@delete="handleDelete"
|
||||
|
||||
@@ -30,7 +30,7 @@ defineEmits<{
|
||||
</v-btn>
|
||||
|
||||
<v-toolbar-title>
|
||||
{{ mode === ComposerMode.Reply ? 'Reply' : mode === ComposerMode.Forward ? 'Forward' : 'New Message' }}
|
||||
{{ mode === ComposerMode.Reply ? 'Reply' : mode === ComposerMode.ReplyAll ? 'Reply All' : mode === ComposerMode.Forward ? 'Forward' : 'New Message' }}
|
||||
</v-toolbar-title>
|
||||
|
||||
<v-spacer />
|
||||
|
||||
@@ -13,6 +13,7 @@ const props = defineProps<Props>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
reply: []
|
||||
replyAll: []
|
||||
forward: []
|
||||
move: []
|
||||
delete: []
|
||||
@@ -47,7 +48,7 @@ const currentSecurityLevel = computed(() => {
|
||||
<v-btn
|
||||
icon="mdi-reply-all"
|
||||
variant="text"
|
||||
@click="emit('reply')"
|
||||
@click="emit('replyAll')"
|
||||
>
|
||||
<v-icon>mdi-reply-all</v-icon>
|
||||
<v-tooltip activator="parent" location="bottom">Reply All</v-tooltip>
|
||||
|
||||
@@ -167,6 +167,8 @@ const handleMessageComposeFresh = () => mailUiStore.openComposer()
|
||||
|
||||
const handleMessageComposeReply = (message: EntityObject) => mailUiStore.openComposer(message, ComposerMode.Reply)
|
||||
|
||||
const handleMessageComposeReplyAll = (message: EntityObject) => mailUiStore.openComposer(message, ComposerMode.ReplyAll)
|
||||
|
||||
const handleMessageComposeForward = (message: EntityObject) => mailUiStore.openComposer(message, ComposerMode.Forward)
|
||||
|
||||
const handleMessageComposeClose = () => mailUiStore.closeComposer()
|
||||
@@ -339,6 +341,7 @@ const handleMessageSelectionDelete = () => mailUiStore.deleteSelectedMessages()
|
||||
:entity="selectedMessage"
|
||||
@compose="handleMessageComposeFresh"
|
||||
@reply="handleMessageComposeReply"
|
||||
@reply-all="handleMessageComposeReplyAll"
|
||||
@forward="handleMessageComposeForward"
|
||||
@move="handleMessageMove"
|
||||
@delete="handleMessageDelete"
|
||||
|
||||
@@ -118,7 +118,8 @@ export const useMailCompositionStore = defineStore('mailCompositionStore', () =>
|
||||
return
|
||||
}
|
||||
|
||||
activeDraft.value = buildDraft(mode, sender, source)
|
||||
const ownAddresses = senderIdentities.value.map(identity => identity.address)
|
||||
activeDraft.value = buildDraft(mode, sender, source, ownAddresses)
|
||||
activeDraft.value.action = mode
|
||||
|
||||
stageDraft()
|
||||
@@ -558,9 +559,9 @@ export const useMailCompositionStore = defineStore('mailCompositionStore', () =>
|
||||
}
|
||||
})
|
||||
|
||||
function buildDraft(mode: ComposerMode, sender: ComposerSenderIdentity, source?: EntityObject | MessageAddressObject | null): ComposerDraft {
|
||||
function buildDraft(mode: ComposerMode, sender: ComposerSenderIdentity, source: EntityObject | MessageAddressObject | null | undefined, ownAddresses: string[]): ComposerDraft {
|
||||
const composition = createIdentifier()
|
||||
const freshMessage = buildMessage(mode, source)
|
||||
const freshMessage = buildMessage(mode, source, ownAddresses)
|
||||
const freshAttachments = buildAttachments(composition, mode, source)
|
||||
const sourceIdentifier = source instanceof EntityObject ? source.identifier : null
|
||||
return {
|
||||
@@ -576,7 +577,7 @@ function buildDraft(mode: ComposerMode, sender: ComposerSenderIdentity, source?:
|
||||
}
|
||||
}
|
||||
|
||||
function buildMessage(mode: ComposerMode, source: EntityObject | MessageAddressObject | null | undefined): ComposerDraftMessage {
|
||||
function buildMessage(mode: ComposerMode, source: EntityObject | MessageAddressObject | null | undefined, ownAddresses: string[] = []): ComposerDraftMessage {
|
||||
|
||||
if (!source) {
|
||||
return emptyMessage()
|
||||
@@ -603,12 +604,28 @@ function buildMessage(mode: ComposerMode, source: EntityObject | MessageAddressO
|
||||
const sentAt = sourceMessage.sent || source.created || ''
|
||||
const sentLabel = sentAt ? new Date(sentAt).toLocaleString() : 'an unknown time'
|
||||
|
||||
if (mode === ComposerMode.Reply) {
|
||||
if (mode === ComposerMode.Reply || mode === ComposerMode.ReplyAll) {
|
||||
const replyToAddr = sourceMessage.replyTo?.[0] ?? sourceMessage.from ?? null
|
||||
const replyToAddress = replyToAddr?.address || ''
|
||||
const to: MessageAddressInterface[] = replyToAddress ? [{ address: replyToAddress, label: replyToAddr?.label }] : []
|
||||
|
||||
let cc: MessageAddressInterface[] = []
|
||||
if (mode === ComposerMode.ReplyAll) {
|
||||
const excluded = new Set([replyToAddress.toLowerCase(), ...ownAddresses.map(addr => addr.toLowerCase())])
|
||||
const seen = new Set<string>()
|
||||
cc = [...(sourceMessage.to || []), ...(sourceMessage.cc || [])].filter(recipient => {
|
||||
const address = recipient.address?.toLowerCase() || ''
|
||||
if (!address || excluded.has(address) || seen.has(address)) {
|
||||
return false
|
||||
}
|
||||
seen.add(address)
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
to: replyToAddress ? [{ address: replyToAddress, label: replyToAddr?.label }] : [],
|
||||
cc: [],
|
||||
to,
|
||||
cc,
|
||||
bcc: [],
|
||||
subject: /^Re:/i.test(originalSubject) ? originalSubject : `Re: ${originalSubject}`,
|
||||
body: {
|
||||
@@ -631,7 +648,7 @@ function buildMessage(mode: ComposerMode, source: EntityObject | MessageAddressO
|
||||
}
|
||||
|
||||
function buildAttachments(composition: string, mode: ComposerMode, source?: EntityObject | MessageAddressObject | null): Record<string, ComposerDraftAttachment> {
|
||||
if (mode === ComposerMode.Fresh || mode === ComposerMode.Reply || !(source instanceof EntityObject)) {
|
||||
if (mode === ComposerMode.Fresh || mode === ComposerMode.Reply || mode === ComposerMode.ReplyAll || !(source instanceof EntityObject)) {
|
||||
return {}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import type { MessageAddressInterface } from "@MailManager/types/message"
|
||||
export enum ComposerMode {
|
||||
Fresh = 'fresh',
|
||||
Reply = 'reply',
|
||||
ReplyAll = 'replyAll',
|
||||
Forward = 'forward',
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user