@rosoftlab/core 1.0.4-alpha-14 → 1.0.5-alpha-2

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.
@@ -1,16 +1,16 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, InjectionToken, inject, Input, Component, Inject, Pipe, NgModule } from '@angular/core';
2
+ import { Injectable, InjectionToken, inject, Input, Component, HostBinding, Directive, Inject, Pipe, NgModule } from '@angular/core';
3
3
  import * as i1 from 'oidc-client-ts';
4
4
  import { UserManager } from 'oidc-client-ts';
5
5
  import { BehaviorSubject, Observable, throwError, of, ReplaySubject } from 'rxjs';
6
6
  import * as i5 from '@angular/common';
7
- import { DatePipe, DecimalPipe, PercentPipe, CommonModule } from '@angular/common';
7
+ import { Location, DatePipe, DecimalPipe, PercentPipe, CommonModule } from '@angular/common';
8
8
  import * as i1$2 from '@angular/forms';
9
- import { UntypedFormGroup, UntypedFormControl, Validators, ReactiveFormsModule } from '@angular/forms';
9
+ import { FormGroup, FormControl, UntypedFormGroup, UntypedFormControl, Validators, ReactiveFormsModule } from '@angular/forms';
10
10
  import * as i2 from '@angular/router';
11
- import { NavigationEnd } from '@angular/router';
11
+ import { Router, ActivatedRoute, UrlSegment, NavigationEnd } from '@angular/router';
12
12
  import * as i1$3 from '@ngx-translate/core';
13
- import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
13
+ import { TranslateService, TranslateModule, TranslateLoader } from '@ngx-translate/core';
14
14
  import * as i1$1 from '@angular/common/http';
15
15
  import { HttpHeaders, HttpParams, HttpResponse, HttpClient, HttpClientModule } from '@angular/common/http';
16
16
  import { compare } from 'fast-json-patch';
@@ -156,6 +156,143 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImpor
156
156
  args: [{ selector: 'rsl-under-construction', standalone: false, template: "<div class=\"forms-view-container\">\n <div class=\"under-construction-view-container\">\n Page under construction\n </div>\n</div>", styles: [".under-construction-view-container{height:calc(100vh - 250px);margin:60px 0 0;padding:0;display:flex;justify-content:center;align-items:center;box-sizing:border-box;font-size:1.8em;line-height:1.3em;font-weight:300;color:#58585b;text-align:center}\n"] }]
157
157
  }], ctorParameters: () => [] });
158
158
 
