@rosoftlab/rdict 1.0.1-alpha-9 → 1.0.1-alpha-10

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,4 +1,4 @@
1
- import * as i4$1 from '@angular/common';
1
+ import * as i6$2 from '@angular/common';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
4
  import { Injectable, Inject, Component, NgModule, forwardRef, ViewChild, Input, EventEmitter, ElementRef, ViewEncapsulation, Output, InjectionToken } from '@angular/core';
@@ -11,24 +11,27 @@ import { ButtonsModule, KENDO_BUTTONS } from '@progress/kendo-angular-buttons';
11
11
  import { KENDO_SVGICON } from '@progress/kendo-angular-icons';
12
12
  import * as i6 from '@progress/kendo-angular-layout';
13
13
  import { LayoutModule } from '@progress/kendo-angular-layout';
14
- import * as i6$1 from '@progress/kendo-angular-toolbar';
14
+ import * as i8 from '@progress/kendo-angular-toolbar';
15
15
  import { ToolBarModule, KENDO_TOOLBAR, ToolBarToolComponent } from '@progress/kendo-angular-toolbar';
16
16
  import * as allIcons from '@progress/kendo-svg-icons';
17
17
  import { menuIcon, saveIcon, pencilIcon, trashIcon, plusIcon } from '@progress/kendo-svg-icons';
18
- import { BehaviorSubject, from, map } from 'rxjs';
18
+ import { Subject, from, mergeMap, map, Observable } from 'rxjs';
19
19
  import { v4 } from 'uuid';
20
20
  import { io } from 'socket.io-client';
21
- import * as msgpackParser from 'socket.io-msgpack-parser';
22
21
  import * as i1 from '@rosoftlab/core';
23
22
  import { BaseModel, Attribute, BaseModelConfig, BaseService } from '@rosoftlab/core';
24
23
  import { __decorate, __metadata } from 'tslib';
25
- import * as i5$1 from '@angular/forms';
24
+ import * as i7 from '@angular/forms';
26
25
  import { FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms';
27
- import * as i4 from '@ngx-formly/core';
26
+ import * as i6$1 from '@ngx-formly/core';
28
27
  import { FORMLY_CONFIG, FormlyModule } from '@ngx-formly/core';
29
28
  import { FormlyKendoModule } from '@ngx-formly/kendo';
30
- import * as i5$2 from '@progress/kendo-angular-grid';
29
+ import * as i2$1 from '@progress/kendo-angular-dialog';
30
+ import { DialogCloseResult, KENDO_DIALOG } from '@progress/kendo-angular-dialog';
31
+ import * as i3 from '@progress/kendo-angular-notification';
32
+ import * as i7$1 from '@progress/kendo-angular-grid';
31
33
  import { KENDO_GRID } from '@progress/kendo-angular-grid';
34
+ import * as i1$2 from '@progress/kendo-angular-label';
32
35
  import { KENDO_LABEL } from '@progress/kendo-angular-label';
33
36
 
34
37
  class SocketService {
@@ -48,14 +51,27 @@ class SocketService {
48
51
  if (this.socket == null && authToken !== null) {
49
52
  this.socket = io(this.socketUrl, {
50
53
  withCredentials: true,
51
- parser: msgpackParser,
54
+ // parser: msgpackParser,
52
55
  auth: {
53
56
  token: authToken, // Include the authentication token
54
- },
55
- query: {
56
- "access_token": authToken
57
57
  }
58
+ // ,
59
+ // query: {
60
+ // "access_token": authToken
61
+ // }
58
62
  });
63
+ // const originalEmit = this.socket.emit;
64
+ // this.socket.emit = (event, ...args) => {
65
+ // // Transform dates before sending
66
+ // const transformedData = this.transformDatesForEncoding(args[0]);
67
+ // originalEmit.call(this.socket, event, transformedData);
68
+ // return this.socket;
69
+ // };
70
+ // Intercept incoming data and apply date transformation
71
+ // this.socket.onAny((event, data) => {
72
+ // const transformedData = this.transformDatesForDecoding(data);
73
+ // this.socket.emit(event, transformedData); // Emit the transformed data back
74
+ // });
59
75
  }
60
76
  }
61
77
  getInitialData() {
@@ -79,6 +95,15 @@ class SocketService {
79
95
  }
80
96
  });
81
97
  }
98
+ getDeleteEvent(rdict) {
99
+ this.socket.on('delete', (data) => {
100
+ // (rdict.get('__guid'), data, this.socket.id)
101
+ if (rdict.get('__guid') === data.did) {
102
+ // ('Set the data')
103
+ rdict.asyncDelete(data.key, false);
104
+ }
105
+ });
106
+ }
82
107
  // Emit the 'lazy_load' event with callback to get the response
83
108
  requestLazyLoad(did, key) {
84
109
  return new Promise((resolve, reject) => {
@@ -105,6 +130,46 @@ class SocketService {
105
130
  });
106
131
  });
107
132
  }
133
+ // Emit the 'set' event to update the data on the server
134
+ emitDelete(did, key) {
135
+ return new Promise((resolve, reject) => {
136
+ this.socket.emit('delete', { did, key }, (response) => {
137
+ if (response && response.error) {
138
+ reject(response.error);
139
+ }
140
+ else {
141
+ resolve();
142
+ }
143
+ });
144
+ });
145
+ }
146
+ transformDatesForEncoding(obj) {
147
+ if (obj instanceof Date) {
148
+ return { __date__: obj.toISOString() };
149
+ }
150
+ else if (Array.isArray(obj)) {
151
+ return obj.map(this.transformDatesForEncoding);
152
+ }
153
+ else if (obj !== null && typeof obj === "object") {
154
+ return Object.keys(obj).reduce((acc, key) => {
155
+ acc[key] = this.transformDatesForEncoding(obj[key]);
156
+ return acc;
157
+ }, {});
158
+ }
159
+ return obj;
160
+ }
161
+ transformDatesForDecoding(obj) {
162
+ if (typeof obj === "object" && obj !== null) {
163
+ if ("__date__" in obj) {
164
+ return new Date(obj.__date__);
165
+ }
166
+ return Object.keys(obj).reduce((acc, key) => {
167
+ acc[key] = this.transformDatesForDecoding(obj[key]);
168
+ return acc;
169
+ }, {});
170
+ }
171
+ return obj;
172
+ }
108
173
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: SocketService, deps: [{ token: SOCKET_URL }], target: i0.ɵɵFactoryTarget.Injectable }); }
109
174
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: SocketService, providedIn: 'root' }); }
110
175
  }
@@ -118,11 +183,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImpor
118
183
  args: [SOCKET_URL]
119
184
  }] }] });
120
185
 
186
+ // import { mergeMap } from 'rxjs/operators';
121
187
  class ReactiveDictionary extends Map {
122
- static { this.instance = new Map; }
188
+ static { this.instance = new Map(); }
123
189
  constructor(socketService) {
124
190
  super();
125
- this.changes$ = new BehaviorSubject(null);
191
+ this.changes$ = new Subject();
192
+ this.deletes$ = new Subject();
126
193
  this.isInitialized = false;
127
194
  this._authToken = null;
128
195
  this._socketService = socketService;
@@ -130,26 +197,12 @@ class ReactiveDictionary extends Map {
130
197
  // this._socketService.getSetEvent(this)
131
198
  }
132
199
  async initialize(authToken) {
133
- this._authToken = authToken;
134
200
  this._authToken = authToken;
135
201
  this._socketService.initSocket(authToken);
136
202
  this._socketService.getSetEvent(this);
203
+ this._socketService.getDeleteEvent(this);
137
204
  await this.asyncInit();
138
205
  }
139
- // // Method to get the singleton instance
140
- // public static getInstance(socketService: SocketService, authToken: string, instance_key?: string): ReactiveDictionary {
141
- // if (!instance_key)
142
- // instance_key = 'root'
143
- // if (!ReactiveDictionary.instance.has(instance_key)) {
144
- // ReactiveDictionary.instance.set(instance_key, new ReactiveDictionary(socketService, authToken));
145
- // }
146
- // const instance = ReactiveDictionary.instance.get(instance_key);
147
- // if (!instance) {
148
- // throw new Error(`No instance found for key: ${instance_key}`); // Handle undefined case
149
- // }
150
- // return instance; // Now TypeScript knows 'instance' is not undefined
151
- // }
152
- // str_keys(): string[] {
153
206
  keys() {
154
207
  const excludedKeys = ['__guid', '__type']; // Key to exclude
155
208
  const iterator = super.keys();
@@ -170,8 +223,8 @@ class ReactiveDictionary extends Map {
170
223
  return { value: key, done: false }; // Return the valid key
171
224
  }
172
225
  } while (true); // Continue until a valid key is found
173
- }
174
- })
226
+ },
227
+ }),
175
228
  };
