diff --git a/src/apps/admin/mailbrokermanagerapp/MailbrokerManager.svelte b/src/apps/admin/mailbrokermanagerapp/MailbrokerManager.svelte new file mode 100644 index 000000000..9ce1a8209 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/MailbrokerManager.svelte @@ -0,0 +1,57 @@ + + + +
+ +
+ {#if loading} + + {:else if Page && data?.success} + {@const result = data.result!} + + {:else} +
+
+ +
+

The page failed to load

+

{data?.errorMessage ?? "An unknown error occurred."}

+
+
+
+ {/if} +
+
diff --git a/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/SentRecordPills.svelte b/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/SentRecordPills.svelte new file mode 100644 index 000000000..ed9f06918 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/SentRecordPills.svelte @@ -0,0 +1,23 @@ + + +
+
+ + {formatBytes(sentRecord.htmlContent.length)} +
+
+ + {formatBytes(sentRecord.textContent.length)} +
+ {#if sentRecord.to.username && sentRecord.to.serverName} +
+ + To a user +
+ {/if} +
diff --git a/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/ServerKeyPills.svelte b/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/ServerKeyPills.svelte new file mode 100644 index 000000000..1f3128d23 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/ServerKeyPills.svelte @@ -0,0 +1,24 @@ + + +
+ {#if disabled} +
+ Disabled +
+ {:else} +
+ Enabled +
+ {/if} + {#if serverKey.serverName === "arcapi.nl"} +
Master key
+ {/if} + {#if Server.hostname === serverKey.serverName} +
This server
+ {/if} +
diff --git a/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/Sidebar.svelte b/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/Sidebar.svelte new file mode 100644 index 000000000..0f37a2d60 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/Sidebar.svelte @@ -0,0 +1,24 @@ + + +
+ +
diff --git a/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/TemplateListing.svelte b/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/TemplateListing.svelte new file mode 100644 index 000000000..191f2e724 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/TemplateListing.svelte @@ -0,0 +1,76 @@ + + +
+
+

{filteredTemplates.length} {Plural("template", filteredTemplates.length)}

+ + {#if !hideNewButton && process.admin.canAccess(AdminScopes.adminMailbrokerTemplatesWrite)} + + {/if} +
+ +
+ {#each filteredTemplates as template (template._id)} + + {/each} + + {#if !filteredTemplates.length} +

+ There are no templates that match the criteria. +

+ {/if} +
+
diff --git a/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/TemplateListing/ListingOption.svelte b/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/TemplateListing/ListingOption.svelte new file mode 100644 index 000000000..2dccedcbb --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/TemplateListing/ListingOption.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/TemplatePills.svelte b/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/TemplatePills.svelte new file mode 100644 index 000000000..47109e684 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/MailbrokerManager/TemplatePills.svelte @@ -0,0 +1,20 @@ + + +
+
+ + {formatBytes(template.htmlContent.length)} +
+
+ + {formatBytes(template.textContent.length)} +
+ {#if deprecated} +
Deprecated
+ {/if} +
diff --git a/src/apps/admin/mailbrokermanagerapp/MailbrokerManagerApp.ts b/src/apps/admin/mailbrokermanagerapp/MailbrokerManagerApp.ts new file mode 100644 index 000000000..781fb6a91 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/MailbrokerManagerApp.ts @@ -0,0 +1,44 @@ +import "$css/apps/admin/mailbroker.css"; +import type { App } from "$types/apps/app"; +import MailbrokerManager from "./MailbrokerManager.svelte"; +import { MailbrokerManagerRuntime } from "./runtime"; + +const MailbrokerManagerApp: App = { + metadata: { + name: "Mailbroker Manager", + version: "1.0.0", + author: "Izaak Kuipers", + appGroup: "adminTools", + icon: "MailbrokerAdminIcon", + }, + position: { centered: true }, + size: { w: 800, h: 480 }, + minSize: { w: 800, h: 480 }, + maxSize: { w: NaN, h: NaN }, + state: { + maximized: false, + minimized: false, + resizable: true, + fullscreen: false, + headless: true, + }, + controls: { + minimize: true, + maximize: true, + close: true, + }, + assets: { + runtime: MailbrokerManagerRuntime, + component: MailbrokerManager as any, + }, + glass: true, + elevated: true, + hidden: false, + core: false, + overlay: false, + noSafeMode: false, + vital: true, + id: "MailbrokerManagerApp", +}; + +export default MailbrokerManagerApp; diff --git a/src/apps/admin/mailbrokermanagerapp/Overlays/NewKeyOverlay/NewKey.svelte b/src/apps/admin/mailbrokermanagerapp/Overlays/NewKeyOverlay/NewKey.svelte new file mode 100644 index 000000000..ae97c6570 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Overlays/NewKeyOverlay/NewKey.svelte @@ -0,0 +1,49 @@ + + +
+ +
+

New server key

+

Enter the name of the server for which you want to create the server key:

+ +
+
+ + + {#snippet rightContent()} + process.closeWindow()}>Cancel + Create + {/snippet} + diff --git a/src/apps/admin/mailbrokermanagerapp/Overlays/NewKeyOverlay/NewKeyOverlay.ts b/src/apps/admin/mailbrokermanagerapp/Overlays/NewKeyOverlay/NewKeyOverlay.ts new file mode 100644 index 000000000..9198073ff --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Overlays/NewKeyOverlay/NewKeyOverlay.ts @@ -0,0 +1,45 @@ +import type { App } from "$types/apps/app"; +import NewKey from "./NewKey.svelte"; +import { MailbrokerNewKeyOverlayRuntime } from "./runtime"; + +const NewKeyOverlay: App = { + metadata: { + name: "New mailbroker key", + author: "Izaak Kuipers", + version: "1.0.0", + icon: "MailbrokerAdminIcon", + }, + position: { centered: true }, + size: { + w: 380, + h: 200, + }, + minSize: { + w: 380, + h: 200, + }, + maxSize: { + w: 380, + h: 200, + }, + controls: { + minimize: false, + maximize: false, + close: true, + }, + state: { + resizable: false, + headless: true, + fullscreen: false, + maximized: false, + minimized: false, + }, + assets: { + runtime: MailbrokerNewKeyOverlayRuntime, + component: NewKey as any, + }, + hidden: true, + id: "MailbrokerManagerApp_NewKeyOverlay", +}; + +export default NewKeyOverlay; diff --git a/src/apps/admin/mailbrokermanagerapp/Overlays/NewKeyOverlay/runtime.ts b/src/apps/admin/mailbrokermanagerapp/Overlays/NewKeyOverlay/runtime.ts new file mode 100644 index 000000000..4c958dfbc --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Overlays/NewKeyOverlay/runtime.ts @@ -0,0 +1,19 @@ +import type { IMailbrokerManagerRuntime, IMailbrokerNewKeyOverlayRuntime } from "$interfaces/runtimes/IMailbrokerRuntime"; +import type { IAdminBootstrapper } from "$interfaces/services/IAdminBootstrapper"; +import { AppProcess } from "$ts/apps/process"; +import { Daemon, Stack } from "$ts/env"; +import type { AppProcessData } from "$types/apps/app"; + +export class MailbrokerNewKeyOverlayRuntime extends AppProcess implements IMailbrokerNewKeyOverlayRuntime { + get admin() { + return Daemon.serviceHost?.getService("AdminBootstrapper")!; + } + + get parent() { + return Stack.getProcess(this.parentPid)!; + } + + constructor(pid: number, parentPid: number, app: AppProcessData) { + super(pid, parentPid, app); + } +} diff --git a/src/apps/admin/mailbrokermanagerapp/Overlays/SendOverlay/SendOverlay.svelte b/src/apps/admin/mailbrokermanagerapp/Overlays/SendOverlay/SendOverlay.svelte new file mode 100644 index 000000000..a3e2955bb --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Overlays/SendOverlay/SendOverlay.svelte @@ -0,0 +1,103 @@ + + +
+ + +
+ +
+ {#each process.properties as property (property.name)} +
+

{property.name}

+
+ {#if property.isUser} + {#if property.variant === MailbrokerSendOverlay.PropertyVariant.UserId} + + + {:else if property.variant === MailbrokerSendOverlay.PropertyVariant.Username} + + + {/if} + {:else if property.variant === MailbrokerSendOverlay.PropertyVariant.Url} + + + {:else} + + + {/if} +
+
+ {/each} +
+ + + {#snippet leftContent()} + {#if process.template?.deprecated} + Deprecated template + {/if} + {/snippet} + {#snippet rightContent()} + process.closeWindow()}>Cancel + Send + {/snippet} + diff --git a/src/apps/admin/mailbrokermanagerapp/Overlays/SendOverlay/SendOverlay.ts b/src/apps/admin/mailbrokermanagerapp/Overlays/SendOverlay/SendOverlay.ts new file mode 100644 index 000000000..553239f52 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Overlays/SendOverlay/SendOverlay.ts @@ -0,0 +1,45 @@ +import type { App } from "$types/apps/app"; +import { MailbrokerSendOverlayRuntime } from "./runtime"; +import SendOverlaySvelte from "./SendOverlay.svelte"; + +const SendOverlay: App = { + metadata: { + name: "Send mailbroker template", + author: "Izaak Kuipers", + version: "1.0.0", + icon: "MailbrokerAdminIcon", + }, + position: { centered: true }, + size: { + w: 450, + h: 300, + }, + minSize: { + w: 450, + h: 300, + }, + maxSize: { + w: 450, + h: 300, + }, + controls: { + minimize: false, + maximize: false, + close: true, + }, + state: { + resizable: false, + headless: true, + fullscreen: false, + maximized: false, + minimized: false, + }, + assets: { + runtime: MailbrokerSendOverlayRuntime, + component: SendOverlaySvelte as any, + }, + hidden: true, + id: "MailbrokerManagerApp_SendOverlay", +}; + +export default SendOverlay; \ No newline at end of file diff --git a/src/apps/admin/mailbrokermanagerapp/Overlays/SendOverlay/runtime.ts b/src/apps/admin/mailbrokermanagerapp/Overlays/SendOverlay/runtime.ts new file mode 100644 index 000000000..e9d0c08be --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Overlays/SendOverlay/runtime.ts @@ -0,0 +1,92 @@ +import type { IMailbrokerSendOverlayRuntime } from "$interfaces/runtimes/IMailbrokerRuntime"; +import type { IAdminBootstrapper } from "$interfaces/services/IAdminBootstrapper"; +import { AppProcess } from "$ts/apps/process"; +import { Daemon } from "$ts/env"; +import { BTN_OKAY_SUG, MessageBox } from "$ts/util/dialog"; +import type { AppProcessData } from "$types/apps/app"; +import type { User } from "$types/server/admin"; +import type { Mailbroker } from "$types/server/mailbroker"; +import type { ExpandedUserInfo } from "$types/user"; +import { MailbrokerSendOverlay } from "./types"; + +export class MailbrokerSendOverlayRuntime extends AppProcess implements IMailbrokerSendOverlayRuntime { + public template?: Mailbroker.MailTemplate; + public templateId: string; + public properties: MailbrokerSendOverlay.Property[] = []; + public users: ExpandedUserInfo[] = []; + + get admin() { + return Daemon.serviceHost?.getService("AdminBootstrapper")!; + } + + constructor(pid: number, parentPid: number, app: AppProcessData, templateId: string) { + super(pid, parentPid, app); + + this.templateId = templateId; + } + + protected async start(): Promise { + const result = await this.admin.getMailbrokerTemplate(this.templateId); + + if (!result.success) { + MessageBox( + { + title: "Not found", + message: `The mailbroker template specified could not be found on the server. Please try again. ${result.errorMessage ?? "Unknown failure"}`, + image: "WarningIcon", + sound: "arcos.dialog.warning", + buttons: [BTN_OKAY_SUG], + }, + Daemon.getShell()?.pid!, + true + ); + + return; + } + + this.template = result.result; + this.users = await this.admin.getAllUsers(); + this.parseProperties(); + } + + private parseProperties() { + if (!this.template) return; + + const result: MailbrokerSendOverlay.Property[] = []; + const testStr = `${this.template.htmlContent}${this.template.subjectContent}${this.template.textContent}`; + const regex = /%(?[a-zA-Z_-]+)%/g; + const matches = testStr.matchAll(regex); + + for (const match of matches ?? []) { + const name = match?.groups?.name; + if (!name || result.find((r) => r.name === name)) continue; + + const property: MailbrokerSendOverlay.Property = { + variant: MailbrokerSendOverlay.PropertyVariant.Unknown, + isUser: false, + name, + }; + + switch (name.toLowerCase()) { + case "url": + property.variant = MailbrokerSendOverlay.PropertyVariant.Url; + break; + case "username": + property.variant = MailbrokerSendOverlay.PropertyVariant.Username; + property.isUser = true; + break; + case "userid": + property.variant = MailbrokerSendOverlay.PropertyVariant.UserId; + property.isUser = true; + break; + default: + property.variant = MailbrokerSendOverlay.PropertyVariant.Unknown; + break; + } + + result.push(property); + } + + this.properties = result; + } +} diff --git a/src/apps/admin/mailbrokermanagerapp/Overlays/SendOverlay/types.ts b/src/apps/admin/mailbrokermanagerapp/Overlays/SendOverlay/types.ts new file mode 100644 index 000000000..5f3c467eb --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Overlays/SendOverlay/types.ts @@ -0,0 +1,14 @@ +export namespace MailbrokerSendOverlay { + export interface Property { + name: string; + variant: PropertyVariant; + isUser: boolean; + } + + export enum PropertyVariant { + Unknown, + Username, + UserId, + Url + } +} \ No newline at end of file diff --git a/src/apps/admin/mailbrokermanagerapp/Overlays/ViewKeyOverlay/KeyOverlay.svelte b/src/apps/admin/mailbrokermanagerapp/Overlays/ViewKeyOverlay/KeyOverlay.svelte new file mode 100644 index 000000000..dc07c8639 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Overlays/ViewKeyOverlay/KeyOverlay.svelte @@ -0,0 +1,145 @@ + + +{#if process.key} +
+ +
+

Key for {process.key?.serverName}

+

{process.key?.value}

+ +
+
+ +
+
+

Created at

+

{dayjs(process.key.createdAt).format("D MMMM YYYY, HH:mm:ss")}

+
+ +
+

Updated at

+

{dayjs(process.key.updatedAt).format("D MMMM YYYY, HH:mm:ss")}

+
+ +
+

Sent records

+

{process.sentRecords.length} {Plural("record", process.sentRecords.length)} sent by this server

+
+
+ + + {#snippet leftContent()} + Copy... + {/snippet} + {#snippet rightContent()} + + {disabled ? "Enable" : "Disable"} + + + Delete + + process.closeWindow()}>Close + {/snippet} + +{/if} diff --git a/src/apps/admin/mailbrokermanagerapp/Overlays/ViewKeyOverlay/KeyOverlay.ts b/src/apps/admin/mailbrokermanagerapp/Overlays/ViewKeyOverlay/KeyOverlay.ts new file mode 100644 index 000000000..e7f470f50 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Overlays/ViewKeyOverlay/KeyOverlay.ts @@ -0,0 +1,45 @@ +import type { App } from "$types/apps/app"; +import KeyOverlaySvelte from "./KeyOverlay.svelte"; +import { MailbrokerViewKeyOverlayRuntime } from "./runtime"; + +const KeyOverlay: App = { + metadata: { + name: "View mailbroker key", + author: "Izaak Kuipers", + version: "1.0.0", + icon: "MailbrokerAdminIcon", + }, + position: { centered: true }, + size: { + w: 450, + h: 300, + }, + minSize: { + w: 450, + h: 300, + }, + maxSize: { + w: 450, + h: 300, + }, + controls: { + minimize: false, + maximize: false, + close: true, + }, + state: { + resizable: false, + headless: true, + fullscreen: false, + maximized: false, + minimized: false, + }, + assets: { + runtime: MailbrokerViewKeyOverlayRuntime, + component: KeyOverlaySvelte as any, + }, + hidden: true, + id: "MailbrokerManagerApp_KeyOverlay", +}; + +export default KeyOverlay; \ No newline at end of file diff --git a/src/apps/admin/mailbrokermanagerapp/Overlays/ViewKeyOverlay/runtime.ts b/src/apps/admin/mailbrokermanagerapp/Overlays/ViewKeyOverlay/runtime.ts new file mode 100644 index 000000000..48fc6b45b --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Overlays/ViewKeyOverlay/runtime.ts @@ -0,0 +1,52 @@ +import type { IMailbrokerViewKeyOverlayRuntime } from "$interfaces/runtimes/IMailbrokerRuntime"; +import type { IAdminBootstrapper } from "$interfaces/services/IAdminBootstrapper"; +import { AppProcess } from "$ts/apps/process"; +import { Daemon } from "$ts/env"; +import { AdminScopes } from "$ts/servicehost/services/AdminBootstrapper/store"; +import { BTN_OKAY_SUG, MessageBox } from "$ts/util/dialog"; +import type { AppProcessData } from "$types/apps/app"; +import type { Mailbroker } from "$types/server/mailbroker"; + +export class MailbrokerViewKeyOverlayRuntime extends AppProcess implements IMailbrokerViewKeyOverlayRuntime { + public key?: Mailbroker.MailKey; + public keyId: string; + public sentRecords: Mailbroker.SentMail[] = []; + + get admin() { + return Daemon.serviceHost?.getService("AdminBootstrapper")!; + } + + constructor(pid: number, parentPid: number, app: AppProcessData, key: string) { + super(pid, parentPid, app); + + this.keyId = key; + } + + protected async start(): Promise { + const result = await this.admin.getMailbrokerKey(this.keyId); + + if (!result.success) { + MessageBox( + { + title: "Not found", + message: `The mailbroker key specified could not be found on the server. Please try again. ${result.errorMessage ?? "Unknown failure"}`, + image: "WarningIcon", + sound: "arcos.dialog.warning", + buttons: [BTN_OKAY_SUG], + }, + Daemon.getShell()?.pid!, + true + ); + + return; + } + + this.key = result.result; + + if (!this.admin.canAccess(AdminScopes.adminMailbrokerSentRead)) return; + + this.sentRecords = + (await this.admin.getMailbrokerSentRecords()).result?.filter((record) => record.to?.serverName === this.key!.serverName) ?? + []; + } +} diff --git a/src/apps/admin/mailbrokermanagerapp/Pages/GenericList.svelte b/src/apps/admin/mailbrokermanagerapp/Pages/GenericList.svelte new file mode 100644 index 000000000..701ea478f --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Pages/GenericList.svelte @@ -0,0 +1,18 @@ + + + diff --git a/src/apps/admin/mailbrokermanagerapp/Pages/Logs.svelte b/src/apps/admin/mailbrokermanagerapp/Pages/Logs.svelte new file mode 100644 index 000000000..8ac8f18ed --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Pages/Logs.svelte @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + {#each data.toReversed() as log (log._id)} + + + + + + + + {/each} + +
CodeMessageDetailsWhen?
+ + {log.code}{log.message}{log.details}{dayjs(log.createdAt).format("D MMM YYYY, HH:mm:ss")}
diff --git a/src/apps/admin/mailbrokermanagerapp/Pages/NewTemplate.svelte b/src/apps/admin/mailbrokermanagerapp/Pages/NewTemplate.svelte new file mode 100644 index 000000000..f6265d6be --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Pages/NewTemplate.svelte @@ -0,0 +1,52 @@ + + + + + + {#snippet rightContent()} + + Save + + {/snippet} + diff --git a/src/apps/admin/mailbrokermanagerapp/Pages/Sent.svelte b/src/apps/admin/mailbrokermanagerapp/Pages/Sent.svelte new file mode 100644 index 000000000..42606a4d9 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Pages/Sent.svelte @@ -0,0 +1,61 @@ + + +
+

{data.length} {Plural("sent email", data.length)}

+ +
+ +
+ {#each filteredSent as sentRecord (sentRecord._id)} + + {/each} + + {#if !filteredSent.length} +

+ There are no sent records that match the criteria. +

+ {/if} +
diff --git a/src/apps/admin/mailbrokermanagerapp/Pages/Sent/SentListingOption.svelte b/src/apps/admin/mailbrokermanagerapp/Pages/Sent/SentListingOption.svelte new file mode 100644 index 000000000..b8aaedcee --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Pages/Sent/SentListingOption.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/apps/admin/mailbrokermanagerapp/Pages/ServerKeys.svelte b/src/apps/admin/mailbrokermanagerapp/Pages/ServerKeys.svelte new file mode 100644 index 000000000..14cf3b723 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Pages/ServerKeys.svelte @@ -0,0 +1,65 @@ + + +
+

{data.length} {Plural("server key", data.length)}

+ + +
+ +
+ {#each filteredKeys as serverKey (serverKey._id)} + + {/each} + + {#if !filteredKeys.length} +

+ There are no server keys that match the criteria. +

+ {/if} +
diff --git a/src/apps/admin/mailbrokermanagerapp/Pages/ServerKeys/ServerKeyOption.svelte b/src/apps/admin/mailbrokermanagerapp/Pages/ServerKeys/ServerKeyOption.svelte new file mode 100644 index 000000000..715395929 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Pages/ServerKeys/ServerKeyOption.svelte @@ -0,0 +1,16 @@ + + + diff --git a/src/apps/admin/mailbrokermanagerapp/Pages/ViewSentRecord.svelte b/src/apps/admin/mailbrokermanagerapp/Pages/ViewSentRecord.svelte new file mode 100644 index 000000000..3606faad7 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Pages/ViewSentRecord.svelte @@ -0,0 +1,88 @@ + + + + +
+ +
+ {#if showCode} + + {:else} + + {/if} +
+
+ + + {#snippet leftContent()} + (showCode = false)} icon="eye" /> + (showCode = true)} icon="code" /> + {/snippet} + {#snippet rightContent()} + + Delete... + + {/snippet} + diff --git a/src/apps/admin/mailbrokermanagerapp/Pages/ViewSentRecord/SentRecordHeader.svelte b/src/apps/admin/mailbrokermanagerapp/Pages/ViewSentRecord/SentRecordHeader.svelte new file mode 100644 index 000000000..13da95971 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Pages/ViewSentRecord/SentRecordHeader.svelte @@ -0,0 +1,35 @@ + + +
+ +
+

{sentRecord.subject}

+ {#if sentRecord.to.serverName && sentRecord.to.username} +

From {sentRecord.to.serverName}, to {sentRecord.to.email} ({sentRecord.to.username})

+ {:else} +

To {sentRecord.to.email}

+ {/if} + +
+ +
+ {#if sentRecord.createdAt} +
+

Created at:

+

{dayjs(sentRecord.createdAt).format("D MMMM YYYY, HH:mm:ss")}

+
+ {/if} + {#if sentRecord.updatedAt} +
+

Updated at:

+

{dayjs(sentRecord.updatedAt).format("D MMMM YYYY, HH:mm:ss")}

+
+ {/if} +
+
diff --git a/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate.svelte b/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate.svelte new file mode 100644 index 000000000..fd3f486b2 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate.svelte @@ -0,0 +1,140 @@ + + + + + + {#snippet leftContent()} + + {#if deprecated} + Undeprecate + {:else} + Deprecate + {/if} + + Delete + {/snippet} + {#snippet rightContent()} + process.spawnOverlay("SendOverlay", pageProps.templateId)}>Send... + Discard + Save + {/snippet} + diff --git a/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate/TemplateEditor.svelte b/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate/TemplateEditor.svelte new file mode 100644 index 000000000..e6d89e7e8 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate/TemplateEditor.svelte @@ -0,0 +1,32 @@ + + +
+
+ {#each Object.entries(tabs) as [tab]} + + {/each} +
+
+ {#if Component} + + {/if} +
+
diff --git a/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate/TemplateEditor/GeneralTab.svelte b/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate/TemplateEditor/GeneralTab.svelte new file mode 100644 index 000000000..c6126f7dd --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate/TemplateEditor/GeneralTab.svelte @@ -0,0 +1,36 @@ + + +
+

Template name

+ +
+ +
+

Subject content

+ +
+ +
+

From suffix

+ +
diff --git a/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate/TemplateEditor/HtmlContentTab.svelte b/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate/TemplateEditor/HtmlContentTab.svelte new file mode 100644 index 000000000..d75534c26 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate/TemplateEditor/HtmlContentTab.svelte @@ -0,0 +1,34 @@ + + + + +
+ +
diff --git a/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate/TemplateEditor/TextContentTab.svelte b/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate/TemplateEditor/TextContentTab.svelte new file mode 100644 index 000000000..515c2c969 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate/TemplateEditor/TextContentTab.svelte @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate/TemplateHeader.svelte b/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate/TemplateHeader.svelte new file mode 100644 index 000000000..cc35df3a8 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/Pages/ViewTemplate/TemplateHeader.svelte @@ -0,0 +1,42 @@ + + +
+ +
+

{$updateData.name} - ArcOS {$updateData.fromSuffix}

+

{$updateData.subjectContent}

+ +
+
+ {#if template.createdAt} +
+

Created at:

+

{dayjs(template.createdAt).format("D MMMM YYYY, HH:mm:ss")}

+
+ {/if} + {#if template.updatedAt} +
+

Updated at:

+

{dayjs(template.updatedAt).format("D MMMM YYYY, HH:mm:ss")}

+
+ {/if} +
+
diff --git a/src/apps/admin/mailbrokermanagerapp/runtime.ts b/src/apps/admin/mailbrokermanagerapp/runtime.ts new file mode 100644 index 000000000..70bddc897 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/runtime.ts @@ -0,0 +1,61 @@ +import type { IMailbrokerManagerRuntime } from "$interfaces/runtimes/IMailbrokerRuntime"; +import type { IAdminBootstrapper } from "$interfaces/services/IAdminBootstrapper"; +import { AppProcess } from "$ts/apps/process"; +import { Daemon } from "$ts/env"; +import { Store } from "$ts/writable"; +import type { App, AppProcessData } from "$types/apps/app"; +import NewKeyOverlay from "./Overlays/NewKeyOverlay/NewKeyOverlay"; +import SendOverlay from "./Overlays/SendOverlay/SendOverlay"; +import KeyOverlay from "./Overlays/ViewKeyOverlay/KeyOverlay"; +import { mailbrokerPages } from "./store"; + +export class MailbrokerManagerRuntime extends AppProcess implements IMailbrokerManagerRuntime { + currentPage = Store(""); + pageProps = Store>({}); + + get admin() { + return Daemon.serviceHost?.getService("AdminBootstrapper")!; + } + + protected overlayStore: Record = { + SendOverlay, + KeyOverlay, + NewKeyOverlay, + }; + + //#region LIFECYCLE + + constructor(pid: number, parentPid: number, app: AppProcessData) { + super(pid, parentPid, app); + + this.switchPage("activeTemplates"); + + this.setSource(__SOURCE__); + } + + switchPage(pageId: string, props?: Record, force = false) { + this.Log(`Loading page '${pageId}'`); + + if (!mailbrokerPages.has(pageId)) return; + + if (force) { + this.currentPage.set(""); + } + + this.pageProps.set({}); + + const page = mailbrokerPages.get(pageId); + + this.pageProps.set(props ?? {}); + this.currentPage.set(pageId); + this.windowTitle.set(`${page?.name}`); + } + + async start() {} + + async stop() {} + + async render() {} + + //#endregion LIFECYCLE +} diff --git a/src/apps/admin/mailbrokermanagerapp/store.ts b/src/apps/admin/mailbrokermanagerapp/store.ts new file mode 100644 index 000000000..948219f62 --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/store.ts @@ -0,0 +1,95 @@ +import { AdminScopes } from "$ts/servicehost/services/AdminBootstrapper/store"; +import GenericList from "./Pages/GenericList.svelte"; +import Logs from "./Pages/Logs.svelte"; +import NewTemplate from "./Pages/NewTemplate.svelte"; +import Sent from "./Pages/Sent.svelte"; +import ServerKeys from "./Pages/ServerKeys.svelte"; +import ViewSentRecord from "./Pages/ViewSentRecord.svelte"; +import ViewTemplate from "./Pages/ViewTemplate.svelte"; +import type { MailbrokerPage, MailbrokerPages } from "./types"; + +export const mailbrokerPages: MailbrokerPages = new Map([ + [ + "activeTemplates", + { + name: "Active templates", + icon: "mails", + content: GenericList, + data: async (process) => await process.admin.getMailbrokerTemplates((template) => !template.deprecated), + scopes: [AdminScopes.adminMailbrokerTemplatesRead], + }, + ], + [ + "deprecatedTemplates", + { + name: "Deprecated templates", + icon: "mails", + content: GenericList, + data: async (process) => await process.admin.getMailbrokerTemplates((template) => template.deprecated), + scopes: [AdminScopes.adminMailbrokerTemplatesRead], + }, + ], + [ + "viewTemplate", + { + name: "View template", + icon: "eye", + hidden: true, + content: ViewTemplate, + data: async (process, props: { templateId: string }) => await process.admin.getMailbrokerTemplate(props.templateId), + scopes: [AdminScopes.adminMailbrokerTemplatesRead], + }, + ], + [ + "newTemplate", + { + name: "Create template", + icon: "plus", + hidden: true, + content: NewTemplate, + scopes: [AdminScopes.adminMailbrokerTemplatesWrite], + }, + ], + [ + "sent", + { + name: "Sent emails", + icon: "send", + content: Sent, + separator: true, + data: async (process) => await process.admin.getMailbrokerSentRecords(), + scopes: [AdminScopes.adminMailbrokerSentRead], + }, + ], + [ + "viewSentRecord", + { + name: "View sent record", + icon: "eye", + hidden: true, + content: ViewSentRecord, + data: async (process, props: { sentRecordId: string }) => await process.admin.getMailbrokerSentRecord(props.sentRecordId), + scopes: [AdminScopes.adminMailbrokerSentRead], + }, + ], + [ + "keys", + { + name: "Server keys", + icon: "key", + content: ServerKeys, + data: async (process) => await process.admin.getAllMailbrokerKeys(), + scopes: [AdminScopes.adminMailbrokerKeysRead], + }, + ], + [ + "logs", + { + name: "Logs", + icon: "list", + content: Logs, + data: async (process) => await process.admin.getMailbrokerLogs(), + scopes: [AdminScopes.adminMailbrokerLogsRead], + }, + ], +]); diff --git a/src/apps/admin/mailbrokermanagerapp/types.ts b/src/apps/admin/mailbrokermanagerapp/types.ts new file mode 100644 index 000000000..057cd861d --- /dev/null +++ b/src/apps/admin/mailbrokermanagerapp/types.ts @@ -0,0 +1,16 @@ +import type { ICommandResult } from "$interfaces/ICommandResult"; +import type { IMailbrokerManagerRuntime } from "$interfaces/runtimes/IMailbrokerRuntime"; +import type { MaybePromise } from "$types/shared/common"; +import type { Component } from "svelte"; + +export interface MailbrokerPage { + name: string; + icon: string; + content: Component; + hidden?: boolean; + separator?: boolean; + data?: (process: IMailbrokerManagerRuntime, pageProps: any) => MaybePromise>>; + scopes?: string[]; +} + +export type MailbrokerPages = Map; diff --git a/src/apps/components/messagebox/messageBox.ts b/src/apps/components/messagebox/messageBox.ts index 8849a4d25..10b1e811b 100644 --- a/src/apps/components/messagebox/messageBox.ts +++ b/src/apps/components/messagebox/messageBox.ts @@ -25,7 +25,7 @@ export const MessageBoxApp: App = { controls: { minimize: false, maximize: false, - close: true, + close: false, }, assets: { runtime: MessageBoxRuntime, diff --git a/src/apps/user/filemanager/FileManager/Sidebar.svelte b/src/apps/user/filemanager/FileManager/Sidebar.svelte index 7099d6d6d..6e9fa46cd 100755 --- a/src/apps/user/filemanager/FileManager/Sidebar.svelte +++ b/src/apps/user/filemanager/FileManager/Sidebar.svelte @@ -10,11 +10,11 @@ const { path, rootFolders, drives } = process; -