159
+ // projects/rosoftlab/core/src/lib/interfaces/dialog.interface.ts
160
+ const DIALOG_SERVICE_TOKEN = new InjectionToken('DIALOG_SERVICE_TOKEN');
161
+
162
+ const MODEL_SERVICE = new InjectionToken('MODEL_SERVICE');
163
+ const MODEL_TOKEN = new InjectionToken('MODEL_TOKEN');
164
+ // This token will store a map of string keys to Component Classes
165
+ const TABLE_IMPLEMENTATIONS_TOKEN = new InjectionToken('TABLE_IMPLEMENTATIONS_TOKEN');
166
+ const CRUD_IMPLEMENTATIONS_TOKEN = new InjectionToken('CRUD_IMPLEMENTATIONS_TOKEN');
167
+
168
+ class BaseCrudImplementation {
169
+ constructor() {
170
+ // Access the Router without a constructor
171
+ this.router = inject(Router);
172
+ this.route = inject(ActivatedRoute);
173
+ this.translate = inject(TranslateService);
174
+ this.location = inject(Location);
175
+ // Common Dependency Injection
176
+ this.modelService = inject(MODEL_SERVICE, { optional: true });
177
+ this.modelToken = inject(MODEL_TOKEN, { optional: true });
178
+ this.dialogService = inject(DIALOG_SERVICE_TOKEN, { optional: true });
179
+ this.model = null;
180
+ this.modelName = null;
181
+ this.dictPath = null; //rdict
182
+ this.fileLayout = ''; //rdict
183
+ this.idProperty = 'id';
184
+ this.customInclude = null;
185
+ this.changeUrlRoute = true;
186
+ this.hostClass = '';
187
+ this.basePath = '';
188
+ this.title = '';
189
+ this.baseForm = new FormGroup({});
190
+ this.isLoading = true;
191
+ }
192
+ ngOnInit() { }
193
+ get hostClasses() {
194
+ return this.hostClass;
195
+ }
196
+ afterSave(model) {
197
+ return new Observable((observer) => {
198
+ observer.next(model);
199
+ observer.complete();
200
+ });
201
+ }
202
+ beforeSave(model) {
203
+ return new Observable((observer) => {
204
+ observer.next(model);
205
+ observer.complete();
206
+ });
207
+ }
208
+ getFromGroup(formGroup = null) {
209
+ if (!formGroup)
210
+ return this.baseForm;
211
+ if (formGroup instanceof FormGroup)
212
+ return formGroup;
213
+ return this.baseForm.controls[formGroup];
214
+ }
215
+ validateAllFormFields(formGroup = null) {
216
+ const fg = this.getFromGroup(formGroup);
217
+ Object.keys(fg.controls).forEach((field) => {
218
+ // console.log(field);
219
+ const control = fg.get(field);
220
+ if (control instanceof FormControl) {
221
+ control.markAsTouched({ onlySelf: true });
222
+ }
223
+ else if (control instanceof FormGroup) {
224
+ this.validateAllFormFields(control);
225
+ }
226
+ });
227
+ }
228
+ canDeactivate() {
229
+ // Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged
230
+ if (!this.baseForm.dirty) {
231
+ return true;
232
+ }
233
+ // Otherwise ask the user with the dialog service and return its
234
+ // observable which resolves to true or false when the user decides
235
+ return this.dialogService.confirm(this.translate.instant('General.DiscardChanges'), null, 'Discard');
236
+ }
237
+ getFiledName(filedTranslationKey) {
238
+ return { field: this.translate.instant(filedTranslationKey) };
239
+ }
240
+ serverErrors(err) {
241
+ if (err.error) {
242
+ if (err.error.errors) {
243
+ const validationErrors = err.error.errors;
244
+ if (Array.isArray(validationErrors)) {
245
+ validationErrors.forEach((prop) => {
246
+ const formControl = this.baseForm.get(prop);
247
+ if (formControl) {
248
+ // activate the error message
249
+ formControl.setErrors({
250
+ serverError: validationErrors[prop].join('\n')
251
+ });
252
+ }
253
+ });
254
+ }
255
+ else {
256
+ const keys = Object.keys(validationErrors);
257
+ keys.forEach((prop) => {
258
+ const formControl = this.baseForm.get(prop);
259
+ if (formControl) {
260
+ // activate the error message
261
+ formControl.setErrors({
262
+ serverError: validationErrors[prop].join('\n')
263
+ });
264
+ }
265
+ });
266
+ }
267
+ }
268
+ }
269
+ }
270
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: BaseCrudImplementation, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
271
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.8", type: BaseCrudImplementation, isStandalone: true, inputs: { model: "model", modelName: "modelName", dictPath: "dictPath", fileLayout: "fileLayout", idProperty: "idProperty", customInclude: "customInclude", changeUrlRoute: "changeUrlRoute", hostClass: "hostClass" }, host: { properties: { "class": "this.hostClasses" } }, ngImport: i0 }); }
272
+ }
273
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: BaseCrudImplementation, decorators: [{
274
+ type: Directive
275
+ }], propDecorators: { model: [{
276
+ type: Input
277
+ }], modelName: [{
278
+ type: Input
279
+ }], dictPath: [{
280
+ type: Input
281
+ }], fileLayout: [{
282
+ type: Input
283
+ }], idProperty: [{
284
+ type: Input
285
+ }], customInclude: [{
286
+ type: Input
287
+ }], changeUrlRoute: [{
288
+ type: Input
289
+ }], hostClass: [{
290
+ type: Input
291
+ }], hostClasses: [{
292
+ type: HostBinding,
293
+ args: ['class']
294
+ }] } });
295
+
159
296
  class BaseQueryData {
160
297
  constructor(jsonApiModels, metaData) {
161
298
  this.jsonApiModels = jsonApiModels;
@@ -877,6 +1014,145 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImpor
877
1014
  args: [DialogSERVICE]
878
1015
  }] }, { type: i1$3.TranslateService }, { type: i5.Location }] });
879
1016
 