176
229
  return filteredIterator;
177
230
  }
@@ -213,7 +266,7 @@ class ReactiveDictionary extends Map {
213
266
  }
214
267
  }
215
268
  else {
216
- const obj = await this.asyncGet(keys[0]);
269
+ const obj = (await this.asyncGet(keys[0]));
217
270
  if (obj)
218
271
  return await obj.asyncGet(keys.slice(1).join('.'));
219
272
  else
@@ -224,9 +277,9 @@ class ReactiveDictionary extends Map {
224
277
  // Transform a value to a format that can be serialized.
225
278
  const dict_type = value['__type'];
226
279
  if (dict_type === 'lazy')
227
- return { "__type": "lazy" };
280
+ return { __type: 'lazy' };
228
281
  else if (value instanceof ReactiveDictionary)
229
- return { "__type": "dict", "__guid": value.get('__guid') };
282
+ return { __type: 'dict', __guid: value.get('__guid') };
230
283
  else
231
284
  return value;
232
285
  }
@@ -243,12 +296,29 @@ class ReactiveDictionary extends Map {
243
296
  this.set(key, value);
244
297
  this.changes$.next({ key, value });
245
298
  }
299
+ async asyncDelete(key, emmit_event = true) {
300
+ if (this.has(key)) {
301
+ if (emmit_event) {
302
+ try {
303
+ await this._socketService.emitDelete(this.get('__guid'), key);
304
+ }
305
+ catch (error) {
306
+ console.error('Error emitting set event:', error);
307
+ }
308
+ }
309
+ this.delete(key);
310
+ this.deletes$.next({ key });
311
+ }
312
+ }
313
+ deleteAsObservable(key, emmit_event = true) {
314
+ return from(this.asyncDelete(key, emmit_event));
315
+ }
246
316
  // Asynchronous method to initialize with a set of key-value pairs
247
317
  async asyncInit(initialData) {
248
318
  if (!this.isInitialized) {
249
319
  try {
250
320
  // If initial data is not provided, fetch it
251
- const data = initialData || await this._socketService.getInitialData();
321
+ const data = initialData || (await this._socketService.getInitialData());
252
322
  // this.known_dicts.set(data.__guid,data);
253
323
  // Set the initial properties on the proxy
254
324
  for (const [key, value] of Object.entries(data)) {
@@ -274,98 +344,166 @@ class ReactiveDictionary extends Map {
274
344
  getPlainObject() {
275
345
  const plainObject = {};
276
346
  this.forEach((value, key) => {
277
- if (value instanceof ReactiveDictionary)
347
+ if (value instanceof ReactiveDictionary) {
278
348
  plainObject[key] = value.getPlainObject();
279
- else
280
- plainObject[key] = value; // Add key-value pairs to the plain object
349
+ }
350
+ else if (typeof value === 'string') {
351
+ const formattedValue = value
352
+ .replace(/'/g, '"') // Convert single quotes to double quotes
353
+ .replace(/\bNone\b/g, 'null') // Replace None with null
354
+ .replace(/\bFalse\b/g, 'false') // Replace False with false
355
+ .replace(/\bTrue\b/g, 'true'); // Replace True with true
356
+ try {
357
+ const parsedValue = JSON.parse(formattedValue, this.jsonDateReviver);
358
+ plainObject[key] = parsedValue;
359
+ }
360
+ catch {
361
+ plainObject[key] = value; // Keep as string if not valid JSON
362
+ }
363
+ }
364
+ else {
365
+ plainObject[key] = value;
366
+ }
281
367
  });
282
368
  return plainObject; // Return the plain object
283
369
  }
370
+ jsonDateReviver(key, value) {
371
+ // Check if the value is a valid ISO date string
372
+ if (typeof value === 'string' &&
373
+ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(value)) {
374
+ return new Date(value); // Convert to JavaScript Date object
375
+ }
376
+ return value;
377
+ }
284
378
  getAsObservable(key) {
285
379
  return from(this.asyncGet(key));
286
380
  }
287
- // getAsObservable(key: string): Observable<any> {
288
- // return from(this.asyncGet(key)).pipe(
289
- // map(value => ({ data: value, success: true })), // Transform the response
290
- // catchError(error => {
291
- // console.error('Error fetching value:', error);
292
- // throw error; // Rethrow the error so subscribers can handle it
293
- // })
294
- // );
295
- // }
296
- getTableAsObservable(key) {
297
- return from(this.getTable(key)).pipe(map(dictionary => {
298
- // Check if dictionary is an array
381
+ getTableAsObservable(key, data = null) {
382
+ return from(this.getTable(key, data)).pipe(mergeMap((dictionary) => {
299
383
  if (!Array.isArray(dictionary)) {
300
384
  throw new Error('Expected an array but received something else');
301
385
  }
302
- // Check if all elements in the array are instances of ReactiveDictionary
303
- const isArrayOfReactiveDictionaries = dictionary.every(item => item instanceof ReactiveDictionary);
386
+ const isArrayOfReactiveDictionaries = dictionary.every((item) => item instanceof ReactiveDictionary);
304
387
  if (!isArrayOfReactiveDictionaries) {
305
388
  throw new Error('Expected an array of ReactiveDictionary instances but received something else');
306
389
  }
307
- // Convert each ReactiveDictionary to a plain object, filtering out '__guid'
308
- return dictionary.map(dict => {
309
- const filteredObject = {};
310
- for (const [key, value] of dict.entries()) {
311
- if (key !== '__guid') {
312
- filteredObject[key] = value;
313
- }
314
- }
315
- return filteredObject;
316
- });
390
+ // WRAP THIS IN from(...) to make it emit real data, not a Promise
391
+ return from(this.processTableData(dictionary));
317
392
  }));
318
393
  }
319
- async getTable(key) {
320
- const data = await this.asyncGet(key); // Get rooms from the ReactiveDictionary
321
- if (!data) {
394
+ async getTable(key, data = null) {
395
+ if (!data)
396
+ data = await this.asyncGet(key); // Get rooms from the ReactiveDictionary
397
+ if (!data)
322
398
  return []; // Return an empty array if data is undefined
323
- }
399
+ console.log('getTable', data);
324
400
  // Filter and get only entries that are instances of ReactiveDictionary
325
- const result = await Promise.all(Array.from(data.entries()).map(async (key) => await data.asyncGet(key[0])) // Get data from asyncGet
326
- ) || []; // Return an empty array if the above yields undefined
401
+ const result = (await Promise.all(Array.from(data.entries()).map(async (key, index) => {
402
+ const entry = (await data.asyncGet(key[0]));
403
+ if (entry instanceof ReactiveDictionary) {
404
+ entry.set('__idx', key[0]);
405
+ }
406
+ return entry;
407
+ }))) || []; // Return an empty array if the above yields undefined
327
408
  return result.filter((entry) => entry instanceof ReactiveDictionary);
328
409
  }
329
410
  async getTableWithoutGuid(key) {
330
- const data = await this.asyncGet(key); // Get rooms from the ReactiveDictionary
331
- if (!data) {
332
- return []; // Return an empty array if data is undefined
411
+ const data = await this.asyncGet(key);
412
+ if (!data)
413
+ return [];
414
+ // Reuse the common processing logic
415
+ return this.processTableData(data);
416
+ }
417
+ async processTableData(data) {
418
+ if (data instanceof ReactiveDictionary) {
419
+ const result = (await Promise.all(Array.from(data.entries()).map(async ([key]) => {
420
+ const entry = (await data.asyncGet(key));
421
+ if (entry instanceof ReactiveDictionary) {
422
+ entry.set('__idx', key);
423
+ }
424
+ return entry;
425
+ }))) || [];
426
+ return result
427
+ .filter((entry) => entry instanceof ReactiveDictionary)
428
+ .map((dictionary) => {
429
+ const filteredObject = {};
430
+ for (const [key, value] of dictionary.entries()) {
431
+ if (key !== '__guid') {
432
+ filteredObject[key] = value;
433
+ }
434
+ }
435
+ return filteredObject;
436
+ });
333
437
  }
334
- // Filter and get only entries that are instances of ReactiveDictionary
335
- const result = await Promise.all(Array.from(data.entries()).map(async (key) => await data.asyncGet(key[0])) // Get data from asyncGet
336
- ) || []; // Return an empty array if the above yields undefined
337
- var filteredResults = result.filter((entry) => entry instanceof ReactiveDictionary);
338
- return filteredResults.map(dictionary => {
339
- // Convert Map to object and filter out __guid
340
- const filteredObject = {};
341
- for (const [key, value] of dictionary.entries()) {
342
- if (key !== '__guid') {
343
- filteredObject[key] = value;
438
+ else if (Array.isArray(data)) {
439
+ // Directly process array of ReactiveDictionary instances
440
+ return data.map((dictionary) => {
441
+ const filteredObject = {};
442
+ for (const [key, value] of dictionary.entries()) {
443
+ if (key !== '__guid') {
444
+ filteredObject[key] = value;
445
+ }
344
446
  }
345
- }
346
- return filteredObject;
347
- });
447
+ return filteredObject;
448
+ });
449
+ }
450
+ else {
451
+ console.warn('processTableData received unexpected data:', data);
452
+ return [];
453
+ }
348
454
  }
455
+ // async processTableData(data: any): Promise<any[]> {
456
+ // // Filter and get only entries that are instances of ReactiveDictionary
457
+ // const result = await Promise.all(
458
+ // Array.from(data.entries()).map(async ([key]) => {
459
+ // const entry = await data.asyncGet(key) as ReactiveDictionary
460
+ // if (entry instanceof ReactiveDictionary) {
461
+ // entry.set('__idx', key);
462
+ // }
463
+ // return entry;
464
+ // })
465
+ // ) || [];
466
+ // // Filter out entries that are not ReactiveDictionary instances
467
+ // const filteredResults = result.filter((entry: any) => entry instanceof ReactiveDictionary);
468
+ // // Remove __guid from each dictionary and return the plain object
469
+ // return filteredResults.map(dictionary => {
470
+ // const filteredObject: Record<string, any> = {};
471
+ // for (const [key, value] of dictionary.entries()) {
472
+ // if (key !== '__guid') {
473
+ // filteredObject[key] = value;
474
+ // }
475
+ // }
476
+ // return filteredObject;
477
+ // });
478
+ // }
349
479
  onChanges() {
350
480
  return this.changes$.asObservable();
351
481
  }
352
- async addNew(record) {
353
- const nextKey = this.size.toString();
354
- const dict = await this.asyncGet(nextKey);
482
+ onDelete() {
483
+ return this.deletes$.asObservable();
484
+ }
485
+ async update(record, key = null) {
486
+ if (!key)
487
+ key = this.size.toString();
488
+ const dict = await this.asyncGet(key);
355
489
  for (const key in record) {
356
490
  if (record.hasOwnProperty(key)) {
357
- await dict.asyncSet(key, record[key]);
491
+ const currentValue = await dict.asyncGet(key);
492
+ if (currentValue !== record[key])
493
+ await dict.asyncSet(key, record[key]);
358
494
  }
359
495
  }
360
496
  }
497
+ modelFormList(property, value) {
498
+ return this.get('__modelFormList');
499
+ }
361
500
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: ReactiveDictionary, deps: [{ token: SocketService }], target: i0.ɵɵFactoryTarget.Injectable }); }
362
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: ReactiveDictionary, providedIn: 'root' // This makes the service a singleton and available throughout the app
363
- }); }
501
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: ReactiveDictionary, providedIn: 'root' }); }
364
502
  }
365
503
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: ReactiveDictionary, decorators: [{
366
504
  type: Injectable,
367
505
  args: [{
368
- providedIn: 'root' // This makes the service a singleton and available throughout the app
506
+ providedIn: 'root', // This makes the service a singleton and available throughout the app
369
507
  }]
370
508
  }], ctorParameters: () => [{ type: SocketService }] });
371
509
 
@@ -629,6 +767,63 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImpor
629
767
  ], template: "<div class=\"custom-toolbar\">\r\n <button kendoButton [svgIcon]=\"menuSvg\" fillMode=\"flat\" (click)=\"drawer.toggle()\"></button>\r\n <!-- <kendo-toolbar-button icon=\"menu\" themeColor=\"tertiary\" (click)=\"drawer.toggle()\"> </kendo-toolbar-button> -->\r\n <span class=\"app-title\">{{apptitle}}</span>\r\n</div>\r\n<kendo-drawer-container>\r\n <kendo-drawer #drawer [items]=\"items\" mode=\"push\" [mini]=\"true\" [expanded]=\"true\" (select)=\"onSelect($event)\"\r\n [autoCollapse]=\"false\" [isItemExpanded]=\"isItemExpanded\">\r\n <!-- <ng-template kendoDrawerItemTemplate let-item>\r\n <div *ngIf=\"item.path !== ''\" class=\"k-drawer-link\" [routerLink]=\"item.path\">\r\n <kendo-svgicon [icon]=\"item.svgIcon\"></kendo-svgicon>\r\n <span>{{ item.text }}</span>\r\n </div>\r\n <div *ngIf=\"item.path == ''\" class=\"k-drawer-link\" >\r\n <kendo-svgicon [icon]=\"item.svgIcon\"></kendo-svgicon>\r\n <span>{{ item.text }}</span>\r\n </div>\r\n </ng-template> -->\r\n </kendo-drawer>\r\n\r\n <kendo-drawer-content>\r\n <router-outlet></router-outlet>\r\n <!-- <div>{{selected}}</div> -->\r\n <!-- <my-content [selectedItem]=\"selected\"></my-content> -->\r\n </kendo-drawer-content>\r\n</kendo-drawer-container>", styles: ["html,body,rdict-full{padding:0;height:100%}rdict-full{display:flex;flex-direction:column}kendo-drawer-container{flex:1 1 auto;overflow-y:auto}.k-icon{font-size:20px}.custom-toolbar{width:100%;background-color:#f6f6f6;line-height:10px;border-bottom:inset;border-bottom-width:1px;color:#656565}.custom-toolbar button{margin:3px 0 3px 8px}.app-title{margin-left:20px;font-weight:700;font-size:17px}\n"] }]
