@isaiahiroko/tilmart-ngx-apps-admin 0.2.4 → 0.2.6
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/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-banners.module-KSapnx6Y.mjs → isaiahiroko-tilmart-ngx-apps-admin-banners.module-BPMlfHaC.mjs} +3 -3
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-banners.module-KSapnx6Y.mjs.map → isaiahiroko-tilmart-ngx-apps-admin-banners.module-BPMlfHaC.mjs.map} +1 -1
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-brands.module-7I0ni-tQ.mjs → isaiahiroko-tilmart-ngx-apps-admin-brands.module-CSp0tWes.mjs} +3 -3
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-brands.module-7I0ni-tQ.mjs.map → isaiahiroko-tilmart-ngx-apps-admin-brands.module-CSp0tWes.mjs.map} +1 -1
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-categories.module-OTUfenf0.mjs → isaiahiroko-tilmart-ngx-apps-admin-categories.module-uKkUREjb.mjs} +3 -3
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-categories.module-OTUfenf0.mjs.map → isaiahiroko-tilmart-ngx-apps-admin-categories.module-uKkUREjb.mjs.map} +1 -1
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-coupons.module-CoRh6Hxq.mjs → isaiahiroko-tilmart-ngx-apps-admin-coupons.module-Dcu1nJBW.mjs} +3 -3
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-coupons.module-CoRh6Hxq.mjs.map → isaiahiroko-tilmart-ngx-apps-admin-coupons.module-Dcu1nJBW.mjs.map} +1 -1
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-flash-sales.module-BPRnC17l.mjs → isaiahiroko-tilmart-ngx-apps-admin-flash-sales.module-DF7iSJaN.mjs} +3 -3
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-flash-sales.module-BPRnC17l.mjs.map → isaiahiroko-tilmart-ngx-apps-admin-flash-sales.module-DF7iSJaN.mjs.map} +1 -1
- package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-profile.module-D-r3HcHq.mjs +139 -0
- package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-profile.module-D-r3HcHq.mjs.map +1 -0
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-promotions.module-DG03OY1q.mjs → isaiahiroko-tilmart-ngx-apps-admin-promotions.module-BO4zRytg.mjs} +3 -3
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-promotions.module-DG03OY1q.mjs.map → isaiahiroko-tilmart-ngx-apps-admin-promotions.module-BO4zRytg.mjs.map} +1 -1
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-redirects.module-oQw5Xo5T.mjs → isaiahiroko-tilmart-ngx-apps-admin-redirects.module-D8H6ujoy.mjs} +3 -3
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-redirects.module-oQw5Xo5T.mjs.map → isaiahiroko-tilmart-ngx-apps-admin-redirects.module-D8H6ujoy.mjs.map} +1 -1
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-routes.module-CGBBHwId.mjs → isaiahiroko-tilmart-ngx-apps-admin-routes.module-fYKd3AOq.mjs} +3 -3
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-routes.module-CGBBHwId.mjs.map → isaiahiroko-tilmart-ngx-apps-admin-routes.module-fYKd3AOq.mjs.map} +1 -1
- package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-staff.module-YjJJe00X.mjs +185 -0
- package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin-staff.module-YjJJe00X.mjs.map +1 -0
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-stock.module-Bt9W1oGR.mjs → isaiahiroko-tilmart-ngx-apps-admin-stock.module-BSAe0CfZ.mjs} +3 -3
- package/fesm2022/{isaiahiroko-tilmart-ngx-apps-admin-stock.module-Bt9W1oGR.mjs.map → isaiahiroko-tilmart-ngx-apps-admin-stock.module-BSAe0CfZ.mjs.map} +1 -1
- package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin.mjs +38 -18
- package/fesm2022/isaiahiroko-tilmart-ngx-apps-admin.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -49,11 +49,11 @@ class FlashSalesComponent extends SimpleCrudDirective {
|
|
|
49
49
|
];
|
|
50
50
|
}
|
|
51
51
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FlashSalesComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
52
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: FlashSalesComponent, isStandalone: false, selector: "x-flash-sales", usesInheritance: true, ngImport: i0, template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">{{ pageTitle }}</div>\n <div class=\"x-page-subtitle\">{{ pageSubtitle }}</div>\n</div>\n\n@if (!editing) {\n <div class=\"x-scrud-toolbar\">\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" (click)=\"startCreate()\">+ New {{ singularLabel }}</button>\n </div>\n\n @if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n} @else if (draft) {\n <div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">{{ draft['id'] ? 'Edit' : 'New' }} {{ singularLabel }}</div>\n <div class=\"x-scrud-editor-actions\">\n @if (draft['id'] && !hideDelete) {\n <button type=\"button\" class=\"x-scrud-btn x-scrud-danger\" (click)=\"remove(draft); cancelEdit()\">Delete</button>\n }\n <button type=\"button\" class=\"x-scrud-btn\" (click)=\"cancelEdit()\">Close</button>\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" [disabled]=\"saving\" (click)=\"save()\">\n {{ saving ? 'Saving\u2026' : 'Save' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n @for (f of fields; track f.key) {\n <label class=\"x-scrud-f\" [class.x-scrud-f-wide]=\"f.type === 'textarea' || f.type === 'json'\">\n {{ f.label }}\n @if (f.required) {\n <span class=\"x-scrud-required\">*</span>\n }\n @switch (f.type) {\n @case ('boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"draft[f.key]\" />\n }\n @case ('select') {\n <select [(ngModel)]=\"draft[f.key]\">\n <option value=\"\">\u2014 choose \u2014</option>\n @for (opt of (f.optionsKey ? dynamicOptions[f.optionsKey] : f.options); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n }\n @case ('textarea') {\n <textarea rows=\"3\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\"></textarea>\n }\n @case ('json') {\n <textarea rows=\"4\" class=\"x-scrud-json\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || '{}'\"></textarea>\n }\n @case ('number') {\n <input type=\"number\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n @case ('date') {\n <input type=\"datetime-local\" [(ngModel)]=\"draft[f.key]\" />\n }\n @default {\n <input type=\"text\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n }\n </label>\n }\n </div>\n </div>\n}\n", styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}.x-scrud-toolbar{display:flex;justify-content:flex-end;margin-bottom:14px}.x-scrud-btn{border:1px solid var(--color-border);background:transparent;border-radius:var(--radius-md);padding:6px 14px;font-size:12.5px;font-weight:700;cursor:pointer;color:var(--color-text-muted)}.x-scrud-btn:disabled{opacity:.5;cursor:default}.x-scrud-btn-primary{border-color:var(--color-accent);color:var(--color-accent-hover)}.x-scrud-danger{color:var(--color-danger, #c0362c)}.x-scrud-editor{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:16px;display:flex;flex-direction:column;gap:14px}.x-scrud-editor-head{display:flex;align-items:center;justify-content:space-between}.x-scrud-editor-title{font-size:16px;font-weight:800;color:var(--color-text)}.x-scrud-editor-actions{display:flex;gap:8px}.x-scrud-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.x-scrud-f{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--color-text-muted);font-weight:700}.x-scrud-f-wide{grid-column:1/-1}.x-scrud-f input,.x-scrud-f select,.x-scrud-f textarea{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:6px 10px;font-size:13px;background:var(--color-surface);color:var(--color-text);font-weight:400}.x-scrud-f input[type=checkbox]{width:18px;height:18px}.x-scrud-json{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.x-scrud-required{color:var(--color-danger, #c0362c)}\n"], dependencies: [{ kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.LoaderComponent, selector: "x-element-loader", inputs: ["data"] }, { kind: "component", type: i2.CollectionComponent, selector: "x-webget-collection", inputs: ["data"], outputs: ["search", "filter", "refresh", "select", "page", "show"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] }); }
|
|
52
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: FlashSalesComponent, isStandalone: false, selector: "x-flash-sales", usesInheritance: true, ngImport: i0, template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">{{ pageTitle }}</div>\n <div class=\"x-page-subtitle\">{{ pageSubtitle }}</div>\n</div>\n\n@if (!editing) {\n <div class=\"x-scrud-toolbar\">\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" (click)=\"startCreate()\">+ New {{ singularLabel }}</button>\n </div>\n\n @if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n} @else if (draft) {\n <div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">{{ draft['id'] ? 'Edit' : 'New' }} {{ singularLabel }}</div>\n <div class=\"x-scrud-editor-actions\">\n @if (draft['id'] && !hideDelete) {\n <button type=\"button\" class=\"x-scrud-btn x-scrud-danger\" (click)=\"remove(draft); cancelEdit()\">Delete</button>\n }\n <button type=\"button\" class=\"x-scrud-btn\" (click)=\"cancelEdit()\">Close</button>\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" [disabled]=\"saving\" (click)=\"save()\">\n {{ saving ? 'Saving\u2026' : 'Save' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n @for (f of fields; track f.key) {\n <label class=\"x-scrud-f\" [class.x-scrud-f-wide]=\"f.type === 'textarea' || f.type === 'json'\">\n {{ f.label }}\n @if (f.required) {\n <span class=\"x-scrud-required\">*</span>\n }\n @switch (f.type) {\n @case ('boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"draft[f.key]\" />\n }\n @case ('select') {\n <select [(ngModel)]=\"draft[f.key]\">\n <option value=\"\">\u2014 choose \u2014</option>\n @for (opt of (f.optionsKey ? dynamicOptions[f.optionsKey] : f.options); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n }\n @case ('textarea') {\n <textarea rows=\"3\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\"></textarea>\n }\n @case ('json') {\n <textarea rows=\"4\" class=\"x-scrud-json\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || '{}'\"></textarea>\n }\n @case ('number') {\n <input type=\"number\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n @case ('date') {\n <input type=\"datetime-local\" [(ngModel)]=\"draft[f.key]\" />\n }\n @default {\n <input type=\"text\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n }\n </label>\n }\n </div>\n </div>\n}\n", styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}.x-scrud-toolbar{display:flex;justify-content:flex-end;margin-bottom:14px}.x-scrud-btn{border:1px solid var(--color-border);background:transparent;border-radius:var(--radius-md);padding:6px 14px;font-size:12.5px;font-weight:700;cursor:pointer;color:var(--color-text-muted)}.x-scrud-btn:disabled{opacity:.5;cursor:default}.x-scrud-btn-primary{border-color:var(--color-accent);color:var(--color-accent-hover)}.x-scrud-danger{color:var(--color-danger, #c0362c)}.x-scrud-editor{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:16px;display:flex;flex-direction:column;gap:14px}.x-scrud-editor-head{display:flex;align-items:center;justify-content:space-between}.x-scrud-editor-title{font-size:16px;font-weight:800;color:var(--color-text)}.x-scrud-editor-actions{display:flex;gap:8px}.x-scrud-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.x-scrud-f{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--color-text-muted);font-weight:700}.x-scrud-f-wide{grid-column:1/-1}.x-scrud-f input,.x-scrud-f select,.x-scrud-f textarea{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:6px 10px;font-size:13px;background:var(--color-surface);color:var(--color-text);font-weight:400}.x-scrud-f input[type=checkbox]{width:18px;height:18px}.x-scrud-pwd{position:relative;display:flex}.x-scrud-pwd input{flex:1;padding-right:34px!important}.x-scrud-pwd-toggle{position:absolute;right:4px;top:50%;transform:translateY(-50%);border:none;background:transparent;color:var(--color-text-muted);padding:4px 6px;cursor:pointer}.x-scrud-pwd-toggle:hover{color:var(--color-text)}.x-scrud-json{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.x-scrud-required{color:var(--color-danger, #c0362c)}\n"], dependencies: [{ kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.LoaderComponent, selector: "x-element-loader", inputs: ["data"] }, { kind: "component", type: i2.CollectionComponent, selector: "x-webget-collection", inputs: ["data"], outputs: ["search", "filter", "refresh", "select", "page", "show"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] }); }
|
|
53
53
|
}
|
|
54
54
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FlashSalesComponent, decorators: [{
|
|
55
55
|
type: Component,
|
|
56
|
-
args: [{ standalone: false, selector: 'x-flash-sales', template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">{{ pageTitle }}</div>\n <div class=\"x-page-subtitle\">{{ pageSubtitle }}</div>\n</div>\n\n@if (!editing) {\n <div class=\"x-scrud-toolbar\">\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" (click)=\"startCreate()\">+ New {{ singularLabel }}</button>\n </div>\n\n @if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n} @else if (draft) {\n <div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">{{ draft['id'] ? 'Edit' : 'New' }} {{ singularLabel }}</div>\n <div class=\"x-scrud-editor-actions\">\n @if (draft['id'] && !hideDelete) {\n <button type=\"button\" class=\"x-scrud-btn x-scrud-danger\" (click)=\"remove(draft); cancelEdit()\">Delete</button>\n }\n <button type=\"button\" class=\"x-scrud-btn\" (click)=\"cancelEdit()\">Close</button>\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" [disabled]=\"saving\" (click)=\"save()\">\n {{ saving ? 'Saving\u2026' : 'Save' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n @for (f of fields; track f.key) {\n <label class=\"x-scrud-f\" [class.x-scrud-f-wide]=\"f.type === 'textarea' || f.type === 'json'\">\n {{ f.label }}\n @if (f.required) {\n <span class=\"x-scrud-required\">*</span>\n }\n @switch (f.type) {\n @case ('boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"draft[f.key]\" />\n }\n @case ('select') {\n <select [(ngModel)]=\"draft[f.key]\">\n <option value=\"\">\u2014 choose \u2014</option>\n @for (opt of (f.optionsKey ? dynamicOptions[f.optionsKey] : f.options); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n }\n @case ('textarea') {\n <textarea rows=\"3\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\"></textarea>\n }\n @case ('json') {\n <textarea rows=\"4\" class=\"x-scrud-json\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || '{}'\"></textarea>\n }\n @case ('number') {\n <input type=\"number\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n @case ('date') {\n <input type=\"datetime-local\" [(ngModel)]=\"draft[f.key]\" />\n }\n @default {\n <input type=\"text\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n }\n </label>\n }\n </div>\n </div>\n}\n", styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}.x-scrud-toolbar{display:flex;justify-content:flex-end;margin-bottom:14px}.x-scrud-btn{border:1px solid var(--color-border);background:transparent;border-radius:var(--radius-md);padding:6px 14px;font-size:12.5px;font-weight:700;cursor:pointer;color:var(--color-text-muted)}.x-scrud-btn:disabled{opacity:.5;cursor:default}.x-scrud-btn-primary{border-color:var(--color-accent);color:var(--color-accent-hover)}.x-scrud-danger{color:var(--color-danger, #c0362c)}.x-scrud-editor{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:16px;display:flex;flex-direction:column;gap:14px}.x-scrud-editor-head{display:flex;align-items:center;justify-content:space-between}.x-scrud-editor-title{font-size:16px;font-weight:800;color:var(--color-text)}.x-scrud-editor-actions{display:flex;gap:8px}.x-scrud-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.x-scrud-f{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--color-text-muted);font-weight:700}.x-scrud-f-wide{grid-column:1/-1}.x-scrud-f input,.x-scrud-f select,.x-scrud-f textarea{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:6px 10px;font-size:13px;background:var(--color-surface);color:var(--color-text);font-weight:400}.x-scrud-f input[type=checkbox]{width:18px;height:18px}.x-scrud-json{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.x-scrud-required{color:var(--color-danger, #c0362c)}\n"] }]
|
|
56
|
+
args: [{ standalone: false, selector: 'x-flash-sales', template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">{{ pageTitle }}</div>\n <div class=\"x-page-subtitle\">{{ pageSubtitle }}</div>\n</div>\n\n@if (!editing) {\n <div class=\"x-scrud-toolbar\">\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" (click)=\"startCreate()\">+ New {{ singularLabel }}</button>\n </div>\n\n @if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n} @else if (draft) {\n <div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">{{ draft['id'] ? 'Edit' : 'New' }} {{ singularLabel }}</div>\n <div class=\"x-scrud-editor-actions\">\n @if (draft['id'] && !hideDelete) {\n <button type=\"button\" class=\"x-scrud-btn x-scrud-danger\" (click)=\"remove(draft); cancelEdit()\">Delete</button>\n }\n <button type=\"button\" class=\"x-scrud-btn\" (click)=\"cancelEdit()\">Close</button>\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" [disabled]=\"saving\" (click)=\"save()\">\n {{ saving ? 'Saving\u2026' : 'Save' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n @for (f of fields; track f.key) {\n <label class=\"x-scrud-f\" [class.x-scrud-f-wide]=\"f.type === 'textarea' || f.type === 'json'\">\n {{ f.label }}\n @if (f.required) {\n <span class=\"x-scrud-required\">*</span>\n }\n @switch (f.type) {\n @case ('boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"draft[f.key]\" />\n }\n @case ('select') {\n <select [(ngModel)]=\"draft[f.key]\">\n <option value=\"\">\u2014 choose \u2014</option>\n @for (opt of (f.optionsKey ? dynamicOptions[f.optionsKey] : f.options); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n }\n @case ('textarea') {\n <textarea rows=\"3\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\"></textarea>\n }\n @case ('json') {\n <textarea rows=\"4\" class=\"x-scrud-json\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || '{}'\"></textarea>\n }\n @case ('number') {\n <input type=\"number\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n @case ('date') {\n <input type=\"datetime-local\" [(ngModel)]=\"draft[f.key]\" />\n }\n @default {\n <input type=\"text\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n }\n </label>\n }\n </div>\n </div>\n}\n", styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}.x-scrud-toolbar{display:flex;justify-content:flex-end;margin-bottom:14px}.x-scrud-btn{border:1px solid var(--color-border);background:transparent;border-radius:var(--radius-md);padding:6px 14px;font-size:12.5px;font-weight:700;cursor:pointer;color:var(--color-text-muted)}.x-scrud-btn:disabled{opacity:.5;cursor:default}.x-scrud-btn-primary{border-color:var(--color-accent);color:var(--color-accent-hover)}.x-scrud-danger{color:var(--color-danger, #c0362c)}.x-scrud-editor{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:16px;display:flex;flex-direction:column;gap:14px}.x-scrud-editor-head{display:flex;align-items:center;justify-content:space-between}.x-scrud-editor-title{font-size:16px;font-weight:800;color:var(--color-text)}.x-scrud-editor-actions{display:flex;gap:8px}.x-scrud-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.x-scrud-f{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--color-text-muted);font-weight:700}.x-scrud-f-wide{grid-column:1/-1}.x-scrud-f input,.x-scrud-f select,.x-scrud-f textarea{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:6px 10px;font-size:13px;background:var(--color-surface);color:var(--color-text);font-weight:400}.x-scrud-f input[type=checkbox]{width:18px;height:18px}.x-scrud-pwd{position:relative;display:flex}.x-scrud-pwd input{flex:1;padding-right:34px!important}.x-scrud-pwd-toggle{position:absolute;right:4px;top:50%;transform:translateY(-50%);border:none;background:transparent;color:var(--color-text-muted);padding:4px 6px;cursor:pointer}.x-scrud-pwd-toggle:hover{color:var(--color-text)}.x-scrud-json{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.x-scrud-required{color:var(--color-danger, #c0362c)}\n"] }]
|
|
57
57
|
}] });
|
|
58
58
|
|
|
59
59
|
class FlashSalesModule {
|
|
@@ -80,4 +80,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
80
80
|
}] });
|
|
81
81
|
|
|
82
82
|
export { FlashSalesModule };
|
|
83
|
-
//# sourceMappingURL=isaiahiroko-tilmart-ngx-apps-admin-flash-sales.module-
|
|
83
|
+
//# sourceMappingURL=isaiahiroko-tilmart-ngx-apps-admin-flash-sales.module-DF7iSJaN.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"isaiahiroko-tilmart-ngx-apps-admin-flash-sales.module-
|
|
1
|
+
{"version":3,"file":"isaiahiroko-tilmart-ngx-apps-admin-flash-sales.module-DF7iSJaN.mjs","sources":["../../../projects/admin/src/lib/pages/flash-sales/flash-sales.component.ts","../../../projects/admin/src/lib/pages/_shared/simple-crud.component.html","../../../projects/admin/src/lib/pages/flash-sales/flash-sales.module.ts"],"sourcesContent":["import { Component } from '@angular/core';\nimport { CrudFieldSpec, SimpleCrudDirective } from '../_shared/simple-crud.base';\n\n// R1 production-readiness pass — PROMO-04. Previously missing entirely:\n// the homepage composer's `flash_sale_rail` module references a flash\n// sale by id, but there was no page to create the sale window itself.\n// Per-SKU allocation/limits stay a follow-up — this covers the sale\n// window (name, schedule, channels), which is what a module needs to\n// resolve and what ops needs to schedule ahead of time.\n@Component({\n standalone: false,\n selector: 'x-flash-sales',\n templateUrl: '../_shared/simple-crud.component.html',\n styleUrl: '../_shared/simple-crud.component.scss',\n})\nexport class FlashSalesComponent extends SimpleCrudDirective {\n protected pageTitle = 'Flash sales';\n protected pageSubtitle = 'Time-boxed sale windows referenced by the homepage flash-sale rail.';\n protected singularLabel = 'flash sale';\n protected pluralName = 'flash sales';\n protected dataSource = this.apiService.on('apps/commerce/flash-sale');\n\n protected columns = [\n { key: 'name', value: 'Name' },\n { key: 'status', value: 'Status', type: 'class', class: 'badge text-bg-light border' },\n { key: 'startsAt', value: 'Starts', type: 'date' },\n { key: 'endsAt', value: 'Ends', type: 'date' },\n ];\n\n protected fields: CrudFieldSpec[] = [\n { key: 'name', label: 'Name', type: 'text', required: true },\n { key: 'description', label: 'Description', type: 'textarea' },\n {\n key: 'status',\n label: 'Status',\n type: 'select',\n options: [\n { value: 'draft', label: 'Draft' },\n { value: 'scheduled', label: 'Scheduled' },\n { value: 'live', label: 'Live' },\n { value: 'ended', label: 'Ended' },\n { value: 'cancelled', label: 'Cancelled' },\n ],\n },\n { key: 'startsAt', label: 'Starts at', type: 'date' },\n { key: 'endsAt', label: 'Ends at', type: 'date' },\n ];\n}\n","<div class=\"x-page-head\">\n <div class=\"x-page-title\">{{ pageTitle }}</div>\n <div class=\"x-page-subtitle\">{{ pageSubtitle }}</div>\n</div>\n\n@if (!editing) {\n <div class=\"x-scrud-toolbar\">\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" (click)=\"startCreate()\">+ New {{ singularLabel }}</button>\n </div>\n\n @if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n} @else if (draft) {\n <div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">{{ draft['id'] ? 'Edit' : 'New' }} {{ singularLabel }}</div>\n <div class=\"x-scrud-editor-actions\">\n @if (draft['id'] && !hideDelete) {\n <button type=\"button\" class=\"x-scrud-btn x-scrud-danger\" (click)=\"remove(draft); cancelEdit()\">Delete</button>\n }\n <button type=\"button\" class=\"x-scrud-btn\" (click)=\"cancelEdit()\">Close</button>\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" [disabled]=\"saving\" (click)=\"save()\">\n {{ saving ? 'Saving…' : 'Save' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n @for (f of fields; track f.key) {\n <label class=\"x-scrud-f\" [class.x-scrud-f-wide]=\"f.type === 'textarea' || f.type === 'json'\">\n {{ f.label }}\n @if (f.required) {\n <span class=\"x-scrud-required\">*</span>\n }\n @switch (f.type) {\n @case ('boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"draft[f.key]\" />\n }\n @case ('select') {\n <select [(ngModel)]=\"draft[f.key]\">\n <option value=\"\">— choose —</option>\n @for (opt of (f.optionsKey ? dynamicOptions[f.optionsKey] : f.options); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n }\n @case ('textarea') {\n <textarea rows=\"3\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\"></textarea>\n }\n @case ('json') {\n <textarea rows=\"4\" class=\"x-scrud-json\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || '{}'\"></textarea>\n }\n @case ('number') {\n <input type=\"number\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n @case ('date') {\n <input type=\"datetime-local\" [(ngModel)]=\"draft[f.key]\" />\n }\n @default {\n <input type=\"text\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n }\n </label>\n }\n </div>\n </div>\n}\n","import { NgModule } from '@angular/core';\nimport { RouterModule } from '@angular/router';\nimport { SharedModule } from '@thescaffold/ngx-core';\nimport { ElementsModule, WebgetsModule } from '@thescaffold/ngx-ui';\nimport { FlashSalesComponent } from './flash-sales.component';\n\n@NgModule({\n declarations: [FlashSalesComponent],\n imports: [\n SharedModule,\n ElementsModule,\n WebgetsModule,\n RouterModule.forChild([{ path: '', component: FlashSalesComponent }]),\n ],\n})\nexport class FlashSalesModule {}\n"],"names":["i1"],"mappings":"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"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, Component, NgModule } from '@angular/core';
|
|
3
|
+
import * as i1$1 from '@angular/router';
|
|
4
|
+
import { RouterModule } from '@angular/router';
|
|
5
|
+
import { BaseDirective, ControlService, notify, SharedModule } from '@thescaffold/ngx-core';
|
|
6
|
+
import * as i2 from '@thescaffold/ngx-ui';
|
|
7
|
+
import { ElementsModule } from '@thescaffold/ngx-ui';
|
|
8
|
+
import { firstValueFrom } from 'rxjs';
|
|
9
|
+
import * as i3 from '@angular/common';
|
|
10
|
+
import * as i1 from '@angular/forms';
|
|
11
|
+
|
|
12
|
+
// The signed-in admin's own profile — personal data and password. Same
|
|
13
|
+
// self-service identity endpoints the buyer account settings use
|
|
14
|
+
// (`attributes/user`, `reset-secret/change`); nothing here needs a
|
|
15
|
+
// super-admin role.
|
|
16
|
+
class ProfileComponent extends BaseDirective {
|
|
17
|
+
constructor() {
|
|
18
|
+
super(...arguments);
|
|
19
|
+
this.controlService = inject(ControlService);
|
|
20
|
+
this.email = '';
|
|
21
|
+
this.loading = true;
|
|
22
|
+
this.saving = false;
|
|
23
|
+
this.profileError = '';
|
|
24
|
+
this.firstName = '';
|
|
25
|
+
this.lastName = '';
|
|
26
|
+
this.phoneNumber = '';
|
|
27
|
+
this.currentSecret = '';
|
|
28
|
+
this.newSecret = '';
|
|
29
|
+
this.confirmNewSecret = '';
|
|
30
|
+
this.showCurrentSecret = false;
|
|
31
|
+
this.showNewSecret = false;
|
|
32
|
+
this.showConfirmSecret = false;
|
|
33
|
+
this.changingPassword = false;
|
|
34
|
+
this.passwordError = '';
|
|
35
|
+
this.passwordDone = false;
|
|
36
|
+
this.init = () => {
|
|
37
|
+
this.email = this.controlService.getMeta()?.ref ?? '';
|
|
38
|
+
void this.load();
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
get canChangePassword() {
|
|
42
|
+
return (this.currentSecret.length >= 7 &&
|
|
43
|
+
this.newSecret.length >= 7 &&
|
|
44
|
+
this.newSecret.length <= 21 &&
|
|
45
|
+
this.newSecret === this.confirmNewSecret);
|
|
46
|
+
}
|
|
47
|
+
async load() {
|
|
48
|
+
try {
|
|
49
|
+
const res = await firstValueFrom(this.apiService.get('apps/identity/attributes'));
|
|
50
|
+
const u = res?.data?.attributes?.user ?? {};
|
|
51
|
+
this.firstName = u.first_name ?? '';
|
|
52
|
+
this.lastName = u.last_name ?? '';
|
|
53
|
+
this.phoneNumber = u.phone_number ?? '';
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
this.profileError = 'Could not load your profile.';
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
this.loading = false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async saveProfile() {
|
|
63
|
+
if (this.saving)
|
|
64
|
+
return;
|
|
65
|
+
if (!this.firstName.trim() || !this.lastName.trim()) {
|
|
66
|
+
this.profileError = 'First and last name are required.';
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
this.saving = true;
|
|
70
|
+
this.profileError = '';
|
|
71
|
+
try {
|
|
72
|
+
await firstValueFrom(this.apiService.patch('apps/identity/attributes/user', {
|
|
73
|
+
first_name: this.firstName.trim(),
|
|
74
|
+
last_name: this.lastName.trim(),
|
|
75
|
+
phone_number: this.phoneNumber.trim(),
|
|
76
|
+
}));
|
|
77
|
+
notify('Profile saved', undefined, 'success');
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
this.profileError = err?.error?.message ?? 'Could not save your profile.';
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
this.saving = false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async changePassword() {
|
|
87
|
+
if (this.changingPassword || !this.canChangePassword)
|
|
88
|
+
return;
|
|
89
|
+
this.changingPassword = true;
|
|
90
|
+
this.passwordError = '';
|
|
91
|
+
try {
|
|
92
|
+
await firstValueFrom(this.apiService.post('apps/identity/reset-secret/change', {
|
|
93
|
+
currentSecret: this.currentSecret,
|
|
94
|
+
newSecret: this.newSecret,
|
|
95
|
+
confirmNewSecret: this.confirmNewSecret,
|
|
96
|
+
}));
|
|
97
|
+
this.passwordDone = true;
|
|
98
|
+
setTimeout(() => {
|
|
99
|
+
this.controlService.logout();
|
|
100
|
+
this.router.navigate(['/start']);
|
|
101
|
+
}, 1500);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
this.passwordError = err?.error?.message ?? 'Could not change your password.';
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
this.changingPassword = false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ProfileComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
111
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ProfileComponent, isStandalone: false, selector: "x-profile", usesInheritance: true, ngImport: i0, template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">My profile</div>\n <div class=\"x-page-subtitle\">Your personal details and password.</div>\n</div>\n\n<div class=\"x-scrud-editor\" style=\"margin-bottom: 16px\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">Personal details</div>\n <div class=\"x-scrud-editor-actions\">\n <button\n type=\"button\"\n class=\"x-scrud-btn x-scrud-btn-primary\"\n [disabled]=\"loading || saving\"\n (click)=\"saveProfile()\"\n >\n {{ saving ? 'Saving\u2026' : 'Save' }}\n </button>\n </div>\n </div>\n\n @if (loading) {\n <x-element-loader></x-element-loader>\n } @else {\n <div class=\"x-scrud-grid\">\n <label class=\"x-scrud-f\">\n First name <span class=\"x-scrud-required\">*</span>\n <input type=\"text\" [(ngModel)]=\"firstName\" autocomplete=\"given-name\" />\n </label>\n <label class=\"x-scrud-f\">\n Last name <span class=\"x-scrud-required\">*</span>\n <input type=\"text\" [(ngModel)]=\"lastName\" autocomplete=\"family-name\" />\n </label>\n <label class=\"x-scrud-f\">\n Email\n <input type=\"email\" [value]=\"email\" disabled />\n </label>\n <label class=\"x-scrud-f\">\n Phone number\n <input type=\"tel\" [(ngModel)]=\"phoneNumber\" placeholder=\"+234\u2026\" autocomplete=\"tel\" />\n </label>\n </div>\n @if (profileError) {\n <div class=\"x-scrud-required\">{{ profileError }}</div>\n }\n }\n</div>\n\n<div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">Change password</div>\n <div class=\"x-scrud-editor-actions\">\n <button\n type=\"button\"\n class=\"x-scrud-btn x-scrud-btn-primary\"\n [disabled]=\"!canChangePassword || changingPassword || passwordDone\"\n (click)=\"changePassword()\"\n >\n {{ changingPassword ? 'Saving\u2026' : 'Change password' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n <label class=\"x-scrud-f\">\n Current password\n <div class=\"x-scrud-pwd\">\n <input\n [type]=\"showCurrentSecret ? 'text' : 'password'\"\n [(ngModel)]=\"currentSecret\"\n autocomplete=\"current-password\"\n />\n <button\n type=\"button\"\n class=\"x-scrud-pwd-toggle\"\n [title]=\"showCurrentSecret ? 'Hide password' : 'Show password'\"\n [attr.aria-label]=\"showCurrentSecret ? 'Hide password' : 'Show password'\"\n (click)=\"showCurrentSecret = !showCurrentSecret\"\n >\n <i class=\"fa-solid\" [ngClass]=\"showCurrentSecret ? 'fa-eye' : 'fa-eye-slash'\"></i>\n </button>\n </div>\n </label>\n <label class=\"x-scrud-f\">\n New password\n <div class=\"x-scrud-pwd\">\n <input\n [type]=\"showNewSecret ? 'text' : 'password'\"\n [(ngModel)]=\"newSecret\"\n autocomplete=\"new-password\"\n />\n <button\n type=\"button\"\n class=\"x-scrud-pwd-toggle\"\n [title]=\"showNewSecret ? 'Hide password' : 'Show password'\"\n [attr.aria-label]=\"showNewSecret ? 'Hide password' : 'Show password'\"\n (click)=\"showNewSecret = !showNewSecret\"\n >\n <i class=\"fa-solid\" [ngClass]=\"showNewSecret ? 'fa-eye' : 'fa-eye-slash'\"></i>\n </button>\n </div>\n </label>\n <label class=\"x-scrud-f\">\n Confirm new password\n <div class=\"x-scrud-pwd\">\n <input\n [type]=\"showConfirmSecret ? 'text' : 'password'\"\n [(ngModel)]=\"confirmNewSecret\"\n autocomplete=\"new-password\"\n />\n <button\n type=\"button\"\n class=\"x-scrud-pwd-toggle\"\n [title]=\"showConfirmSecret ? 'Hide password' : 'Show password'\"\n [attr.aria-label]=\"showConfirmSecret ? 'Hide password' : 'Show password'\"\n (click)=\"showConfirmSecret = !showConfirmSecret\"\n >\n <i class=\"fa-solid\" [ngClass]=\"showConfirmSecret ? 'fa-eye' : 'fa-eye-slash'\"></i>\n </button>\n </div>\n </label>\n </div>\n <div class=\"x-page-subtitle\">7\u201321 characters. You'll be signed out after changing it.</div>\n @if (passwordError) {\n <div class=\"x-scrud-required\">{{ passwordError }}</div>\n }\n @if (passwordDone) {\n <div class=\"x-page-subtitle\">Password changed. Signing you out\u2026</div>\n }\n</div>\n", styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}.x-scrud-toolbar{display:flex;justify-content:flex-end;margin-bottom:14px}.x-scrud-btn{border:1px solid var(--color-border);background:transparent;border-radius:var(--radius-md);padding:6px 14px;font-size:12.5px;font-weight:700;cursor:pointer;color:var(--color-text-muted)}.x-scrud-btn:disabled{opacity:.5;cursor:default}.x-scrud-btn-primary{border-color:var(--color-accent);color:var(--color-accent-hover)}.x-scrud-danger{color:var(--color-danger, #c0362c)}.x-scrud-editor{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:16px;display:flex;flex-direction:column;gap:14px}.x-scrud-editor-head{display:flex;align-items:center;justify-content:space-between}.x-scrud-editor-title{font-size:16px;font-weight:800;color:var(--color-text)}.x-scrud-editor-actions{display:flex;gap:8px}.x-scrud-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.x-scrud-f{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--color-text-muted);font-weight:700}.x-scrud-f-wide{grid-column:1/-1}.x-scrud-f input,.x-scrud-f select,.x-scrud-f textarea{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:6px 10px;font-size:13px;background:var(--color-surface);color:var(--color-text);font-weight:400}.x-scrud-f input[type=checkbox]{width:18px;height:18px}.x-scrud-pwd{position:relative;display:flex}.x-scrud-pwd input{flex:1;padding-right:34px!important}.x-scrud-pwd-toggle{position:absolute;right:4px;top:50%;transform:translateY(-50%);border:none;background:transparent;color:var(--color-text-muted);padding:4px 6px;cursor:pointer}.x-scrud-pwd-toggle:hover{color:var(--color-text)}.x-scrud-json{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.x-scrud-required{color:var(--color-danger, #c0362c)}\n"], dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.LoaderComponent, selector: "x-element-loader", inputs: ["data"] }] }); }
|
|
112
|
+
}
|
|
113
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ProfileComponent, decorators: [{
|
|
114
|
+
type: Component,
|
|
115
|
+
args: [{ standalone: false, selector: 'x-profile', template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">My profile</div>\n <div class=\"x-page-subtitle\">Your personal details and password.</div>\n</div>\n\n<div class=\"x-scrud-editor\" style=\"margin-bottom: 16px\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">Personal details</div>\n <div class=\"x-scrud-editor-actions\">\n <button\n type=\"button\"\n class=\"x-scrud-btn x-scrud-btn-primary\"\n [disabled]=\"loading || saving\"\n (click)=\"saveProfile()\"\n >\n {{ saving ? 'Saving\u2026' : 'Save' }}\n </button>\n </div>\n </div>\n\n @if (loading) {\n <x-element-loader></x-element-loader>\n } @else {\n <div class=\"x-scrud-grid\">\n <label class=\"x-scrud-f\">\n First name <span class=\"x-scrud-required\">*</span>\n <input type=\"text\" [(ngModel)]=\"firstName\" autocomplete=\"given-name\" />\n </label>\n <label class=\"x-scrud-f\">\n Last name <span class=\"x-scrud-required\">*</span>\n <input type=\"text\" [(ngModel)]=\"lastName\" autocomplete=\"family-name\" />\n </label>\n <label class=\"x-scrud-f\">\n Email\n <input type=\"email\" [value]=\"email\" disabled />\n </label>\n <label class=\"x-scrud-f\">\n Phone number\n <input type=\"tel\" [(ngModel)]=\"phoneNumber\" placeholder=\"+234\u2026\" autocomplete=\"tel\" />\n </label>\n </div>\n @if (profileError) {\n <div class=\"x-scrud-required\">{{ profileError }}</div>\n }\n }\n</div>\n\n<div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">Change password</div>\n <div class=\"x-scrud-editor-actions\">\n <button\n type=\"button\"\n class=\"x-scrud-btn x-scrud-btn-primary\"\n [disabled]=\"!canChangePassword || changingPassword || passwordDone\"\n (click)=\"changePassword()\"\n >\n {{ changingPassword ? 'Saving\u2026' : 'Change password' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n <label class=\"x-scrud-f\">\n Current password\n <div class=\"x-scrud-pwd\">\n <input\n [type]=\"showCurrentSecret ? 'text' : 'password'\"\n [(ngModel)]=\"currentSecret\"\n autocomplete=\"current-password\"\n />\n <button\n type=\"button\"\n class=\"x-scrud-pwd-toggle\"\n [title]=\"showCurrentSecret ? 'Hide password' : 'Show password'\"\n [attr.aria-label]=\"showCurrentSecret ? 'Hide password' : 'Show password'\"\n (click)=\"showCurrentSecret = !showCurrentSecret\"\n >\n <i class=\"fa-solid\" [ngClass]=\"showCurrentSecret ? 'fa-eye' : 'fa-eye-slash'\"></i>\n </button>\n </div>\n </label>\n <label class=\"x-scrud-f\">\n New password\n <div class=\"x-scrud-pwd\">\n <input\n [type]=\"showNewSecret ? 'text' : 'password'\"\n [(ngModel)]=\"newSecret\"\n autocomplete=\"new-password\"\n />\n <button\n type=\"button\"\n class=\"x-scrud-pwd-toggle\"\n [title]=\"showNewSecret ? 'Hide password' : 'Show password'\"\n [attr.aria-label]=\"showNewSecret ? 'Hide password' : 'Show password'\"\n (click)=\"showNewSecret = !showNewSecret\"\n >\n <i class=\"fa-solid\" [ngClass]=\"showNewSecret ? 'fa-eye' : 'fa-eye-slash'\"></i>\n </button>\n </div>\n </label>\n <label class=\"x-scrud-f\">\n Confirm new password\n <div class=\"x-scrud-pwd\">\n <input\n [type]=\"showConfirmSecret ? 'text' : 'password'\"\n [(ngModel)]=\"confirmNewSecret\"\n autocomplete=\"new-password\"\n />\n <button\n type=\"button\"\n class=\"x-scrud-pwd-toggle\"\n [title]=\"showConfirmSecret ? 'Hide password' : 'Show password'\"\n [attr.aria-label]=\"showConfirmSecret ? 'Hide password' : 'Show password'\"\n (click)=\"showConfirmSecret = !showConfirmSecret\"\n >\n <i class=\"fa-solid\" [ngClass]=\"showConfirmSecret ? 'fa-eye' : 'fa-eye-slash'\"></i>\n </button>\n </div>\n </label>\n </div>\n <div class=\"x-page-subtitle\">7\u201321 characters. You'll be signed out after changing it.</div>\n @if (passwordError) {\n <div class=\"x-scrud-required\">{{ passwordError }}</div>\n }\n @if (passwordDone) {\n <div class=\"x-page-subtitle\">Password changed. Signing you out\u2026</div>\n }\n</div>\n", styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}.x-scrud-toolbar{display:flex;justify-content:flex-end;margin-bottom:14px}.x-scrud-btn{border:1px solid var(--color-border);background:transparent;border-radius:var(--radius-md);padding:6px 14px;font-size:12.5px;font-weight:700;cursor:pointer;color:var(--color-text-muted)}.x-scrud-btn:disabled{opacity:.5;cursor:default}.x-scrud-btn-primary{border-color:var(--color-accent);color:var(--color-accent-hover)}.x-scrud-danger{color:var(--color-danger, #c0362c)}.x-scrud-editor{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:16px;display:flex;flex-direction:column;gap:14px}.x-scrud-editor-head{display:flex;align-items:center;justify-content:space-between}.x-scrud-editor-title{font-size:16px;font-weight:800;color:var(--color-text)}.x-scrud-editor-actions{display:flex;gap:8px}.x-scrud-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.x-scrud-f{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--color-text-muted);font-weight:700}.x-scrud-f-wide{grid-column:1/-1}.x-scrud-f input,.x-scrud-f select,.x-scrud-f textarea{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:6px 10px;font-size:13px;background:var(--color-surface);color:var(--color-text);font-weight:400}.x-scrud-f input[type=checkbox]{width:18px;height:18px}.x-scrud-pwd{position:relative;display:flex}.x-scrud-pwd input{flex:1;padding-right:34px!important}.x-scrud-pwd-toggle{position:absolute;right:4px;top:50%;transform:translateY(-50%);border:none;background:transparent;color:var(--color-text-muted);padding:4px 6px;cursor:pointer}.x-scrud-pwd-toggle:hover{color:var(--color-text)}.x-scrud-json{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.x-scrud-required{color:var(--color-danger, #c0362c)}\n"] }]
|
|
116
|
+
}] });
|
|
117
|
+
|
|
118
|
+
class ProfileModule {
|
|
119
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ProfileModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
120
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: ProfileModule, declarations: [ProfileComponent], imports: [SharedModule,
|
|
121
|
+
ElementsModule, i1$1.RouterModule] }); }
|
|
122
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ProfileModule, imports: [SharedModule,
|
|
123
|
+
ElementsModule,
|
|
124
|
+
RouterModule.forChild([{ path: '', component: ProfileComponent }])] }); }
|
|
125
|
+
}
|
|
126
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ProfileModule, decorators: [{
|
|
127
|
+
type: NgModule,
|
|
128
|
+
args: [{
|
|
129
|
+
declarations: [ProfileComponent],
|
|
130
|
+
imports: [
|
|
131
|
+
SharedModule,
|
|
132
|
+
ElementsModule,
|
|
133
|
+
RouterModule.forChild([{ path: '', component: ProfileComponent }]),
|
|
134
|
+
],
|
|
135
|
+
}]
|
|
136
|
+
}] });
|
|
137
|
+
|
|
138
|
+
export { ProfileModule };
|
|
139
|
+
//# sourceMappingURL=isaiahiroko-tilmart-ngx-apps-admin-profile.module-D-r3HcHq.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isaiahiroko-tilmart-ngx-apps-admin-profile.module-D-r3HcHq.mjs","sources":["../../../projects/admin/src/lib/pages/profile/profile.component.ts","../../../projects/admin/src/lib/pages/profile/profile.component.html","../../../projects/admin/src/lib/pages/profile/profile.module.ts"],"sourcesContent":["import { Component, inject } from '@angular/core';\nimport { BaseDirective, ControlService, notify } from '@thescaffold/ngx-core';\nimport { firstValueFrom } from 'rxjs';\n\n// The signed-in admin's own profile — personal data and password. Same\n// self-service identity endpoints the buyer account settings use\n// (`attributes/user`, `reset-secret/change`); nothing here needs a\n// super-admin role.\n@Component({\n standalone: false,\n selector: 'x-profile',\n templateUrl: './profile.component.html',\n styleUrl: '../_shared/simple-crud.component.scss',\n})\nexport class ProfileComponent extends BaseDirective {\n private readonly controlService = inject(ControlService);\n\n email = '';\n\n loading = true;\n saving = false;\n profileError = '';\n firstName = '';\n lastName = '';\n phoneNumber = '';\n\n currentSecret = '';\n newSecret = '';\n confirmNewSecret = '';\n showCurrentSecret = false;\n showNewSecret = false;\n showConfirmSecret = false;\n changingPassword = false;\n passwordError = '';\n passwordDone = false;\n\n get canChangePassword(): boolean {\n return (\n this.currentSecret.length >= 7 &&\n this.newSecret.length >= 7 &&\n this.newSecret.length <= 21 &&\n this.newSecret === this.confirmNewSecret\n );\n }\n\n override init = () => {\n this.email = (this.controlService.getMeta() as { ref?: string } | null)?.ref ?? '';\n void this.load();\n };\n\n private async load(): Promise<void> {\n try {\n const res: any = await firstValueFrom(this.apiService.get('apps/identity/attributes'));\n const u = res?.data?.attributes?.user ?? {};\n this.firstName = u.first_name ?? '';\n this.lastName = u.last_name ?? '';\n this.phoneNumber = u.phone_number ?? '';\n } catch {\n this.profileError = 'Could not load your profile.';\n } finally {\n this.loading = false;\n }\n }\n\n async saveProfile(): Promise<void> {\n if (this.saving) return;\n if (!this.firstName.trim() || !this.lastName.trim()) {\n this.profileError = 'First and last name are required.';\n return;\n }\n this.saving = true;\n this.profileError = '';\n try {\n await firstValueFrom(\n this.apiService.patch('apps/identity/attributes/user', {\n first_name: this.firstName.trim(),\n last_name: this.lastName.trim(),\n phone_number: this.phoneNumber.trim(),\n }),\n );\n notify('Profile saved', undefined, 'success');\n } catch (err: any) {\n this.profileError = err?.error?.message ?? 'Could not save your profile.';\n } finally {\n this.saving = false;\n }\n }\n\n async changePassword(): Promise<void> {\n if (this.changingPassword || !this.canChangePassword) return;\n this.changingPassword = true;\n this.passwordError = '';\n try {\n await firstValueFrom(\n this.apiService.post('apps/identity/reset-secret/change', {\n currentSecret: this.currentSecret,\n newSecret: this.newSecret,\n confirmNewSecret: this.confirmNewSecret,\n }),\n );\n this.passwordDone = true;\n setTimeout(() => {\n this.controlService.logout();\n this.router.navigate(['/start']);\n }, 1500);\n } catch (err: any) {\n this.passwordError = err?.error?.message ?? 'Could not change your password.';\n } finally {\n this.changingPassword = false;\n }\n }\n}\n","<div class=\"x-page-head\">\n <div class=\"x-page-title\">My profile</div>\n <div class=\"x-page-subtitle\">Your personal details and password.</div>\n</div>\n\n<div class=\"x-scrud-editor\" style=\"margin-bottom: 16px\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">Personal details</div>\n <div class=\"x-scrud-editor-actions\">\n <button\n type=\"button\"\n class=\"x-scrud-btn x-scrud-btn-primary\"\n [disabled]=\"loading || saving\"\n (click)=\"saveProfile()\"\n >\n {{ saving ? 'Saving…' : 'Save' }}\n </button>\n </div>\n </div>\n\n @if (loading) {\n <x-element-loader></x-element-loader>\n } @else {\n <div class=\"x-scrud-grid\">\n <label class=\"x-scrud-f\">\n First name <span class=\"x-scrud-required\">*</span>\n <input type=\"text\" [(ngModel)]=\"firstName\" autocomplete=\"given-name\" />\n </label>\n <label class=\"x-scrud-f\">\n Last name <span class=\"x-scrud-required\">*</span>\n <input type=\"text\" [(ngModel)]=\"lastName\" autocomplete=\"family-name\" />\n </label>\n <label class=\"x-scrud-f\">\n Email\n <input type=\"email\" [value]=\"email\" disabled />\n </label>\n <label class=\"x-scrud-f\">\n Phone number\n <input type=\"tel\" [(ngModel)]=\"phoneNumber\" placeholder=\"+234…\" autocomplete=\"tel\" />\n </label>\n </div>\n @if (profileError) {\n <div class=\"x-scrud-required\">{{ profileError }}</div>\n }\n }\n</div>\n\n<div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">Change password</div>\n <div class=\"x-scrud-editor-actions\">\n <button\n type=\"button\"\n class=\"x-scrud-btn x-scrud-btn-primary\"\n [disabled]=\"!canChangePassword || changingPassword || passwordDone\"\n (click)=\"changePassword()\"\n >\n {{ changingPassword ? 'Saving…' : 'Change password' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n <label class=\"x-scrud-f\">\n Current password\n <div class=\"x-scrud-pwd\">\n <input\n [type]=\"showCurrentSecret ? 'text' : 'password'\"\n [(ngModel)]=\"currentSecret\"\n autocomplete=\"current-password\"\n />\n <button\n type=\"button\"\n class=\"x-scrud-pwd-toggle\"\n [title]=\"showCurrentSecret ? 'Hide password' : 'Show password'\"\n [attr.aria-label]=\"showCurrentSecret ? 'Hide password' : 'Show password'\"\n (click)=\"showCurrentSecret = !showCurrentSecret\"\n >\n <i class=\"fa-solid\" [ngClass]=\"showCurrentSecret ? 'fa-eye' : 'fa-eye-slash'\"></i>\n </button>\n </div>\n </label>\n <label class=\"x-scrud-f\">\n New password\n <div class=\"x-scrud-pwd\">\n <input\n [type]=\"showNewSecret ? 'text' : 'password'\"\n [(ngModel)]=\"newSecret\"\n autocomplete=\"new-password\"\n />\n <button\n type=\"button\"\n class=\"x-scrud-pwd-toggle\"\n [title]=\"showNewSecret ? 'Hide password' : 'Show password'\"\n [attr.aria-label]=\"showNewSecret ? 'Hide password' : 'Show password'\"\n (click)=\"showNewSecret = !showNewSecret\"\n >\n <i class=\"fa-solid\" [ngClass]=\"showNewSecret ? 'fa-eye' : 'fa-eye-slash'\"></i>\n </button>\n </div>\n </label>\n <label class=\"x-scrud-f\">\n Confirm new password\n <div class=\"x-scrud-pwd\">\n <input\n [type]=\"showConfirmSecret ? 'text' : 'password'\"\n [(ngModel)]=\"confirmNewSecret\"\n autocomplete=\"new-password\"\n />\n <button\n type=\"button\"\n class=\"x-scrud-pwd-toggle\"\n [title]=\"showConfirmSecret ? 'Hide password' : 'Show password'\"\n [attr.aria-label]=\"showConfirmSecret ? 'Hide password' : 'Show password'\"\n (click)=\"showConfirmSecret = !showConfirmSecret\"\n >\n <i class=\"fa-solid\" [ngClass]=\"showConfirmSecret ? 'fa-eye' : 'fa-eye-slash'\"></i>\n </button>\n </div>\n </label>\n </div>\n <div class=\"x-page-subtitle\">7–21 characters. You'll be signed out after changing it.</div>\n @if (passwordError) {\n <div class=\"x-scrud-required\">{{ passwordError }}</div>\n }\n @if (passwordDone) {\n <div class=\"x-page-subtitle\">Password changed. Signing you out…</div>\n }\n</div>\n","import { NgModule } from '@angular/core';\nimport { RouterModule } from '@angular/router';\nimport { SharedModule } from '@thescaffold/ngx-core';\nimport { ElementsModule } from '@thescaffold/ngx-ui';\nimport { ProfileComponent } from './profile.component';\n\n@NgModule({\n declarations: [ProfileComponent],\n imports: [\n SharedModule,\n ElementsModule,\n RouterModule.forChild([{ path: '', component: ProfileComponent }]),\n ],\n})\nexport class ProfileModule {}\n"],"names":["i1","i2","i3"],"mappings":"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"}
|
|
@@ -60,11 +60,11 @@ class PromotionsComponent extends SimpleCrudDirective {
|
|
|
60
60
|
];
|
|
61
61
|
}
|
|
62
62
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: PromotionsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
63
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: PromotionsComponent, isStandalone: false, selector: "x-promotions", usesInheritance: true, ngImport: i0, template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">{{ pageTitle }}</div>\n <div class=\"x-page-subtitle\">{{ pageSubtitle }}</div>\n</div>\n\n@if (!editing) {\n <div class=\"x-scrud-toolbar\">\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" (click)=\"startCreate()\">+ New {{ singularLabel }}</button>\n </div>\n\n @if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n} @else if (draft) {\n <div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">{{ draft['id'] ? 'Edit' : 'New' }} {{ singularLabel }}</div>\n <div class=\"x-scrud-editor-actions\">\n @if (draft['id'] && !hideDelete) {\n <button type=\"button\" class=\"x-scrud-btn x-scrud-danger\" (click)=\"remove(draft); cancelEdit()\">Delete</button>\n }\n <button type=\"button\" class=\"x-scrud-btn\" (click)=\"cancelEdit()\">Close</button>\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" [disabled]=\"saving\" (click)=\"save()\">\n {{ saving ? 'Saving\u2026' : 'Save' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n @for (f of fields; track f.key) {\n <label class=\"x-scrud-f\" [class.x-scrud-f-wide]=\"f.type === 'textarea' || f.type === 'json'\">\n {{ f.label }}\n @if (f.required) {\n <span class=\"x-scrud-required\">*</span>\n }\n @switch (f.type) {\n @case ('boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"draft[f.key]\" />\n }\n @case ('select') {\n <select [(ngModel)]=\"draft[f.key]\">\n <option value=\"\">\u2014 choose \u2014</option>\n @for (opt of (f.optionsKey ? dynamicOptions[f.optionsKey] : f.options); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n }\n @case ('textarea') {\n <textarea rows=\"3\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\"></textarea>\n }\n @case ('json') {\n <textarea rows=\"4\" class=\"x-scrud-json\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || '{}'\"></textarea>\n }\n @case ('number') {\n <input type=\"number\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n @case ('date') {\n <input type=\"datetime-local\" [(ngModel)]=\"draft[f.key]\" />\n }\n @default {\n <input type=\"text\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n }\n </label>\n }\n </div>\n </div>\n}\n", styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}.x-scrud-toolbar{display:flex;justify-content:flex-end;margin-bottom:14px}.x-scrud-btn{border:1px solid var(--color-border);background:transparent;border-radius:var(--radius-md);padding:6px 14px;font-size:12.5px;font-weight:700;cursor:pointer;color:var(--color-text-muted)}.x-scrud-btn:disabled{opacity:.5;cursor:default}.x-scrud-btn-primary{border-color:var(--color-accent);color:var(--color-accent-hover)}.x-scrud-danger{color:var(--color-danger, #c0362c)}.x-scrud-editor{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:16px;display:flex;flex-direction:column;gap:14px}.x-scrud-editor-head{display:flex;align-items:center;justify-content:space-between}.x-scrud-editor-title{font-size:16px;font-weight:800;color:var(--color-text)}.x-scrud-editor-actions{display:flex;gap:8px}.x-scrud-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.x-scrud-f{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--color-text-muted);font-weight:700}.x-scrud-f-wide{grid-column:1/-1}.x-scrud-f input,.x-scrud-f select,.x-scrud-f textarea{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:6px 10px;font-size:13px;background:var(--color-surface);color:var(--color-text);font-weight:400}.x-scrud-f input[type=checkbox]{width:18px;height:18px}.x-scrud-json{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.x-scrud-required{color:var(--color-danger, #c0362c)}\n"], dependencies: [{ kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.LoaderComponent, selector: "x-element-loader", inputs: ["data"] }, { kind: "component", type: i2.CollectionComponent, selector: "x-webget-collection", inputs: ["data"], outputs: ["search", "filter", "refresh", "select", "page", "show"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] }); }
|
|
63
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: PromotionsComponent, isStandalone: false, selector: "x-promotions", usesInheritance: true, ngImport: i0, template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">{{ pageTitle }}</div>\n <div class=\"x-page-subtitle\">{{ pageSubtitle }}</div>\n</div>\n\n@if (!editing) {\n <div class=\"x-scrud-toolbar\">\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" (click)=\"startCreate()\">+ New {{ singularLabel }}</button>\n </div>\n\n @if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n} @else if (draft) {\n <div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">{{ draft['id'] ? 'Edit' : 'New' }} {{ singularLabel }}</div>\n <div class=\"x-scrud-editor-actions\">\n @if (draft['id'] && !hideDelete) {\n <button type=\"button\" class=\"x-scrud-btn x-scrud-danger\" (click)=\"remove(draft); cancelEdit()\">Delete</button>\n }\n <button type=\"button\" class=\"x-scrud-btn\" (click)=\"cancelEdit()\">Close</button>\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" [disabled]=\"saving\" (click)=\"save()\">\n {{ saving ? 'Saving\u2026' : 'Save' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n @for (f of fields; track f.key) {\n <label class=\"x-scrud-f\" [class.x-scrud-f-wide]=\"f.type === 'textarea' || f.type === 'json'\">\n {{ f.label }}\n @if (f.required) {\n <span class=\"x-scrud-required\">*</span>\n }\n @switch (f.type) {\n @case ('boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"draft[f.key]\" />\n }\n @case ('select') {\n <select [(ngModel)]=\"draft[f.key]\">\n <option value=\"\">\u2014 choose \u2014</option>\n @for (opt of (f.optionsKey ? dynamicOptions[f.optionsKey] : f.options); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n }\n @case ('textarea') {\n <textarea rows=\"3\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\"></textarea>\n }\n @case ('json') {\n <textarea rows=\"4\" class=\"x-scrud-json\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || '{}'\"></textarea>\n }\n @case ('number') {\n <input type=\"number\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n @case ('date') {\n <input type=\"datetime-local\" [(ngModel)]=\"draft[f.key]\" />\n }\n @default {\n <input type=\"text\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n }\n </label>\n }\n </div>\n </div>\n}\n", styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}.x-scrud-toolbar{display:flex;justify-content:flex-end;margin-bottom:14px}.x-scrud-btn{border:1px solid var(--color-border);background:transparent;border-radius:var(--radius-md);padding:6px 14px;font-size:12.5px;font-weight:700;cursor:pointer;color:var(--color-text-muted)}.x-scrud-btn:disabled{opacity:.5;cursor:default}.x-scrud-btn-primary{border-color:var(--color-accent);color:var(--color-accent-hover)}.x-scrud-danger{color:var(--color-danger, #c0362c)}.x-scrud-editor{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:16px;display:flex;flex-direction:column;gap:14px}.x-scrud-editor-head{display:flex;align-items:center;justify-content:space-between}.x-scrud-editor-title{font-size:16px;font-weight:800;color:var(--color-text)}.x-scrud-editor-actions{display:flex;gap:8px}.x-scrud-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.x-scrud-f{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--color-text-muted);font-weight:700}.x-scrud-f-wide{grid-column:1/-1}.x-scrud-f input,.x-scrud-f select,.x-scrud-f textarea{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:6px 10px;font-size:13px;background:var(--color-surface);color:var(--color-text);font-weight:400}.x-scrud-f input[type=checkbox]{width:18px;height:18px}.x-scrud-pwd{position:relative;display:flex}.x-scrud-pwd input{flex:1;padding-right:34px!important}.x-scrud-pwd-toggle{position:absolute;right:4px;top:50%;transform:translateY(-50%);border:none;background:transparent;color:var(--color-text-muted);padding:4px 6px;cursor:pointer}.x-scrud-pwd-toggle:hover{color:var(--color-text)}.x-scrud-json{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.x-scrud-required{color:var(--color-danger, #c0362c)}\n"], dependencies: [{ kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.LoaderComponent, selector: "x-element-loader", inputs: ["data"] }, { kind: "component", type: i2.CollectionComponent, selector: "x-webget-collection", inputs: ["data"], outputs: ["search", "filter", "refresh", "select", "page", "show"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] }); }
|
|
64
64
|
}
|
|
65
65
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: PromotionsComponent, decorators: [{
|
|
66
66
|
type: Component,
|
|
67
|
-
args: [{ standalone: false, selector: 'x-promotions', template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">{{ pageTitle }}</div>\n <div class=\"x-page-subtitle\">{{ pageSubtitle }}</div>\n</div>\n\n@if (!editing) {\n <div class=\"x-scrud-toolbar\">\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" (click)=\"startCreate()\">+ New {{ singularLabel }}</button>\n </div>\n\n @if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n} @else if (draft) {\n <div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">{{ draft['id'] ? 'Edit' : 'New' }} {{ singularLabel }}</div>\n <div class=\"x-scrud-editor-actions\">\n @if (draft['id'] && !hideDelete) {\n <button type=\"button\" class=\"x-scrud-btn x-scrud-danger\" (click)=\"remove(draft); cancelEdit()\">Delete</button>\n }\n <button type=\"button\" class=\"x-scrud-btn\" (click)=\"cancelEdit()\">Close</button>\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" [disabled]=\"saving\" (click)=\"save()\">\n {{ saving ? 'Saving\u2026' : 'Save' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n @for (f of fields; track f.key) {\n <label class=\"x-scrud-f\" [class.x-scrud-f-wide]=\"f.type === 'textarea' || f.type === 'json'\">\n {{ f.label }}\n @if (f.required) {\n <span class=\"x-scrud-required\">*</span>\n }\n @switch (f.type) {\n @case ('boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"draft[f.key]\" />\n }\n @case ('select') {\n <select [(ngModel)]=\"draft[f.key]\">\n <option value=\"\">\u2014 choose \u2014</option>\n @for (opt of (f.optionsKey ? dynamicOptions[f.optionsKey] : f.options); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n }\n @case ('textarea') {\n <textarea rows=\"3\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\"></textarea>\n }\n @case ('json') {\n <textarea rows=\"4\" class=\"x-scrud-json\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || '{}'\"></textarea>\n }\n @case ('number') {\n <input type=\"number\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n @case ('date') {\n <input type=\"datetime-local\" [(ngModel)]=\"draft[f.key]\" />\n }\n @default {\n <input type=\"text\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n }\n </label>\n }\n </div>\n </div>\n}\n", styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}.x-scrud-toolbar{display:flex;justify-content:flex-end;margin-bottom:14px}.x-scrud-btn{border:1px solid var(--color-border);background:transparent;border-radius:var(--radius-md);padding:6px 14px;font-size:12.5px;font-weight:700;cursor:pointer;color:var(--color-text-muted)}.x-scrud-btn:disabled{opacity:.5;cursor:default}.x-scrud-btn-primary{border-color:var(--color-accent);color:var(--color-accent-hover)}.x-scrud-danger{color:var(--color-danger, #c0362c)}.x-scrud-editor{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:16px;display:flex;flex-direction:column;gap:14px}.x-scrud-editor-head{display:flex;align-items:center;justify-content:space-between}.x-scrud-editor-title{font-size:16px;font-weight:800;color:var(--color-text)}.x-scrud-editor-actions{display:flex;gap:8px}.x-scrud-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.x-scrud-f{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--color-text-muted);font-weight:700}.x-scrud-f-wide{grid-column:1/-1}.x-scrud-f input,.x-scrud-f select,.x-scrud-f textarea{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:6px 10px;font-size:13px;background:var(--color-surface);color:var(--color-text);font-weight:400}.x-scrud-f input[type=checkbox]{width:18px;height:18px}.x-scrud-json{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.x-scrud-required{color:var(--color-danger, #c0362c)}\n"] }]
|
|
67
|
+
args: [{ standalone: false, selector: 'x-promotions', template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">{{ pageTitle }}</div>\n <div class=\"x-page-subtitle\">{{ pageSubtitle }}</div>\n</div>\n\n@if (!editing) {\n <div class=\"x-scrud-toolbar\">\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" (click)=\"startCreate()\">+ New {{ singularLabel }}</button>\n </div>\n\n @if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n} @else if (draft) {\n <div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">{{ draft['id'] ? 'Edit' : 'New' }} {{ singularLabel }}</div>\n <div class=\"x-scrud-editor-actions\">\n @if (draft['id'] && !hideDelete) {\n <button type=\"button\" class=\"x-scrud-btn x-scrud-danger\" (click)=\"remove(draft); cancelEdit()\">Delete</button>\n }\n <button type=\"button\" class=\"x-scrud-btn\" (click)=\"cancelEdit()\">Close</button>\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" [disabled]=\"saving\" (click)=\"save()\">\n {{ saving ? 'Saving\u2026' : 'Save' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n @for (f of fields; track f.key) {\n <label class=\"x-scrud-f\" [class.x-scrud-f-wide]=\"f.type === 'textarea' || f.type === 'json'\">\n {{ f.label }}\n @if (f.required) {\n <span class=\"x-scrud-required\">*</span>\n }\n @switch (f.type) {\n @case ('boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"draft[f.key]\" />\n }\n @case ('select') {\n <select [(ngModel)]=\"draft[f.key]\">\n <option value=\"\">\u2014 choose \u2014</option>\n @for (opt of (f.optionsKey ? dynamicOptions[f.optionsKey] : f.options); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n }\n @case ('textarea') {\n <textarea rows=\"3\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\"></textarea>\n }\n @case ('json') {\n <textarea rows=\"4\" class=\"x-scrud-json\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || '{}'\"></textarea>\n }\n @case ('number') {\n <input type=\"number\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n @case ('date') {\n <input type=\"datetime-local\" [(ngModel)]=\"draft[f.key]\" />\n }\n @default {\n <input type=\"text\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n }\n </label>\n }\n </div>\n </div>\n}\n", styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}.x-scrud-toolbar{display:flex;justify-content:flex-end;margin-bottom:14px}.x-scrud-btn{border:1px solid var(--color-border);background:transparent;border-radius:var(--radius-md);padding:6px 14px;font-size:12.5px;font-weight:700;cursor:pointer;color:var(--color-text-muted)}.x-scrud-btn:disabled{opacity:.5;cursor:default}.x-scrud-btn-primary{border-color:var(--color-accent);color:var(--color-accent-hover)}.x-scrud-danger{color:var(--color-danger, #c0362c)}.x-scrud-editor{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:16px;display:flex;flex-direction:column;gap:14px}.x-scrud-editor-head{display:flex;align-items:center;justify-content:space-between}.x-scrud-editor-title{font-size:16px;font-weight:800;color:var(--color-text)}.x-scrud-editor-actions{display:flex;gap:8px}.x-scrud-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.x-scrud-f{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--color-text-muted);font-weight:700}.x-scrud-f-wide{grid-column:1/-1}.x-scrud-f input,.x-scrud-f select,.x-scrud-f textarea{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:6px 10px;font-size:13px;background:var(--color-surface);color:var(--color-text);font-weight:400}.x-scrud-f input[type=checkbox]{width:18px;height:18px}.x-scrud-pwd{position:relative;display:flex}.x-scrud-pwd input{flex:1;padding-right:34px!important}.x-scrud-pwd-toggle{position:absolute;right:4px;top:50%;transform:translateY(-50%);border:none;background:transparent;color:var(--color-text-muted);padding:4px 6px;cursor:pointer}.x-scrud-pwd-toggle:hover{color:var(--color-text)}.x-scrud-json{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.x-scrud-required{color:var(--color-danger, #c0362c)}\n"] }]
|
|
68
68
|
}] });
|
|
69
69
|
|
|
70
70
|
class PromotionsModule {
|
|
@@ -91,4 +91,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
91
91
|
}] });
|
|
92
92
|
|
|
93
93
|
export { PromotionsModule };
|
|
94
|
-
//# sourceMappingURL=isaiahiroko-tilmart-ngx-apps-admin-promotions.module-
|
|
94
|
+
//# sourceMappingURL=isaiahiroko-tilmart-ngx-apps-admin-promotions.module-BO4zRytg.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"isaiahiroko-tilmart-ngx-apps-admin-promotions.module-DG03OY1q.mjs","sources":["../../../projects/admin/src/lib/pages/promotions/promotions.component.ts","../../../projects/admin/src/lib/pages/_shared/simple-crud.component.html","../../../projects/admin/src/lib/pages/promotions/promotions.module.ts"],"sourcesContent":["import { Component } from '@angular/core';\nimport { CrudFieldSpec, SimpleCrudDirective } from '../_shared/simple-crud.base';\n\n// R1 production-readiness pass — PROMO-02. Was list-only; ops had no way\n// to configure a discount rule. `conditions`/`actions` stay raw JSON —\n// a full visual rule builder is real, separate scope beyond this pass.\n@Component({\n standalone: false,\n selector: 'x-promotions',\n templateUrl: '../_shared/simple-crud.component.html',\n styleUrl: '../_shared/simple-crud.component.scss',\n})\nexport class PromotionsComponent extends SimpleCrudDirective {\n protected pageTitle = 'Promotions';\n protected pageSubtitle = 'Automatic and coupon-gated discount rules evaluated at checkout.';\n protected singularLabel = 'promotion';\n protected pluralName = 'promotions';\n protected dataSource = this.apiService.on('apps/commerce/promotion');\n\n protected columns = [\n { key: 'name', value: 'Name' },\n { key: 'status', value: 'Status', type: 'class', class: 'badge text-bg-light border' },\n { key: 'priority', value: 'Priority' },\n { key: 'usageCount', value: 'Used' },\n ];\n\n protected fields: CrudFieldSpec[] = [\n { key: 'name', label: 'Name', type: 'text', required: true },\n { key: 'description', label: 'Description', type: 'textarea' },\n {\n key: 'status',\n label: 'Status',\n type: 'select',\n options: [\n { value: 'draft', label: 'Draft' },\n { value: 'active', label: 'Active' },\n { value: 'paused', label: 'Paused' },\n { value: 'expired', label: 'Expired' },\n ],\n },\n { key: 'priority', label: 'Priority (lower runs first)', type: 'number' },\n { key: 'stackable', label: 'Stackable with other promotions', type: 'boolean' },\n { key: 'requiresCoupon', label: 'Requires a coupon code', type: 'boolean' },\n { key: 'startsAt', label: 'Starts at', type: 'date' },\n { key: 'endsAt', label: 'Ends at', type: 'date' },\n {\n key: 'conditions',\n label: 'Conditions (JSON)',\n type: 'json',\n placeholder: '{\"minSubtotal\": 50000, \"categoryIds\": []}',\n },\n {\n key: 'actions',\n label: 'Actions (JSON array)',\n type: 'json',\n placeholder: '[{\"type\": \"percent_off\", \"value\": 10}]',\n },\n ];\n}\n","<div class=\"x-page-head\">\n <div class=\"x-page-title\">{{ pageTitle }}</div>\n <div class=\"x-page-subtitle\">{{ pageSubtitle }}</div>\n</div>\n\n@if (!editing) {\n <div class=\"x-scrud-toolbar\">\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" (click)=\"startCreate()\">+ New {{ singularLabel }}</button>\n </div>\n\n @if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n} @else if (draft) {\n <div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">{{ draft['id'] ? 'Edit' : 'New' }} {{ singularLabel }}</div>\n <div class=\"x-scrud-editor-actions\">\n @if (draft['id'] && !hideDelete) {\n <button type=\"button\" class=\"x-scrud-btn x-scrud-danger\" (click)=\"remove(draft); cancelEdit()\">Delete</button>\n }\n <button type=\"button\" class=\"x-scrud-btn\" (click)=\"cancelEdit()\">Close</button>\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" [disabled]=\"saving\" (click)=\"save()\">\n {{ saving ? 'Saving…' : 'Save' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n @for (f of fields; track f.key) {\n <label class=\"x-scrud-f\" [class.x-scrud-f-wide]=\"f.type === 'textarea' || f.type === 'json'\">\n {{ f.label }}\n @if (f.required) {\n <span class=\"x-scrud-required\">*</span>\n }\n @switch (f.type) {\n @case ('boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"draft[f.key]\" />\n }\n @case ('select') {\n <select [(ngModel)]=\"draft[f.key]\">\n <option value=\"\">— choose —</option>\n @for (opt of (f.optionsKey ? dynamicOptions[f.optionsKey] : f.options); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n }\n @case ('textarea') {\n <textarea rows=\"3\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\"></textarea>\n }\n @case ('json') {\n <textarea rows=\"4\" class=\"x-scrud-json\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || '{}'\"></textarea>\n }\n @case ('number') {\n <input type=\"number\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n @case ('date') {\n <input type=\"datetime-local\" [(ngModel)]=\"draft[f.key]\" />\n }\n @default {\n <input type=\"text\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n }\n </label>\n }\n </div>\n </div>\n}\n","import { NgModule } from '@angular/core';\nimport { RouterModule } from '@angular/router';\nimport { SharedModule } from '@thescaffold/ngx-core';\nimport { ElementsModule, WebgetsModule } from '@thescaffold/ngx-ui';\nimport { PromotionsComponent } from './promotions.component';\n\n@NgModule({\n declarations: [PromotionsComponent],\n imports: [\n SharedModule,\n ElementsModule,\n WebgetsModule,\n RouterModule.forChild([{ path: '', component: PromotionsComponent }]),\n ],\n})\nexport class PromotionsModule {}\n"],"names":["i1"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"isaiahiroko-tilmart-ngx-apps-admin-promotions.module-BO4zRytg.mjs","sources":["../../../projects/admin/src/lib/pages/promotions/promotions.component.ts","../../../projects/admin/src/lib/pages/_shared/simple-crud.component.html","../../../projects/admin/src/lib/pages/promotions/promotions.module.ts"],"sourcesContent":["import { Component } from '@angular/core';\nimport { CrudFieldSpec, SimpleCrudDirective } from '../_shared/simple-crud.base';\n\n// R1 production-readiness pass — PROMO-02. Was list-only; ops had no way\n// to configure a discount rule. `conditions`/`actions` stay raw JSON —\n// a full visual rule builder is real, separate scope beyond this pass.\n@Component({\n standalone: false,\n selector: 'x-promotions',\n templateUrl: '../_shared/simple-crud.component.html',\n styleUrl: '../_shared/simple-crud.component.scss',\n})\nexport class PromotionsComponent extends SimpleCrudDirective {\n protected pageTitle = 'Promotions';\n protected pageSubtitle = 'Automatic and coupon-gated discount rules evaluated at checkout.';\n protected singularLabel = 'promotion';\n protected pluralName = 'promotions';\n protected dataSource = this.apiService.on('apps/commerce/promotion');\n\n protected columns = [\n { key: 'name', value: 'Name' },\n { key: 'status', value: 'Status', type: 'class', class: 'badge text-bg-light border' },\n { key: 'priority', value: 'Priority' },\n { key: 'usageCount', value: 'Used' },\n ];\n\n protected fields: CrudFieldSpec[] = [\n { key: 'name', label: 'Name', type: 'text', required: true },\n { key: 'description', label: 'Description', type: 'textarea' },\n {\n key: 'status',\n label: 'Status',\n type: 'select',\n options: [\n { value: 'draft', label: 'Draft' },\n { value: 'active', label: 'Active' },\n { value: 'paused', label: 'Paused' },\n { value: 'expired', label: 'Expired' },\n ],\n },\n { key: 'priority', label: 'Priority (lower runs first)', type: 'number' },\n { key: 'stackable', label: 'Stackable with other promotions', type: 'boolean' },\n { key: 'requiresCoupon', label: 'Requires a coupon code', type: 'boolean' },\n { key: 'startsAt', label: 'Starts at', type: 'date' },\n { key: 'endsAt', label: 'Ends at', type: 'date' },\n {\n key: 'conditions',\n label: 'Conditions (JSON)',\n type: 'json',\n placeholder: '{\"minSubtotal\": 50000, \"categoryIds\": []}',\n },\n {\n key: 'actions',\n label: 'Actions (JSON array)',\n type: 'json',\n placeholder: '[{\"type\": \"percent_off\", \"value\": 10}]',\n },\n ];\n}\n","<div class=\"x-page-head\">\n <div class=\"x-page-title\">{{ pageTitle }}</div>\n <div class=\"x-page-subtitle\">{{ pageSubtitle }}</div>\n</div>\n\n@if (!editing) {\n <div class=\"x-scrud-toolbar\">\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" (click)=\"startCreate()\">+ New {{ singularLabel }}</button>\n </div>\n\n @if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n} @else if (draft) {\n <div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">{{ draft['id'] ? 'Edit' : 'New' }} {{ singularLabel }}</div>\n <div class=\"x-scrud-editor-actions\">\n @if (draft['id'] && !hideDelete) {\n <button type=\"button\" class=\"x-scrud-btn x-scrud-danger\" (click)=\"remove(draft); cancelEdit()\">Delete</button>\n }\n <button type=\"button\" class=\"x-scrud-btn\" (click)=\"cancelEdit()\">Close</button>\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" [disabled]=\"saving\" (click)=\"save()\">\n {{ saving ? 'Saving…' : 'Save' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n @for (f of fields; track f.key) {\n <label class=\"x-scrud-f\" [class.x-scrud-f-wide]=\"f.type === 'textarea' || f.type === 'json'\">\n {{ f.label }}\n @if (f.required) {\n <span class=\"x-scrud-required\">*</span>\n }\n @switch (f.type) {\n @case ('boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"draft[f.key]\" />\n }\n @case ('select') {\n <select [(ngModel)]=\"draft[f.key]\">\n <option value=\"\">— choose —</option>\n @for (opt of (f.optionsKey ? dynamicOptions[f.optionsKey] : f.options); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n }\n @case ('textarea') {\n <textarea rows=\"3\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\"></textarea>\n }\n @case ('json') {\n <textarea rows=\"4\" class=\"x-scrud-json\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || '{}'\"></textarea>\n }\n @case ('number') {\n <input type=\"number\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n @case ('date') {\n <input type=\"datetime-local\" [(ngModel)]=\"draft[f.key]\" />\n }\n @default {\n <input type=\"text\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n }\n </label>\n }\n </div>\n </div>\n}\n","import { NgModule } from '@angular/core';\nimport { RouterModule } from '@angular/router';\nimport { SharedModule } from '@thescaffold/ngx-core';\nimport { ElementsModule, WebgetsModule } from '@thescaffold/ngx-ui';\nimport { PromotionsComponent } from './promotions.component';\n\n@NgModule({\n declarations: [PromotionsComponent],\n imports: [\n SharedModule,\n ElementsModule,\n WebgetsModule,\n RouterModule.forChild([{ path: '', component: PromotionsComponent }]),\n ],\n})\nexport class PromotionsModule {}\n"],"names":["i1"],"mappings":"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"}
|
|
@@ -44,11 +44,11 @@ class RedirectsComponent extends SimpleCrudDirective {
|
|
|
44
44
|
];
|
|
45
45
|
}
|
|
46
46
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RedirectsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
47
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: RedirectsComponent, isStandalone: false, selector: "x-redirects", usesInheritance: true, ngImport: i0, template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">{{ pageTitle }}</div>\n <div class=\"x-page-subtitle\">{{ pageSubtitle }}</div>\n</div>\n\n@if (!editing) {\n <div class=\"x-scrud-toolbar\">\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" (click)=\"startCreate()\">+ New {{ singularLabel }}</button>\n </div>\n\n @if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n} @else if (draft) {\n <div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">{{ draft['id'] ? 'Edit' : 'New' }} {{ singularLabel }}</div>\n <div class=\"x-scrud-editor-actions\">\n @if (draft['id'] && !hideDelete) {\n <button type=\"button\" class=\"x-scrud-btn x-scrud-danger\" (click)=\"remove(draft); cancelEdit()\">Delete</button>\n }\n <button type=\"button\" class=\"x-scrud-btn\" (click)=\"cancelEdit()\">Close</button>\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" [disabled]=\"saving\" (click)=\"save()\">\n {{ saving ? 'Saving\u2026' : 'Save' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n @for (f of fields; track f.key) {\n <label class=\"x-scrud-f\" [class.x-scrud-f-wide]=\"f.type === 'textarea' || f.type === 'json'\">\n {{ f.label }}\n @if (f.required) {\n <span class=\"x-scrud-required\">*</span>\n }\n @switch (f.type) {\n @case ('boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"draft[f.key]\" />\n }\n @case ('select') {\n <select [(ngModel)]=\"draft[f.key]\">\n <option value=\"\">\u2014 choose \u2014</option>\n @for (opt of (f.optionsKey ? dynamicOptions[f.optionsKey] : f.options); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n }\n @case ('textarea') {\n <textarea rows=\"3\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\"></textarea>\n }\n @case ('json') {\n <textarea rows=\"4\" class=\"x-scrud-json\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || '{}'\"></textarea>\n }\n @case ('number') {\n <input type=\"number\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n @case ('date') {\n <input type=\"datetime-local\" [(ngModel)]=\"draft[f.key]\" />\n }\n @default {\n <input type=\"text\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n }\n </label>\n }\n </div>\n </div>\n}\n", styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}.x-scrud-toolbar{display:flex;justify-content:flex-end;margin-bottom:14px}.x-scrud-btn{border:1px solid var(--color-border);background:transparent;border-radius:var(--radius-md);padding:6px 14px;font-size:12.5px;font-weight:700;cursor:pointer;color:var(--color-text-muted)}.x-scrud-btn:disabled{opacity:.5;cursor:default}.x-scrud-btn-primary{border-color:var(--color-accent);color:var(--color-accent-hover)}.x-scrud-danger{color:var(--color-danger, #c0362c)}.x-scrud-editor{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:16px;display:flex;flex-direction:column;gap:14px}.x-scrud-editor-head{display:flex;align-items:center;justify-content:space-between}.x-scrud-editor-title{font-size:16px;font-weight:800;color:var(--color-text)}.x-scrud-editor-actions{display:flex;gap:8px}.x-scrud-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.x-scrud-f{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--color-text-muted);font-weight:700}.x-scrud-f-wide{grid-column:1/-1}.x-scrud-f input,.x-scrud-f select,.x-scrud-f textarea{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:6px 10px;font-size:13px;background:var(--color-surface);color:var(--color-text);font-weight:400}.x-scrud-f input[type=checkbox]{width:18px;height:18px}.x-scrud-json{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.x-scrud-required{color:var(--color-danger, #c0362c)}\n"], dependencies: [{ kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.LoaderComponent, selector: "x-element-loader", inputs: ["data"] }, { kind: "component", type: i2.CollectionComponent, selector: "x-webget-collection", inputs: ["data"], outputs: ["search", "filter", "refresh", "select", "page", "show"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] }); }
|
|
47
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: RedirectsComponent, isStandalone: false, selector: "x-redirects", usesInheritance: true, ngImport: i0, template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">{{ pageTitle }}</div>\n <div class=\"x-page-subtitle\">{{ pageSubtitle }}</div>\n</div>\n\n@if (!editing) {\n <div class=\"x-scrud-toolbar\">\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" (click)=\"startCreate()\">+ New {{ singularLabel }}</button>\n </div>\n\n @if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n} @else if (draft) {\n <div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">{{ draft['id'] ? 'Edit' : 'New' }} {{ singularLabel }}</div>\n <div class=\"x-scrud-editor-actions\">\n @if (draft['id'] && !hideDelete) {\n <button type=\"button\" class=\"x-scrud-btn x-scrud-danger\" (click)=\"remove(draft); cancelEdit()\">Delete</button>\n }\n <button type=\"button\" class=\"x-scrud-btn\" (click)=\"cancelEdit()\">Close</button>\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" [disabled]=\"saving\" (click)=\"save()\">\n {{ saving ? 'Saving\u2026' : 'Save' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n @for (f of fields; track f.key) {\n <label class=\"x-scrud-f\" [class.x-scrud-f-wide]=\"f.type === 'textarea' || f.type === 'json'\">\n {{ f.label }}\n @if (f.required) {\n <span class=\"x-scrud-required\">*</span>\n }\n @switch (f.type) {\n @case ('boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"draft[f.key]\" />\n }\n @case ('select') {\n <select [(ngModel)]=\"draft[f.key]\">\n <option value=\"\">\u2014 choose \u2014</option>\n @for (opt of (f.optionsKey ? dynamicOptions[f.optionsKey] : f.options); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n }\n @case ('textarea') {\n <textarea rows=\"3\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\"></textarea>\n }\n @case ('json') {\n <textarea rows=\"4\" class=\"x-scrud-json\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || '{}'\"></textarea>\n }\n @case ('number') {\n <input type=\"number\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n @case ('date') {\n <input type=\"datetime-local\" [(ngModel)]=\"draft[f.key]\" />\n }\n @default {\n <input type=\"text\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n }\n </label>\n }\n </div>\n </div>\n}\n", styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}.x-scrud-toolbar{display:flex;justify-content:flex-end;margin-bottom:14px}.x-scrud-btn{border:1px solid var(--color-border);background:transparent;border-radius:var(--radius-md);padding:6px 14px;font-size:12.5px;font-weight:700;cursor:pointer;color:var(--color-text-muted)}.x-scrud-btn:disabled{opacity:.5;cursor:default}.x-scrud-btn-primary{border-color:var(--color-accent);color:var(--color-accent-hover)}.x-scrud-danger{color:var(--color-danger, #c0362c)}.x-scrud-editor{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:16px;display:flex;flex-direction:column;gap:14px}.x-scrud-editor-head{display:flex;align-items:center;justify-content:space-between}.x-scrud-editor-title{font-size:16px;font-weight:800;color:var(--color-text)}.x-scrud-editor-actions{display:flex;gap:8px}.x-scrud-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.x-scrud-f{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--color-text-muted);font-weight:700}.x-scrud-f-wide{grid-column:1/-1}.x-scrud-f input,.x-scrud-f select,.x-scrud-f textarea{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:6px 10px;font-size:13px;background:var(--color-surface);color:var(--color-text);font-weight:400}.x-scrud-f input[type=checkbox]{width:18px;height:18px}.x-scrud-pwd{position:relative;display:flex}.x-scrud-pwd input{flex:1;padding-right:34px!important}.x-scrud-pwd-toggle{position:absolute;right:4px;top:50%;transform:translateY(-50%);border:none;background:transparent;color:var(--color-text-muted);padding:4px 6px;cursor:pointer}.x-scrud-pwd-toggle:hover{color:var(--color-text)}.x-scrud-json{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.x-scrud-required{color:var(--color-danger, #c0362c)}\n"], dependencies: [{ kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.LoaderComponent, selector: "x-element-loader", inputs: ["data"] }, { kind: "component", type: i2.CollectionComponent, selector: "x-webget-collection", inputs: ["data"], outputs: ["search", "filter", "refresh", "select", "page", "show"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] }); }
|
|
48
48
|
}
|
|
49
49
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RedirectsComponent, decorators: [{
|
|
50
50
|
type: Component,
|
|
51
|
-
args: [{ standalone: false, selector: 'x-redirects', template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">{{ pageTitle }}</div>\n <div class=\"x-page-subtitle\">{{ pageSubtitle }}</div>\n</div>\n\n@if (!editing) {\n <div class=\"x-scrud-toolbar\">\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" (click)=\"startCreate()\">+ New {{ singularLabel }}</button>\n </div>\n\n @if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n} @else if (draft) {\n <div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">{{ draft['id'] ? 'Edit' : 'New' }} {{ singularLabel }}</div>\n <div class=\"x-scrud-editor-actions\">\n @if (draft['id'] && !hideDelete) {\n <button type=\"button\" class=\"x-scrud-btn x-scrud-danger\" (click)=\"remove(draft); cancelEdit()\">Delete</button>\n }\n <button type=\"button\" class=\"x-scrud-btn\" (click)=\"cancelEdit()\">Close</button>\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" [disabled]=\"saving\" (click)=\"save()\">\n {{ saving ? 'Saving\u2026' : 'Save' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n @for (f of fields; track f.key) {\n <label class=\"x-scrud-f\" [class.x-scrud-f-wide]=\"f.type === 'textarea' || f.type === 'json'\">\n {{ f.label }}\n @if (f.required) {\n <span class=\"x-scrud-required\">*</span>\n }\n @switch (f.type) {\n @case ('boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"draft[f.key]\" />\n }\n @case ('select') {\n <select [(ngModel)]=\"draft[f.key]\">\n <option value=\"\">\u2014 choose \u2014</option>\n @for (opt of (f.optionsKey ? dynamicOptions[f.optionsKey] : f.options); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n }\n @case ('textarea') {\n <textarea rows=\"3\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\"></textarea>\n }\n @case ('json') {\n <textarea rows=\"4\" class=\"x-scrud-json\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || '{}'\"></textarea>\n }\n @case ('number') {\n <input type=\"number\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n @case ('date') {\n <input type=\"datetime-local\" [(ngModel)]=\"draft[f.key]\" />\n }\n @default {\n <input type=\"text\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n }\n </label>\n }\n </div>\n </div>\n}\n", styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}.x-scrud-toolbar{display:flex;justify-content:flex-end;margin-bottom:14px}.x-scrud-btn{border:1px solid var(--color-border);background:transparent;border-radius:var(--radius-md);padding:6px 14px;font-size:12.5px;font-weight:700;cursor:pointer;color:var(--color-text-muted)}.x-scrud-btn:disabled{opacity:.5;cursor:default}.x-scrud-btn-primary{border-color:var(--color-accent);color:var(--color-accent-hover)}.x-scrud-danger{color:var(--color-danger, #c0362c)}.x-scrud-editor{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:16px;display:flex;flex-direction:column;gap:14px}.x-scrud-editor-head{display:flex;align-items:center;justify-content:space-between}.x-scrud-editor-title{font-size:16px;font-weight:800;color:var(--color-text)}.x-scrud-editor-actions{display:flex;gap:8px}.x-scrud-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.x-scrud-f{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--color-text-muted);font-weight:700}.x-scrud-f-wide{grid-column:1/-1}.x-scrud-f input,.x-scrud-f select,.x-scrud-f textarea{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:6px 10px;font-size:13px;background:var(--color-surface);color:var(--color-text);font-weight:400}.x-scrud-f input[type=checkbox]{width:18px;height:18px}.x-scrud-json{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.x-scrud-required{color:var(--color-danger, #c0362c)}\n"] }]
|
|
51
|
+
args: [{ standalone: false, selector: 'x-redirects', template: "<div class=\"x-page-head\">\n <div class=\"x-page-title\">{{ pageTitle }}</div>\n <div class=\"x-page-subtitle\">{{ pageSubtitle }}</div>\n</div>\n\n@if (!editing) {\n <div class=\"x-scrud-toolbar\">\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" (click)=\"startCreate()\">+ New {{ singularLabel }}</button>\n </div>\n\n @if (list$ | async; as list) {\n <x-webget-collection [data]=\"list\"></x-webget-collection>\n } @else {\n <x-element-loader></x-element-loader>\n }\n} @else if (draft) {\n <div class=\"x-scrud-editor\">\n <div class=\"x-scrud-editor-head\">\n <div class=\"x-scrud-editor-title\">{{ draft['id'] ? 'Edit' : 'New' }} {{ singularLabel }}</div>\n <div class=\"x-scrud-editor-actions\">\n @if (draft['id'] && !hideDelete) {\n <button type=\"button\" class=\"x-scrud-btn x-scrud-danger\" (click)=\"remove(draft); cancelEdit()\">Delete</button>\n }\n <button type=\"button\" class=\"x-scrud-btn\" (click)=\"cancelEdit()\">Close</button>\n <button type=\"button\" class=\"x-scrud-btn x-scrud-btn-primary\" [disabled]=\"saving\" (click)=\"save()\">\n {{ saving ? 'Saving\u2026' : 'Save' }}\n </button>\n </div>\n </div>\n\n <div class=\"x-scrud-grid\">\n @for (f of fields; track f.key) {\n <label class=\"x-scrud-f\" [class.x-scrud-f-wide]=\"f.type === 'textarea' || f.type === 'json'\">\n {{ f.label }}\n @if (f.required) {\n <span class=\"x-scrud-required\">*</span>\n }\n @switch (f.type) {\n @case ('boolean') {\n <input type=\"checkbox\" [(ngModel)]=\"draft[f.key]\" />\n }\n @case ('select') {\n <select [(ngModel)]=\"draft[f.key]\">\n <option value=\"\">\u2014 choose \u2014</option>\n @for (opt of (f.optionsKey ? dynamicOptions[f.optionsKey] : f.options); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n }\n @case ('textarea') {\n <textarea rows=\"3\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\"></textarea>\n }\n @case ('json') {\n <textarea rows=\"4\" class=\"x-scrud-json\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || '{}'\"></textarea>\n }\n @case ('number') {\n <input type=\"number\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n @case ('date') {\n <input type=\"datetime-local\" [(ngModel)]=\"draft[f.key]\" />\n }\n @default {\n <input type=\"text\" [(ngModel)]=\"draft[f.key]\" [placeholder]=\"f.placeholder || ''\" />\n }\n }\n </label>\n }\n </div>\n </div>\n}\n", styles: [".x-page-head{margin-bottom:20px}.x-page-title{font-size:24px;font-weight:800;color:var(--color-text)}.x-page-subtitle{font-size:13.5px;color:var(--color-text-muted);margin-top:2px}.x-scrud-toolbar{display:flex;justify-content:flex-end;margin-bottom:14px}.x-scrud-btn{border:1px solid var(--color-border);background:transparent;border-radius:var(--radius-md);padding:6px 14px;font-size:12.5px;font-weight:700;cursor:pointer;color:var(--color-text-muted)}.x-scrud-btn:disabled{opacity:.5;cursor:default}.x-scrud-btn-primary{border-color:var(--color-accent);color:var(--color-accent-hover)}.x-scrud-danger{color:var(--color-danger, #c0362c)}.x-scrud-editor{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:16px;display:flex;flex-direction:column;gap:14px}.x-scrud-editor-head{display:flex;align-items:center;justify-content:space-between}.x-scrud-editor-title{font-size:16px;font-weight:800;color:var(--color-text)}.x-scrud-editor-actions{display:flex;gap:8px}.x-scrud-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.x-scrud-f{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--color-text-muted);font-weight:700}.x-scrud-f-wide{grid-column:1/-1}.x-scrud-f input,.x-scrud-f select,.x-scrud-f textarea{border:1px solid var(--color-border);border-radius:var(--radius-md);padding:6px 10px;font-size:13px;background:var(--color-surface);color:var(--color-text);font-weight:400}.x-scrud-f input[type=checkbox]{width:18px;height:18px}.x-scrud-pwd{position:relative;display:flex}.x-scrud-pwd input{flex:1;padding-right:34px!important}.x-scrud-pwd-toggle{position:absolute;right:4px;top:50%;transform:translateY(-50%);border:none;background:transparent;color:var(--color-text-muted);padding:4px 6px;cursor:pointer}.x-scrud-pwd-toggle:hover{color:var(--color-text)}.x-scrud-json{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.x-scrud-required{color:var(--color-danger, #c0362c)}\n"] }]
|
|
52
52
|
}] });
|
|
53
53
|
|
|
54
54
|
class RedirectsModule {
|
|
@@ -75,4 +75,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
75
75
|
}] });
|
|
76
76
|
|
|
77
77
|
export { RedirectsModule };
|
|
78
|
-
//# sourceMappingURL=isaiahiroko-tilmart-ngx-apps-admin-redirects.module-
|
|
78
|
+
//# sourceMappingURL=isaiahiroko-tilmart-ngx-apps-admin-redirects.module-D8H6ujoy.mjs.map
|