1017
+ class BaseTableImplementation {
1018
+ constructor() {
1019
+ // Access the Router without a constructor
1020
+ this.router = inject(Router);
1021
+ this.translate = inject(TranslateService);
1022
+ // Common Dependency Injection
1023
+ this.dataService = inject(MODEL_SERVICE, { optional: true });
1024
+ this.modelToken = inject(MODEL_TOKEN, { optional: true });
1025
+ this.dialogService = inject(DIALOG_SERVICE_TOKEN, { optional: true });
1026
+ this.basePath = '';
1027
+ this.title = '';
1028
+ // --- Configuration Inputs (Your previous snapshot keys) ---
1029
+ this.model = null;
1030
+ this.dictPath = null; //rdict
1031
+ this.fileLayout = ''; //rdict
1032
+ this.idProperty = 'id';
1033
+ // Visibility & UI
1034
+ this.showHeader = true;
1035
+ this.showSearch = false;
1036
+ this.searchFields = null;
1037
+ // Data & Pagination
1038
+ this.pageable = false;
1039
+ this.pageSizes = [10, 20, 30, 50, 100];
1040
+ this.defaultSort = null;
1041
+ this.defaultSortDirection = null;
1042
+ this.defaultFilter = null;
1043
+ this.customInclude = null;
1044
+ // Actions & Rules
1045
+ this.hasAdd = true;
1046
+ this.canDelete = true;
1047
+ this.canEdit = true;
1048
+ this.deletePropertyName = 'name';
1049
+ // Edit Behavior
1050
+ this.editOnClick = false;
1051
+ this.editOnDblClick = false;
1052
+ this.editColumn = null;
1053
+ this.useView = false; //rdict
1054
+ this.hostClass = '';
1055
+ }
1056
+ ngOnInit() {
1057
+ const urlTree = this.router.url.split('?')[0];
1058
+ const currentUrlSegments = urlTree
1059
+ .split('/')
1060
+ .filter((segment) => segment !== '')
1061
+ .map((segment) => new UrlSegment(segment, {}));
1062
+ this.basePath = currentUrlSegments.map((segment) => segment.path).join('/');
1063
+ }
1064
+ get hostClasses() {
1065
+ return this.hostClass;
1066
+ }
1067
+ addHandler() {
1068
+ this.router.navigate([`${this.basePath}/add`]);
1069
+ }
1070
+ edit(dataItem, column) {
1071
+ // 1. Resolve the dynamic ID value from the object
1072
+ const idValue = dataItem[this.idProperty];
1073
+ if (idValue) {
1074
+ // 2. Navigate using the resolved value
1075
+ this.router.navigate([`${this.basePath}/edit/${idValue}`]);
1076
+ }
1077
+ else {
1078
+ console.warn(`Property "${this.idProperty}" not found on data item:`, dataItem);
1079
+ }
1080
+ }
1081
+ /**
1082
+ * Shared delete logic that can be called by any implementation
1083
+ */
1084
+ delete(dataItem) {
1085
+ const idValue = Reflect.get(dataItem, this.idProperty);
1086
+ const modelName = Reflect.get(dataItem, this.deletePropertyName);
1087
+ const message = this.translate.instant('Are you sure you want to delete this {{modelName}}?', { modelName });
1088
+ if (this.dialogService) {
1089
+ // Use the generic confirm method
1090
+ this.dialogService.confirmDelete().subscribe((confirmed) => {
1091
+ if (confirmed)
1092
+ this.performDelete(idValue);
1093
+ });
1094
+ }
1095
+ else if (confirm(message)) {
1096
+ // Fallback to browser confirm if no service is provided
1097
+ this.performDelete(idValue);
1098
+ }
1099
+ }
1100
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: BaseTableImplementation, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1101
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.8", type: BaseTableImplementation, isStandalone: true, inputs: { model: "model", dictPath: "dictPath", fileLayout: "fileLayout", idProperty: "idProperty", showHeader: "showHeader", showSearch: "showSearch", searchFields: "searchFields", pageable: "pageable", pageSizes: "pageSizes", defaultSort: "defaultSort", defaultSortDirection: "defaultSortDirection", defaultFilter: "defaultFilter", customInclude: "customInclude", hasAdd: "hasAdd", canDelete: "canDelete", canEdit: "canEdit", deletePropertyName: "deletePropertyName", deleteDisableRule: "deleteDisableRule", editOnClick: "editOnClick", editOnDblClick: "editOnDblClick", editColumn: "editColumn", useView: "useView", hostClass: "hostClass" }, host: { properties: { "class": "this.hostClasses" } }, ngImport: i0 }); }
1102
+ }
1103
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: BaseTableImplementation, decorators: [{
1104
+ type: Directive
1105
+ }], propDecorators: { model: [{
1106
+ type: Input
1107
+ }], dictPath: [{
1108
+ type: Input
1109
+ }], fileLayout: [{
1110
+ type: Input
1111
+ }], idProperty: [{
1112
+ type: Input
1113
+ }], showHeader: [{
1114
+ type: Input
1115
+ }], showSearch: [{
1116
+ type: Input
1117
+ }], searchFields: [{
1118
+ type: Input
1119
+ }], pageable: [{
1120
+ type: Input
1121
+ }], pageSizes: [{
1122
+ type: Input
1123
+ }], defaultSort: [{
1124
+ type: Input
1125
+ }], defaultSortDirection: [{
1126
+ type: Input
1127
+ }], defaultFilter: [{
1128
+ type: Input
1129
+ }], customInclude: [{
1130
+ type: Input
1131
+ }], hasAdd: [{
1132
+ type: Input
1133
+ }], canDelete: [{
1134
+ type: Input
1135
+ }], canEdit: [{
1136
+ type: Input
1137
+ }], deletePropertyName: [{
1138
+ type: Input
1139
+ }], deleteDisableRule: [{
1140
+ type: Input
1141
+ }], editOnClick: [{
1142
+ type: Input
1143
+ }], editOnDblClick: [{
1144
+ type: Input
1145
+ }], editColumn: [{
1146
+ type: Input
1147
+ }], useView: [{
1148
+ type: Input
1149
+ }], hostClass: [{
1150
+ type: Input
1151
+ }], hostClasses: [{
1152
+ type: HostBinding,
1153
+ args: ['class']
1154
+ }] } });
1155
+
880
1156
  class Configurations {
881
1157
  constructor() {
882
1158
  this.baseUrl = '';
@@ -1183,7 +1459,7 @@ class BaseModel {
1183
1459
  const controlsConfig = {};
1184
1460
  const that = this;
1185
1461
  if (props) {
1186
- props.forEach(property => {
1462
+ props.forEach((property) => {
1187
1463
  const value = that[property] !== undefined ? that[property] : defaultValues[property];
1188
1464
  const formSubGroup = formSubGroupsValues[property] ?? null;
1189
1465
  if (requiredProps[property]) {
@@ -1208,27 +1484,32 @@ class BaseModel {
1208
1484
  return controlsConfig[subGroup];
1209
1485
  }
1210
1486
  getModelFromFormGroup(formGroup, id) {
1211
- const props = Object.keys(this.getModelPropertyNames(this));
1212
- const formSubGroupsValues = this.getModelSubGroupPropertyNames(this);
1213
- const data = {};
1214
- if (id) {
1215
- data.id = id;
1216
- }
1217
- const that = this;
1218
- if (props) {
1219
- props.forEach(property => {
1220
- const formSubGroup = formSubGroupsValues[property] ?? null;
1221
- if (!formSubGroup)
1222
- data[property] = formGroup.controls[property].value ?? null;
1223
- else
1224
- data[property] = formGroup.controls[formSubGroup].controls[property].value ?? null;
1225
- });
1226
- }
1227
- if (data) {
1487
+ try {
1488
+ const props = Object.keys(this.getModelPropertyNames(this));
1489
+ const formSubGroupsValues = this.getModelSubGroupPropertyNames(this);
1490
+ const data = {};
1228
1491
  if (id) {
1229
- this.id = id;
1492
+ data.id = id;
1493
+ }
1494
+ const that = this;
1495
+ if (props) {
1496
+ props.forEach((property) => {
1497
+ const formSubGroup = formSubGroupsValues[property] ?? null;
1498
+ if (!formSubGroup)
1499
+ data[property] = formGroup.controls[property].value ?? null;
1500
+ else
1501
+ data[property] = formGroup.controls[formSubGroup].controls[property].value ?? null;
1502
+ });
1503
+ }
1504
+ if (data) {
1505
+ if (id) {
1506
+ this.id = id;
1507
+ }
1508
+ Object.assign(this, data);
1230
1509
  }
1231
- Object.assign(this, data);
1510
+ }
1511
+ catch (error) {
1512
+ Object.assign(this, formGroup.value);
1232
1513
  }
1233
1514
  }
1234
1515
  getSerializedModel() {
@@ -1481,7 +1762,7 @@ __decorate([
1481
1762
  Right = __decorate([
1482
1763
  BaseModelConfig({
1483
1764
  type: 'right',
1484
- modelEndpointUrl: 'user/rights'
1765
+ modelEndpointUrl: 'right'
1485
1766
  })
1486
1767
  ], Right);
1487
1768
 
@@ -1495,6 +1776,10 @@ __decorate([
1495
1776
  Attribute({ serializedName: 'name' }),
1496
1777
  __metadata("design:type", String)
1497
1778
  ], Role.prototype, "name", void 0);
1779
+ __decorate([
1780
+ Attribute({ serializedName: 'roleDetail' }),
1781
+ __metadata("design:type", Object)
1782
+ ], Role.prototype, "roleDetail", void 0);
1498
1783
  Role = __decorate([
1499
1784
  BaseModelConfig({
1500
1785
  type: 'role'
@@ -1576,6 +1861,10 @@ class RoleService extends BaseService {
1576
1861
  super(datastore);
1577
1862
  this.setModelType(Role);
1578
1863
  }
1864
+ getRoleRights(roleId) {
1865
+ const url = `${this.datastore.buildUrl(Role)}/${roleId}/rights`;
1866
+ return this.getCustom(null, null, url);
1867
+ }
1579
1868
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: RoleService, deps: [{ token: DatastoreCore }], target: i0.ɵɵFactoryTarget.Injectable }); }
1580
1869
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: RoleService, providedIn: 'root' }); }
1581
1870
  }
@@ -1651,12 +1940,13 @@ class UserService extends BaseService {
1651
1940
  this.setModelType(User);
1652
1941
  }
1653
1942
  getRights() {
1654
- const response = this.datastore.findAll(Right);
1943
+ const url = `${this.datastore.buildUrl(User)}/rights`;
1944
+ const response = this.datastore.findAll(Right, null, null, url);
1655
1945
  return response;
1656
1946
  }
1657
1947
  hasRightForLink(link) {
1658
1948
  if (this.userRights && link) {
1659
- const right = this.userRights.find(f => link.indexOf(f.pagePath) >= 0);
1949
+ const right = this.userRights.find((f) => link.indexOf(f.pagePath) >= 0);
1660
1950
  return true;
1661
1951
  }
1662
1952
  return false;
@@ -1796,6 +2086,21 @@ class CustomValidators {
1796
2086
  }
1797
2087
  }
1798
2088
 
2089
+ class RightService extends BaseService {
2090
+ constructor(datastore) {
2091
+ super(datastore);
2092
+ this.setModelType(Right);
2093
+ }
2094
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: RightService, deps: [{ token: DatastoreCore }], target: i0.ɵɵFactoryTarget.Injectable }); }
2095
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: RightService, providedIn: 'root' }); }
2096
+ }
2097
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: RightService, decorators: [{
2098
+ type: Injectable,
2099
+ args: [{
2100
+ providedIn: 'root'
2101
+ }]
2102
+ }], ctorParameters: () => [{ type: DatastoreCore }] });
2103
+
1799
2104
  function readFileAsync(file) {
1800
2105
  return new Promise((resolve, reject) => {
1801
2106
  const reader = new FileReader();
@@ -1831,5 +2136,5 @@ function getValueFromJsonData(jsonData, key) {
1831
2136
  * Generated bundle index. Do not edit.
1832
2137
  */
1833
2138
 
1834
- export { Attribute, AuthService, BaseDatastore, BaseDatastoreConfig, BaseFormEditComponent, BaseMetaModel, BaseModel, BaseModelConfig, BaseQueryData, BaseService, CacheInterceptor, CacheService, CellTextAlign, Configurations, CustomType, CustomValidators, DatastoreCore, DynamicallyModelResolver, DynamicallyServiceResolver, Employee, EmployeeService, ErrorResponse, FieldErrorDisplayComponent, GridLayoutFormat, InputErrorPipe, LocalFileService, Menu, MetadataStorage, Nl2brPipe, OIDC_CLIENT_SETTINGS, PROVIDERS, PageNotFoundComponent, Right, Role, RoleService, RouteHistoryService, RslBaseModule, Rule, Tokens, TranslateloaderService, UnderConstructionComponent, User, UserService, getValueFromJsonData, provideAuth, provideOidcUserManager, readFileAsync };
2139
+ export { Attribute, AuthService, BaseCrudImplementation, BaseDatastore, BaseDatastoreConfig, BaseFormEditComponent, BaseMetaModel, BaseModel, BaseModelConfig, BaseQueryData, BaseService, BaseTableImplementation, CRUD_IMPLEMENTATIONS_TOKEN, CacheInterceptor, CacheService, CellTextAlign, Configurations, CustomType, CustomValidators, DIALOG_SERVICE_TOKEN, DatastoreCore, DynamicallyModelResolver, DynamicallyServiceResolver, Employee, EmployeeService, ErrorResponse, FieldErrorDisplayComponent, GridLayoutFormat, InputErrorPipe, LocalFileService, MODEL_SERVICE, MODEL_TOKEN, Menu, MetadataStorage, Nl2brPipe, OIDC_CLIENT_SETTINGS, PROVIDERS, PageNotFoundComponent, Right, RightService, Role, RoleService, RouteHistoryService, RslBaseModule, Rule, TABLE_IMPLEMENTATIONS_TOKEN, Tokens, TranslateloaderService, UnderConstructionComponent, User, UserService, getValueFromJsonData, provideAuth, provideOidcUserManager, readFileAsync };
1835
2140
  //# sourceMappingURL=rosoftlab-core.mjs.map