630
768
  }], ctorParameters: () => [{ type: UserService }, { type: i1$1.Router }, { type: i2.TranslateService }, { type: ReactiveDictionary }] });
631
769
 
770
+ class MaterialDialogService {
771
+ constructor(translate, dialogService, notificationService) {
772
+ this.translate = translate;
773
+ this.dialogService = dialogService;
774
+ this.notificationService = notificationService;
775
+ this.state = {
776
+ content: "Your data has been saved.",
777
+ type: { style: "success", icon: true },
778
+ animation: { type: "slide", duration: 400 },
779
+ hideAfter: 3000,
780
+ };
781
+ }
782
+ confirmDelete() {
783
+ return this.confirm(this.translate.instant("Are you sure you want to delete this record ?"), this.translate.instant("Delete Record"), this.translate.instant("General.Yes"), this.translate.instant("General.No"));
784
+ }
785
+ confirm(content, title, confirmButtonText, cancelButtonText) {
786
+ const dialog = this.dialogService.open({
787
+ title: title || "Confirm",
788
+ content: content || "Are you sure?",
789
+ actions: [
790
+ { text: cancelButtonText || "No", result: false },
791
+ { text: confirmButtonText || "Yes", themeColor: "primary", result: true }
792
+ ],
793
+ width: 450,
794
+ height: 200,
795
+ minWidth: 250,
796
+ });
797
+ // Return an Observable<boolean>
798
+ return new Observable((observer) => {
799
+ dialog.result.subscribe((result) => {
800
+ if (result instanceof DialogCloseResult) {
801
+ // Dialog was closed without an action
802
+ observer.next(false);
803
+ }
804
+ else {
805
+ const actionResult = result;
806
+ observer.next(actionResult.result);
807
+ }
808
+ observer.complete(); // Complete the observable
809
+ });
810
+ });
811
+ }
812
+ showSaveMessage(message) {
813
+ this.state.content = message || "Your data has been saved.";
814
+ this.state.type = { style: "success", icon: true };
815
+ this.notificationService.show(this.state);
816
+ }
817
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: MaterialDialogService, deps: [{ token: i2.TranslateService }, { token: i2$1.DialogService }, { token: i3.NotificationService }], target: i0.ɵɵFactoryTarget.Injectable }); }
818
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: MaterialDialogService, providedIn: 'root' }); }
819
+ }
820
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: MaterialDialogService, decorators: [{
821
+ type: Injectable,
822
+ args: [{
823
+ providedIn: 'root'
824
+ }]
825
+ }], ctorParameters: () => [{ type: i2.TranslateService }, { type: i2$1.DialogService }, { type: i3.NotificationService }] });
826
+
632
827
  class TranslateExtension {
633
828
  constructor(translate) {
634
829
  this.translate = translate;
@@ -697,11 +892,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImpor
697
892
  }] });
