@smallpearl/ngx-helper 0.31.4 → 0.31.8
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/assets/i18n/sp-mat-entity-crud/zh-hant.json +12 -12
- package/entity-field/index.d.ts +1 -1
- package/entity-field/src/{entity-field-spec.d.ts → entity-field.d.ts} +4 -1
- package/entity-field/src/provider.d.ts +1 -1
- package/fesm2022/smallpearl-ngx-helper-entity-field.mjs.map +1 -1
- package/fesm2022/smallpearl-ngx-helper-mat-entity-crud.mjs +142 -94
- package/fesm2022/smallpearl-ngx-helper-mat-entity-crud.mjs.map +1 -1
- package/fesm2022/smallpearl-ngx-helper-mat-entity-list.mjs +11 -8
- package/fesm2022/smallpearl-ngx-helper-mat-entity-list.mjs.map +1 -1
- package/mat-entity-crud/src/form-view-host.component.d.ts +7 -5
- package/mat-entity-crud/src/mat-entity-crud.component.d.ts +4 -4
- package/mat-entity-list/src/mat-entity-list.component.d.ts +1 -0
- package/package.json +9 -9
|
@@ -4,18 +4,18 @@
|
|
|
4
4
|
"delete": "刪除",
|
|
5
5
|
"createNew": "新建",
|
|
6
6
|
"refresh": "刷新",
|
|
7
|
-
"newItem": "新建
|
|
8
|
-
"editItem": "編輯
|
|
9
|
-
"deleteItem": "刪除
|
|
10
|
-
"deleteItemConfirm": "確定要刪除這個
|
|
11
|
-
"deleteItemSuccess": "{{item}}
|
|
12
|
-
"deleteItemError": "{{item}}
|
|
13
|
-
"saveSuccess": "{{item}}
|
|
14
|
-
"saveError": "{{item}}
|
|
15
|
-
"createSuccess": "{{item}}
|
|
16
|
-
"createError": "{{item}}
|
|
17
|
-
"updateSuccess": "{{item}}
|
|
18
|
-
"updateError": "{{item}}
|
|
7
|
+
"newItem": "新建{{item}}",
|
|
8
|
+
"editItem": "編輯{{item}}",
|
|
9
|
+
"deleteItem": "刪除{{item}}",
|
|
10
|
+
"deleteItemConfirm": "確定要刪除這個{{item}}嗎?",
|
|
11
|
+
"deleteItemSuccess": "{{item}}刪除成功",
|
|
12
|
+
"deleteItemError": "{{item}}刪除失敗",
|
|
13
|
+
"saveSuccess": "{{item}}保存成功",
|
|
14
|
+
"saveError": "{{item}}保存失敗",
|
|
15
|
+
"createSuccess": "{{item}}創建成功",
|
|
16
|
+
"createError": "{{item}}創建失敗",
|
|
17
|
+
"updateSuccess": "{{item}}更新成功",
|
|
18
|
+
"updateError": "{{item}}更新失敗",
|
|
19
19
|
"loseChangesConfirm": "您有未保存的更改。確定要離開嗎?",
|
|
20
20
|
"cancel": "取消",
|
|
21
21
|
"confirm": "確認",
|
package/entity-field/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './src/entity-field
|
|
1
|
+
export * from './src/entity-field';
|
|
2
2
|
export * from './src/provider';
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { SPIntlDateFormat } from '@smallpearl/ngx-helper/locale';
|
|
2
2
|
import { SPEntityFieldConfig } from './provider';
|
|
3
|
+
import { Observable } from 'rxjs';
|
|
4
|
+
type FieldValueTypes = string | number | Date | boolean;
|
|
3
5
|
/**
|
|
4
6
|
* This structure defines the data formatting details for a field of the
|
|
5
7
|
* entity. All entity fields need not necessarily be actual entity object's
|
|
@@ -19,7 +21,7 @@ export type SPEntityFieldSpec<TEntity extends {
|
|
|
19
21
|
alignment?: 'start' | 'center' | 'end';
|
|
20
22
|
routerLink?: ((e: TEntity) => string[]) | [string];
|
|
21
23
|
};
|
|
22
|
-
valueFn?: (item: TEntity) =>
|
|
24
|
+
valueFn?: (item: TEntity) => FieldValueTypes | Observable<FieldValueTypes>;
|
|
23
25
|
};
|
|
24
26
|
/**
|
|
25
27
|
* A class that represents a SPEntityFieldSpec<>. This is typically used
|
|
@@ -65,3 +67,4 @@ export declare class SPEntityField<TEntity extends {
|
|
|
65
67
|
hasRouterLink(entity: TEntity): boolean;
|
|
66
68
|
getRouterLink(entity: TEntity): string[];
|
|
67
69
|
}
|
|
70
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { InjectionToken } from '@angular/core';
|
|
2
|
-
import { SPEntityFieldSpec } from './entity-field
|
|
2
|
+
import { SPEntityFieldSpec } from './entity-field';
|
|
3
3
|
export type FIELD_VALUE_FN = (entity: any, fieldName: string) => string | number | Date | boolean;
|
|
4
4
|
/**
|
|
5
5
|
* Global config for SPEntityField component.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smallpearl-ngx-helper-entity-field.mjs","sources":["../../../../projects/smallpearl/ngx-helper/entity-field/src/entity-field
|
|
1
|
+
{"version":3,"file":"smallpearl-ngx-helper-entity-field.mjs","sources":["../../../../projects/smallpearl/ngx-helper/entity-field/src/entity-field.ts","../../../../projects/smallpearl/ngx-helper/entity-field/src/provider.ts","../../../../projects/smallpearl/ngx-helper/entity-field/smallpearl-ngx-helper-entity-field.ts"],"sourcesContent":["import {\n spFormatCurrency,\n spFormatDate,\n SPIntlDateFormat,\n} from '@smallpearl/ngx-helper/locale';\nimport { SPEntityFieldConfig } from './provider';\nimport { Observable } from 'rxjs';\n\ntype FieldValueTypes = string | number | Date | boolean;\n\n/**\n * This structure defines the data formatting details for a field of the\n * entity. All entity fields need not necessarily be actual entity object's\n * properties. Fields can also be computed fields, in which case the valueFn\n * should be initialized with a valid function to provide the field's value.\n */\nexport type SPEntityFieldSpec<TEntity extends { [P in IdKey]: PropertyKey }, IdKey extends string = 'id'> = {\n // Column name. If valueFn is not specified, this will be used as the\n // key name to retrieve the value for the column from TEntity.\n name: string;\n // If omitted, 'name' will be used as field label.\n label?: string;\n // Column value specific formatting options. Currently, only used for\n // Date types.\n valueOptions?: {\n // Specify the same format string argument that is passed to DatePipe.\n dateTimeFormat?: SPIntlDateFormat;\n // If boolean, number field will be formatted using spFormatCurrency()\n // using the current currency or 'currency' value below.\n isCurrency?: boolean;\n // Currency code, if different from default locale.\n currency?: string;\n // CSS class name; if provided will be applied to field value's wrapper\n // element. This will be <td> & <th>.\n class?: string;\n // Alignment options. Field's value will be aligned based on this.\n alignment?: 'start'|'center'|'end';\n // A fixed string or a function that returns an array of strings\n // to be used as the routerlink for the column value.\n routerLink?: ((e: TEntity) => string[])|[string];\n };\n // If the column value cannot be derived by simple TEntity[name] lookup,\n // use this function to return a custom computed or formatted value.\n valueFn?: (item: TEntity) => FieldValueTypes | Observable<FieldValueTypes>;\n};\n\n/**\n * A class that represents a SPEntityFieldSpec<>. This is typically used\n * by the library to evaluate a SPEntityFieldSpec<> object.\n */\nexport class SPEntityField<TEntity extends { [P in IdKey]: PropertyKey }, IdKey extends string = 'id'> {\n public _fieldSpec!: SPEntityFieldSpec<TEntity, IdKey>;\n\n constructor(\n spec: SPEntityFieldSpec<TEntity, IdKey> | string,\n public fieldConfig?: SPEntityFieldConfig\n ) {\n if (typeof spec === 'string') {\n this._fieldSpec = {\n name: spec,\n };\n } else {\n this._fieldSpec = spec;\n }\n }\n\n get spec() {\n return this._fieldSpec;\n }\n\n /**\n * Returns the effective fieldValueOptions by merging the global field\n * options (if one has been spefified) with the local field value options.\n * @returns SPEntityFieldSpec<any>['valueOptions']\n */\n get options() {\n let globalFieldValueOptions: SPEntityFieldSpec<any>['valueOptions'] = {};\n if (this.fieldConfig && this.fieldConfig?.fieldValueOptions && this.fieldConfig.fieldValueOptions.has(this._fieldSpec.name)) {\n globalFieldValueOptions = this.fieldConfig.fieldValueOptions.get(this._fieldSpec.name);\n }\n return {\n ...globalFieldValueOptions,\n ...(this._fieldSpec?.valueOptions ?? {})\n };\n }\n /**\n * @returns the label for the field.\n */\n label() {\n return this._fieldSpec.label ?? this._fieldSpec.name\n }\n\n /**\n * Given an entity, returns the value of the field matching the\n * SPEntityFieldSpec<> in fieldSpec.\n * @param entity TEntity instance which will be evaluated for\n * SPEntityFieldSpec<>.\n * @returns\n */\n value(entity: TEntity) {\n let val = undefined;\n if (!this._fieldSpec.valueFn) {\n if (\n this.fieldConfig &&\n this.fieldConfig?.fieldValueFns &&\n this.fieldConfig.fieldValueFns.has(this._fieldSpec.name)\n ) {\n val = this.fieldConfig.fieldValueFns.get(this._fieldSpec.name)!(entity, this._fieldSpec.name);\n } else {\n val = (entity as any)[this._fieldSpec.name];\n }\n } else {\n val = this._fieldSpec.valueFn(entity);\n }\n const valueOptions = this.options;\n if (val instanceof Date) {\n val = spFormatDate(val);\n } else if (\n typeof val === 'number' &&\n valueOptions?.isCurrency\n ) {\n val = spFormatCurrency(val, this._fieldSpec?.valueOptions?.currency);\n } else if (typeof val === 'boolean') {\n val = val ? '✔' : '✖';\n }\n return val;\n }\n\n /**\n * If specified, will be added to the CSS classes of the field's wrapper\n * element.\n */\n get class() {\n return this._fieldSpec?.valueOptions?.class ?? '';\n }\n\n hasRouterLink(entity: TEntity) {\n return !!this._fieldSpec?.valueOptions?.routerLink;\n }\n\n getRouterLink(entity: TEntity) {\n const rl = this._fieldSpec?.valueOptions?.routerLink;\n if (rl) {\n if (typeof rl == 'function') {\n return rl(entity);\n }\n return rl\n }\n return [];\n }\n}\n","import { InjectionToken } from '@angular/core';\nimport { SPEntityFieldSpec } from './entity-field';\n\n\nexport type FIELD_VALUE_FN = (entity: any, fieldName: string) => string|number|Date|boolean;\n\n/**\n * Global config for SPEntityField component.\n */\nexport interface SPEntityFieldConfig {\n /**\n * These are global field value functions.\n *\n * If a value function for a field is not explicitly specified, this map is\n * looked up with the field name. If an entry exists in this table, it will\n * be used to render the field's value.\n *\n * This is useful for formatting certain fields which tend to have the\n * same name across the app. For instance fields such as 'amount', 'total'\n * or 'balance'. Or 'date', 'timestamp', etc.\n */\n fieldValueFns?: Map<string, FIELD_VALUE_FN>;\n /**\n * Similar to above, but allows setting the options for certain fields\n * globally. As in the case of `fieldValueFns`, the per field specification,\n * if one exists, takes precedence over the global setting.\n */\n fieldValueOptions?: Map<string, SPEntityFieldSpec<any>['valueOptions']>;\n}\n\nexport const SP_ENTITY_FIELD_CONFIG = new InjectionToken<SPEntityFieldConfig>(\n 'SPEntityFieldConfig'\n);\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i1$1 from '@angular/common/http';
|
|
2
2
|
import { HttpContextToken, HttpContext } from '@angular/common/http';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { InjectionToken, inject, input, signal, viewChild, ViewContainerRef, Component, ChangeDetectionStrategy,
|
|
4
|
+
import { InjectionToken, inject, input, computed, signal, viewChild, ViewContainerRef, Component, ChangeDetectionStrategy, viewChildren, EventEmitter, effect, ContentChildren, Output, ChangeDetectorRef } from '@angular/core';
|
|
5
5
|
import * as i4 from '@angular/common';
|
|
6
6
|
import { CommonModule } from '@angular/common';
|
|
7
7
|
import * as i1 from '@angular/material/button';
|
|
@@ -27,7 +27,7 @@ import * as i11 from 'angular-split';
|
|
|
27
27
|
import { AngularSplitModule } from 'angular-split';
|
|
28
28
|
import { startCase } from 'lodash';
|
|
29
29
|
import { plural } from 'pluralize';
|
|
30
|
-
import {
|
|
30
|
+
import { Observable, of, Subscription, firstValueFrom, tap, switchMap, map } from 'rxjs';
|
|
31
31
|
import * as i1$2 from '@angular/material/toolbar';
|
|
32
32
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
|
33
33
|
import { setServerErrorsAsFormErrors } from '@smallpearl/ngx-helper/forms';
|
|
@@ -82,6 +82,14 @@ class FormViewHostComponent {
|
|
|
82
82
|
clientViewTemplate = input(null);
|
|
83
83
|
itemLabel = input.required();
|
|
84
84
|
itemLabelPlural = input.required();
|
|
85
|
+
_itemLabel = computed(() => {
|
|
86
|
+
const label = this.itemLabel();
|
|
87
|
+
return label instanceof Observable ? label : of(label);
|
|
88
|
+
});
|
|
89
|
+
_itemLabelPlural = computed(() => {
|
|
90
|
+
const label = this.itemLabelPlural();
|
|
91
|
+
return label instanceof Observable ? label : of(label);
|
|
92
|
+
});
|
|
85
93
|
entity = signal(undefined);
|
|
86
94
|
title = signal('');
|
|
87
95
|
params = signal(undefined);
|
|
@@ -103,10 +111,17 @@ class FormViewHostComponent {
|
|
|
103
111
|
this.title.set(params.title);
|
|
104
112
|
}
|
|
105
113
|
else {
|
|
114
|
+
firstValueFrom(this._itemLabel()).then((itemLabel) => {
|
|
115
|
+
this.title.set(this.transloco.translate(entity ? 'editItem' : 'newItem', {
|
|
116
|
+
item: itemLabel,
|
|
117
|
+
}));
|
|
118
|
+
});
|
|
106
119
|
// this.title.set(entity ? this.config.i18n.editItemLabel(this.itemLabel()) : this.config.i18n.newItemLabel(this.itemLabel()));
|
|
107
|
-
this.title.set(
|
|
108
|
-
|
|
109
|
-
|
|
120
|
+
// this.title.set(
|
|
121
|
+
// this.transloco.translate(entity ? 'editItem' : 'newItem', {
|
|
122
|
+
// item: this.itemLabel(),
|
|
123
|
+
// })
|
|
124
|
+
// );
|
|
110
125
|
}
|
|
111
126
|
this.params.set(params);
|
|
112
127
|
this.createClientView();
|
|
@@ -126,7 +141,9 @@ class FormViewHostComponent {
|
|
|
126
141
|
// )}`
|
|
127
142
|
// );
|
|
128
143
|
const crudComponent = this.entityCrudComponentBase();
|
|
129
|
-
return crudComponent
|
|
144
|
+
return crudComponent
|
|
145
|
+
?.create(entityValue)
|
|
146
|
+
.pipe(tap(() => this.close(false)));
|
|
130
147
|
}
|
|
131
148
|
update(id, entityValue) {
|
|
132
149
|
// console.log(
|
|
@@ -135,7 +152,9 @@ class FormViewHostComponent {
|
|
|
135
152
|
// )}, entity: ${entityValue}`
|
|
136
153
|
// );
|
|
137
154
|
const crudComponent = this.entityCrudComponentBase();
|
|
138
|
-
return crudComponent
|
|
155
|
+
return crudComponent
|
|
156
|
+
?.update(id, entityValue)
|
|
157
|
+
.pipe(tap(() => this.close(false)));
|
|
139
158
|
}
|
|
140
159
|
/**
|
|
141
160
|
* Creates the client view provided via template
|
|
@@ -149,7 +168,7 @@ class FormViewHostComponent {
|
|
|
149
168
|
$implicit: {
|
|
150
169
|
bridge: this,
|
|
151
170
|
entity: this.entity(),
|
|
152
|
-
params: this.params()
|
|
171
|
+
params: this.params(),
|
|
153
172
|
},
|
|
154
173
|
});
|
|
155
174
|
this.clientFormView.detectChanges();
|
|
@@ -189,7 +208,12 @@ class FormViewHostComponent {
|
|
|
189
208
|
}
|
|
190
209
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImport: i0, type: FormViewHostComponent, decorators: [{
|
|
191
210
|
type: Component,
|
|
192
|
-
args: [{ imports: [
|
|
211
|
+
args: [{ imports: [
|
|
212
|
+
CommonModule,
|
|
213
|
+
MatButtonModule,
|
|
214
|
+
MatIconModule,
|
|
215
|
+
SPMatHostBusyWheelDirective,
|
|
216
|
+
], selector: 'sp-create-edit-entity-host', template: `
|
|
193
217
|
<div spHostBusyWheel="formBusyWheel">
|
|
194
218
|
<div class="create-edit-topbar">
|
|
195
219
|
<div class="title">
|
|
@@ -440,12 +464,18 @@ class SPMatEntityCrudComponent extends SPMatEntityListComponent {
|
|
|
440
464
|
}
|
|
441
465
|
return startCase(source);
|
|
442
466
|
};
|
|
443
|
-
_itemLabel = computed(() =>
|
|
444
|
-
|
|
445
|
-
: this.getLabel(this.entityName())
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
467
|
+
_itemLabel = computed(() => {
|
|
468
|
+
const itemLabel = this.itemLabel();
|
|
469
|
+
const label = itemLabel ? itemLabel : this.getLabel(this.entityName());
|
|
470
|
+
return label instanceof Observable ? label : of(label);
|
|
471
|
+
});
|
|
472
|
+
_itemLabelPlural = computed(() => {
|
|
473
|
+
const itemLabelPlural = this.itemLabelPlural();
|
|
474
|
+
const label = itemLabelPlural
|
|
475
|
+
? itemLabelPlural
|
|
476
|
+
: this.getLabel(plural(this.entityName()));
|
|
477
|
+
return label instanceof Observable ? label : of(label);
|
|
478
|
+
});
|
|
449
479
|
// Computed title
|
|
450
480
|
_title = computed(() => {
|
|
451
481
|
const title = this.title() ? this.title() : this._itemLabelPlural();
|
|
@@ -570,16 +600,14 @@ class SPMatEntityCrudComponent extends SPMatEntityListComponent {
|
|
|
570
600
|
]);
|
|
571
601
|
}
|
|
572
602
|
}
|
|
573
|
-
ngOnInit() {
|
|
574
|
-
}
|
|
603
|
+
ngOnInit() { }
|
|
575
604
|
ngOnDestroy() {
|
|
576
605
|
this.sub$.unsubscribe();
|
|
577
606
|
}
|
|
578
607
|
/**
|
|
579
608
|
* Override so that we can suppress default action in SPMatEntityListComponent
|
|
580
609
|
*/
|
|
581
|
-
ngAfterViewInit() {
|
|
582
|
-
}
|
|
610
|
+
ngAfterViewInit() { }
|
|
583
611
|
/**
|
|
584
612
|
* If the create/edit entity form is active, it calls its registered
|
|
585
613
|
* canCancelEdit callback to determine if it's okay to cancel the edit.
|
|
@@ -742,36 +770,49 @@ class SPMatEntityCrudComponent extends SPMatEntityListComponent {
|
|
|
742
770
|
if (!this.newItemLink() || this.newItemLink()?.length == 0) {
|
|
743
771
|
event.preventDefault();
|
|
744
772
|
event.stopImmediatePropagation();
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
this.
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
//
|
|
758
|
-
//
|
|
759
|
-
//
|
|
760
|
-
//
|
|
761
|
-
//
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
this.
|
|
773
|
+
firstValueFrom(this._itemLabel()).then((itemLabel) => {
|
|
774
|
+
const params = {
|
|
775
|
+
title: this.newItemLabel() ??
|
|
776
|
+
this.transloco.translate('spMatEntityCrud.newItem', {
|
|
777
|
+
item: itemLabel
|
|
778
|
+
}),
|
|
779
|
+
};
|
|
780
|
+
this.showCreateEditView(undefined, params);
|
|
781
|
+
if (!this.createEditViewActive()) {
|
|
782
|
+
this.action.emit({ role: '_new_' });
|
|
783
|
+
}
|
|
784
|
+
});
|
|
785
|
+
// const params = {
|
|
786
|
+
// title:
|
|
787
|
+
// this.newItemLabel() ??
|
|
788
|
+
// this.transloco.translate('spMatEntityCrud.newItem', {
|
|
789
|
+
// item: this._itemLabel(),
|
|
790
|
+
// }),
|
|
791
|
+
// };
|
|
792
|
+
// this.showCreateEditView(undefined, params);
|
|
765
793
|
}
|
|
766
794
|
}
|
|
767
795
|
onUpdate(entity) {
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
this.
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
796
|
+
firstValueFrom(this._itemLabel()).then((itemLabel) => {
|
|
797
|
+
const params = {
|
|
798
|
+
title: this.editItemTitle() ??
|
|
799
|
+
this.transloco.translate('spMatEntityCrud.editItem', {
|
|
800
|
+
item: itemLabel
|
|
801
|
+
}),
|
|
802
|
+
};
|
|
803
|
+
this.showCreateEditView(entity, params);
|
|
804
|
+
if (!this.createEditViewActive()) {
|
|
805
|
+
this.action.emit({ role: '_update_' });
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
// const params = {
|
|
809
|
+
// title:
|
|
810
|
+
// this.editItemTitle() ??
|
|
811
|
+
// this.transloco.translate('spMatEntityCrud.editItem', {
|
|
812
|
+
// item: this._itemLabel(),
|
|
813
|
+
// }),
|
|
814
|
+
// };
|
|
815
|
+
// this.showCreateEditView(entity, params);
|
|
775
816
|
// const tmpl = this.createEditFormTemplate();
|
|
776
817
|
// if (tmpl) {
|
|
777
818
|
// // If preview is active deactivate it
|
|
@@ -784,9 +825,9 @@ class SPMatEntityCrudComponent extends SPMatEntityListComponent {
|
|
|
784
825
|
// this.createEditViewActive.set(true);
|
|
785
826
|
// }
|
|
786
827
|
// }
|
|
787
|
-
if (!this.createEditViewActive()) {
|
|
788
|
-
|
|
789
|
-
}
|
|
828
|
+
// if (!this.createEditViewActive()) {
|
|
829
|
+
// this.action.emit({ role: '_update_' });
|
|
830
|
+
// }
|
|
790
831
|
}
|
|
791
832
|
/**
|
|
792
833
|
* Show the create/edit component. This is deliberately made public so as to
|
|
@@ -840,36 +881,41 @@ class SPMatEntityCrudComponent extends SPMatEntityListComponent {
|
|
|
840
881
|
// Do the delete prompt asynchronously so that the context menu is
|
|
841
882
|
// dismissed before the prompt is displayed.
|
|
842
883
|
setTimeout(() => {
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
884
|
+
// We use firstValueFrom() to get the value of the observable
|
|
885
|
+
// synchronously. firstValueFrom() also gracefully cleans up the
|
|
886
|
+
// observable after a value is emitted.
|
|
887
|
+
firstValueFrom(this._itemLabel()).then((itemLabel) => {
|
|
888
|
+
const deletedItemPrompt = this.transloco.translate('spMatEntityCrud.deleteItemConfirm', { item: itemLabel.toLocaleLowerCase() });
|
|
889
|
+
const yes = confirm(deletedItemPrompt);
|
|
890
|
+
if (yes) {
|
|
891
|
+
const entityId = entity[this.idKey()];
|
|
892
|
+
// If preview is active deactivate it
|
|
893
|
+
if (this.previewActive()) {
|
|
894
|
+
this.closePreviewImpl(false);
|
|
895
|
+
}
|
|
896
|
+
let obs;
|
|
897
|
+
const crudOpFn = this.crudOpFn();
|
|
898
|
+
if (crudOpFn) {
|
|
899
|
+
obs = crudOpFn('delete', entityId, undefined, this);
|
|
900
|
+
}
|
|
901
|
+
else {
|
|
902
|
+
obs = this.http.delete(this.getEntityUrl(entityId), {
|
|
903
|
+
context: this.getCrudReqHttpContext('delete'),
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
this.sub$.add(obs
|
|
907
|
+
.pipe(
|
|
908
|
+
// TODO: how to display a busy wheel?
|
|
909
|
+
// showBusyWheelUntilComplete(this.busyWheelId),
|
|
910
|
+
tap(() => {
|
|
911
|
+
this.spEntitiesList().removeEntity(entityId);
|
|
912
|
+
// TODO: customize by providing an interface via SPMatEntityCrudConfig?
|
|
913
|
+
const deletedMessage = this.transloco.translate('spMatEntityCrud.deleteItemSuccess', { item: this._itemLabel() });
|
|
914
|
+
this.snackBar.open(deletedMessage);
|
|
915
|
+
}))
|
|
916
|
+
.subscribe());
|
|
855
917
|
}
|
|
856
|
-
|
|
857
|
-
obs = this.http.delete(this.getEntityUrl(entityId), {
|
|
858
|
-
context: this.getCrudReqHttpContext('delete'),
|
|
859
|
-
});
|
|
860
|
-
}
|
|
861
|
-
this.sub$.add(obs
|
|
862
|
-
.pipe(
|
|
863
|
-
// TODO: how to display a busy wheel?
|
|
864
|
-
// showBusyWheelUntilComplete(this.busyWheelId),
|
|
865
|
-
tap(() => {
|
|
866
|
-
this.spEntitiesList().removeEntity(entityId);
|
|
867
|
-
// TODO: customize by providing an interface via SPMatEntityCrudConfig?
|
|
868
|
-
const deletedMessage = this.transloco.translate('spMatEntityCrud.deleteItemSuccess', { item: this._itemLabel() });
|
|
869
|
-
this.snackBar.open(deletedMessage);
|
|
870
|
-
}))
|
|
871
|
-
.subscribe());
|
|
872
|
-
}
|
|
918
|
+
});
|
|
873
919
|
});
|
|
874
920
|
}
|
|
875
921
|
getUrl(endpoint) {
|
|
@@ -1048,7 +1094,9 @@ class SPMatEntityCrudComponent extends SPMatEntityListComponent {
|
|
|
1048
1094
|
>
|
|
1049
1095
|
{{
|
|
1050
1096
|
newItemLabel() ??
|
|
1051
|
-
t('spMatEntityCrud.
|
|
1097
|
+
t('spMatEntityCrud.newItem', {
|
|
1098
|
+
item: _itemLabel() | async
|
|
1099
|
+
})
|
|
1052
1100
|
}}
|
|
1053
1101
|
<mat-icon>expand_circle_down</mat-icon>
|
|
1054
1102
|
</button>
|
|
@@ -1073,7 +1121,9 @@ class SPMatEntityCrudComponent extends SPMatEntityListComponent {
|
|
|
1073
1121
|
>
|
|
1074
1122
|
{{
|
|
1075
1123
|
newItemLabel() ??
|
|
1076
|
-
t('spMatEntityCrud.
|
|
1124
|
+
t('spMatEntityCrud.newItem', {
|
|
1125
|
+
item: _itemLabel() | async
|
|
1126
|
+
})
|
|
1077
1127
|
}}
|
|
1078
1128
|
<mat-icon>add_circle</mat-icon>
|
|
1079
1129
|
</button>
|
|
@@ -1127,10 +1177,7 @@ class SPMatEntityCrudComponent extends SPMatEntityListComponent {
|
|
|
1127
1177
|
-->
|
|
1128
1178
|
<ng-container matColumnDef="action">
|
|
1129
1179
|
<th mat-header-cell *matHeaderCellDef></th>
|
|
1130
|
-
<td
|
|
1131
|
-
mat-cell
|
|
1132
|
-
*matCellDef="let element"
|
|
1133
|
-
>
|
|
1180
|
+
<td mat-cell *matCellDef="let element">
|
|
1134
1181
|
<!-- <button
|
|
1135
1182
|
mat-icon-button
|
|
1136
1183
|
hoverDropDown
|
|
@@ -1159,8 +1206,8 @@ class SPMatEntityCrudComponent extends SPMatEntityListComponent {
|
|
|
1159
1206
|
<!-- Create/Edit Entity -->
|
|
1160
1207
|
<sp-create-edit-entity-host
|
|
1161
1208
|
[ngClass]="createEditViewActive() ? 'd-inherit' : 'd-none'"
|
|
1162
|
-
|
|
1163
|
-
|
|
1209
|
+
itemLabel="{{ _itemLabel() | async }}"
|
|
1210
|
+
itemLabelPlural="{{ _itemLabelPlural() | async }}"
|
|
1164
1211
|
[entityCrudComponentBase]="this"
|
|
1165
1212
|
[clientViewTemplate]="createEditFormTemplate()"
|
|
1166
1213
|
></sp-create-edit-entity-host>
|
|
@@ -1208,7 +1255,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImpor
|
|
|
1208
1255
|
>
|
|
1209
1256
|
{{
|
|
1210
1257
|
newItemLabel() ??
|
|
1211
|
-
t('spMatEntityCrud.
|
|
1258
|
+
t('spMatEntityCrud.newItem', {
|
|
1259
|
+
item: _itemLabel() | async
|
|
1260
|
+
})
|
|
1212
1261
|
}}
|
|
1213
1262
|
<mat-icon>expand_circle_down</mat-icon>
|
|
1214
1263
|
</button>
|
|
@@ -1233,7 +1282,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImpor
|
|
|
1233
1282
|
>
|
|
1234
1283
|
{{
|
|
1235
1284
|
newItemLabel() ??
|
|
1236
|
-
t('spMatEntityCrud.
|
|
1285
|
+
t('spMatEntityCrud.newItem', {
|
|
1286
|
+
item: _itemLabel() | async
|
|
1287
|
+
})
|
|
1237
1288
|
}}
|
|
1238
1289
|
<mat-icon>add_circle</mat-icon>
|
|
1239
1290
|
</button>
|
|
@@ -1287,10 +1338,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImpor
|
|
|
1287
1338
|
-->
|
|
1288
1339
|
<ng-container matColumnDef="action">
|
|
1289
1340
|
<th mat-header-cell *matHeaderCellDef></th>
|
|
1290
|
-
<td
|
|
1291
|
-
mat-cell
|
|
1292
|
-
*matCellDef="let element"
|
|
1293
|
-
>
|
|
1341
|
+
<td mat-cell *matCellDef="let element">
|
|
1294
1342
|
<!-- <button
|
|
1295
1343
|
mat-icon-button
|
|
1296
1344
|
hoverDropDown
|
|
@@ -1319,8 +1367,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.6", ngImpor
|
|
|
1319
1367
|
<!-- Create/Edit Entity -->
|
|
1320
1368
|
<sp-create-edit-entity-host
|
|
1321
1369
|
[ngClass]="createEditViewActive() ? 'd-inherit' : 'd-none'"
|
|
1322
|
-
|
|
1323
|
-
|
|
1370
|
+
itemLabel="{{ _itemLabel() | async }}"
|
|
1371
|
+
itemLabelPlural="{{ _itemLabelPlural() | async }}"
|
|
1324
1372
|
[entityCrudComponentBase]="this"
|
|
1325
1373
|
[clientViewTemplate]="createEditFormTemplate()"
|
|
1326
1374
|
></sp-create-edit-entity-host>
|