@hartl-services/medusa-base 2.7.0 → 2.8.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 +9 -5
- package/.medusa/server/src/admin/admin-components/features/plugin-features/hooks/usePluginFeatureEnabled.d.ts +5 -1
- package/.medusa/server/src/admin/admin-components/features/plugin-features/hooks/usePluginFeatures.d.ts +20 -4
- package/.medusa/server/src/admin/admin-components/features/plugin-features/hooks/usePluginSettingsForm.d.ts +5 -1
- package/.medusa/server/src/admin/admin-components/features/plugin-features/lib/plugin-features-admin-client.d.ts +20 -4
- package/.medusa/server/src/admin/admin-components/features/plugin-features/lib/settings-layout.d.ts +4 -0
- package/.medusa/server/src/admin/admin-components/features/plugin-features/lib/settings-layout.js +4 -0
- package/.medusa/server/src/admin/index.js +54 -36
- package/.medusa/server/src/admin/index.mjs +55 -37
- package/.medusa/server/src/customer-auth/plugin-features.js +10 -10
- package/.medusa/server/src/modules/plugin-features/domain/plugin-settings.js +27 -6
- package/.medusa/server/src/modules/plugin-features/service.js +4 -3
- package/.medusa/server/src/public/descriptor.js +24 -3
- package/.medusa/server/src/shared/lib/dates.js +8 -2
- package/dist/customer-auth/plugin-features.js +9 -9
- package/dist/public/descriptor.js +23 -2
- package/dist/public/types.d.ts +14 -4
- package/dist/shared/lib/dates.d.ts +2 -0
- package/dist/shared/lib/dates.js +7 -1
- package/package.json +2 -2
|
@@ -6,7 +6,9 @@ import { InfoTooltip } from "../../../shared/ui/InfoTooltip";
|
|
|
6
6
|
import { SwitchRow } from "../../../shared/ui/SwitchRow";
|
|
7
7
|
import { invalidatedByLabels, invalidatesLabels, isGroupDimmed, settingInfoText, showsBoundsLine, showsSourceHint, } from "../lib/plugin-view";
|
|
8
8
|
import { isHexColor, normalizeColorInput } from "../lib/settings-draft";
|
|
9
|
-
import {
|
|
9
|
+
import { dateFromInputValue, inputValueFromDate } from "../../../shared/lib/date-input";
|
|
10
|
+
import { AdminDatePicker } from "../../../shared/ui/AdminDatePicker";
|
|
11
|
+
import { buildSettingGroups, isGroupVisible, } from "../lib/settings-layout";
|
|
10
12
|
import { usePluginSettingsForm } from "../hooks/usePluginSettingsForm";
|
|
11
13
|
import { ImageSettingInput } from "./ImageSettingInput";
|
|
12
14
|
const fieldId = (pluginKey, key) => `plugin-setting-${pluginKey}-${key}`;
|
|
@@ -36,6 +38,7 @@ const ColorSettingInput = ({ id, hintId, label, value, invalid, required, disabl
|
|
|
36
38
|
/** A non-boolean setting: label (with source hint), control and hints. */
|
|
37
39
|
const SettingField = ({ pluginKey, setting, invalidatedBy, invalidates, value, invalid, disabled, onChange, }) => {
|
|
38
40
|
const id = fieldId(pluginKey, setting.key);
|
|
41
|
+
const labelId = `${id}-label`;
|
|
39
42
|
const hintId = `${id}-hint`;
|
|
40
43
|
const clearPending = setting.type === "secret" && value === null;
|
|
41
44
|
const bounds = setting.type === "number" ? boundsText(setting) : undefined;
|
|
@@ -51,22 +54,23 @@ const SettingField = ({ pluginKey, setting, invalidatedBy, invalidates, value, i
|
|
|
51
54
|
invalid;
|
|
52
55
|
const describedBy = hasHints ? hintId : undefined;
|
|
53
56
|
const placeholder = setting.placeholder ?? undefined;
|
|
54
|
-
return (_jsxs("div", { className: "flex flex-col gap-y-2", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-x-1", children: [_jsx(Label, { htmlFor: id, size: "small", weight: "plus", children: labelText(setting) }), info && (_jsx(InfoTooltip, { label: texts.info.label(setting.label), children: info }))] }), showsSourceHint(setting.source) && (_jsx(Text, { size: "xsmall", className: "text-ui-fg-muted shrink-0", children: texts.settings.source[setting.source] }))] }), setting.type === "secret" ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Input, { id: id, "aria-describedby": describedBy, "aria-required": required || undefined, className: "flex-1", type: "password", autoComplete: "new-password", placeholder: setting.is_set ? texts.settings.secretPlaceholder : placeholder, value: typeof value === "string" ? value : "", disabled: disabled || clearPending, onChange: (event) => onChange(event.target.value) }), setting.source === "stored" && (_jsx(Button, { type: "button", size: "small", variant: "secondary", disabled: disabled, "aria-label": clearPending
|
|
57
|
+
return (_jsxs("div", { className: "flex flex-col gap-y-2", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-x-1", children: [_jsx(Label, { id: labelId, htmlFor: id, size: "small", weight: "plus", children: labelText(setting) }), info && (_jsx(InfoTooltip, { label: texts.info.label(setting.label), children: info }))] }), showsSourceHint(setting.source) && (_jsx(Text, { size: "xsmall", className: "text-ui-fg-muted shrink-0", children: texts.settings.source[setting.source] }))] }), setting.type === "secret" ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Input, { id: id, "aria-describedby": describedBy, "aria-required": required || undefined, className: "flex-1", type: "password", autoComplete: "new-password", placeholder: setting.is_set ? texts.settings.secretPlaceholder : placeholder, value: typeof value === "string" ? value : "", disabled: disabled || clearPending, onChange: (event) => onChange(event.target.value) }), setting.source === "stored" && (_jsx(Button, { type: "button", size: "small", variant: "secondary", disabled: disabled, "aria-label": clearPending
|
|
55
58
|
? texts.settings.secretClearUndoLabel(setting.label)
|
|
56
59
|
: texts.settings.secretClearLabel(setting.label), onClick: () => onChange(clearPending ? "" : null), children: clearPending
|
|
57
60
|
? texts.settings.secretClearUndo
|
|
58
|
-
: 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 === "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) })), invalidates.length > 0 && (_jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: texts.settings.invalidates(invalidates.join(", ")) })), showBounds && !invalid && (_jsx(Text, { size: "small", className: "text-ui-fg-muted", children: bounds })), invalid && (_jsx(Hint, { variant: "error", children: setting.type === "color"
|
|
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) })), invalidates.length > 0 && (_jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: texts.settings.invalidates(invalidates.join(", ")) })), showBounds && !invalid && (_jsx(Text, { size: "small", className: "text-ui-fg-muted", children: bounds })), invalid && (_jsx(Hint, { variant: "error", children: setting.type === "color"
|
|
59
62
|
? texts.settings.invalidColor
|
|
60
63
|
: (bounds ?? texts.settings.invalidNumber) }))] }))] }));
|
|
61
64
|
};
|
|
62
65
|
export const PluginSettingsForm = ({ plugin }) => {
|
|
63
66
|
const form = usePluginSettingsForm(plugin);
|
|
64
67
|
const pending = form.mutation.isPending;
|
|
65
|
-
const groups = buildSettingGroups(plugin.settings, plugin.setting_groups, texts.sections.settings);
|
|
68
|
+
const groups = buildSettingGroups(plugin.settings, plugin.setting_groups, texts.sections.settings).filter((group) => isGroupVisible(group, form.draft));
|
|
66
69
|
const hasTextFields = plugin.settings.some((setting) => setting.type === "string" ||
|
|
67
70
|
setting.type === "url" ||
|
|
68
71
|
setting.type === "number" ||
|
|
69
|
-
setting.type === "color"
|
|
72
|
+
setting.type === "color" ||
|
|
73
|
+
setting.type === "date");
|
|
70
74
|
const renderField = (setting) => (_jsx(SettingField, { pluginKey: plugin.plugin_key, setting: setting, invalidatedBy: setting.type === "secret"
|
|
71
75
|
? invalidatedByLabels(plugin.settings, setting.key)
|
|
72
76
|
: [], invalidates: invalidatesLabels(plugin.settings, setting), value: form.draft[setting.key], invalid: form.invalid.includes(setting.key), disabled: pending, onChange: (value, badInput) => form.setValue(setting.key, value, badInput) }, setting.key));
|
|
@@ -90,7 +90,7 @@ export declare const pluginFeatureEnabledQueryOptions: (pluginKey: string, featu
|
|
|
90
90
|
width: "full" | "half";
|
|
91
91
|
section: string | null;
|
|
92
92
|
} | {
|
|
93
|
-
type: "string" | "boolean" | "color" | "image" | "url";
|
|
93
|
+
type: "string" | "boolean" | "color" | "image" | "url" | "date";
|
|
94
94
|
default: string | number | boolean | null;
|
|
95
95
|
value: string | number | boolean | null;
|
|
96
96
|
key: string;
|
|
@@ -130,6 +130,10 @@ export declare const pluginFeatureEnabledQueryOptions: (pluginKey: string, featu
|
|
|
130
130
|
description: string | null;
|
|
131
131
|
note: string | null;
|
|
132
132
|
requires_feature: string | null;
|
|
133
|
+
visible_when: {
|
|
134
|
+
setting: string;
|
|
135
|
+
equals: string | boolean;
|
|
136
|
+
} | null;
|
|
133
137
|
}[];
|
|
134
138
|
}[];
|
|
135
139
|
}>;
|
|
@@ -70,7 +70,7 @@ export declare function usePluginFeatures(): import("@tanstack/react-query").Use
|
|
|
70
70
|
width: "full" | "half";
|
|
71
71
|
section: string | null;
|
|
72
72
|
} | {
|
|
73
|
-
type: "string" | "boolean" | "color" | "image" | "url";
|
|
73
|
+
type: "string" | "boolean" | "color" | "image" | "url" | "date";
|
|
74
74
|
default: string | number | boolean | null;
|
|
75
75
|
value: string | number | boolean | null;
|
|
76
76
|
key: string;
|
|
@@ -110,6 +110,10 @@ export declare function usePluginFeatures(): import("@tanstack/react-query").Use
|
|
|
110
110
|
description: string | null;
|
|
111
111
|
note: string | null;
|
|
112
112
|
requires_feature: string | null;
|
|
113
|
+
visible_when: {
|
|
114
|
+
setting: string;
|
|
115
|
+
equals: string | boolean;
|
|
116
|
+
} | null;
|
|
113
117
|
}[];
|
|
114
118
|
}[];
|
|
115
119
|
}, Error>;
|
|
@@ -192,7 +196,7 @@ export declare function usePluginFeature(pluginKey: string | undefined): import(
|
|
|
192
196
|
width: "full" | "half";
|
|
193
197
|
section: string | null;
|
|
194
198
|
} | {
|
|
195
|
-
type: "string" | "boolean" | "color" | "image" | "url";
|
|
199
|
+
type: "string" | "boolean" | "color" | "image" | "url" | "date";
|
|
196
200
|
default: string | number | boolean | null;
|
|
197
201
|
value: string | number | boolean | null;
|
|
198
202
|
key: string;
|
|
@@ -232,6 +236,10 @@ export declare function usePluginFeature(pluginKey: string | undefined): import(
|
|
|
232
236
|
description: string | null;
|
|
233
237
|
note: string | null;
|
|
234
238
|
requires_feature: string | null;
|
|
239
|
+
visible_when: {
|
|
240
|
+
setting: string;
|
|
241
|
+
equals: string | boolean;
|
|
242
|
+
} | null;
|
|
235
243
|
}[];
|
|
236
244
|
};
|
|
237
245
|
}, Error>;
|
|
@@ -308,7 +316,7 @@ export declare function useUpdatePluginFeatures(): import("@tanstack/react-query
|
|
|
308
316
|
width: "full" | "half";
|
|
309
317
|
section: string | null;
|
|
310
318
|
} | {
|
|
311
|
-
type: "string" | "boolean" | "color" | "image" | "url";
|
|
319
|
+
type: "string" | "boolean" | "color" | "image" | "url" | "date";
|
|
312
320
|
default: string | number | boolean | null;
|
|
313
321
|
value: string | number | boolean | null;
|
|
314
322
|
key: string;
|
|
@@ -348,6 +356,10 @@ export declare function useUpdatePluginFeatures(): import("@tanstack/react-query
|
|
|
348
356
|
description: string | null;
|
|
349
357
|
note: string | null;
|
|
350
358
|
requires_feature: string | null;
|
|
359
|
+
visible_when: {
|
|
360
|
+
setting: string;
|
|
361
|
+
equals: string | boolean;
|
|
362
|
+
} | null;
|
|
351
363
|
}[];
|
|
352
364
|
};
|
|
353
365
|
}, Error, {
|
|
@@ -428,7 +440,7 @@ export declare function useUpdatePluginSettings(pluginKey: string): import("@tan
|
|
|
428
440
|
width: "full" | "half";
|
|
429
441
|
section: string | null;
|
|
430
442
|
} | {
|
|
431
|
-
type: "string" | "boolean" | "color" | "image" | "url";
|
|
443
|
+
type: "string" | "boolean" | "color" | "image" | "url" | "date";
|
|
432
444
|
default: string | number | boolean | null;
|
|
433
445
|
value: string | number | boolean | null;
|
|
434
446
|
key: string;
|
|
@@ -468,6 +480,10 @@ export declare function useUpdatePluginSettings(pluginKey: string): import("@tan
|
|
|
468
480
|
description: string | null;
|
|
469
481
|
note: string | null;
|
|
470
482
|
requires_feature: string | null;
|
|
483
|
+
visible_when: {
|
|
484
|
+
setting: string;
|
|
485
|
+
equals: string | boolean;
|
|
486
|
+
} | null;
|
|
471
487
|
}[];
|
|
472
488
|
};
|
|
473
489
|
}, Error, {
|
|
@@ -79,7 +79,7 @@ export declare function usePluginSettingsForm(plugin: AdminPluginFeatures): {
|
|
|
79
79
|
width: "full" | "half";
|
|
80
80
|
section: string | null;
|
|
81
81
|
} | {
|
|
82
|
-
type: "string" | "boolean" | "color" | "image" | "url";
|
|
82
|
+
type: "string" | "boolean" | "color" | "image" | "url" | "date";
|
|
83
83
|
default: string | number | boolean | null;
|
|
84
84
|
value: string | number | boolean | null;
|
|
85
85
|
key: string;
|
|
@@ -119,6 +119,10 @@ export declare function usePluginSettingsForm(plugin: AdminPluginFeatures): {
|
|
|
119
119
|
description: string | null;
|
|
120
120
|
note: string | null;
|
|
121
121
|
requires_feature: string | null;
|
|
122
|
+
visible_when: {
|
|
123
|
+
setting: string;
|
|
124
|
+
equals: string | boolean;
|
|
125
|
+
} | null;
|
|
122
126
|
}[];
|
|
123
127
|
};
|
|
124
128
|
}, Error, {
|
|
@@ -71,7 +71,7 @@ export declare const listPluginFeatures: () => Promise<{
|
|
|
71
71
|
width: "full" | "half";
|
|
72
72
|
section: string | null;
|
|
73
73
|
} | {
|
|
74
|
-
type: "string" | "boolean" | "color" | "image" | "url";
|
|
74
|
+
type: "string" | "boolean" | "color" | "image" | "url" | "date";
|
|
75
75
|
default: string | number | boolean | null;
|
|
76
76
|
value: string | number | boolean | null;
|
|
77
77
|
key: string;
|
|
@@ -111,6 +111,10 @@ export declare const listPluginFeatures: () => Promise<{
|
|
|
111
111
|
description: string | null;
|
|
112
112
|
note: string | null;
|
|
113
113
|
requires_feature: string | null;
|
|
114
|
+
visible_when: {
|
|
115
|
+
setting: string;
|
|
116
|
+
equals: string | boolean;
|
|
117
|
+
} | null;
|
|
114
118
|
}[];
|
|
115
119
|
}[];
|
|
116
120
|
}>;
|
|
@@ -186,7 +190,7 @@ export declare const retrievePluginFeatures: (pluginKey: string) => Promise<{
|
|
|
186
190
|
width: "full" | "half";
|
|
187
191
|
section: string | null;
|
|
188
192
|
} | {
|
|
189
|
-
type: "string" | "boolean" | "color" | "image" | "url";
|
|
193
|
+
type: "string" | "boolean" | "color" | "image" | "url" | "date";
|
|
190
194
|
default: string | number | boolean | null;
|
|
191
195
|
value: string | number | boolean | null;
|
|
192
196
|
key: string;
|
|
@@ -226,6 +230,10 @@ export declare const retrievePluginFeatures: (pluginKey: string) => Promise<{
|
|
|
226
230
|
description: string | null;
|
|
227
231
|
note: string | null;
|
|
228
232
|
requires_feature: string | null;
|
|
233
|
+
visible_when: {
|
|
234
|
+
setting: string;
|
|
235
|
+
equals: string | boolean;
|
|
236
|
+
} | null;
|
|
229
237
|
}[];
|
|
230
238
|
};
|
|
231
239
|
}>;
|
|
@@ -301,7 +309,7 @@ export declare const updatePluginFeatures: (payload: UpdatePluginFeaturesPayload
|
|
|
301
309
|
width: "full" | "half";
|
|
302
310
|
section: string | null;
|
|
303
311
|
} | {
|
|
304
|
-
type: "string" | "boolean" | "color" | "image" | "url";
|
|
312
|
+
type: "string" | "boolean" | "color" | "image" | "url" | "date";
|
|
305
313
|
default: string | number | boolean | null;
|
|
306
314
|
value: string | number | boolean | null;
|
|
307
315
|
key: string;
|
|
@@ -341,6 +349,10 @@ export declare const updatePluginFeatures: (payload: UpdatePluginFeaturesPayload
|
|
|
341
349
|
description: string | null;
|
|
342
350
|
note: string | null;
|
|
343
351
|
requires_feature: string | null;
|
|
352
|
+
visible_when: {
|
|
353
|
+
setting: string;
|
|
354
|
+
equals: string | boolean;
|
|
355
|
+
} | null;
|
|
344
356
|
}[];
|
|
345
357
|
};
|
|
346
358
|
}>;
|
|
@@ -416,7 +428,7 @@ export declare const updatePluginSettings: (pluginKey: string, payload: UpdatePl
|
|
|
416
428
|
width: "full" | "half";
|
|
417
429
|
section: string | null;
|
|
418
430
|
} | {
|
|
419
|
-
type: "string" | "boolean" | "color" | "image" | "url";
|
|
431
|
+
type: "string" | "boolean" | "color" | "image" | "url" | "date";
|
|
420
432
|
default: string | number | boolean | null;
|
|
421
433
|
value: string | number | boolean | null;
|
|
422
434
|
key: string;
|
|
@@ -456,6 +468,10 @@ export declare const updatePluginSettings: (pluginKey: string, payload: UpdatePl
|
|
|
456
468
|
description: string | null;
|
|
457
469
|
note: string | null;
|
|
458
470
|
requires_feature: string | null;
|
|
471
|
+
visible_when: {
|
|
472
|
+
setting: string;
|
|
473
|
+
equals: string | boolean;
|
|
474
|
+
} | null;
|
|
459
475
|
}[];
|
|
460
476
|
};
|
|
461
477
|
}>;
|
package/.medusa/server/src/admin/admin-components/features/plugin-features/lib/settings-layout.d.ts
CHANGED
|
@@ -30,6 +30,8 @@ export type SettingGroupView = {
|
|
|
30
30
|
description: string | null;
|
|
31
31
|
note: string | null;
|
|
32
32
|
requiresFeature: string | null;
|
|
33
|
+
/** The group applies only while this setting's draft value equals `equals`. */
|
|
34
|
+
visibleWhen: AdminPluginSettingGroup["visible_when"];
|
|
33
35
|
settings: AdminPluginSetting[];
|
|
34
36
|
blocks: SettingBlock[];
|
|
35
37
|
};
|
|
@@ -41,3 +43,5 @@ export declare const buildSettingBlocks: (settings: readonly AdminPluginSetting[
|
|
|
41
43
|
* `groups` supplies the description, note and required feature per group.
|
|
42
44
|
*/
|
|
43
45
|
export declare const buildSettingGroups: (settings: readonly AdminPluginSetting[], groups: readonly AdminPluginSettingGroup[], ungroupedTitle: string) => SettingGroupView[];
|
|
46
|
+
/** Whether a group's `visible_when` holds for the current form values. */
|
|
47
|
+
export declare const isGroupVisible: (group: Pick<SettingGroupView, "visibleWhen">, draft: Readonly<Record<string, string | boolean | null>>) => boolean;
|
package/.medusa/server/src/admin/admin-components/features/plugin-features/lib/settings-layout.js
CHANGED
|
@@ -59,8 +59,12 @@ export const buildSettingGroups = (settings, groups, ungroupedTitle) => {
|
|
|
59
59
|
description: meta?.description ?? null,
|
|
60
60
|
note: meta?.note ?? null,
|
|
61
61
|
requiresFeature: meta?.requires_feature ?? null,
|
|
62
|
+
visibleWhen: meta?.visible_when ?? null,
|
|
62
63
|
settings: groupSettings,
|
|
63
64
|
blocks: buildSettingBlocks(groupSettings),
|
|
64
65
|
};
|
|
65
66
|
});
|
|
66
67
|
};
|
|
68
|
+
/** Whether a group's `visible_when` holds for the current form values. */
|
|
69
|
+
export const isGroupVisible = (group, draft) => group.visibleWhen === null ||
|
|
70
|
+
draft[group.visibleWhen.setting] === group.visibleWhen.equals;
|
|
@@ -963,6 +963,35 @@ const changedSettingValues = (settings, draft, unparsable = []) => {
|
|
|
963
963
|
}
|
|
964
964
|
return values;
|
|
965
965
|
};
|
|
966
|
+
const DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
967
|
+
const DATE_TIME_PATTERN = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})$/;
|
|
968
|
+
const pad = (value, length = 2) => String(value).padStart(length, "0");
|
|
969
|
+
const build = ([year, month, day, hour = 0, minute = 0]) => {
|
|
970
|
+
const date = new Date(year, month - 1, day, hour, minute);
|
|
971
|
+
const matches = date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day && date.getHours() === hour && date.getMinutes() === minute;
|
|
972
|
+
return matches ? date : null;
|
|
973
|
+
};
|
|
974
|
+
const dateFromInputValue = (value) => {
|
|
975
|
+
const match = value ? DATE_PATTERN.exec(value) : null;
|
|
976
|
+
return match ? build(match.slice(1).map(Number)) : null;
|
|
977
|
+
};
|
|
978
|
+
const inputValueFromDate = (date) => {
|
|
979
|
+
if (!date || Number.isNaN(date.getTime())) {
|
|
980
|
+
return "";
|
|
981
|
+
}
|
|
982
|
+
return `${pad(date.getFullYear(), 4)}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
|
|
983
|
+
};
|
|
984
|
+
const dateTimeFromInputValue = (value) => {
|
|
985
|
+
const match = value ? DATE_TIME_PATTERN.exec(value) : null;
|
|
986
|
+
return match ? build(match.slice(1).map(Number)) : null;
|
|
987
|
+
};
|
|
988
|
+
const inputValueFromDateTime = (date) => {
|
|
989
|
+
if (!date || Number.isNaN(date.getTime())) {
|
|
990
|
+
return "";
|
|
991
|
+
}
|
|
992
|
+
return `${inputValueFromDate(date)}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
993
|
+
};
|
|
994
|
+
const AdminDatePicker = (props) => /* @__PURE__ */ jsxRuntime.jsx(ui.I18nProvider, { locale: ADMIN_LOCALE, children: /* @__PURE__ */ jsxRuntime.jsx(ui.DatePicker, { ...props }) });
|
|
966
995
|
const buildSettingBlocks = (settings) => {
|
|
967
996
|
const blocks = [];
|
|
968
997
|
let previousSection = null;
|
|
@@ -1014,11 +1043,13 @@ const buildSettingGroups = (settings, groups, ungroupedTitle) => {
|
|
|
1014
1043
|
description: meta?.description ?? null,
|
|
1015
1044
|
note: meta?.note ?? null,
|
|
1016
1045
|
requiresFeature: meta?.requires_feature ?? null,
|
|
1046
|
+
visibleWhen: meta?.visible_when ?? null,
|
|
1017
1047
|
settings: groupSettings,
|
|
1018
1048
|
blocks: buildSettingBlocks(groupSettings)
|
|
1019
1049
|
};
|
|
1020
1050
|
});
|
|
1021
1051
|
};
|
|
1052
|
+
const isGroupVisible = (group, draft) => group.visibleWhen === null || draft[group.visibleWhen.setting] === group.visibleWhen.equals;
|
|
1022
1053
|
function usePluginSettingsForm(plugin2) {
|
|
1023
1054
|
const mutation = useUpdatePluginSettings(plugin2.plugin_key);
|
|
1024
1055
|
const [draft, setDraft] = react.useState(
|
|
@@ -1319,6 +1350,7 @@ const SettingField = ({
|
|
|
1319
1350
|
onChange
|
|
1320
1351
|
}) => {
|
|
1321
1352
|
const id = fieldId(pluginKey, setting.key);
|
|
1353
|
+
const labelId = `${id}-label`;
|
|
1322
1354
|
const hintId = `${id}-hint`;
|
|
1323
1355
|
const clearPending = setting.type === "secret" && value === null;
|
|
1324
1356
|
const bounds = setting.type === "number" ? boundsText(setting) : void 0;
|
|
@@ -1332,7 +1364,7 @@ const SettingField = ({
|
|
|
1332
1364
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2", children: [
|
|
1333
1365
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
1334
1366
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-1", children: [
|
|
1335
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: id, size: "small", weight: "plus", children: labelText(setting) }),
|
|
1367
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { id: labelId, htmlFor: id, size: "small", weight: "plus", children: labelText(setting) }),
|
|
1336
1368
|
info && /* @__PURE__ */ jsxRuntime.jsx(InfoTooltip, { label: texts.info.label(setting.label), children: info })
|
|
1337
1369
|
] }),
|
|
1338
1370
|
showsSourceHint(setting.source) && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xsmall", className: "text-ui-fg-muted shrink-0", children: texts.settings.source[setting.source] })
|
|
@@ -1406,6 +1438,16 @@ const SettingField = ({
|
|
|
1406
1438
|
disabled,
|
|
1407
1439
|
onChange: (next) => onChange(next)
|
|
1408
1440
|
}
|
|
1441
|
+
) : setting.type === "date" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1442
|
+
AdminDatePicker,
|
|
1443
|
+
{
|
|
1444
|
+
id,
|
|
1445
|
+
"aria-labelledby": labelId,
|
|
1446
|
+
"aria-describedby": describedBy,
|
|
1447
|
+
isDisabled: disabled,
|
|
1448
|
+
value: dateFromInputValue(typeof value === "string" ? value : ""),
|
|
1449
|
+
onChange: (date) => onChange(inputValueFromDate(date))
|
|
1450
|
+
}
|
|
1409
1451
|
) : setting.type === "number" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1410
1452
|
ui.Input,
|
|
1411
1453
|
{
|
|
@@ -1453,9 +1495,9 @@ const PluginSettingsForm = ({ plugin: plugin2 }) => {
|
|
|
1453
1495
|
plugin2.settings,
|
|
1454
1496
|
plugin2.setting_groups,
|
|
1455
1497
|
texts.sections.settings
|
|
1456
|
-
);
|
|
1498
|
+
).filter((group) => isGroupVisible(group, form.draft));
|
|
1457
1499
|
const hasTextFields = plugin2.settings.some(
|
|
1458
|
-
(setting) => setting.type === "string" || setting.type === "url" || setting.type === "number" || setting.type === "color"
|
|
1500
|
+
(setting) => setting.type === "string" || setting.type === "url" || setting.type === "number" || setting.type === "color" || setting.type === "date"
|
|
1459
1501
|
);
|
|
1460
1502
|
const renderField = (setting) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1461
1503
|
SettingField,
|
|
@@ -1641,29 +1683,6 @@ const PluginFeatureDisabledNotice = ({
|
|
|
1641
1683
|
]
|
|
1642
1684
|
}
|
|
1643
1685
|
);
|
|
1644
|
-
const DATE_TIME_PATTERN = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})$/;
|
|
1645
|
-
const pad = (value, length = 2) => String(value).padStart(length, "0");
|
|
1646
|
-
const build = ([year, month, day, hour = 0, minute = 0]) => {
|
|
1647
|
-
const date = new Date(year, month - 1, day, hour, minute);
|
|
1648
|
-
const matches = date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day && date.getHours() === hour && date.getMinutes() === minute;
|
|
1649
|
-
return matches ? date : null;
|
|
1650
|
-
};
|
|
1651
|
-
const inputValueFromDate = (date) => {
|
|
1652
|
-
if (!date || Number.isNaN(date.getTime())) {
|
|
1653
|
-
return "";
|
|
1654
|
-
}
|
|
1655
|
-
return `${pad(date.getFullYear(), 4)}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
|
|
1656
|
-
};
|
|
1657
|
-
const dateTimeFromInputValue = (value) => {
|
|
1658
|
-
const match = value ? DATE_TIME_PATTERN.exec(value) : null;
|
|
1659
|
-
return match ? build(match.slice(1).map(Number)) : null;
|
|
1660
|
-
};
|
|
1661
|
-
const inputValueFromDateTime = (date) => {
|
|
1662
|
-
if (!date || Number.isNaN(date.getTime())) {
|
|
1663
|
-
return "";
|
|
1664
|
-
}
|
|
1665
|
-
return `${inputValueFromDate(date)}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
1666
|
-
};
|
|
1667
1686
|
const fetchPdfObjectUrl = async (path) => {
|
|
1668
1687
|
const response = await sdk.client.fetch(path, {
|
|
1669
1688
|
headers: { accept: "application/pdf" }
|
|
@@ -1751,7 +1770,6 @@ const useDebouncedValue = (value, delayMs) => {
|
|
|
1751
1770
|
}, [value, delayMs]);
|
|
1752
1771
|
return debounced;
|
|
1753
1772
|
};
|
|
1754
|
-
const AdminDatePicker = (props) => /* @__PURE__ */ jsxRuntime.jsx(ui.I18nProvider, { locale: ADMIN_LOCALE, children: /* @__PURE__ */ jsxRuntime.jsx(ui.DatePicker, { ...props }) });
|
|
1755
1773
|
const FocusModalShell = ({
|
|
1756
1774
|
open,
|
|
1757
1775
|
onOpenChange,
|
|
@@ -4619,17 +4637,17 @@ const handle$5 = {
|
|
|
4619
4637
|
breadcrumb: () => "Protokoll"
|
|
4620
4638
|
};
|
|
4621
4639
|
const EmailLogRoute = () => /* @__PURE__ */ jsxRuntime.jsx(PluginFeatureRoute, { pluginKey: "email", children: /* @__PURE__ */ jsxRuntime.jsx(EmailLogPage, {}) });
|
|
4622
|
-
const handle$4 = {
|
|
4623
|
-
breadcrumb: () => EMAIL_TEMPLATE_GROUPS.order.label
|
|
4624
|
-
};
|
|
4625
|
-
const EmailOrderMailsRoute = () => /* @__PURE__ */ jsxRuntime.jsx(PluginFeatureRoute, { pluginKey: "email", children: /* @__PURE__ */ jsxRuntime.jsx(EmailTemplateGroupPage, { group: "order" }) });
|
|
4626
4640
|
const PluginDetailPage = () => {
|
|
4627
4641
|
const { plugin_key: pluginKey = "" } = reactRouterDom.useParams();
|
|
4628
4642
|
return /* @__PURE__ */ jsxRuntime.jsx(PluginPageShell, { pluginKey, variant: "header", children: /* @__PURE__ */ jsxRuntime.jsx(PluginFeatureSections, { pluginKey }) });
|
|
4629
4643
|
};
|
|
4630
|
-
const handle$
|
|
4644
|
+
const handle$4 = {
|
|
4631
4645
|
breadcrumb: (match) => /* @__PURE__ */ jsxRuntime.jsx(PluginLabelCrumb, { pluginKey: match.params.plugin_key ?? "" })
|
|
4632
4646
|
};
|
|
4647
|
+
const handle$3 = {
|
|
4648
|
+
breadcrumb: () => EMAIL_TEMPLATE_GROUPS.order.label
|
|
4649
|
+
};
|
|
4650
|
+
const EmailOrderMailsRoute = () => /* @__PURE__ */ jsxRuntime.jsx(PluginFeatureRoute, { pluginKey: "email", children: /* @__PURE__ */ jsxRuntime.jsx(EmailTemplateGroupPage, { group: "order" }) });
|
|
4633
4651
|
const STATUS_BADGES = {
|
|
4634
4652
|
current: { label: "aktuell", color: "green" },
|
|
4635
4653
|
planned: { label: "geplant", color: "blue" },
|
|
@@ -6715,13 +6733,13 @@ const routeModule = {
|
|
|
6715
6733
|
handle: handle$5
|
|
6716
6734
|
},
|
|
6717
6735
|
{
|
|
6718
|
-
Component:
|
|
6719
|
-
path: "/settings/hartl-services/
|
|
6736
|
+
Component: PluginDetailPage,
|
|
6737
|
+
path: "/settings/hartl-services/plugin/:plugin_key",
|
|
6720
6738
|
handle: handle$4
|
|
6721
6739
|
},
|
|
6722
6740
|
{
|
|
6723
|
-
Component:
|
|
6724
|
-
path: "/settings/hartl-services/
|
|
6741
|
+
Component: EmailOrderMailsRoute,
|
|
6742
|
+
path: "/settings/hartl-services/email/order",
|
|
6725
6743
|
handle: handle$3
|
|
6726
6744
|
},
|
|
6727
6745
|
{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { defineWidgetConfig, defineRouteConfig } from "@medusajs/admin-sdk";
|
|
3
|
-
import { Container, IconBadge, Heading, Text, Tooltip, IconButton, toast, StatusBadge, Button, clx, usePrompt, Label, Switch, Hint, Input, Select, Alert,
|
|
3
|
+
import { Container, IconBadge, Heading, Text, Tooltip, IconButton, toast, StatusBadge, Button, clx, usePrompt, Label, Switch, I18nProvider, DatePicker, Hint, Input, Select, Alert, FocusModal, DropdownMenu, Badge, Table, Prompt } from "@medusajs/ui";
|
|
4
4
|
import { useQuery, useQueryClient, useMutation, keepPreviousData, skipToken } from "@tanstack/react-query";
|
|
5
5
|
import { emailAdminPaths } from "@hartl-services/medusa-food-supplements-contracts/paths/email";
|
|
6
6
|
import Medusa from "@medusajs/js-sdk";
|
|
@@ -957,6 +957,35 @@ const changedSettingValues = (settings, draft, unparsable = []) => {
|
|
|
957
957
|
}
|
|
958
958
|
return values;
|
|
959
959
|
};
|
|
960
|
+
const DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
961
|
+
const DATE_TIME_PATTERN = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})$/;
|
|
962
|
+
const pad = (value, length = 2) => String(value).padStart(length, "0");
|
|
963
|
+
const build = ([year, month, day, hour = 0, minute = 0]) => {
|
|
964
|
+
const date = new Date(year, month - 1, day, hour, minute);
|
|
965
|
+
const matches = date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day && date.getHours() === hour && date.getMinutes() === minute;
|
|
966
|
+
return matches ? date : null;
|
|
967
|
+
};
|
|
968
|
+
const dateFromInputValue = (value) => {
|
|
969
|
+
const match = value ? DATE_PATTERN.exec(value) : null;
|
|
970
|
+
return match ? build(match.slice(1).map(Number)) : null;
|
|
971
|
+
};
|
|
972
|
+
const inputValueFromDate = (date) => {
|
|
973
|
+
if (!date || Number.isNaN(date.getTime())) {
|
|
974
|
+
return "";
|
|
975
|
+
}
|
|
976
|
+
return `${pad(date.getFullYear(), 4)}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
|
|
977
|
+
};
|
|
978
|
+
const dateTimeFromInputValue = (value) => {
|
|
979
|
+
const match = value ? DATE_TIME_PATTERN.exec(value) : null;
|
|
980
|
+
return match ? build(match.slice(1).map(Number)) : null;
|
|
981
|
+
};
|
|
982
|
+
const inputValueFromDateTime = (date) => {
|
|
983
|
+
if (!date || Number.isNaN(date.getTime())) {
|
|
984
|
+
return "";
|
|
985
|
+
}
|
|
986
|
+
return `${inputValueFromDate(date)}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
987
|
+
};
|
|
988
|
+
const AdminDatePicker = (props) => /* @__PURE__ */ jsx(I18nProvider, { locale: ADMIN_LOCALE, children: /* @__PURE__ */ jsx(DatePicker, { ...props }) });
|
|
960
989
|
const buildSettingBlocks = (settings) => {
|
|
961
990
|
const blocks = [];
|
|
962
991
|
let previousSection = null;
|
|
@@ -1008,11 +1037,13 @@ const buildSettingGroups = (settings, groups, ungroupedTitle) => {
|
|
|
1008
1037
|
description: meta?.description ?? null,
|
|
1009
1038
|
note: meta?.note ?? null,
|
|
1010
1039
|
requiresFeature: meta?.requires_feature ?? null,
|
|
1040
|
+
visibleWhen: meta?.visible_when ?? null,
|
|
1011
1041
|
settings: groupSettings,
|
|
1012
1042
|
blocks: buildSettingBlocks(groupSettings)
|
|
1013
1043
|
};
|
|
1014
1044
|
});
|
|
1015
1045
|
};
|
|
1046
|
+
const isGroupVisible = (group, draft) => group.visibleWhen === null || draft[group.visibleWhen.setting] === group.visibleWhen.equals;
|
|
1016
1047
|
function usePluginSettingsForm(plugin2) {
|
|
1017
1048
|
const mutation = useUpdatePluginSettings(plugin2.plugin_key);
|
|
1018
1049
|
const [draft, setDraft] = useState(
|
|
@@ -1313,6 +1344,7 @@ const SettingField = ({
|
|
|
1313
1344
|
onChange
|
|
1314
1345
|
}) => {
|
|
1315
1346
|
const id = fieldId(pluginKey, setting.key);
|
|
1347
|
+
const labelId = `${id}-label`;
|
|
1316
1348
|
const hintId = `${id}-hint`;
|
|
1317
1349
|
const clearPending = setting.type === "secret" && value === null;
|
|
1318
1350
|
const bounds = setting.type === "number" ? boundsText(setting) : void 0;
|
|
@@ -1326,7 +1358,7 @@ const SettingField = ({
|
|
|
1326
1358
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-2", children: [
|
|
1327
1359
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
1328
1360
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-1", children: [
|
|
1329
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: id, size: "small", weight: "plus", children: labelText(setting) }),
|
|
1361
|
+
/* @__PURE__ */ jsx(Label, { id: labelId, htmlFor: id, size: "small", weight: "plus", children: labelText(setting) }),
|
|
1330
1362
|
info && /* @__PURE__ */ jsx(InfoTooltip, { label: texts.info.label(setting.label), children: info })
|
|
1331
1363
|
] }),
|
|
1332
1364
|
showsSourceHint(setting.source) && /* @__PURE__ */ jsx(Text, { size: "xsmall", className: "text-ui-fg-muted shrink-0", children: texts.settings.source[setting.source] })
|
|
@@ -1400,6 +1432,16 @@ const SettingField = ({
|
|
|
1400
1432
|
disabled,
|
|
1401
1433
|
onChange: (next) => onChange(next)
|
|
1402
1434
|
}
|
|
1435
|
+
) : setting.type === "date" ? /* @__PURE__ */ jsx(
|
|
1436
|
+
AdminDatePicker,
|
|
1437
|
+
{
|
|
1438
|
+
id,
|
|
1439
|
+
"aria-labelledby": labelId,
|
|
1440
|
+
"aria-describedby": describedBy,
|
|
1441
|
+
isDisabled: disabled,
|
|
1442
|
+
value: dateFromInputValue(typeof value === "string" ? value : ""),
|
|
1443
|
+
onChange: (date) => onChange(inputValueFromDate(date))
|
|
1444
|
+
}
|
|
1403
1445
|
) : setting.type === "number" ? /* @__PURE__ */ jsx(
|
|
1404
1446
|
Input,
|
|
1405
1447
|
{
|
|
@@ -1447,9 +1489,9 @@ const PluginSettingsForm = ({ plugin: plugin2 }) => {
|
|
|
1447
1489
|
plugin2.settings,
|
|
1448
1490
|
plugin2.setting_groups,
|
|
1449
1491
|
texts.sections.settings
|
|
1450
|
-
);
|
|
1492
|
+
).filter((group) => isGroupVisible(group, form.draft));
|
|
1451
1493
|
const hasTextFields = plugin2.settings.some(
|
|
1452
|
-
(setting) => setting.type === "string" || setting.type === "url" || setting.type === "number" || setting.type === "color"
|
|
1494
|
+
(setting) => setting.type === "string" || setting.type === "url" || setting.type === "number" || setting.type === "color" || setting.type === "date"
|
|
1453
1495
|
);
|
|
1454
1496
|
const renderField = (setting) => /* @__PURE__ */ jsx(
|
|
1455
1497
|
SettingField,
|
|
@@ -1635,29 +1677,6 @@ const PluginFeatureDisabledNotice = ({
|
|
|
1635
1677
|
]
|
|
1636
1678
|
}
|
|
1637
1679
|
);
|
|
1638
|
-
const DATE_TIME_PATTERN = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})$/;
|
|
1639
|
-
const pad = (value, length = 2) => String(value).padStart(length, "0");
|
|
1640
|
-
const build = ([year, month, day, hour = 0, minute = 0]) => {
|
|
1641
|
-
const date = new Date(year, month - 1, day, hour, minute);
|
|
1642
|
-
const matches = date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day && date.getHours() === hour && date.getMinutes() === minute;
|
|
1643
|
-
return matches ? date : null;
|
|
1644
|
-
};
|
|
1645
|
-
const inputValueFromDate = (date) => {
|
|
1646
|
-
if (!date || Number.isNaN(date.getTime())) {
|
|
1647
|
-
return "";
|
|
1648
|
-
}
|
|
1649
|
-
return `${pad(date.getFullYear(), 4)}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
|
|
1650
|
-
};
|
|
1651
|
-
const dateTimeFromInputValue = (value) => {
|
|
1652
|
-
const match = value ? DATE_TIME_PATTERN.exec(value) : null;
|
|
1653
|
-
return match ? build(match.slice(1).map(Number)) : null;
|
|
1654
|
-
};
|
|
1655
|
-
const inputValueFromDateTime = (date) => {
|
|
1656
|
-
if (!date || Number.isNaN(date.getTime())) {
|
|
1657
|
-
return "";
|
|
1658
|
-
}
|
|
1659
|
-
return `${inputValueFromDate(date)}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
1660
|
-
};
|
|
1661
1680
|
const fetchPdfObjectUrl = async (path) => {
|
|
1662
1681
|
const response = await sdk.client.fetch(path, {
|
|
1663
1682
|
headers: { accept: "application/pdf" }
|
|
@@ -1745,7 +1764,6 @@ const useDebouncedValue = (value, delayMs) => {
|
|
|
1745
1764
|
}, [value, delayMs]);
|
|
1746
1765
|
return debounced;
|
|
1747
1766
|
};
|
|
1748
|
-
const AdminDatePicker = (props) => /* @__PURE__ */ jsx(I18nProvider, { locale: ADMIN_LOCALE, children: /* @__PURE__ */ jsx(DatePicker, { ...props }) });
|
|
1749
1767
|
const FocusModalShell = ({
|
|
1750
1768
|
open,
|
|
1751
1769
|
onOpenChange,
|
|
@@ -4613,17 +4631,17 @@ const handle$5 = {
|
|
|
4613
4631
|
breadcrumb: () => "Protokoll"
|
|
4614
4632
|
};
|
|
4615
4633
|
const EmailLogRoute = () => /* @__PURE__ */ jsx(PluginFeatureRoute, { pluginKey: "email", children: /* @__PURE__ */ jsx(EmailLogPage, {}) });
|
|
4616
|
-
const handle$4 = {
|
|
4617
|
-
breadcrumb: () => EMAIL_TEMPLATE_GROUPS.order.label
|
|
4618
|
-
};
|
|
4619
|
-
const EmailOrderMailsRoute = () => /* @__PURE__ */ jsx(PluginFeatureRoute, { pluginKey: "email", children: /* @__PURE__ */ jsx(EmailTemplateGroupPage, { group: "order" }) });
|
|
4620
4634
|
const PluginDetailPage = () => {
|
|
4621
4635
|
const { plugin_key: pluginKey = "" } = useParams();
|
|
4622
4636
|
return /* @__PURE__ */ jsx(PluginPageShell, { pluginKey, variant: "header", children: /* @__PURE__ */ jsx(PluginFeatureSections, { pluginKey }) });
|
|
4623
4637
|
};
|
|
4624
|
-
const handle$
|
|
4638
|
+
const handle$4 = {
|
|
4625
4639
|
breadcrumb: (match) => /* @__PURE__ */ jsx(PluginLabelCrumb, { pluginKey: match.params.plugin_key ?? "" })
|
|
4626
4640
|
};
|
|
4641
|
+
const handle$3 = {
|
|
4642
|
+
breadcrumb: () => EMAIL_TEMPLATE_GROUPS.order.label
|
|
4643
|
+
};
|
|
4644
|
+
const EmailOrderMailsRoute = () => /* @__PURE__ */ jsx(PluginFeatureRoute, { pluginKey: "email", children: /* @__PURE__ */ jsx(EmailTemplateGroupPage, { group: "order" }) });
|
|
4627
4645
|
const STATUS_BADGES = {
|
|
4628
4646
|
current: { label: "aktuell", color: "green" },
|
|
4629
4647
|
planned: { label: "geplant", color: "blue" },
|
|
@@ -6709,13 +6727,13 @@ const routeModule = {
|
|
|
6709
6727
|
handle: handle$5
|
|
6710
6728
|
},
|
|
6711
6729
|
{
|
|
6712
|
-
Component:
|
|
6713
|
-
path: "/settings/hartl-services/
|
|
6730
|
+
Component: PluginDetailPage,
|
|
6731
|
+
path: "/settings/hartl-services/plugin/:plugin_key",
|
|
6714
6732
|
handle: handle$4
|
|
6715
6733
|
},
|
|
6716
6734
|
{
|
|
6717
|
-
Component:
|
|
6718
|
-
path: "/settings/hartl-services/
|
|
6735
|
+
Component: EmailOrderMailsRoute,
|
|
6736
|
+
path: "/settings/hartl-services/email/order",
|
|
6719
6737
|
handle: handle$3
|
|
6720
6738
|
},
|
|
6721
6739
|
{
|