698
893
 
699
894
  class RdictCrudComponent {
700
- constructor(router, route, translate, rdict) {
895
+ constructor(router, route, translate, rdict, localFileService, dialogService) {
701
896
  this.router = router;
702
897
  this.route = route;
703
898
  this.translate = translate;
704
899
  this.rdict = rdict;
900
+ this.localFileService = localFileService;
901
+ this.dialogService = dialogService;
705
902
  this.baseForm = new FormGroup({});
706
903
  this.model = {};
707
904
  this.options = {};
@@ -709,38 +906,133 @@ class RdictCrudComponent {
709
906
  this.saveIcon = saveIcon;
710
907
  }
711
908
  async ngOnInit() {
909
+ this.setValueFromSnapshot(this, this.route.snapshot, 'fileLayout', '');
712
910
  const currentUrlSegments = this.router.url.split('/').filter(segment => segment !== '' && isNaN(Number(segment)));
713
911
  if (['add', 'edit'].includes(currentUrlSegments[currentUrlSegments.length - 1])) {
714
912
  currentUrlSegments.pop();
715
913
  }
716
914
  this.dictPath = currentUrlSegments.join('.');
717
915
  this.rdictModel = currentUrlSegments.length > 0 ? currentUrlSegments[currentUrlSegments.length - 1] : '';
916
+ const id = this.route.snapshot.paramMap.get('id');
917
+ this.modelKey = id ?? null;
718
918
  this.getModelFields();
919
+ this.getModel();
920
+ }
921
+ setValueFromSnapshot(component, snapshot, key, defaultValue) {
922
+ if (component[key] === undefined) {
923
+ let dataFromSnapshot = snapshot.data[key];
924
+ if (dataFromSnapshot === null || dataFromSnapshot === undefined) {
925
+ dataFromSnapshot = snapshot.params[key];
926
+ }
927
+ component[key] = dataFromSnapshot !== undefined ? dataFromSnapshot : defaultValue;
928
+ }
719
929
  }
720
930
  onSubmit(model) {
721
- this.saveModel(this.baseForm);
931
+ // this.saveModel(this.baseForm)
722
932
  }
723
- getModelFields() {
724
- if (this.rdictModel) {
725
- this.rdict.getAsObservable("config.models." + this.rdictModel + ".formLayout").subscribe({
726
- next: formLayout => {
727
- if (formLayout) {
728
- this.title = this.translate.instant(formLayout["title"]);
729
- this.fields = formLayout["fields"];
730
- }
933
+ getModel() {
934
+ if (this.modelKey) {
935
+ this.rdict.getAsObservable(this.dictPath).subscribe({
936
+ next: value => {
937
+ value.getAsObservable(this.modelKey).subscribe({
938
+ next: modelValue => {
939
+ this.modelRdict = modelValue;
940
+ this.model = this.modelRdict.getPlainObject();
941
+ this.modelRdict.onChanges().subscribe(changes => {
942
+ if (changes) {
943
+ console.log("Changes detected:", changes);
944
+ this.baseForm.get(changes.key).patchValue(changes.value);
945
+ // this.model[changes.key] = changes.value;
946
+ }
947
+ });
948
+ }
949
+ });
731
950
  },
732
951
  error: err => console.error('Error:', err.message),
733
952
  });
734
953
  }
735
954
  }
955
+ getModelFields() {
956
+ if (this.rdictModel) {
957
+ if (this.fileLayout) {
958
+ //load from file
959
+ this.localFileService.getJsonData(this.fileLayout).subscribe({
960
+ next: value => {
961
+ if (value) {
962
+ const layout = value.find(item => item.model === this.rdictModel);
963
+ this.setLayout(layout?.formLayout);
964
+ }
965
+ },
966
+ error: err => console.error('Error:', err.message),
967
+ });
968
+ }
969
+ else
970
+ this.rdict.getAsObservable("config.models." + this.rdictModel + ".formLayout").subscribe({
971
+ next: formLayout => {
972
+ if (formLayout) {
973
+ this.setLayout(formLayout);
974
+ }
975
+ },
976
+ error: err => console.error('Error:', err.message),
977
+ });
978
+ }
979
+ }
980
+ setLayout(formLayout) {
981
+ this.title = this.translate.instant(formLayout["title"]);
982
+ // console.log(formLayout["fields"]);
983
+ let fieldsTmp = formLayout["fields"];
984
+ this.fields = this.transformFields(fieldsTmp);
985
+ // this.transformJsonToFormlyFields()
986
+ }
987
+ // transformJsonToFormlyFields(json: any[]): FormlyFieldConfig[] {
988
+ // // return json.map(field => {
989
+ // // if (field.type === 'select' && field.props.options) {
990
+ // // field.props.options = this.getSelectData(field.props.options);
991
+ // // }
992
+ // // return {
993
+ // // key: field.key,
994
+ // // type: field.type,
995
+ // // props: field.props,
996
+ // // fieldGroup: field?.fieldGroup
997
+ // // };
998
+ // // });
999
+ // }
1000
+ transformFields(fields) {
1001
+ return fields.map(field => this.transformField(field));
1002
+ }
1003
+ transformField(field) {
1004
+ // Handle the current field
1005
+ if (field.type === 'select' && field.props?.options && typeof field.props.options === 'string') {
1006
+ field.props.options = this.getSelectData(field.props.options);
1007
+ }
1008
+ // Recursively handle fieldGroup
1009
+ if (field.fieldGroup) {
1010
+ field.fieldGroup = this.transformFields(field.fieldGroup);
1011
+ }
1012
+ // Recursively handle fieldArray
1013
+ if (field.fieldArray) {
1014
+ if (typeof field.fieldArray === 'function') {
1015
+ const originalFieldArrayFn = field.fieldArray;
1016
+ field.fieldArray = (fieldConfig) => {
1017
+ const transformedField = this.transformField(originalFieldArrayFn(fieldConfig));
1018
+ return transformedField;
1019
+ };
1020
+ }
1021
+ else {
1022
+ field.fieldArray = this.transformField(field.fieldArray);
1023
+ }
1024
+ }
1025
+ return field;
1026
+ }
736
1027
  async onSave() {
737
1028
  await this.saveModel(this.baseForm);
738
1029
  }
739
1030
  async saveModel(fg) {
740
1031
  if (fg.valid) {
741
1032
  var dict = await this.rdict.asyncGet(this.dictPath);
742
- await dict.addNew(fg.value);
743
- console.log(fg.value);
1033
+ await dict.update(fg.value, this.modelKey);
1034
+ this.dialogService.showSaveMessage();
1035
+ // console.log(fg.value);
744
1036
  }
745
1037
  else {
746
1038
  this.validateAllFormFields(fg);
@@ -758,8 +1050,11 @@ class RdictCrudComponent {
758
1050
  }
759
1051
  });
760
1052
  }
761
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: RdictCrudComponent, deps: [{ token: i1$1.Router }, { token: i1$1.ActivatedRoute }, { token: i2.TranslateService }, { token: ReactiveDictionary }], target: i0.ɵɵFactoryTarget.Component }); }
762
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.3", type: RdictCrudComponent, isStandalone: true, selector: "app-rdict-crud", ngImport: i0, template: "<kendo-toolbar>\r\n <kendo-toolbar-spacer></kendo-toolbar-spacer>\r\n <kendo-toolbar-button text=\"Save\" showText=\"both\" [svgIcon]=\"saveIcon\" showIcon=\"both\" themeColor=\"primary\"\r\n [disabled]=\"false\" (click)=\"onSave()\">\r\n </kendo-toolbar-button>\r\n</kendo-toolbar>\r\n<form [formGroup]=\"baseForm\" (ngSubmit)=\"onSubmit(model)\">\r\n\r\n <formly-form [form]=\"baseForm\" [fields]=\"fields\" [model]=\"model\" [options]=\"options\"></formly-form>\r\n</form>", styles: [""], dependencies: [{ kind: "ngmodule", type: FormlyModule }, { kind: "component", type: i4.FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i5$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormlyKendoModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: CrudFormlyTransaltionModule }, { kind: "component", type: i6$1.ToolBarComponent, selector: "kendo-toolbar", inputs: ["overflow", "resizable", "popupSettings", "fillMode", "tabindex", "size", "tabIndex"], outputs: ["open", "close"], exportAs: ["kendoToolBar"] }, { kind: "component", type: i6$1.ToolBarButtonComponent, selector: "kendo-toolbar-button", inputs: ["showText", "showIcon", "text", "style", "className", "title", "disabled", "toggleable", "look", "togglable", "selected", "fillMode", "themeColor", "icon", "iconClass", "svgIcon", "imageUrl"], outputs: ["click", "pointerdown", "selectedChange"], exportAs: ["kendoToolBarButton"] }, { kind: "component", type: i6$1.ToolBarSpacerComponent, selector: "kendo-toolbar-spacer", exportAs: ["kendoToolBarSpacer"] }] }); }
1053
+ getSelectData(key) {
1054
+ return this.rdict.getTableAsObservable(key);
1055
+ }
1056
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: RdictCrudComponent, deps: [{ token: i1$1.Router }, { token: i1$1.ActivatedRoute }, { token: i2.TranslateService }, { token: ReactiveDictionary }, { token: i1.LocalFileService }, { token: MaterialDialogService }], target: i0.ɵɵFactoryTarget.Component }); }
1057
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.3", type: RdictCrudComponent, isStandalone: true, selector: "app-rdict-crud", ngImport: i0, template: "<kendo-toolbar>\r\n <kendo-toolbar-spacer></kendo-toolbar-spacer>\r\n <kendo-toolbar-button text=\"Save\" showText=\"both\" [svgIcon]=\"saveIcon\" showIcon=\"both\" themeColor=\"primary\"\r\n [disabled]=\"false\" (click)=\"onSave()\">\r\n </kendo-toolbar-button>\r\n</kendo-toolbar>\r\n<form [formGroup]=\"baseForm\" (ngSubmit)=\"onSubmit(model)\">\r\n\r\n <formly-form [form]=\"baseForm\" [fields]=\"fields\" [model]=\"model\" [options]=\"options\"></formly-form>\r\n</form>", styles: [""], dependencies: [{ kind: "ngmodule", type: FormlyModule }, { kind: "component", type: i6$1.FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i7.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i7.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormlyKendoModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: CrudFormlyTransaltionModule }, { kind: "component", type: i8.ToolBarComponent, selector: "kendo-toolbar", inputs: ["overflow", "resizable", "popupSettings", "fillMode", "tabindex", "size", "tabIndex"], outputs: ["open", "close"], exportAs: ["kendoToolBar"] }, { kind: "component", type: i8.ToolBarButtonComponent, selector: "kendo-toolbar-button", inputs: ["showText", "showIcon", "text", "style", "className", "title", "disabled", "toggleable", "look", "togglable", "selected", "fillMode", "themeColor", "icon", "iconClass", "svgIcon", "imageUrl"], outputs: ["click", "pointerdown", "selectedChange"], exportAs: ["kendoToolBarButton"] }, { kind: "component", type: i8.ToolBarSpacerComponent, selector: "kendo-toolbar-spacer", exportAs: ["kendoToolBarSpacer"] }] }); }
763
1058
  }
