@hartl-services/medusa-base 2.8.0 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.medusa/server/src/admin/admin-components/features/plugin-features/components/PluginSettingsForm.js +4 -5
- package/.medusa/server/src/admin/admin-components/features/plugin-features/lib/plugin-view.d.ts +0 -5
- package/.medusa/server/src/admin/admin-components/features/plugin-features/lib/plugin-view.js +0 -5
- package/.medusa/server/src/admin/admin-components/i18n/texts.d.ts +1 -2
- package/.medusa/server/src/admin/admin-components/i18n/texts.js +1 -2
- package/.medusa/server/src/admin/index.js +106 -69
- package/.medusa/server/src/admin/index.mjs +107 -70
- package/.medusa/server/src/api/admin/email/templates/[kind]/send-test/route.js +7 -1
- package/.medusa/server/src/email/application/warn-credential-expiry.js +77 -0
- package/.medusa/server/src/email/config/index.js +8 -2
- package/.medusa/server/src/email/config/notification-module.js +28 -2
- package/.medusa/server/src/email/domain/business-keys.js +5 -2
- package/.medusa/server/src/email/domain/failure-classification.js +9 -1
- package/.medusa/server/src/email/plugin-features.js +123 -1
- package/.medusa/server/src/email/rendering/default-templates.js +16 -1
- package/.medusa/server/src/email/rendering/render-email.js +2 -1
- package/.medusa/server/src/email/types/email-kinds.js +2 -1
- package/.medusa/server/src/email/types/template-data.js +8 -1
- package/.medusa/server/src/jobs/email-credential-expiry.js +27 -0
- package/.medusa/server/src/modules/email/domain/message-state.js +3 -1
- package/.medusa/server/src/modules/email/migrations/Migration20261011120000.js +20 -0
- package/.medusa/server/src/providers/smtp/delivery-settings.js +75 -0
- package/.medusa/server/src/providers/smtp/graph-transport.js +150 -0
- package/.medusa/server/src/providers/smtp/service.js +105 -37
- package/.medusa/server/src/providers/smtp/types.js +7 -1
- package/.medusa/server/src/shop-config/build-food-shop-config.js +3 -5
- package/README.md +100 -65
- package/dist/email/config/index.d.ts +6 -1
- package/dist/email/config/index.js +7 -1
- package/dist/email/config/notification-module.d.ts +25 -0
- package/dist/email/config/notification-module.js +27 -1
- package/dist/email/types/email-kinds.d.ts +2 -1
- package/dist/email/types/email-kinds.js +1 -0
- package/dist/email/types/template-data.d.ts +10 -0
- package/dist/email/types/template-data.js +7 -0
- package/dist/shop-config/build-food-shop-config.d.ts +1 -1
- package/dist/shop-config/build-food-shop-config.js +2 -4
- package/package.json +2 -2
|
@@ -4,7 +4,7 @@ import { texts } from "../../../i18n/texts";
|
|
|
4
4
|
import { AdminSection } from "../../../shared/ui/AdminSection";
|
|
5
5
|
import { InfoTooltip } from "../../../shared/ui/InfoTooltip";
|
|
6
6
|
import { SwitchRow } from "../../../shared/ui/SwitchRow";
|
|
7
|
-
import { invalidatedByLabels,
|
|
7
|
+
import { invalidatedByLabels, isGroupDimmed, settingInfoText, showsBoundsLine, showsSourceHint, } from "../lib/plugin-view";
|
|
8
8
|
import { isHexColor, normalizeColorInput } from "../lib/settings-draft";
|
|
9
9
|
import { dateFromInputValue, inputValueFromDate } from "../../../shared/lib/date-input";
|
|
10
10
|
import { AdminDatePicker } from "../../../shared/ui/AdminDatePicker";
|
|
@@ -36,7 +36,7 @@ const ColorSettingInput = ({ id, hintId, label, value, invalid, required, disabl
|
|
|
36
36
|
className: `h-8 w-10 shrink-0 cursor-pointer rounded-md border border-ui-border-base bg-ui-bg-field p-1 disabled:cursor-not-allowed ${hasColor ? "" : "opacity-30"}`, value: hasColor ? value.trim() : "#000000", disabled: disabled, onChange: (event) => onChange(normalizeColorInput(event.target.value)) })] }));
|
|
37
37
|
};
|
|
38
38
|
/** A non-boolean setting: label (with source hint), control and hints. */
|
|
39
|
-
const SettingField = ({ pluginKey, setting, invalidatedBy,
|
|
39
|
+
const SettingField = ({ pluginKey, setting, invalidatedBy, value, invalid, disabled, onChange, }) => {
|
|
40
40
|
const id = fieldId(pluginKey, setting.key);
|
|
41
41
|
const labelId = `${id}-label`;
|
|
42
42
|
const hintId = `${id}-hint`;
|
|
@@ -49,7 +49,6 @@ const SettingField = ({ pluginKey, setting, invalidatedBy, invalidates, value, i
|
|
|
49
49
|
const hasHints = Boolean(hint) ||
|
|
50
50
|
clearPending ||
|
|
51
51
|
invalidatedBy.length > 0 ||
|
|
52
|
-
invalidates.length > 0 ||
|
|
53
52
|
showBounds ||
|
|
54
53
|
invalid;
|
|
55
54
|
const describedBy = hasHints ? hintId : undefined;
|
|
@@ -58,7 +57,7 @@ const SettingField = ({ pluginKey, setting, invalidatedBy, invalidates, value, i
|
|
|
58
57
|
? texts.settings.secretClearUndoLabel(setting.label)
|
|
59
58
|
: texts.settings.secretClearLabel(setting.label), onClick: () => onChange(clearPending ? "" : null), children: clearPending
|
|
60
59
|
? texts.settings.secretClearUndo
|
|
61
|
-
: texts.settings.secretClear }))] })) : setting.type === "select" ? (_jsxs(Select, { value: typeof value === "string" ? value : "", disabled: disabled, onValueChange: (next) => onChange(next), children: [_jsx(Select.Trigger, { id: id, "aria-describedby": describedBy, "aria-required": required || undefined, children: _jsx(Select.Value, { placeholder: texts.settings.selectPlaceholder }) }), _jsx(Select.Content, { children: setting.options.map((option) => (_jsx(Select.Item, { value: option.value, children: option.label }, option.value))) })] })) : setting.type === "image" ? (_jsx(ImageSettingInput, { id: id, describedBy: describedBy, label: setting.label, value: typeof value === "string" ? value : "", disabled: disabled, onChange: (url) => onChange(url) })) : setting.type === "color" ? (_jsx(ColorSettingInput, { id: id, hintId: describedBy, label: setting.label, value: typeof value === "string" ? value : "", invalid: invalid, required: required, disabled: disabled, onChange: (next) => onChange(next) })) : setting.type === "date" ? (_jsx(AdminDatePicker, { id: id, "aria-labelledby": labelId, "aria-describedby": describedBy, isDisabled: disabled, value: dateFromInputValue(typeof value === "string" ? value : ""), onChange: (date) => onChange(inputValueFromDate(date)) })) : setting.type === "number" ? (_jsx(Input, { id: id, "aria-describedby": describedBy, "aria-invalid": invalid, "aria-required": required || undefined, type: "number", step: setting.integer ? 1 : "any", min: setting.min ?? undefined, max: setting.max ?? undefined, placeholder: placeholder, value: typeof value === "string" ? value : "", disabled: disabled, onChange: (event) => onChange(event.target.value, event.target.validity.badInput) })) : (_jsx(Input, { id: id, "aria-describedby": describedBy, "aria-invalid": invalid, "aria-required": required || undefined, type: setting.type === "url" ? "url" : "text", placeholder: placeholder, value: typeof value === "string" ? value : "", disabled: disabled, onChange: (event) => onChange(event.target.value) })), hasHints && (_jsxs("div", { id: hintId, className: "flex flex-col gap-y-1", children: [hint && (_jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: hint })), clearPending && (_jsx(Hint, { variant: "info", children: texts.settings.secretClearPending })), invalidatedBy.length > 0 && (_jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: texts.settings.invalidatedBy(invalidatedBy) })),
|
|
60
|
+
: texts.settings.secretClear }))] })) : setting.type === "select" ? (_jsxs(Select, { value: typeof value === "string" ? value : "", disabled: disabled, onValueChange: (next) => onChange(next), children: [_jsx(Select.Trigger, { id: id, "aria-describedby": describedBy, "aria-required": required || undefined, children: _jsx(Select.Value, { placeholder: texts.settings.selectPlaceholder }) }), _jsx(Select.Content, { children: setting.options.map((option) => (_jsx(Select.Item, { value: option.value, children: option.label }, option.value))) })] })) : setting.type === "image" ? (_jsx(ImageSettingInput, { id: id, describedBy: describedBy, label: setting.label, value: typeof value === "string" ? value : "", disabled: disabled, onChange: (url) => onChange(url) })) : setting.type === "color" ? (_jsx(ColorSettingInput, { id: id, hintId: describedBy, label: setting.label, value: typeof value === "string" ? value : "", invalid: invalid, required: required, disabled: disabled, onChange: (next) => onChange(next) })) : setting.type === "date" ? (_jsx(AdminDatePicker, { id: id, "aria-labelledby": labelId, "aria-describedby": describedBy, isDisabled: disabled, value: dateFromInputValue(typeof value === "string" ? value : ""), onChange: (date) => onChange(inputValueFromDate(date)) })) : setting.type === "number" ? (_jsx(Input, { id: id, "aria-describedby": describedBy, "aria-invalid": invalid, "aria-required": required || undefined, type: "number", step: setting.integer ? 1 : "any", min: setting.min ?? undefined, max: setting.max ?? undefined, placeholder: placeholder, value: typeof value === "string" ? value : "", disabled: disabled, onChange: (event) => onChange(event.target.value, event.target.validity.badInput) })) : (_jsx(Input, { id: id, "aria-describedby": describedBy, "aria-invalid": invalid, "aria-required": required || undefined, type: setting.type === "url" ? "url" : "text", placeholder: placeholder, value: typeof value === "string" ? value : "", disabled: disabled, onChange: (event) => onChange(event.target.value) })), hasHints && (_jsxs("div", { id: hintId, className: "flex flex-col gap-y-1", children: [hint && (_jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: hint })), clearPending && (_jsx(Hint, { variant: "info", children: texts.settings.secretClearPending })), invalidatedBy.length > 0 && (_jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: texts.settings.invalidatedBy(invalidatedBy) })), showBounds && !invalid && (_jsx(Text, { size: "small", className: "text-ui-fg-muted", children: bounds })), invalid && (_jsx(Hint, { variant: "error", children: setting.type === "color"
|
|
62
61
|
? texts.settings.invalidColor
|
|
63
62
|
: (bounds ?? texts.settings.invalidNumber) }))] }))] }));
|
|
64
63
|
};
|
|
@@ -73,7 +72,7 @@ export const PluginSettingsForm = ({ plugin }) => {
|
|
|
73
72
|
setting.type === "date");
|
|
74
73
|
const renderField = (setting) => (_jsx(SettingField, { pluginKey: plugin.plugin_key, setting: setting, invalidatedBy: setting.type === "secret"
|
|
75
74
|
? invalidatedByLabels(plugin.settings, setting.key)
|
|
76
|
-
: [],
|
|
75
|
+
: [], value: form.draft[setting.key], invalid: form.invalid.includes(setting.key), disabled: pending, onChange: (value, badInput) => form.setValue(setting.key, value, badInput) }, setting.key));
|
|
77
76
|
// `dimmed`: the group's required feature is off; the rows stay editable.
|
|
78
77
|
const renderBlock = (block, dimmed) => {
|
|
79
78
|
const dim = dimmed ? "opacity-50 transition-opacity" : "transition-opacity";
|
package/.medusa/server/src/admin/admin-components/features/plugin-features/lib/plugin-view.d.ts
CHANGED
|
@@ -27,11 +27,6 @@ export declare const disabledParent: (features: readonly AdminPluginFeature[], f
|
|
|
27
27
|
export declare const invalidatedByLabels: (settings: readonly AdminPluginSetting[], secretKey: string) => string[];
|
|
28
28
|
/** Whether a settings group is dimmed: its required feature exists and is not effective. */
|
|
29
29
|
export declare const isGroupDimmed: (features: readonly AdminPluginFeature[], requiresFeature: string | null) => boolean;
|
|
30
|
-
/**
|
|
31
|
-
* Labels of the secrets that a change of `setting` deletes (forward
|
|
32
|
-
* `invalidates`), in the setting's order; unknown keys fall back to the key.
|
|
33
|
-
*/
|
|
34
|
-
export declare const invalidatesLabels: (settings: readonly AdminPluginSetting[], setting: Pick<AdminPluginSetting, "invalidates">) => string[];
|
|
35
30
|
/**
|
|
36
31
|
* The description a setting shows in its info tooltip: only when a `hint`
|
|
37
32
|
* takes the place under the field and the description says something else.
|
package/.medusa/server/src/admin/admin-components/features/plugin-features/lib/plugin-view.js
CHANGED
|
@@ -41,11 +41,6 @@ export const invalidatedByLabels = (settings, secretKey) => settings
|
|
|
41
41
|
export const isGroupDimmed = (features, requiresFeature) => requiresFeature !== null &&
|
|
42
42
|
features.find((feature) => feature.key === requiresFeature)
|
|
43
43
|
?.effective_enabled === false;
|
|
44
|
-
/**
|
|
45
|
-
* Labels of the secrets that a change of `setting` deletes (forward
|
|
46
|
-
* `invalidates`), in the setting's order; unknown keys fall back to the key.
|
|
47
|
-
*/
|
|
48
|
-
export const invalidatesLabels = (settings, setting) => setting.invalidates.map((key) => settings.find((candidate) => candidate.key === key)?.label ?? key);
|
|
49
44
|
/**
|
|
50
45
|
* The description a setting shows in its info tooltip: only when a `hint`
|
|
51
46
|
* takes the place under the field and the description says something else.
|
|
@@ -5,6 +5,7 @@ export declare const texts: {
|
|
|
5
5
|
breadcrumbs: {
|
|
6
6
|
hub: string;
|
|
7
7
|
emailAttachments: string;
|
|
8
|
+
emailDelivery: string;
|
|
8
9
|
};
|
|
9
10
|
page: {
|
|
10
11
|
title: string;
|
|
@@ -70,8 +71,6 @@ export declare const texts: {
|
|
|
70
71
|
secretClearUndoLabel: (label: string) => string;
|
|
71
72
|
/** Shown on a secret: the settings whose change deletes it ("A", "A oder B"). */
|
|
72
73
|
invalidatedBy: (labels: readonly string[]) => string;
|
|
73
|
-
/** Shown on the changing setting: the secrets its change deletes. */
|
|
74
|
-
invalidates: (labels: string) => string;
|
|
75
74
|
invalidNumber: string;
|
|
76
75
|
invalidColor: string;
|
|
77
76
|
colorPlaceholder: string;
|
|
@@ -5,6 +5,7 @@ export const texts = {
|
|
|
5
5
|
breadcrumbs: {
|
|
6
6
|
hub: "Plugins",
|
|
7
7
|
emailAttachments: "Anhänge",
|
|
8
|
+
emailDelivery: "Versand",
|
|
8
9
|
},
|
|
9
10
|
page: {
|
|
10
11
|
title: "Hartl Services Plugins",
|
|
@@ -72,8 +73,6 @@ export const texts = {
|
|
|
72
73
|
invalidatedBy: (labels) => `Wird gelöscht, wenn ${labels.length > 1
|
|
73
74
|
? `${labels.slice(0, -1).join(", ")} oder ${labels[labels.length - 1]}`
|
|
74
75
|
: labels.join("")} sich ändert.`,
|
|
75
|
-
/** Shown on the changing setting: the secrets its change deletes. */
|
|
76
|
-
invalidates: (labels) => `Beim Ändern muss ${labels} neu eingegeben werden.`,
|
|
77
76
|
invalidNumber: "Bitte eine gültige Zahl eingeben.",
|
|
78
77
|
invalidColor: "Bitte eine Hex-Farbe wie #1a2b3c eingeben.",
|
|
79
78
|
colorPlaceholder: "Standard",
|
|
@@ -28,7 +28,8 @@ const texts = {
|
|
|
28
28
|
},
|
|
29
29
|
breadcrumbs: {
|
|
30
30
|
hub: "Plugins",
|
|
31
|
-
emailAttachments: "Anhänge"
|
|
31
|
+
emailAttachments: "Anhänge",
|
|
32
|
+
emailDelivery: "Versand"
|
|
32
33
|
},
|
|
33
34
|
page: {
|
|
34
35
|
title: "Hartl Services Plugins",
|
|
@@ -94,8 +95,6 @@ const texts = {
|
|
|
94
95
|
secretClearUndoLabel: (label) => `${label} nicht löschen`,
|
|
95
96
|
/** Shown on a secret: the settings whose change deletes it ("A", "A oder B"). */
|
|
96
97
|
invalidatedBy: (labels) => `Wird gelöscht, wenn ${labels.length > 1 ? `${labels.slice(0, -1).join(", ")} oder ${labels[labels.length - 1]}` : labels.join("")} sich ändert.`,
|
|
97
|
-
/** Shown on the changing setting: the secrets its change deletes. */
|
|
98
|
-
invalidates: (labels) => `Beim Ändern muss ${labels} neu eingegeben werden.`,
|
|
99
98
|
invalidNumber: "Bitte eine gültige Zahl eingeben.",
|
|
100
99
|
invalidColor: "Bitte eine Hex-Farbe wie #1a2b3c eingeben.",
|
|
101
100
|
colorPlaceholder: "Standard",
|
|
@@ -396,9 +395,6 @@ const disabledParent = (features, feature) => {
|
|
|
396
395
|
};
|
|
397
396
|
const invalidatedByLabels = (settings, secretKey) => settings.filter((setting) => setting.invalidates.includes(secretKey)).map((setting) => setting.label);
|
|
398
397
|
const isGroupDimmed = (features, requiresFeature) => requiresFeature !== null && features.find((feature) => feature.key === requiresFeature)?.effective_enabled === false;
|
|
399
|
-
const invalidatesLabels = (settings, setting) => setting.invalidates.map(
|
|
400
|
-
(key) => settings.find((candidate) => candidate.key === key)?.label ?? key
|
|
401
|
-
);
|
|
402
398
|
const settingInfoText = (setting) => setting.hint !== null && setting.description !== null && setting.description !== setting.hint ? setting.description : null;
|
|
403
399
|
const headerInfoText = (plugin2) => plugin2.summary !== null && plugin2.description !== null && plugin2.description !== plugin2.summary ? plugin2.description : null;
|
|
404
400
|
const showsSourceHint = (source) => source !== "default";
|
|
@@ -1343,7 +1339,6 @@ const SettingField = ({
|
|
|
1343
1339
|
pluginKey,
|
|
1344
1340
|
setting,
|
|
1345
1341
|
invalidatedBy,
|
|
1346
|
-
invalidates,
|
|
1347
1342
|
value,
|
|
1348
1343
|
invalid,
|
|
1349
1344
|
disabled,
|
|
@@ -1358,7 +1353,7 @@ const SettingField = ({
|
|
|
1358
1353
|
const info = settingInfoText(setting);
|
|
1359
1354
|
const showBounds = Boolean(bounds) && showsBoundsLine(setting);
|
|
1360
1355
|
const required = setting.required;
|
|
1361
|
-
const hasHints = Boolean(hint) || clearPending || invalidatedBy.length > 0 ||
|
|
1356
|
+
const hasHints = Boolean(hint) || clearPending || invalidatedBy.length > 0 || showBounds || invalid;
|
|
1362
1357
|
const describedBy = hasHints ? hintId : void 0;
|
|
1363
1358
|
const placeholder = setting.placeholder ?? void 0;
|
|
1364
1359
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2", children: [
|
|
@@ -1482,7 +1477,6 @@ const SettingField = ({
|
|
|
1482
1477
|
hint && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: hint }),
|
|
1483
1478
|
clearPending && /* @__PURE__ */ jsxRuntime.jsx(ui.Hint, { variant: "info", children: texts.settings.secretClearPending }),
|
|
1484
1479
|
invalidatedBy.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: texts.settings.invalidatedBy(invalidatedBy) }),
|
|
1485
|
-
invalidates.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: texts.settings.invalidates(invalidates.join(", ")) }),
|
|
1486
1480
|
showBounds && !invalid && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: bounds }),
|
|
1487
1481
|
invalid && /* @__PURE__ */ jsxRuntime.jsx(ui.Hint, { variant: "error", children: setting.type === "color" ? texts.settings.invalidColor : bounds ?? texts.settings.invalidNumber })
|
|
1488
1482
|
] })
|
|
@@ -1505,7 +1499,6 @@ const PluginSettingsForm = ({ plugin: plugin2 }) => {
|
|
|
1505
1499
|
pluginKey: plugin2.plugin_key,
|
|
1506
1500
|
setting,
|
|
1507
1501
|
invalidatedBy: setting.type === "secret" ? invalidatedByLabels(plugin2.settings, setting.key) : [],
|
|
1508
|
-
invalidates: invalidatesLabels(plugin2.settings, setting),
|
|
1509
1502
|
value: form.draft[setting.key],
|
|
1510
1503
|
invalid: form.invalid.includes(setting.key),
|
|
1511
1504
|
disabled: pending,
|
|
@@ -3528,7 +3521,7 @@ const PluginFeaturesSettingsPage = () => {
|
|
|
3528
3521
|
const config = adminSdk.defineRouteConfig({
|
|
3529
3522
|
label: texts.menu.label
|
|
3530
3523
|
});
|
|
3531
|
-
const handle$
|
|
3524
|
+
const handle$b = {
|
|
3532
3525
|
breadcrumb: () => texts.breadcrumbs.hub
|
|
3533
3526
|
};
|
|
3534
3527
|
const KINDS = [
|
|
@@ -3544,7 +3537,8 @@ const KINDS = [
|
|
|
3544
3537
|
"auth.login_code",
|
|
3545
3538
|
"affiliate.consignment_report_due",
|
|
3546
3539
|
"affiliate.application_submitted.admin",
|
|
3547
|
-
"user.invite"
|
|
3540
|
+
"user.invite",
|
|
3541
|
+
"system.credential_expiry.admin"
|
|
3548
3542
|
];
|
|
3549
3543
|
const KIND_LABELS = {
|
|
3550
3544
|
"order.received": "Bestellbestätigung (Kunde)",
|
|
@@ -3559,10 +3553,12 @@ const KIND_LABELS = {
|
|
|
3559
3553
|
"auth.login_code": "Anmeldecode",
|
|
3560
3554
|
"affiliate.consignment_report_due": "Affiliate-Meldung",
|
|
3561
3555
|
"affiliate.application_submitted.admin": "Neue Partner-Bewerbung (Shop)",
|
|
3562
|
-
"user.invite": "Admin-Einladung"
|
|
3556
|
+
"user.invite": "Admin-Einladung",
|
|
3557
|
+
"system.credential_expiry.admin": "Secret läuft ab (Shop)"
|
|
3563
3558
|
};
|
|
3564
3559
|
const EMAIL_PAGE_PATH = `${PLUGIN_HUB_PATH}/email`;
|
|
3565
3560
|
const EMAIL_ATTACHMENTS_PAGE_PATH = `${EMAIL_PAGE_PATH}/attachments`;
|
|
3561
|
+
const EMAIL_DELIVERY_PAGE_PATH = `${EMAIL_PAGE_PATH}/delivery`;
|
|
3566
3562
|
const emailAttachmentPagePath = (attachmentId) => `${EMAIL_ATTACHMENTS_PAGE_PATH}/${encodeURIComponent(attachmentId)}`;
|
|
3567
3563
|
const NO_MAIL_ASSIGNED_LABEL = "keiner Mail zugeordnet";
|
|
3568
3564
|
const MAIL_KIND_OPTIONS = email$1.EMAIL_ATTACHABLE_KINDS.map((kind) => ({
|
|
@@ -3820,52 +3816,61 @@ const LinkRow = ({
|
|
|
3820
3816
|
description,
|
|
3821
3817
|
to,
|
|
3822
3818
|
disabled
|
|
3823
|
-
}) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3824
|
-
|
|
3825
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-y-0.5", children: [
|
|
3826
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", weight: "plus", children: title }),
|
|
3827
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", className: "text-ui-fg-subtle", children: description })
|
|
3828
|
-
] }),
|
|
3829
|
-
disabled ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3830
|
-
ui.Button,
|
|
3831
|
-
{
|
|
3832
|
-
"aria-label": texts.plugin.openLabel(title),
|
|
3833
|
-
disabled: true,
|
|
3834
|
-
size: "small",
|
|
3835
|
-
variant: "secondary",
|
|
3836
|
-
children: texts.plugin.open
|
|
3837
|
-
}
|
|
3838
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { asChild: true, size: "small", variant: "secondary", children: /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Link, { "aria-label": texts.plugin.openLabel(title), to, children: texts.plugin.open }) })
|
|
3839
|
-
] });
|
|
3840
|
-
const EmailManagementSection = ({ disabled }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3841
|
-
AdminSection,
|
|
3819
|
+
}) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3820
|
+
"div",
|
|
3842
3821
|
{
|
|
3843
|
-
className: `transition-opacity ${disabled ? "opacity-50" : ""}`,
|
|
3844
|
-
title: "Verwaltung",
|
|
3822
|
+
className: `flex items-center gap-4 px-6 py-3 transition-opacity ${disabled ? "opacity-50" : ""}`,
|
|
3845
3823
|
children: [
|
|
3846
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3847
|
-
|
|
3848
|
-
{
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
to: EMAIL_ATTACHMENTS_PAGE_PATH
|
|
3854
|
-
}
|
|
3855
|
-
),
|
|
3856
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3857
|
-
LinkRow,
|
|
3824
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.IconBadge, { children: icon }),
|
|
3825
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-y-0.5", children: [
|
|
3826
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", weight: "plus", children: title }),
|
|
3827
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", leading: "compact", className: "text-ui-fg-subtle", children: description })
|
|
3828
|
+
] }),
|
|
3829
|
+
disabled ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3830
|
+
ui.Button,
|
|
3858
3831
|
{
|
|
3859
|
-
|
|
3860
|
-
disabled,
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3832
|
+
"aria-label": texts.plugin.openLabel(title),
|
|
3833
|
+
disabled: true,
|
|
3834
|
+
size: "small",
|
|
3835
|
+
variant: "secondary",
|
|
3836
|
+
children: texts.plugin.open
|
|
3864
3837
|
}
|
|
3865
|
-
)
|
|
3838
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { asChild: true, size: "small", variant: "secondary", children: /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Link, { "aria-label": texts.plugin.openLabel(title), to, children: texts.plugin.open }) })
|
|
3866
3839
|
]
|
|
3867
3840
|
}
|
|
3868
3841
|
);
|
|
3842
|
+
const EmailManagementSection = ({ disabled }) => /* @__PURE__ */ jsxRuntime.jsxs(AdminSection, { title: "Verwaltung", children: [
|
|
3843
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3844
|
+
LinkRow,
|
|
3845
|
+
{
|
|
3846
|
+
description: "SMTP oder Microsoft 365.",
|
|
3847
|
+
disabled: false,
|
|
3848
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.PaperPlane, {}),
|
|
3849
|
+
title: texts.breadcrumbs.emailDelivery,
|
|
3850
|
+
to: EMAIL_DELIVERY_PAGE_PATH
|
|
3851
|
+
}
|
|
3852
|
+
),
|
|
3853
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3854
|
+
LinkRow,
|
|
3855
|
+
{
|
|
3856
|
+
description: "PDFs an Kunden-Mails, z. B. AGB.",
|
|
3857
|
+
disabled,
|
|
3858
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.PaperClip, {}),
|
|
3859
|
+
title: "Anhänge",
|
|
3860
|
+
to: EMAIL_ATTACHMENTS_PAGE_PATH
|
|
3861
|
+
}
|
|
3862
|
+
),
|
|
3863
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3864
|
+
LinkRow,
|
|
3865
|
+
{
|
|
3866
|
+
description: "Status und Zustellversuche.",
|
|
3867
|
+
disabled,
|
|
3868
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ClockSolid, {}),
|
|
3869
|
+
title: "E-Mail-Protokoll",
|
|
3870
|
+
to: EMAIL_LOG_PAGE_PATH
|
|
3871
|
+
}
|
|
3872
|
+
)
|
|
3873
|
+
] });
|
|
3869
3874
|
const EmailOverviewSections = () => {
|
|
3870
3875
|
const plugin2 = usePluginFeature("email").data?.plugin;
|
|
3871
3876
|
if (!plugin2) {
|
|
@@ -3877,7 +3882,7 @@ const EmailOverviewSections = () => {
|
|
|
3877
3882
|
] });
|
|
3878
3883
|
};
|
|
3879
3884
|
const EmailOverviewPage = () => /* @__PURE__ */ jsxRuntime.jsx(PluginPageShell, { pluginKey: "email", variant: "header", children: /* @__PURE__ */ jsxRuntime.jsx(EmailOverviewSections, {}) });
|
|
3880
|
-
const handle$
|
|
3885
|
+
const handle$a = {
|
|
3881
3886
|
breadcrumb: (_match) => /* @__PURE__ */ jsxRuntime.jsx(PluginLabelCrumb, { pluginKey: "email" })
|
|
3882
3887
|
};
|
|
3883
3888
|
const EMAIL_TEMPLATES_PATH = `${EMAIL_PAGE_PATH}/templates`;
|
|
@@ -3997,11 +4002,11 @@ const EmailTemplateGroupPage = ({
|
|
|
3997
4002
|
) })
|
|
3998
4003
|
] });
|
|
3999
4004
|
};
|
|
4000
|
-
const handle$
|
|
4005
|
+
const handle$9 = {
|
|
4001
4006
|
breadcrumb: () => EMAIL_TEMPLATE_GROUPS.account.label
|
|
4002
4007
|
};
|
|
4003
4008
|
const EmailAccountMailsRoute = () => /* @__PURE__ */ jsxRuntime.jsx(PluginFeatureRoute, { pluginKey: "email", children: /* @__PURE__ */ jsxRuntime.jsx(EmailTemplateGroupPage, { group: "account" }) });
|
|
4004
|
-
const handle$
|
|
4009
|
+
const handle$8 = {
|
|
4005
4010
|
breadcrumb: () => EMAIL_TEMPLATE_GROUPS.affiliate.label
|
|
4006
4011
|
};
|
|
4007
4012
|
const EmailAffiliateMailsRoute = () => /* @__PURE__ */ jsxRuntime.jsx(PluginFeatureRoute, { pluginKey: "email", children: /* @__PURE__ */ jsxRuntime.jsx(EmailTemplateGroupPage, { group: "affiliate" }) });
|
|
@@ -4402,10 +4407,37 @@ const EmailAttachmentsPage = () => {
|
|
|
4402
4407
|
/* @__PURE__ */ jsxRuntime.jsx(NewAttachmentModal, { onOpenChange: setNewOpen, open: newOpen })
|
|
4403
4408
|
] });
|
|
4404
4409
|
};
|
|
4405
|
-
const handle$
|
|
4410
|
+
const handle$7 = {
|
|
4406
4411
|
breadcrumb: () => texts.breadcrumbs.emailAttachments
|
|
4407
4412
|
};
|
|
4408
4413
|
const EmailAttachmentsRoute = () => /* @__PURE__ */ jsxRuntime.jsx(PluginFeatureRoute, { pluginKey: "email", children: /* @__PURE__ */ jsxRuntime.jsx(EmailAttachmentsPage, {}) });
|
|
4414
|
+
const EmailDeliveryPage = () => {
|
|
4415
|
+
const query = usePluginFeature("email");
|
|
4416
|
+
const plugin2 = query.data?.plugin;
|
|
4417
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-3", children: [
|
|
4418
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4419
|
+
AdminPageHeader,
|
|
4420
|
+
{
|
|
4421
|
+
badges: plugin2 && /* @__PURE__ */ jsxRuntime.jsx(ui.StatusBadge, { color: plugin2.configured ? "green" : "orange", children: plugin2.configured ? texts.chips.configured : texts.chips.notConfigured }),
|
|
4422
|
+
description: "SMTP oder Microsoft 365.",
|
|
4423
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(icons.PaperPlane, {}),
|
|
4424
|
+
title: texts.breadcrumbs.emailDelivery
|
|
4425
|
+
}
|
|
4426
|
+
),
|
|
4427
|
+
plugin2 ? /* @__PURE__ */ jsxRuntime.jsx(PluginSettingsForm, { plugin: plugin2 }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "p-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4428
|
+
QueryState,
|
|
4429
|
+
{
|
|
4430
|
+
error: query.error,
|
|
4431
|
+
errorText: texts.states.error,
|
|
4432
|
+
isLoading: query.isPending,
|
|
4433
|
+
loadingText: texts.states.loading
|
|
4434
|
+
}
|
|
4435
|
+
) })
|
|
4436
|
+
] });
|
|
4437
|
+
};
|
|
4438
|
+
const handle$6 = {
|
|
4439
|
+
breadcrumb: () => texts.breadcrumbs.emailDelivery
|
|
4440
|
+
};
|
|
4409
4441
|
const LOG_PAGE_SIZE = 20;
|
|
4410
4442
|
const LOG_MAX_OFFSET = 1e4;
|
|
4411
4443
|
const LOG_MAX_RESOURCE_ID_LENGTH = 255;
|
|
@@ -4637,17 +4669,17 @@ const handle$5 = {
|
|
|
4637
4669
|
breadcrumb: () => "Protokoll"
|
|
4638
4670
|
};
|
|
4639
4671
|
const EmailLogRoute = () => /* @__PURE__ */ jsxRuntime.jsx(PluginFeatureRoute, { pluginKey: "email", children: /* @__PURE__ */ jsxRuntime.jsx(EmailLogPage, {}) });
|
|
4672
|
+
const handle$4 = {
|
|
4673
|
+
breadcrumb: () => EMAIL_TEMPLATE_GROUPS.order.label
|
|
4674
|
+
};
|
|
4675
|
+
const EmailOrderMailsRoute = () => /* @__PURE__ */ jsxRuntime.jsx(PluginFeatureRoute, { pluginKey: "email", children: /* @__PURE__ */ jsxRuntime.jsx(EmailTemplateGroupPage, { group: "order" }) });
|
|
4640
4676
|
const PluginDetailPage = () => {
|
|
4641
4677
|
const { plugin_key: pluginKey = "" } = reactRouterDom.useParams();
|
|
4642
4678
|
return /* @__PURE__ */ jsxRuntime.jsx(PluginPageShell, { pluginKey, variant: "header", children: /* @__PURE__ */ jsxRuntime.jsx(PluginFeatureSections, { pluginKey }) });
|
|
4643
4679
|
};
|
|
4644
|
-
const handle$4 = {
|
|
4645
|
-
breadcrumb: (match) => /* @__PURE__ */ jsxRuntime.jsx(PluginLabelCrumb, { pluginKey: match.params.plugin_key ?? "" })
|
|
4646
|
-
};
|
|
4647
4680
|
const handle$3 = {
|
|
4648
|
-
breadcrumb: () =>
|
|
4681
|
+
breadcrumb: (match) => /* @__PURE__ */ jsxRuntime.jsx(PluginLabelCrumb, { pluginKey: match.params.plugin_key ?? "" })
|
|
4649
4682
|
};
|
|
4650
|
-
const EmailOrderMailsRoute = () => /* @__PURE__ */ jsxRuntime.jsx(PluginFeatureRoute, { pluginKey: "email", children: /* @__PURE__ */ jsxRuntime.jsx(EmailTemplateGroupPage, { group: "order" }) });
|
|
4651
4683
|
const STATUS_BADGES = {
|
|
4652
4684
|
current: { label: "aktuell", color: "green" },
|
|
4653
4685
|
planned: { label: "geplant", color: "blue" },
|
|
@@ -6705,26 +6737,31 @@ const routeModule = {
|
|
|
6705
6737
|
{
|
|
6706
6738
|
Component: PluginFeaturesSettingsPage,
|
|
6707
6739
|
path: "/settings/hartl-services",
|
|
6708
|
-
handle: { label: config.label, translationNs: config.translationNs, ...handle$
|
|
6740
|
+
handle: { label: config.label, translationNs: config.translationNs, ...handle$b }
|
|
6709
6741
|
},
|
|
6710
6742
|
{
|
|
6711
6743
|
Component: EmailOverviewPage,
|
|
6712
6744
|
path: "/settings/hartl-services/email",
|
|
6713
|
-
handle: handle$
|
|
6745
|
+
handle: handle$a
|
|
6714
6746
|
},
|
|
6715
6747
|
{
|
|
6716
6748
|
Component: EmailAccountMailsRoute,
|
|
6717
6749
|
path: "/settings/hartl-services/email/account",
|
|
6718
|
-
handle: handle$
|
|
6750
|
+
handle: handle$9
|
|
6719
6751
|
},
|
|
6720
6752
|
{
|
|
6721
6753
|
Component: EmailAffiliateMailsRoute,
|
|
6722
6754
|
path: "/settings/hartl-services/email/affiliate",
|
|
6723
|
-
handle: handle$
|
|
6755
|
+
handle: handle$8
|
|
6724
6756
|
},
|
|
6725
6757
|
{
|
|
6726
6758
|
Component: EmailAttachmentsRoute,
|
|
6727
6759
|
path: "/settings/hartl-services/email/attachments",
|
|
6760
|
+
handle: handle$7
|
|
6761
|
+
},
|
|
6762
|
+
{
|
|
6763
|
+
Component: EmailDeliveryPage,
|
|
6764
|
+
path: "/settings/hartl-services/email/delivery",
|
|
6728
6765
|
handle: handle$6
|
|
6729
6766
|
},
|
|
6730
6767
|
{
|
|
@@ -6733,13 +6770,13 @@ const routeModule = {
|
|
|
6733
6770
|
handle: handle$5
|
|
6734
6771
|
},
|
|
6735
6772
|
{
|
|
6736
|
-
Component:
|
|
6737
|
-
path: "/settings/hartl-services/
|
|
6773
|
+
Component: EmailOrderMailsRoute,
|
|
6774
|
+
path: "/settings/hartl-services/email/order",
|
|
6738
6775
|
handle: handle$4
|
|
6739
6776
|
},
|
|
6740
6777
|
{
|
|
6741
|
-
Component:
|
|
6742
|
-
path: "/settings/hartl-services/
|
|
6778
|
+
Component: PluginDetailPage,
|
|
6779
|
+
path: "/settings/hartl-services/plugin/:plugin_key",
|
|
6743
6780
|
handle: handle$3
|
|
6744
6781
|
},
|
|
6745
6782
|
{
|