764
1059
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: RdictCrudComponent, decorators: [{
765
1060
  type: Component,
@@ -771,7 +1066,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImpor
771
1066
  CrudFormlyTransaltionModule,
772
1067
  KENDO_TOOLBAR
773
1068
  ], template: "<kendo-toolbar>\r\n <kendo-toolbar-spacer></kendo-toolbar-spacer>\r\n <kendo-toolbar-button text=\"Save\" showText=\"both\" [svgIcon]=\"saveIcon\" showIcon=\"both\" themeColor=\"primary\"\r\n [disabled]=\"false\" (click)=\"onSave()\">\r\n </kendo-toolbar-button>\r\n</kendo-toolbar>\r\n<form [formGroup]=\"baseForm\" (ngSubmit)=\"onSubmit(model)\">\r\n\r\n <formly-form [form]=\"baseForm\" [fields]=\"fields\" [model]=\"model\" [options]=\"options\"></formly-form>\r\n</form>" }]
774
- }], ctorParameters: () => [{ type: i1$1.Router }, { type: i1$1.ActivatedRoute }, { type: i2.TranslateService }, { type: ReactiveDictionary }] });
1069
+ }], ctorParameters: () => [{ type: i1$1.Router }, { type: i1$1.ActivatedRoute }, { type: i2.TranslateService }, { type: ReactiveDictionary }, { type: i1.LocalFileService }, { type: MaterialDialogService }] });
775
1070
 
776
1071
  class RdictTableTitle extends ToolBarToolComponent {
777
1072
  constructor() {
@@ -783,7 +1078,7 @@ class RdictTableTitle extends ToolBarToolComponent {
783
1078
  <ng-template #toolbarTemplate>
784
1079
  <kendo-label>{{text}}</kendo-label>
785
1080
  </ng-template>
786
- `, isInline: true }); }
1081
+ `, isInline: true, dependencies: [{ kind: "component", type: i1$2.LabelComponent, selector: "kendo-label", inputs: ["text", "for", "optional", "labelCssStyle", "labelCssClass"], exportAs: ["kendoLabel"] }] }); }
787
1082
  }
788
1083
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: RdictTableTitle, decorators: [{
789
1084
  type: Component,
@@ -791,6 +1086,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImpor
791
1086
  providers: [{ provide: ToolBarToolComponent, useExisting: forwardRef(() => RdictTableTitle) }],
792
1087
  selector: 'table-title',
793
1088
  standalone: true,
1089
+ imports: [
1090
+ KENDO_LABEL,
1091
+ ],
794
1092
  template: `
795
1093
  <ng-template #toolbarTemplate>
796
1094
  <kendo-label>{{text}}</kendo-label>
@@ -805,26 +1103,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImpor
805
1103
  }] } });
806
1104
 
807
1105
  class GenericRdictTableComponent {
808
- constructor(router, route, translate, injector, el, rdict) {
1106
+ constructor(router, route, translate, injector, localFileService, rdict, dialogService) {
809
1107
  this.router = router;
810
1108
  this.route = route;
811
1109
  this.translate = translate;
812
1110
  this.injector = injector;
813
- this.el = el;
1111
+ this.localFileService = localFileService;
814
1112
  this.rdict = rdict;
815
- this.themeColors = [
816
- "base",
817
- "primary",
818
- "secondary",
819
- "tertiary",
820
- "info",
821
- "success",
822
- "warning",
823
- "error",
824
- "dark",
825
- "light",
826
- "inverse",
827
- ];
1113
+ this.dialogService = dialogService;
828
1114
  this.editOnClick = false;
829
1115
  this.editOnDblClick = false;
830
1116
  this.data = [];
@@ -864,6 +1150,8 @@ class GenericRdictTableComponent {
864
1150
  this.setValueFromSnapshot(this, this.route.snapshot, 'canEdit', true);
865
1151
  this.setValueFromSnapshot(this, this.route.snapshot, 'editOnClick', false);
866
1152
  this.setValueFromSnapshot(this, this.route.snapshot, 'editOnDblClick', false);
1153
+ this.setValueFromSnapshot(this, this.route.snapshot, 'editColumn', null);
1154
+ this.setValueFromSnapshot(this, this.route.snapshot, 'fileLayout', '');
867
1155
  const currentUrlSegments = this.router.url.split('/').map(segment => new UrlSegment(segment, {}));
868
1156
  this.basePath = currentUrlSegments.map(segment => segment.path).join('/');
869
1157
  const filteredSegments = currentUrlSegments.filter(segment => segment.path !== '');
@@ -890,48 +1178,147 @@ class GenericRdictTableComponent {
890
1178
  }
891
1179
  }
892
1180
  async loadData() {
893
- this.rdict.getTableAsObservable(this.dictPath).subscribe({
894
- next: value => {
895
- this.dataSource = value;
1181
+ this.rdict.getAsObservable(this.dictPath).subscribe({
1182
+ next: rdictData => {
1183
+ this.tableRdict = rdictData;
1184
+ this.tableRdict.onChanges().subscribe({
1185
+ next: (changes) => {
1186
+ console.log("Changes detected grid:", changes);
1187
+ this.onChangeEvent(changes);
1188
+ }
1189
+ });
1190
+ this.tableRdict.onDelete().subscribe({
1191
+ next: (changes) => {
1192
+ console.log("Delete detected grid:", changes);
1193
+ this.ondDeleteEvent(changes);
1194
+ }
1195
+ });
1196
+ this.rdict.getTableAsObservable(this.dictPath, this.tableRdict).subscribe({
1197
+ next: value => {
1198
+ this.dataSource = value;
1199
+ },
1200
+ error: err => console.error('Error:', err.message),
1201
+ });
896
1202
  },
897
1203
  error: err => console.error('Error:', err.message),
898
1204
  });
899
1205
  }
1206
+ onChangeEvent(changes) {
1207
+ if (changes) {
1208
+ const key = changes?.key;
1209
+ const value = changes?.value;
1210
+ if (key && value) {
1211
+ const index = this.dataSource.findIndex((item) => item.__idx === key);
1212
+ if (index > -1) {
1213
+ this.dataSource[index] = value;
1214
+ }
1215
+ else {
1216
+ //get the object from rdict
1217
+ this.tableRdict.getAsObservable(key).subscribe({
1218
+ next: value => {
1219
+ var dd = value.getPlainObject();
1220
+ this.dataSource.push(dd);
1221
+ }
1222
+ });
1223
+ }
1224
+ }
1225
+ }
1226
+ }
1227
+ ondDeleteEvent(changes) {
1228
+ if (changes) {
1229
+ const key = changes?.key;
1230
+ if (key) {
1231
+ const index = this.dataSource.findIndex((item) => item.__idx === key);
1232
+ if (index > -1) {
1233
+ this.dataSource.splice(index, 1);
1234
+ }
1235
+ // this.tableRdict.delete(key)
1236
+ }
1237
+ }
1238
+ }
900
1239
  getListLayout() {
901
1240
  if (this.model) {
902
- this.rdict.getAsObservable("config.models." + this.model + ".tableLayout").subscribe({
903
- next: value => {
904
- if (value) {
905
- this.tableLayout = value;
906
- this.title = this.translate.instant(this.tableLayout["title"]);
907
- this.allColumns = this.tableLayout["columns"].map(item => {
908
- if (!item.isTranslated) {
909
- item.name = this.translate.instant(item.translateKey);
910
- item.isTranslated = true;
911
- }
912
- return item;
913
- });
914
- this.columns = [];
915
- this.allColumns.sort((a, b) => a.order - b.order);
916
- this.displayedColumns = [];
917
- this.displayedColumns.push.apply(this.displayedColumns, this.allColumns.map(x => x.propertyName));
1241
+ if (this.fileLayout) {
1242
+ //load from file
1243
+ this.localFileService.getJsonData(this.fileLayout).subscribe({
1244
+ next: value => {
1245
+ if (value) {
1246
+ const layout = value.find(item => item.model === this.model);
1247
+ this.setLayout(layout?.tableLayout);
1248
+ }
1249
+ },
1250
+ error: err => console.error('Error:', err.message),
1251
+ });
1252
+ }
1253
+ else
1254
+ //Use rdict layout
1255
+ this.rdict.getAsObservable("config.models." + this.model + ".tableLayout").subscribe({
1256
+ next: value => {
1257
+ this.setLayout(value);
1258
+ },
1259
+ error: err => console.error('Error:', err.message),
1260
+ });
1261
+ }
1262
+ }
1263
+ setLayout(layout) {
1264
+ if (layout) {
1265
+ this.tableLayout = layout;
1266
+ this.title = this.translate.instant(this.tableLayout["title"]);
1267
+ this.allColumns = this.tableLayout["columns"].map(item => {
1268
+ if (!item.isTranslated) {
1269
+ item.name = this.translate.instant(item.translateKey);
1270
+ item.isTranslated = true;
1271
+ item.isEditLink = false;
1272
+ if (this.editColumn && this.editColumn === item.propertyName) {
1273
+ item.isEditLink = true;
918
1274
  }
919
- },
920
- error: err => console.error('Error:', err.message),
1275
+ }
1276
+ return item;
921
1277
  });
1278
+ this.columns = [];
1279
+ this.allColumns.sort((a, b) => a.order - b.order);
1280
+ this.displayedColumns = [];
1281
+ this.displayedColumns.push.apply(this.displayedColumns, this.allColumns.map(x => x.propertyName));
922
1282
  }
923
1283
  }
924
1284
  addHandler() {
925
- console.log("add");
926
- this.router.navigate([this.basePath + '/add']);
927
- // this.editDataItem = new Product();
928
- // this.isNew = true;
1285
+ this.router.navigate([`${this.basePath}/add`]);
1286
+ }
1287
+ editHandler(args) {
1288
+ this.edit(args.dataItem);
1289
+ // this.editDataItem = args.dataItem;
1290
+ // this.isNew = false;
1291
+ }
1292
+ edit(dataItem) {
1293
+ this.router.navigate([`${this.basePath}/edit/${dataItem.__idx}`]);
1294
+ }
1295
+ removeHandler(args) {
1296
+ this.dialogService.confirmDelete().subscribe({
1297
+ next: (result) => {
1298
+ if (result) {
1299
+ this.tableRdict.deleteAsObservable(args.dataItem.__idx).subscribe({
1300
+ next: (result) => {
1301
+ this.dataSource.splice(args.rowIndex, 1);
1302
+ }
1303
+ });
1304
+ }
1305
+ }
1306
+ });
1307
+ // this.editService.remove(args.dataItem);
1308
+ }
1309
+ getCellValue(item, propertyName) {
1310
+ if (item instanceof ReactiveDictionary) {
1311
+ console.log(item);
1312
+ }
1313
+ else {
1314
+ return item[propertyName];
1315
+ }
929
1316
  }
930
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: GenericRdictTableComponent, deps: [{ token: i1$1.Router }, { token: i1$1.ActivatedRoute }, { token: i2.TranslateService }, { token: i0.Injector }, { token: i0.ElementRef }, { token: ReactiveDictionary }], target: i0.ɵɵFactoryTarget.Component }); }
931
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.3", type: GenericRdictTableComponent, isStandalone: true, selector: "rsl-rdict-generic-table", inputs: { showSerach: "showSerach", searchFields: "searchFields", customInclude: "customInclude", defaultSort: "defaultSort", deletePropertyName: "deletePropertyName", defaultFilter: "defaultFilter", showHeader: "showHeader", hasAdd: "hasAdd", canDelete: "canDelete", canEdit: "canEdit", editOnClick: "editOnClick", editOnDblClick: "editOnDblClick" }, outputs: { selectedObject: "selectedObject", click: "click", editModel: "editModel" }, providers: [], viewQueries: [{ propertyName: "filter", first: true, predicate: ElementRef, descendants: true }], ngImport: i0, template: "<kendo-grid [data]=\"dataSource\" \r\n [sortable]=\"true\" \r\n [filterable]=\"showSerach\"\r\n [resizable]=\"true\"\r\n (add)=\"addHandler()\">\r\n <kendo-toolbar>\r\n <table-title text=\"{{title}}\"></table-title>\r\n <kendo-toolbar-messages>Test</kendo-toolbar-messages>\r\n <!-- <kendo-toolbar-separator></kendo-toolbar-separator> -->\r\n <kendo-toolbar-spacer></kendo-toolbar-spacer>\r\n <kendo-toolbar-button kendoButton [svgIcon]=\"svgAdd\" text=\"Add new\" kendoGridAddTool></kendo-toolbar-button>\r\n </kendo-toolbar>\r\n\r\n <!-- <kendo-toolbar>\r\n \r\n <kendo-toolbar-spacer></kendo-toolbar-spacer>\r\n <button kendoGridAddCommand type=\"button\">Add new</button>\r\n </kendo-toolbar> -->\r\n <kendo-grid-column *ngFor=\"let column of allColumns\" field=\"{{ column.propertyName }}\"\r\n title=\" {{column.translateKey | translate}}\">\r\n </kendo-grid-column>\r\n <kendo-grid-command-column title=\"\" [width]=\"100\" >\r\n <ng-template kendoGridCellTemplate>\r\n <button kendoButton [svgIcon]=\"svgEdit\" themeColor=\"light\" ></button>\r\n <button kendoButton [svgIcon]=\"svgDelete\" themeColor=\"error\"></button>\r\n </ng-template>\r\n </kendo-grid-command-column>\r\n</kendo-grid>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i4$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type:
1317
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: GenericRdictTableComponent, deps: [{ token: i1$1.Router }, { token: i1$1.ActivatedRoute }, { token: i2.TranslateService }, { token: i0.Injector }, { token: i1.LocalFileService }, { token: ReactiveDictionary }, { token: MaterialDialogService }], target: i0.ɵɵFactoryTarget.Component }); }
1318
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.3", type: GenericRdictTableComponent, isStandalone: true, selector: "rsl-rdict-generic-table", inputs: { showSerach: "showSerach", searchFields: "searchFields", customInclude: "customInclude", defaultSort: "defaultSort", deletePropertyName: "deletePropertyName", defaultFilter: "defaultFilter", showHeader: "showHeader", hasAdd: "hasAdd", canDelete: "canDelete", canEdit: "canEdit", editOnClick: "editOnClick", editOnDblClick: "editOnDblClick" }, outputs: { selectedObject: "selectedObject", click: "click", editModel: "editModel" }, providers: [], viewQueries: [{ propertyName: "filter", first: true, predicate: ElementRef, descendants: true }], ngImport: i0, template: "<kendo-grid [data]=\"dataSource\" [sortable]=\"true\" [filterable]=\"showSerach\" [resizable]=\"true\" (add)=\"addHandler()\"\r\n (edit)=\"editHandler($event)\" (remove)=\"removeHandler($event)\">\r\n <kendo-toolbar>\r\n <table-title text=\"{{title}}\"></table-title>\r\n <kendo-toolbar-messages>Test</kendo-toolbar-messages>\r\n <!-- <kendo-toolbar-separator></kendo-toolbar-separator> -->\r\n <kendo-toolbar-spacer></kendo-toolbar-spacer>\r\n <kendo-toolbar-button kendoButton [svgIcon]=\"svgAdd\" text=\"Add new\" kendoGridAddTool></kendo-toolbar-button>\r\n </kendo-toolbar>\r\n\r\n <!-- <kendo-toolbar>\r\n \r\n <kendo-toolbar-spacer></kendo-toolbar-spacer>\r\n <button kendoGridAddCommand type=\"button\">Add new</button>\r\n </kendo-toolbar> -->\r\n <!-- <kendo-grid-column *ngFor=\"let column of allColumns\" field=\"{{ column.propertyName }}\"\r\n title=\" {{column.translateKey | translate}}\">\r\n </kendo-grid-column> -->\r\n\r\n <kendo-grid-column *ngFor=\"let column of allColumns\" [field]=\"column.propertyName\"\r\n [title]=\"column.translateKey | translate\">\r\n <!-- Use ng-template to customize the column content -->\r\n <ng-template *ngIf=\"column.isEditLink; else defaultTemplate\" kendoGridCellTemplate let-dataItem>\r\n <!-- Create a link that calls editHandler(dataItem) -->\r\n <a href=\"javascript:void(0)\" (click)=\"edit(dataItem)\" class=\"edit-link\">\r\n {{ getCellValue(dataItem,column.propertyName) }}\r\n </a>\r\n </ng-template>\r\n <!-- Default template for non-link columns -->\r\n <ng-template #defaultTemplate kendoGridCellTemplate let-dataItem>\r\n {{ getCellValue(dataItem,column.propertyName) }}\r\n </ng-template>\r\n </kendo-grid-column>\r\n\r\n\r\n <kendo-grid-command-column title=\"\" [width]=\"100\">\r\n <ng-template kendoGridCellTemplate>\r\n <!-- <button kendoButton kendoGridEditCommand [svgIcon]=\"svgEdit\" themeColor=\"light\" ></button>\r\n <button kendoButton kendoGridRemoveCommand [svgIcon]=\"svgDelete\" themeColor=\"error\"></button> -->\r\n <button kendoGridEditCommand [svgIcon]=\"svgEdit\" themeColor=\"light\"></button>\r\n <button kendoGridRemoveCommand [svgIcon]=\"svgDelete\" themeColor=\"error\"></button>\r\n </ng-template>\r\n </kendo-grid-command-column>\r\n</kendo-grid>\r\n<div kendoDialogContainer></div>", styles: [".edit-link{color:#00f!important;text-decoration:underline!important;cursor:pointer!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type:
932
1319
  // MatPaginatorModule,
933
1320
  // MatTableModule,
934
- TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "component", type: i5$2.GridComponent, selector: "kendo-grid", inputs: ["data", "pageSize", "height", "rowHeight", "detailRowHeight", "skip", "scrollable", "selectable", "sort", "size", "trackBy", "filter", "group", "virtualColumns", "filterable", "sortable", "pageable", "groupable", "rowReorderable", "navigable", "navigatable", "autoSize", "rowClass", "rowSticky", "rowSelected", "isRowSelectable", "cellSelected", "resizable", "reorderable", "loading", "columnMenu", "hideHeader", "isDetailExpanded", "isGroupExpanded"], outputs: ["filterChange", "pageChange", "groupChange", "sortChange", "selectionChange", "rowReorder", "dataStateChange", "groupExpand", "groupCollapse", "detailExpand", "detailCollapse", "edit", "cancel", "save", "remove", "add", "cellClose", "cellClick", "pdfExport", "excelExport", "columnResize", "columnReorder", "columnVisibilityChange", "columnLockedChange", "columnStickyChange", "scrollBottom", "contentScroll"], exportAs: ["kendoGrid"] }, { kind: "component", type: i5$2.ColumnComponent, selector: "kendo-grid-column", inputs: ["field", "format", "sortable", "groupable", "editor", "filter", "filterable", "editable"] }, { kind: "component", type: i5$2.CommandColumnComponent, selector: "kendo-grid-command-column" }, { kind: "directive", type: i5$2.CellTemplateDirective, selector: "[kendoGridCellTemplate]" }, { kind: "directive", type: i5$2.AddCommandToolbarDirective, selector: "[kendoGridAddTool]" }, { kind: "component", type: i6$1.ToolBarComponent, selector: "kendo-toolbar", inputs: ["overflow", "resizable", "popupSettings", "fillMode", "tabindex", "size", "tabIndex"], outputs: ["open", "close"], exportAs: ["kendoToolBar"] }, { kind: "component", type: i6$1.ToolbarCustomMessagesComponent, selector: "kendo-toolbar-messages" }, { kind: "component", type: i6$1.ToolBarButtonComponent, selector: "kendo-toolbar-button", inputs: ["showText", "showIcon", "text", "style", "className", "title", "disabled", "toggleable", "look", "togglable", "selected", "fillMode", "themeColor", "icon", "iconClass", "svgIcon", "imageUrl"], outputs: ["click", "pointerdown", "selectedChange"], exportAs: ["kendoToolBarButton"] }, { kind: "component", type: i6$1.ToolBarSpacerComponent, selector: "kendo-toolbar-spacer", exportAs: ["kendoToolBarSpacer"] }, { kind: "component", type: i5.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "component", type: RdictTableTitle, selector: "table-title", inputs: ["text"] }], encapsulation: i0.ViewEncapsulation.None }); }
1321
+ TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "component", type: i7$1.GridComponent, selector: "kendo-grid", inputs: ["data", "pageSize", "height", "rowHeight", "detailRowHeight", "skip", "scrollable", "selectable", "sort", "size", "trackBy", "filter", "group", "virtualColumns", "filterable", "sortable", "pageable", "groupable", "rowReorderable", "navigable", "navigatable", "autoSize", "rowClass", "rowSticky", "rowSelected", "isRowSelectable", "cellSelected", "resizable", "reorderable", "loading", "columnMenu", "hideHeader", "isDetailExpanded", "isGroupExpanded"], outputs: ["filterChange", "pageChange", "groupChange", "sortChange", "selectionChange", "rowReorder", "dataStateChange", "groupExpand", "groupCollapse", "detailExpand", "detailCollapse", "edit", "cancel", "save", "remove", "add", "cellClose", "cellClick", "pdfExport", "excelExport", "columnResize", "columnReorder", "columnVisibilityChange", "columnLockedChange", "columnStickyChange", "scrollBottom", "contentScroll"], exportAs: ["kendoGrid"] }, { kind: "directive", type: i7$1.GridToolbarFocusableDirective, selector: " [kendoGridToolbarFocusable], [kendoGridAddCommand], [kendoGridCancelCommand], [kendoGridEditCommand], [kendoGridRemoveCommand], [kendoGridSaveCommand], [kendoGridExcelCommand], [kendoGridPDFCommand] " }, { kind: "component", type: i7$1.ColumnComponent, selector: "kendo-grid-column", inputs: ["field", "format", "sortable", "groupable", "editor", "filter", "filterable", "editable"] }, { kind: "directive", type: i7$1.FocusableDirective, selector: "[kendoGridFocusable], [kendoGridEditCommand], [kendoGridRemoveCommand], [kendoGridSaveCommand], [kendoGridCancelCommand], [kendoGridSelectionCheckbox] ", inputs: ["kendoGridFocusable"] }, { kind: "component", type: i7$1.CommandColumnComponent, selector: "kendo-grid-command-column" }, { kind: "directive", type: i7$1.CellTemplateDirective, selector: "[kendoGridCellTemplate]" }, { kind: "component", type: i7$1.EditCommandDirective, selector: "[kendoGridEditCommand]" }, { kind: "component", type: i7$1.RemoveCommandDirective, selector: "[kendoGridRemoveCommand]" }, { kind: "directive", type: i7$1.AddCommandToolbarDirective, selector: "[kendoGridAddTool]" }, { kind: "component", type: i8.ToolBarComponent, selector: "kendo-toolbar", inputs: ["overflow", "resizable", "popupSettings", "fillMode", "tabindex", "size", "tabIndex"], outputs: ["open", "close"], exportAs: ["kendoToolBar"] }, { kind: "component", type: i8.ToolbarCustomMessagesComponent, selector: "kendo-toolbar-messages" }, { kind: "component", type: i8.ToolBarButtonComponent, selector: "kendo-toolbar-button", inputs: ["showText", "showIcon", "text", "style", "className", "title", "disabled", "toggleable", "look", "togglable", "selected", "fillMode", "themeColor", "icon", "iconClass", "svgIcon", "imageUrl"], outputs: ["click", "pointerdown", "selectedChange"], exportAs: ["kendoToolBarButton"] }, { kind: "component", type: i8.ToolBarSpacerComponent, selector: "kendo-toolbar-spacer", exportAs: ["kendoToolBarSpacer"] }, { kind: "directive", type: i2$1.DialogContainerDirective, selector: "[kendoDialogContainer]" }, { kind: "component", type: RdictTableTitle, selector: "table-title", inputs: ["text"] }], encapsulation: i0.ViewEncapsulation.None }); }
935
1322
  }
936
1323
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImport: i0, type: GenericRdictTableComponent, decorators: [{
937
1324
  type: Component,
@@ -945,9 +1332,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.3", ngImpor
945
1332
  KENDO_TOOLBAR,
946
1333
  KENDO_LABEL,
947
1334
  KENDO_BUTTONS,
1335
+ KENDO_DIALOG,
948
1336
  RdictTableTitle
949
- ], providers: [], template: "<kendo-grid [data]=\"dataSource\" \r\n [sortable]=\"true\" \r\n [filterable]=\"showSerach\"\r\n [resizable]=\"true\"\r\n (add)=\"addHandler()\">\r\n <kendo-toolbar>\r\n <table-title text=\"{{title}}\"></table-title>\r\n <kendo-toolbar-messages>Test</kendo-toolbar-messages>\r\n <!-- <kendo-toolbar-separator></kendo-toolbar-separator> -->\r\n <kendo-toolbar-spacer></kendo-toolbar-spacer>\r\n <kendo-toolbar-button kendoButton [svgIcon]=\"svgAdd\" text=\"Add new\" kendoGridAddTool></kendo-toolbar-button>\r\n </kendo-toolbar>\r\n\r\n <!-- <kendo-toolbar>\r\n \r\n <kendo-toolbar-spacer></kendo-toolbar-spacer>\r\n <button kendoGridAddCommand type=\"button\">Add new</button>\r\n </kendo-toolbar> -->\r\n <kendo-grid-column *ngFor=\"let column of allColumns\" field=\"{{ column.propertyName }}\"\r\n title=\" {{column.translateKey | translate}}\">\r\n </kendo-grid-column>\r\n <kendo-grid-command-column title=\"\" [width]=\"100\" >\r\n <ng-template kendoGridCellTemplate>\r\n <button kendoButton [svgIcon]=\"svgEdit\" themeColor=\"light\" ></button>\r\n <button kendoButton [svgIcon]=\"svgDelete\" themeColor=\"error\"></button>\r\n </ng-template>\r\n </kendo-grid-command-column>\r\n</kendo-grid>\r\n" }]
950
- }], ctorParameters: () => [{ type: i1$1.Router }, { type: i1$1.ActivatedRoute }, { type: i2.TranslateService }, { type: i0.Injector }, { type: i0.ElementRef }, { type: ReactiveDictionary }], propDecorators: { showSerach: [{
1337
+ ], providers: [], template: "<kendo-grid [data]=\"dataSource\" [sortable]=\"true\" [filterable]=\"showSerach\" [resizable]=\"true\" (add)=\"addHandler()\"\r\n (edit)=\"editHandler($event)\" (remove)=\"removeHandler($event)\">\r\n <kendo-toolbar>\r\n <table-title text=\"{{title}}\"></table-title>\r\n <kendo-toolbar-messages>Test</kendo-toolbar-messages>\r\n <!-- <kendo-toolbar-separator></kendo-toolbar-separator> -->\r\n <kendo-toolbar-spacer></kendo-toolbar-spacer>\r\n <kendo-toolbar-button kendoButton [svgIcon]=\"svgAdd\" text=\"Add new\" kendoGridAddTool></kendo-toolbar-button>\r\n </kendo-toolbar>\r\n\r\n <!-- <kendo-toolbar>\r\n \r\n <kendo-toolbar-spacer></kendo-toolbar-spacer>\r\n <button kendoGridAddCommand type=\"button\">Add new</button>\r\n </kendo-toolbar> -->\r\n <!-- <kendo-grid-column *ngFor=\"let column of allColumns\" field=\"{{ column.propertyName }}\"\r\n title=\" {{column.translateKey | translate}}\">\r\n </kendo-grid-column> -->\r\n\r\n <kendo-grid-column *ngFor=\"let column of allColumns\" [field]=\"column.propertyName\"\r\n [title]=\"column.translateKey | translate\">\r\n <!-- Use ng-template to customize the column content -->\r\n <ng-template *ngIf=\"column.isEditLink; else defaultTemplate\" kendoGridCellTemplate let-dataItem>\r\n <!-- Create a link that calls editHandler(dataItem) -->\r\n <a href=\"javascript:void(0)\" (click)=\"edit(dataItem)\" class=\"edit-link\">\r\n {{ getCellValue(dataItem,column.propertyName) }}\r\n </a>\r\n </ng-template>\r\n <!-- Default template for non-link columns -->\r\n <ng-template #defaultTemplate kendoGridCellTemplate let-dataItem>\r\n {{ getCellValue(dataItem,column.propertyName) }}\r\n </ng-template>\r\n </kendo-grid-column>\r\n\r\n\r\n <kendo-grid-command-column title=\"\" [width]=\"100\">\r\n <ng-template kendoGridCellTemplate>\r\n <!-- <button kendoButton kendoGridEditCommand [svgIcon]=\"svgEdit\" themeColor=\"light\" ></button>\r\n <button kendoButton kendoGridRemoveCommand [svgIcon]=\"svgDelete\" themeColor=\"error\"></button> -->\r\n <button kendoGridEditCommand [svgIcon]=\"svgEdit\" themeColor=\"light\"></button>\r\n <button kendoGridRemoveCommand [svgIcon]=\"svgDelete\" themeColor=\"error\"></button>\r\n </ng-template>\r\n </kendo-grid-command-column>\r\n</kendo-grid>\r\n<div kendoDialogContainer></div>", styles: [".edit-link{color:#00f!important;text-decoration:underline!important;cursor:pointer!important}\n"] }]
1338
+ }], ctorParameters: () => [{ type: i1$1.Router }, { type: i1$1.ActivatedRoute }, { type: i2.TranslateService }, { type: i0.Injector }, { type: i1.LocalFileService }, { type: ReactiveDictionary }, { type: MaterialDialogService }], propDecorators: { showSerach: [{
951
1339
  type: Input
952
1340
  }], searchFields: [{
953
1341
  type: Input