ngx-techlify-core 11.4.6 → 11.4.8-beta.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.
@@ -5,7 +5,7 @@ import { MatTableDataSource, MatTableModule } from '@angular/material/table';
5
5
  import { MatSort, MatSortModule } from '@angular/material/sort';
6
6
  import { untilDestroyed, UntilDestroy } from '@ngneat/until-destroy';
7
7
  import { Location, DatePipe, CommonModule } from '@angular/common';
8
- import { Validators, FormBuilder, FormControl, NgControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
8
+ import { Validators, FormBuilder, NgControl, FormControl, ReactiveFormsModule, FormsModule } from '@angular/forms';
9
9
  import { HttpResponse, HttpClient, HttpHandler, HttpClientModule } from '@angular/common/http';
10
10
  import { throwError, Observable, Subject, of, from, fromEvent } from 'rxjs';
11
11
  import { catchError, debounceTime, distinctUntilChanged, startWith, switchMap, finalize, takeUntil, tap, concatMap, filter } from 'rxjs/operators';
@@ -33,12 +33,12 @@ import { MatButtonToggleModule } from '@angular/material/button-toggle';
33
33
  import { FlexLayoutModule } from '@angular/flex-layout';
34
34
  import { InfiniteScrollModule } from 'ngx-infinite-scroll';
35
35
  import { NgxDocViewerModule } from 'ngx-doc-viewer';
36
+ import { ENTER, COMMA } from '@angular/cdk/keycodes';
37
+ import { MatAutocompleteModule } from '@angular/material/autocomplete';
36
38
  import { Editor, NgxEditorModule } from 'ngx-editor';
37
39
  import { utils, writeFile, read } from 'xlsx';
38
40
  import { DomSanitizer } from '@angular/platform-browser';
39
41
  import { diff, formatters } from 'jsondiffpatch';
40
- import { ENTER, COMMA } from '@angular/cdk/keycodes';
41
- import { MatAutocompleteModule } from '@angular/material/autocomplete';
42
42
  import { MatSlideToggleModule } from '@angular/material/slide-toggle';
43
43
 
44
44
  class ActionPopup {
@@ -73,6 +73,162 @@ ActionPopupComponent.ctorParameters = () => [
73
73
  { type: ActionPopup, decorators: [{ type: Inject, args: [MAT_DIALOG_DATA,] }] }
74
74
  ];
75
75
 
76
+ /**
77
+ * Interface used to ensure we have a consistent structure across our form components
78
+ *
79
+ * It also provides some abstraction of repeated code to reduce our codebase size
80
+ *
81
+ * @todo This should be moved to ngx-techlify-core
82
+ *
83
+ * Advantages of this abstract class
84
+ * - Less code, less maintenance, less bugs
85
+ * - more consistent code
86
+ * - comments on more code
87
+ * - save time, save energy
88
+ */
89
+ class TechlifyFormComponentInterface {
90
+ constructor(formValidatorService) {
91
+ this.formValidatorService = formValidatorService;
92
+ }
93
+ /**
94
+ * Resets the value of a field in the HTML form
95
+ *
96
+ * @param event
97
+ * @param field
98
+ */
99
+ resetFieldValue(event, field) {
100
+ var _a, _b;
101
+ (_b = (_a = this.form) === null || _a === void 0 ? void 0 : _a.get(field)) === null || _b === void 0 ? void 0 : _b.setValue('');
102
+ }
103
+ /**
104
+ * Retrieves the value of a field from the HTML form
105
+ *
106
+ * @param field
107
+ * @returns
108
+ */
109
+ getFieldValue(field) {
110
+ var _a, _b;
111
+ return (_b = (_a = this.form) === null || _a === void 0 ? void 0 : _a.get(field)) === null || _b === void 0 ? void 0 : _b.value;
112
+ }
113
+ /**
114
+ * Method to evaluate form fields
115
+ * */
116
+ isFieldValid(field) {
117
+ return this.formValidatorService.isFieldValid(field, this.form, true);
118
+ }
119
+ /**
120
+ * Method to find error in form fields
121
+ * */
122
+ getErrorMessage(field) {
123
+ return this.formValidatorService.getErrorMessage(field, this.form, this.errorMessages);
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Interface used to ensure we have a consistent structure across our listing pages
129
+ *
130
+ * @todo This should be moved to ngx-techlify-core
131
+ *
132
+ * Advantages of this abstract class
133
+ * - Less code, less maintenance, less bugs
134
+ * - more consistent code
135
+ * - comments on more code
136
+ * - save time, save energy
137
+ */
138
+ class TechlifyListingControllerInterface {
139
+ constructor() {
140
+ this.models = [];
141
+ this.page = 1;
142
+ this.perPage = 25;
143
+ this.lastPage = 500;
144
+ this.isWorking = false;
145
+ }
146
+ /**
147
+ * Reload all data from page 1
148
+ */
149
+ reload() {
150
+ this.models = [];
151
+ this.page = 1;
152
+ if (!this.isWorking) {
153
+ this.loadData();
154
+ }
155
+ }
156
+ /**
157
+ * Can be called when the user is scrolling,
158
+ * to trigger loading a new page of data
159
+ */
160
+ onScroll() {
161
+ if (!this.isWorking && this.page < this.lastPage) {
162
+ this.page += 1;
163
+ this.loadData();
164
+ }
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Interface used to ensure we have a consistent structure across our listing pages
170
+ *
171
+ * @todo This should be moved to ngx-techlify-core
172
+ *
173
+ * Advantages of this abstract class
174
+ * - Less code, less maintenance, less bugs
175
+ * - more consistent code
176
+ * - comments on more code
177
+ * - save time, save energy
178
+ */
179
+ class TechlifyServiceBaseClass {
180
+ constructor(http, baseUrl) {
181
+ this.http = http;
182
+ this.baseUrl = "you-forgot-to-set-a-base-url";
183
+ this.baseUrl = baseUrl;
184
+ }
185
+ /**
186
+ * Loads a set of the model this service is for
187
+ *
188
+ * @param filters Restrictors to filter the set of models
189
+ * @returns
190
+ */
191
+ index(filters) {
192
+ return this.http.get(`api/${this.baseUrl}`, { params: Object.assign({}, filters) }).toPromise();
193
+ }
194
+ /**
195
+ * Add a new record to the database
196
+ *
197
+ * @param model The data of the model to add
198
+ * @returns
199
+ */
200
+ store(model) {
201
+ return this.http.post(`api/${this.baseUrl}`, model).toPromise();
202
+ }
203
+ /**
204
+ * Load a single model record, often with all relations and related data
205
+ *
206
+ * @param modelId ID of the model to load
207
+ * @returns
208
+ */
209
+ show(modelId) {
210
+ return this.http.get(`api/${this.baseUrl}/${modelId}`).toPromise();
211
+ }
212
+ /**
213
+ * Update fields of a single existing model
214
+ *
215
+ * @param model Model to update
216
+ * @returns
217
+ */
218
+ update(model) {
219
+ return this.http.put(`api/${this.baseUrl}/${model.id}`, model).toPromise();
220
+ }
221
+ /**
222
+ * Delete a single model
223
+ *
224
+ * @param model Model to delete
225
+ * @returns
226
+ */
227
+ delete(model) {
228
+ return this.http.delete(`api/${this.baseUrl}/${model.id}`).toPromise();
229
+ }
230
+ }
231
+
76
232
  var DataTableComponent_1;
77
233
  let DataTableComponent = DataTableComponent_1 = class DataTableComponent {
78
234
  constructor() {
@@ -1118,6 +1274,10 @@ class EntityFileFormComponent {
1118
1274
  this.entityFileService = entityFileService;
1119
1275
  this.alertService = alertService;
1120
1276
  this.fileList = [];
1277
+ /**
1278
+ * Should we allow tagging entity-files?
1279
+ */
1280
+ this.useTechlifyTags = false;
1121
1281
  this.createForm();
1122
1282
  }
1123
1283
  /** Method to create a form **/
@@ -1132,10 +1292,11 @@ class EntityFileFormComponent {
1132
1292
  file: ['', Validators.required],
1133
1293
  url: ['', Validators.required],
1134
1294
  file_size: ['', Validators.required],
1295
+ tag_ids: [[]]
1135
1296
  });
1136
1297
  }
1137
1298
  ngOnInit() {
1138
- var _a, _b;
1299
+ var _a, _b, _c, _d;
1139
1300
  if (this.data.entity) {
1140
1301
  this.entityFileGroup.get('entity_type').setValue(this.data.entity.entity_type);
1141
1302
  this.entityFileGroup.get('entity_id').setValue(this.data.entity.entity_id);
@@ -1147,6 +1308,9 @@ class EntityFileFormComponent {
1147
1308
  if ((_a = this.data) === null || _a === void 0 ? void 0 : _a.hideTitleAndDetails) {
1148
1309
  this.hideTitleAndDetails = (_b = this.data) === null || _b === void 0 ? void 0 : _b.hideTitleAndDetails;
1149
1310
  }
1311
+ if ((_c = this.data) === null || _c === void 0 ? void 0 : _c.useTechlifyTags) {
1312
+ this.useTechlifyTags = (_d = this.data) === null || _d === void 0 ? void 0 : _d.useTechlifyTags;
1313
+ }
1150
1314
  //File dropper config
1151
1315
  this.fileConfig = {
1152
1316
  fileId: "subjectFile",
@@ -1177,6 +1341,7 @@ class EntityFileFormComponent {
1177
1341
  if (this.hideTitleAndDetails) {
1178
1342
  model.title = model.file;
1179
1343
  }
1344
+ model.tag_ids = model.tag_ids.toString();
1180
1345
  const result = this.updateMode
1181
1346
  ? yield this.entityFileService.updateEntityFile(model)
1182
1347
  : yield this.entityFileService.createEntityFile(model);
@@ -1222,7 +1387,7 @@ class EntityFileFormComponent {
1222
1387
  EntityFileFormComponent.decorators = [
1223
1388
  { type: Component, args: [{
1224
1389
  selector: 'entity-file-form',
1225
- template: "<form [formGroup]=\"entityFileGroup\" (ngSubmit)=\"submit()\">\n <div fxLayout=\"column\" class=\"mat-typography\">\n <div mat-dialog-title class=\"text-center\">\n <div>Entity File</div>\n </div>\n <div mat-dialog-content fxLayout=\"column\" fxLayoutAlign.=\"start\">\n <ng-container *ngIf=\"!hideTitleAndDetails\">\n <mat-form-field>\n <input type=\"text\" matInput formControlName=\"title\" placeholder=\"Title\" autocomplete=\"off\">\n </mat-form-field>\n <mat-form-field>\n <textarea matInput formControlName=\"details\" placeholder=\"Details\" autocomplete=\"off\"></textarea>\n </mat-form-field>\n </ng-container>\n <ng-template #fileUpload>\n <section fxFlex=\"100%\">\n <div>Entity File*</div>\n <app-file-dropper [config]=\"fileConfig\" (fileChanged)=\"fileChanged($event)\" [fileArray]=\"fileList\">\n </app-file-dropper>\n <div class=\"text-danger\" *ngIf=\"isFieldValid('url')\">\n {{getErrorMessage(\"url\")}}\n </div>\n </section>\n </ng-template>\n <div fxFlex=\"100%\" class=\"mt-2\" *ngIf=\"entityFileGroup.get('url').value;else fileUpload;\">\n <app-document-viewer [file]=\"entityFileGroup.get('file').value\" [fileUrl]=\"entityFileGroup.get('url').value\"\n [config]=\"this.viewerConfig\" (remove)=\"removeFile()\" [disableEdit]=\"updateMode\">\n </app-document-viewer>\n </div>\n <div class=\"mt-4 mb-2\" fxLayout=\"row\" fxLayoutGap=\"30px\" fxLayoutAlign=\"end\" fxFlex=\"100%\">\n <button mat-raised-button type=\"button\" (click)=\"dialogRef.close()\">\n Cancel\n </button>\n <button mat-raised-button type=\"submit\" color=\"primary\">Save</button>\n </div>\n </div>\n </div>\n</form>\n",
1390
+ template: "<form [formGroup]=\"entityFileGroup\" (ngSubmit)=\"submit()\">\n <div fxLayout=\"column\" class=\"mat-typography\">\n <div mat-dialog-title class=\"text-center\">\n <div>Entity File</div>\n </div>\n <div mat-dialog-content fxLayout=\"column\" fxLayoutAlign.=\"start\">\n <ng-container *ngIf=\"!hideTitleAndDetails\">\n <mat-form-field>\n <input type=\"text\" matInput formControlName=\"title\" placeholder=\"Title\" autocomplete=\"off\">\n </mat-form-field>\n <mat-form-field>\n <textarea matInput formControlName=\"details\" placeholder=\"Details\" autocomplete=\"off\"></textarea>\n </mat-form-field>\n </ng-container>\n <ng-container *ngIf=\"useTechlifyTags\">\n <mat-form-field>\n <mat-label>Tag</mat-label>\n <app-techlify-tagger-tag-form-field modelType=\"entity-file\" formControlName=\"tag_ids\"\n [modelId]=\"entityFileGroup.get('id').value\"></app-techlify-tagger-tag-form-field>\n </mat-form-field>\n </ng-container>\n <ng-template #fileUpload>\n <section fxFlex=\"100%\">\n <div>Entity File*</div>\n <app-file-dropper [config]=\"fileConfig\" (fileChanged)=\"fileChanged($event)\" [fileArray]=\"fileList\">\n </app-file-dropper>\n <div class=\"text-danger\" *ngIf=\"isFieldValid('url')\">\n {{getErrorMessage(\"url\")}}\n </div>\n </section>\n </ng-template>\n <div fxFlex=\"100%\" class=\"mt-2\" *ngIf=\"entityFileGroup.get('url').value;else fileUpload;\">\n <app-document-viewer [file]=\"entityFileGroup.get('file').value\" [fileUrl]=\"entityFileGroup.get('url').value\"\n [config]=\"this.viewerConfig\" (remove)=\"removeFile()\" [disableEdit]=\"updateMode\">\n </app-document-viewer>\n </div>\n <div class=\"mt-4 mb-2\" fxLayout=\"row\" fxLayoutGap=\"30px\" fxLayoutAlign=\"end\" fxFlex=\"100%\">\n <button mat-raised-button type=\"button\" (click)=\"dialogRef.close()\">\n Cancel\n </button>\n <button mat-raised-button type=\"submit\" color=\"primary\">Save</button>\n </div>\n </div>\n </div>\n</form>\n",
1226
1391
  styles: [""]
1227
1392
  },] }
1228
1393
  ];
@@ -1236,12 +1401,18 @@ EntityFileFormComponent.ctorParameters = () => [
1236
1401
  ];
1237
1402
 
1238
1403
  let EntityFilesViewAllComponent = class EntityFilesViewAllComponent {
1239
- constructor(entityFileService, location, alertService, dialog) {
1404
+ constructor(entityFileService, location, alertService, dialog, fb) {
1240
1405
  this.entityFileService = entityFileService;
1241
1406
  this.location = location;
1242
1407
  this.alertService = alertService;
1243
1408
  this.dialog = dialog;
1409
+ this.fb = fb;
1244
1410
  this.viewOnly = false;
1411
+ this.allowMultipleFiles = false;
1412
+ /**
1413
+ * Should we allow tagging entity-files?
1414
+ */
1415
+ this.useTechlifyTags = false;
1245
1416
  this.title = "File";
1246
1417
  this.filters = {};
1247
1418
  this.entityFiles = [];
@@ -1253,11 +1424,14 @@ let EntityFilesViewAllComponent = class EntityFilesViewAllComponent {
1253
1424
  'uploaded_on',
1254
1425
  ];
1255
1426
  this.isWorking = false;
1256
- this.search = new FormControl('');
1257
1427
  this.page = 1;
1258
1428
  this.perPage = 25;
1259
1429
  this.lastPage = 0;
1260
1430
  this.fileList = [];
1431
+ this.filterFormGroup = this.fb.group({
1432
+ title: [""],
1433
+ tag_ids: [""]
1434
+ });
1261
1435
  }
1262
1436
  ngOnInit() {
1263
1437
  //File dropper config
@@ -1267,7 +1441,7 @@ let EntityFilesViewAllComponent = class EntityFilesViewAllComponent {
1267
1441
  styles: {
1268
1442
  height: "500px"
1269
1443
  },
1270
- multiple: false,
1444
+ multiple: this.allowMultipleFiles,
1271
1445
  acceptFile: "*",
1272
1446
  maxSize: 10,
1273
1447
  acceptFileText: "All Files"
@@ -1286,24 +1460,33 @@ let EntityFilesViewAllComponent = class EntityFilesViewAllComponent {
1286
1460
  if (this.hideTitleAndDetails) {
1287
1461
  this.displayedColumns = this.displayedColumns.filter(x => (x !== 'details') && (x !== 'title'));
1288
1462
  }
1463
+ this.listenRoutes();
1289
1464
  this.filters = {
1290
1465
  entity_type: this.entityType,
1291
1466
  entity_id: this.entityId,
1292
1467
  title: ""
1293
1468
  };
1294
- this.search.valueChanges.pipe(debounceTime(500), distinctUntilChanged(), untilDestroyed(this)).subscribe(value => {
1295
- this.filters.title = value;
1296
- this.reload();
1297
- });
1298
1469
  this.fetchEntityFilesDetails();
1470
+ if (this.useTechlifyTags) {
1471
+ this.displayedColumns.push('tag');
1472
+ }
1299
1473
  if (!this.viewOnly) {
1300
1474
  this.displayedColumns.push('actions');
1301
1475
  }
1302
1476
  }
1477
+ listenRoutes() {
1478
+ this.filterFormGroup.valueChanges.pipe(debounceTime(500), untilDestroyed(this))
1479
+ .subscribe(changes => {
1480
+ this.reload();
1481
+ });
1482
+ }
1303
1483
  fetchEntityFilesDetails() {
1304
1484
  return __awaiter(this, void 0, void 0, function* () {
1305
1485
  this.filters.page = this.page;
1306
1486
  this.filters.perPage = this.perPage;
1487
+ let formGroup = this.filterFormGroup.value;
1488
+ formGroup.tag_ids = formGroup.tag_ids.toString();
1489
+ this.filters = Object.assign(Object.assign({}, this.filters), formGroup);
1307
1490
  this.isWorking = true;
1308
1491
  const result = yield this.entityFileService.getEntityFiles(this.filters);
1309
1492
  this.lastPage = result.last_page || this.page;
@@ -1316,7 +1499,8 @@ let EntityFilesViewAllComponent = class EntityFilesViewAllComponent {
1316
1499
  width: "700px",
1317
1500
  data: {
1318
1501
  entity: this.filters,
1319
- hideTitleAndDetails: this.hideTitleAndDetails
1502
+ hideTitleAndDetails: this.hideTitleAndDetails,
1503
+ useTechlifyTags: this.useTechlifyTags,
1320
1504
  },
1321
1505
  autoFocus: false,
1322
1506
  restoreFocus: false
@@ -1335,7 +1519,8 @@ let EntityFilesViewAllComponent = class EntityFilesViewAllComponent {
1335
1519
  autoFocus: false,
1336
1520
  data: {
1337
1521
  file: file,
1338
- hideTitleAndDetails: this.hideTitleAndDetails
1522
+ hideTitleAndDetails: this.hideTitleAndDetails,
1523
+ useTechlifyTags: this.useTechlifyTags,
1339
1524
  } // Any data passed here will be injected into the model
1340
1525
  });
1341
1526
  dialogRef.afterClosed().subscribe(result => {
@@ -1376,8 +1561,9 @@ let EntityFilesViewAllComponent = class EntityFilesViewAllComponent {
1376
1561
  }
1377
1562
  }
1378
1563
  ngOnDestroy() { }
1379
- resetFieldValue() {
1380
- this.search.setValue("");
1564
+ resetFieldValue(event, field) {
1565
+ event.stopPropagation();
1566
+ this.filterFormGroup.get(field).setValue("");
1381
1567
  }
1382
1568
  sizeOf(bytes) {
1383
1569
  if (!bytes) {
@@ -1390,13 +1576,15 @@ let EntityFilesViewAllComponent = class EntityFilesViewAllComponent {
1390
1576
  return __awaiter(this, void 0, void 0, function* () {
1391
1577
  this.fileList = event;
1392
1578
  if (this.fileList.length > 0) {
1393
- const result = yield this.entityFileService.uploadEntityFile(this.fileList[0], {
1394
- entity_type: this.entityType,
1395
- entity_id: this.entityId,
1396
- });
1579
+ yield this.fileList.forEach((file) => __awaiter(this, void 0, void 0, function* () {
1580
+ const result = yield this.entityFileService.uploadEntityFile(file, {
1581
+ entity_type: this.entityType,
1582
+ entity_id: this.entityId,
1583
+ });
1584
+ this.reload();
1585
+ }));
1397
1586
  this.fileList = [];
1398
1587
  this.alertService.addAlert('Successfull uploaded', 'success');
1399
- this.reload();
1400
1588
  }
1401
1589
  });
1402
1590
  }
@@ -1404,7 +1592,7 @@ let EntityFilesViewAllComponent = class EntityFilesViewAllComponent {
1404
1592
  EntityFilesViewAllComponent.decorators = [
1405
1593
  { type: Component, args: [{
1406
1594
  selector: 'app-entity-files-view-all',
1407
- template: "<div class=\"mat-typography\" *ngIf=\"!displayMode\">\n <div fxLayout=\"row\" fxLayoutGap=\"1rem\">\n <mat-card fxFlex=\"70%\">\n <mat-card-title fxLayout fxLayoutGap=\"1rem\">\n <h3 class=\"font-weight-bold primary-color\" fxLayout=\"center center\">\n <mat-icon>\n <span class=\"material-icons\">\n description\n </span>\n </mat-icon>\n {{title}}s\n </h3>\n <div>\n <button type=\"button\" class=\"mx-1\" mat-raised-button color=\"primary\" (click)=\"addEntityFile()\"\n *ngIf=\"!viewOnly\">\n <mat-icon>\n <span class=\"material-icons\">\n add_circle_outline\n </span>\n </mat-icon>\n {{title}}\n </button>\n </div>\n <mat-form-field *ngIf=\"!removeSearch\" appearance=\"outline\" style=\"font-size: 10px;\">\n <mat-label>Search</mat-label>\n <input type=\"text\" matInput [formControl]=\"search\" placeholder=\"Search\" name=\"title\" autocomplete=\"off\" />\n <button mat-button *ngIf=\"filters.title\" matSuffix mat-icon-button (click)=\"resetFieldValue()\">\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </mat-card-title>\n <mat-card-content class=\"entity-file-card\">\n <table mat-table [dataSource]=\"entityFiles\" class=\"w-100\" matSort multiTemplateDataRows infiniteScroll\n [infiniteScrollDistance]=\"1.5\" [infiniteScrollThrottle]=\"50\" (scrolled)=\"onScroll()\">\n\n <!-- Index Column -->\n <ng-container matColumnDef=\"index\">\n <th mat-header-cell *matHeaderCellDef> # </th>\n <td mat-cell *matCellDef=\"let element; let i = dataIndex\"> {{ i+1 }} </td>\n </ng-container>\n\n <!-- Title Column -->\n <ng-container matColumnDef=\"title\">\n <th mat-header-cell *matHeaderCellDef> Title </th>\n <td mat-cell *matCellDef=\"let element\">\n <div>\n <span>\n {{element.title}}\n </span>\n <span>\n <a href=\"{{element.url}}\" target=\"_blank\" class=\"text-decoration-none text-muted\">\n <button mat-icon-button type=\"button\">\n <mat-icon>download</mat-icon>\n </button>\n </a>\n </span>\n </div>\n </td>\n </ng-container>\n\n <!-- Details Column -->\n <ng-container matColumnDef=\"details\">\n <th mat-header-cell *matHeaderCellDef> Details </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.details}} </td>\n </ng-container>\n\n <!-- File size Column -->\n <ng-container matColumnDef=\"file_size\">\n <th mat-header-cell *matHeaderCellDef> File Size </th>\n <td mat-cell *matCellDef=\"let element\"> {{ sizeOf(element.file_size)}} </td>\n </ng-container>\n\n <!-- Uploaded On Column -->\n <ng-container matColumnDef=\"uploaded_on\">\n <th mat-header-cell *matHeaderCellDef> Uploaded On </th>\n <td mat-cell *matCellDef=\"let element\">\n <div>\n {{element.created_at | date: 'mediumDate'}}\n </div>\n <div class=\"text-muted\">\n By {{element.creator?.name}}\n </div>\n </td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"actions\">\n <th mat-header-cell *matHeaderCellDef> Actions </th>\n <td mat-cell *matCellDef=\"let element\" style=\"min-width:110px\" class=\"text-muted\">\n <button type=\"button\" mat-icon-button (click)=\"editEntityFile(element)\">\n <mat-icon>edit</mat-icon>\n </button>\n <button type=\"button\" mat-icon-button (click)=\"deleteEntityFile(element)\">\n <mat-icon>delete</mat-icon>\n </button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n </mat-card-content>\n </mat-card>\n <section fxFlex=\"30%\">\n <app-file-dropper [config]=\"fileConfig\" (fileChanged)=\"fileChanged($event)\" [fileArray]=\"fileList\">\n </app-file-dropper>\n </section>\n </div>\n</div>\n\n<div fxLayout=\"row wrap\" fxLayoutGap=\"1rem\" class=\"mat-typography p-4\" *ngIf=\"displayMode\">\n <div *ngFor=\"let efile of entityFiles\">\n <app-document-viewer [file]=\"efile.file\" [fileUrl]=\"efile.url\" [config]=\"this.viewerConfig\" [disableEdit]=\"true\">\n </app-document-viewer>\n <a href=\"{{efile.url}}\" target=\"_blank\">\n <button mat-button type=\"button\">View</button>\n </a>\n </div>\n</div>\n",
1595
+ template: "<div class=\"mat-typography\" *ngIf=\"!displayMode\">\n <div fxLayout=\"row\" fxLayoutGap=\"1rem\">\n <mat-card fxFlex=\"70%\">\n <mat-card-title fxLayout fxLayoutGap=\"1rem\">\n <h3 class=\"font-weight-bold primary-color\" fxLayout=\"center center\">\n <mat-icon>\n <span class=\"material-icons\">\n description\n </span>\n </mat-icon>\n {{title}}s\n </h3>\n <div>\n <button type=\"button\" class=\"mx-1\" mat-raised-button color=\"primary\" (click)=\"addEntityFile()\"\n *ngIf=\"!viewOnly\">\n <mat-icon>\n <span class=\"material-icons\">\n add_circle_outline\n </span>\n </mat-icon>\n {{title}}\n </button>\n </div>\n <form [formGroup]=\"filterFormGroup\" style=\"font-size: 10px;\" fxLayout fxLayoutGap=\"1rem\">\n <mat-form-field *ngIf=\"!removeSearch\" appearance=\"outline\">\n <mat-label>Search</mat-label>\n <input type=\"text\" matInput formControlName=\"title\" placeholder=\"Search\" name=\"title\" autocomplete=\"off\" />\n <button mat-button *ngIf=\"filters.title\" matSuffix mat-icon-button\n (click)=\"resetFieldValue($event, 'title')\">\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" *ngIf=\"useTechlifyTags\">\n <mat-label>Tag</mat-label>\n <app-searchable-selector formControlName=\"tag_ids\" apiUrl=\"api/techlify-tagger-tags\" [multiple]=\"true\"\n placeHolder=\"Tag\">\n </app-searchable-selector>\n <button mat-icon-button matSuffix *ngIf=\"filterFormGroup.get('tag_ids').value.length\"\n (click)=\"resetFieldValue($event, 'tag_ids')\">\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </form>\n </mat-card-title>\n <mat-card-content class=\"entity-file-card\">\n <table mat-table [dataSource]=\"entityFiles\" class=\"w-100\" matSort multiTemplateDataRows infiniteScroll\n [infiniteScrollDistance]=\"1.5\" [infiniteScrollThrottle]=\"50\" (scrolled)=\"onScroll()\">\n\n <!-- Index Column -->\n <ng-container matColumnDef=\"index\">\n <th mat-header-cell *matHeaderCellDef> # </th>\n <td mat-cell *matCellDef=\"let element; let i = dataIndex\"> {{ i+1 }} </td>\n </ng-container>\n\n <!-- Title Column -->\n <ng-container matColumnDef=\"title\">\n <th mat-header-cell *matHeaderCellDef> Title </th>\n <td mat-cell *matCellDef=\"let element\">\n <div>\n <span>\n {{element.title}}\n </span>\n <span>\n <a href=\"{{element.url}}\" target=\"_blank\" class=\"text-decoration-none text-muted\">\n <button mat-icon-button type=\"button\">\n <mat-icon>download</mat-icon>\n </button>\n </a>\n </span>\n </div>\n </td>\n </ng-container>\n\n <!-- Details Column -->\n <ng-container matColumnDef=\"details\">\n <th mat-header-cell *matHeaderCellDef> Details </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.details}} </td>\n </ng-container>\n\n <!-- File size Column -->\n <ng-container matColumnDef=\"file_size\">\n <th mat-header-cell *matHeaderCellDef> File Size </th>\n <td mat-cell *matCellDef=\"let element\"> {{ sizeOf(element.file_size)}} </td>\n </ng-container>\n\n <!-- Tags Column -->\n <ng-container matColumnDef=\"tag\">\n <th mat-header-cell *matHeaderCellDef> Tag </th>\n <td mat-cell *matCellDef=\"let element\" class=\"text-muted\">\n <ng-container *ngFor=\"let taggerModel of element.tags\">\n {{taggerModel?.tag?.title}},\n </ng-container>\n </td>\n </ng-container>\n\n <!-- Uploaded On Column -->\n <ng-container matColumnDef=\"uploaded_on\">\n <th mat-header-cell *matHeaderCellDef> Uploaded On </th>\n <td mat-cell *matCellDef=\"let element\">\n <div>\n {{element.created_at | date: 'mediumDate'}}\n </div>\n <div class=\"text-muted\">\n By {{element.creator?.name}}\n </div>\n </td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"actions\">\n <th mat-header-cell *matHeaderCellDef> Actions </th>\n <td mat-cell *matCellDef=\"let element\" style=\"min-width:110px\" class=\"text-muted\">\n <button type=\"button\" mat-icon-button (click)=\"editEntityFile(element)\">\n <mat-icon>edit</mat-icon>\n </button>\n <button type=\"button\" mat-icon-button (click)=\"deleteEntityFile(element)\">\n <mat-icon>delete</mat-icon>\n </button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n </mat-card-content>\n </mat-card>\n <section fxFlex=\"30%\">\n <app-file-dropper [config]=\"fileConfig\" (fileChanged)=\"fileChanged($event)\" [fileArray]=\"fileList\">\n </app-file-dropper>\n </section>\n </div>\n</div>\n\n<div fxLayout=\"row wrap\" fxLayoutGap=\"1rem\" class=\"mat-typography p-4\" *ngIf=\"displayMode\">\n <div *ngFor=\"let efile of entityFiles\">\n <app-document-viewer [file]=\"efile.file\" [fileUrl]=\"efile.url\" [config]=\"this.viewerConfig\" [disableEdit]=\"true\">\n </app-document-viewer>\n <a href=\"{{efile.url}}\" target=\"_blank\">\n <button mat-button type=\"button\">View</button>\n </a>\n </div>\n</div>\n",
1408
1596
  styles: [""]
1409
1597
  },] }
1410
1598
  ];
@@ -1412,7 +1600,8 @@ EntityFilesViewAllComponent.ctorParameters = () => [
1412
1600
  { type: EntityFileService },
1413
1601
  { type: Location },
1414
1602
  { type: AlertService },
1415
- { type: MatDialog }
1603
+ { type: MatDialog },
1604
+ { type: FormBuilder }
1416
1605
  ];
1417
1606
  EntityFilesViewAllComponent.propDecorators = {
1418
1607
  entityId: [{ type: Input }],
@@ -1421,6 +1610,8 @@ EntityFilesViewAllComponent.propDecorators = {
1421
1610
  removeSearch: [{ type: Input }],
1422
1611
  hideTitleAndDetails: [{ type: Input }],
1423
1612
  displayMode: [{ type: Input }],
1613
+ allowMultipleFiles: [{ type: Input }],
1614
+ useTechlifyTags: [{ type: Input }],
1424
1615
  title: [{ type: Input }]
1425
1616
  };
1426
1617
  EntityFilesViewAllComponent = __decorate([
@@ -3118,109 +3309,292 @@ FileDropperModule.decorators = [
3118
3309
  },] }
3119
3310
  ];
3120
3311
 
3121
- class EntityFilesViewAllModule {
3312
+ class TechlifyTaggerTagFormConfigModel {
3313
+ constructor() {
3314
+ this.selectable = true;
3315
+ this.removable = true;
3316
+ this.separatorKeysCodes = [ENTER, COMMA];
3317
+ this.placeholder = 'New Tag..';
3318
+ this.apiUrl = 'api/techlify-tagger-tags';
3319
+ this.createApiUrl = 'api/techlify-tagger-tags';
3320
+ this.isCreateable = true;
3321
+ this.isCacheTags = false;
3322
+ this.isSingle = false;
3323
+ }
3122
3324
  }
3123
- EntityFilesViewAllModule.decorators = [
3124
- { type: NgModule, args: [{
3125
- declarations: [EntityFileFormComponent, EntityFilesViewAllComponent],
3126
- imports: [
3127
- CommonModule,
3128
- FormsModule,
3129
- ReactiveFormsModule,
3130
- FlexLayoutModule,
3131
- FileDropperModule,
3132
- DocumentViewerModule,
3133
- InfiniteScrollModule,
3134
- ActionPopupModule,
3135
- MaterialModule
3136
- ],
3137
- exports: [
3138
- EntityFilesViewAllComponent
3139
- ],
3140
- entryComponents: [EntityFileFormComponent]
3141
- },] }
3142
- ];
3143
3325
 
3144
- class ReadMoreComponent {
3145
- constructor() {
3146
- this.maxLength = 100;
3147
- this.hideToggle = true;
3148
- this.isCollapsed = true;
3326
+ var TechlifyTaggerTagFormFieldComponent_1;
3327
+ let TechlifyTaggerTagFormFieldComponent = TechlifyTaggerTagFormFieldComponent_1 = class TechlifyTaggerTagFormFieldComponent {
3328
+ constructor(_focusMonitor, _elementRef, httpService, _formField, ngControl) {
3329
+ this._focusMonitor = _focusMonitor;
3330
+ this._elementRef = _elementRef;
3331
+ this.httpService = httpService;
3332
+ this._formField = _formField;
3333
+ this.ngControl = ngControl;
3334
+ this.stateChanges = new Subject();
3335
+ this.focused = false;
3336
+ this.controlType = 'techlify-tagger-form-field';
3337
+ this.id = `techlify-tagger-form-field-${TechlifyTaggerTagFormFieldComponent_1.nextId++}`;
3338
+ this.onChange = (_) => { };
3339
+ this.onTouched = () => { };
3340
+ this.tagInputCtrl = new FormControl();
3341
+ /**Pass the configuration for Techlify Tagger */
3342
+ this.config = new TechlifyTaggerTagFormConfigModel();
3343
+ /**Pass the default list of tags */
3344
+ this._allTags = [];
3345
+ /**Pass the Categories to filter for a model */
3346
+ this.categories = [];
3347
+ this._required = false;
3348
+ this._disabled = false;
3349
+ this._value = [];
3350
+ this.tagInputCtrl.valueChanges
3351
+ .subscribe(filterValue => {
3352
+ this.filterString = filterValue;
3353
+ });
3354
+ //Set Focus Monitor
3355
+ _focusMonitor.monitor(_elementRef, true).subscribe(origin => {
3356
+ if (this.focused && !origin) {
3357
+ this.onTouched();
3358
+ }
3359
+ this.focused = !!origin;
3360
+ this.stateChanges.next();
3361
+ });
3362
+ if (this.ngControl != null) {
3363
+ this.ngControl.valueAccessor = this;
3364
+ }
3149
3365
  }
3150
- ngOnInit() {
3151
- this.determineView();
3366
+ get allTags() {
3367
+ return this._allTags;
3152
3368
  }
3153
- toggleView() {
3154
- this.isCollapsed = !this.isCollapsed;
3155
- this.determineView();
3369
+ set allTags(value) {
3370
+ this._allTags = value;
3156
3371
  }
3157
- determineView() {
3158
- if (!this.text || this.text.length <= this.maxLength) {
3159
- this.currentText = this.text;
3160
- this.isCollapsed = false;
3161
- this.hideToggle = true;
3162
- return;
3163
- }
3164
- this.hideToggle = false;
3165
- if (this.isCollapsed == true) {
3166
- this.currentText = this.text.substring(0, this.maxLength) + "...";
3167
- }
3168
- else if (this.isCollapsed == false) {
3169
- this.currentText = this.text;
3170
- }
3372
+ get tags() {
3373
+ return this.allTags.filter(x => this.value.some(y => y == x.id));
3171
3374
  }
3172
- }
3173
- ReadMoreComponent.decorators = [
3174
- { type: Component, args: [{
3175
- selector: "app-read-more",
3176
- template: "<div [innerHTML]=\"currentText\"></div>\n<a href=\"javascript:;\" *ngIf=\"!hideToggle\" class=\"primary-color hoverable\" (click)=\"toggleView()\">Read\n {{ isCollapsed ? \"more\" : \"less\" }}</a>",
3177
- styles: ["div.collapsed{height:250px;overflow:hidden}.primary-color{color:#009fdd!important}"]
3178
- },] }
3179
- ];
3180
- ReadMoreComponent.ctorParameters = () => [];
3181
- ReadMoreComponent.propDecorators = {
3182
- text: [{ type: Input }],
3183
- maxLength: [{ type: Input }]
3184
- };
3185
-
3186
- class ReadMoreModule {
3187
- }
3188
- ReadMoreModule.decorators = [
3189
- { type: NgModule, args: [{
3190
- declarations: [ReadMoreComponent],
3191
- imports: [
3192
- CommonModule,
3193
- MaterialModule,
3194
- FlexLayoutModule
3195
- ],
3196
- exports: [
3197
- ReadMoreComponent
3198
- ]
3199
- },] }
3200
- ];
3201
-
3202
- class NoteModule {
3203
- }
3204
- NoteModule.decorators = [
3205
- { type: NgModule, args: [{
3206
- declarations: [
3207
- NoteListComponent,
3208
- NoteFormComponent,
3209
- CommentFormComponent,
3210
- ],
3375
+ //Default Getter and Setters for a Form Field Implementation
3376
+ get empty() {
3377
+ return this.value.length == 0;
3378
+ }
3379
+ get shouldLabelFloat() {
3380
+ return this.focused || !this.empty || this.tagInputCtrl.value;
3381
+ }
3382
+ get required() {
3383
+ return this._required;
3384
+ }
3385
+ set required(value) {
3386
+ this._required = coerceBooleanProperty(value);
3387
+ this.stateChanges.next();
3388
+ }
3389
+ get disabled() {
3390
+ return this._disabled;
3391
+ }
3392
+ set disabled(value) {
3393
+ this._disabled = coerceBooleanProperty(value);
3394
+ this._disabled ? this.tagInputCtrl.disable() : this.tagInputCtrl.enable();
3395
+ this.stateChanges.next();
3396
+ }
3397
+ get value() {
3398
+ return this._value;
3399
+ }
3400
+ set value(tagIds) {
3401
+ this._value = tagIds || [];
3402
+ this.stateChanges.next();
3403
+ }
3404
+ get errorState() {
3405
+ return this.tagInputCtrl.dirty && this.required && (this.value.length == 0);
3406
+ }
3407
+ get placeholder() {
3408
+ return this._placeholder;
3409
+ }
3410
+ set placeholder(value) {
3411
+ this._placeholder = value;
3412
+ this.stateChanges.next();
3413
+ }
3414
+ ngOnInit() {
3415
+ }
3416
+ ngOnChanges(changes) {
3417
+ //API to load all tags for the model type
3418
+ if (this.allTags.length == 0) {
3419
+ this.httpService
3420
+ .cache(!this.config.isCacheTags)
3421
+ .get(this.config.apiUrl, {
3422
+ params: {
3423
+ categories: this.categories.join(','),
3424
+ perPage: '1000'
3425
+ }
3426
+ }).pipe(debounceTime(500), untilDestroyed(this)).subscribe((result) => {
3427
+ this.allTags = result.data;
3428
+ });
3429
+ }
3430
+ //API to load only the selected tags for the model
3431
+ if (this.modelId && this.value.length == 0) {
3432
+ //Model Id is passed and no tags are present, so we query db for the avilable tags for the model ID.
3433
+ this.httpService
3434
+ .cache(!this.config.isCacheTags)
3435
+ .get(this.config.apiUrl, {
3436
+ params: {
3437
+ categories: this.categories.join(','),
3438
+ model_type: this.modelType,
3439
+ model_id: this.modelId,
3440
+ perPage: '1000'
3441
+ }
3442
+ }).pipe(debounceTime(500), untilDestroyed(this)).subscribe((result) => {
3443
+ this.value = ((result === null || result === void 0 ? void 0 : result.data) || []).map((x) => x.id);
3444
+ this._handleInput();
3445
+ });
3446
+ }
3447
+ }
3448
+ init() {
3449
+ if (this.modelId && this.allTags.length == 0) {
3450
+ //Model Id is passed and no tags are passed, so we query db for the avilable tags for the model ID.
3451
+ this.httpService
3452
+ .cache(!this.config.isCacheTags)
3453
+ .get(this.config.apiUrl, {
3454
+ params: {
3455
+ categories: this.categories.join(','),
3456
+ model_type: this.modelType,
3457
+ model_id: this.modelId
3458
+ }
3459
+ }).pipe(untilDestroyed(this)).subscribe((result) => {
3460
+ this.allTags = result.data;
3461
+ });
3462
+ }
3463
+ }
3464
+ get filteredTags() {
3465
+ return this._filter();
3466
+ }
3467
+ setDescribedByIds(ids) {
3468
+ // Just a empty implementation for Mat Form Field Interface
3469
+ }
3470
+ onContainerClick() {
3471
+ // Just a empty implementation for Mat Form Field Interface
3472
+ }
3473
+ add(event) {
3474
+ return __awaiter(this, void 0, void 0, function* () {
3475
+ const value = (event.value || '').trim();
3476
+ // Add our tag
3477
+ // Validate for single mode
3478
+ if (!this.config.isSingle || (this.value.length === 0)) {
3479
+ if (value && this.config.isCreateable) {
3480
+ const tags = this.allTags;
3481
+ let tag = tags.find((item) => item.title.toLowerCase() == value.toLowerCase());
3482
+ if (!tag) {
3483
+ //No tag present in the list
3484
+ try {
3485
+ const result = yield this.httpService.post(this.config.createApiUrl, {
3486
+ title: value,
3487
+ description: value,
3488
+ category_title: (this.categories.length > 0) ? (this.defaultCreateCategory ? this.defaultCreateCategory : this.categories[0]) : ''
3489
+ }).toPromise();
3490
+ tag = result.item;
3491
+ }
3492
+ catch (error) {
3493
+ return;
3494
+ }
3495
+ this.allTags.push(tag);
3496
+ }
3497
+ else {
3498
+ //Optionally clean the existing value, to avoid duplicate
3499
+ this.remove(tag);
3500
+ }
3501
+ this.value.push(tag.id);
3502
+ this._handleInput();
3503
+ }
3504
+ }
3505
+ // Clear the input value
3506
+ event.input.value = '';
3507
+ this.tagInputCtrl.setValue(null);
3508
+ });
3509
+ }
3510
+ remove(tag) {
3511
+ this.value = this.value.filter(x => x !== tag.id);
3512
+ this._handleInput();
3513
+ }
3514
+ selected(event) {
3515
+ // Validate for single mode
3516
+ if (!this.config.isSingle || (this.value.length === 0)) {
3517
+ //Clean the existing value, to avoid duplicate
3518
+ this.remove({ id: event.option.value });
3519
+ this.value.push(event.option.value);
3520
+ this._handleInput();
3521
+ }
3522
+ this.tagInput.nativeElement.value = '';
3523
+ this.tagInputCtrl.setValue(null);
3524
+ }
3525
+ _filter() {
3526
+ const filterValue = this.filterString ? this.filterString.toString().toLowerCase() : null;
3527
+ const availableTags = this.allTags.filter((tag) => !this.value.some((item) => item == tag.id));
3528
+ return filterValue ? availableTags.filter((tag) => tag.title.toLowerCase().includes(filterValue)) : availableTags;
3529
+ }
3530
+ writeValue(tagIds) {
3531
+ this.value = tagIds || [];
3532
+ }
3533
+ registerOnChange(fn) {
3534
+ this.onChange = fn;
3535
+ }
3536
+ registerOnTouched(fn) {
3537
+ this.onTouched = fn;
3538
+ }
3539
+ setDisabledState(isDisabled) {
3540
+ this.disabled = isDisabled;
3541
+ }
3542
+ _handleInput() {
3543
+ this.onChange(this.value);
3544
+ }
3545
+ ngOnDestroy() {
3546
+ this.stateChanges.complete();
3547
+ this._focusMonitor.stopMonitoring(this._elementRef);
3548
+ }
3549
+ };
3550
+ TechlifyTaggerTagFormFieldComponent.nextId = 0;
3551
+ TechlifyTaggerTagFormFieldComponent.decorators = [
3552
+ { type: Component, args: [{
3553
+ selector: 'app-techlify-tagger-tag-form-field',
3554
+ template: "<mat-chip-list #chipList aria-label=\"Tag Selection\">\n <mat-chip *ngFor=\"let tag of tags\" [selectable]=\"config.selectable\" [removable]=\"config.removable\"\n (removed)=\"remove(tag)\">\n {{tag.title}}\n <button matChipRemove *ngIf=\"config.removable\" class=\"border-0\">\n <mat-icon class=\"mat-relative-icon\">cancel</mat-icon>\n </button>\n </mat-chip>\n <input placeholder=\"{{config.isCreateable? config.placeholder:''}}\" #tagInput [formControl]=\"tagInputCtrl\"\n [matAutocomplete]=\"auto\" [matChipInputFor]=\"chipList\"\n [matChipInputSeparatorKeyCodes]=\"config.separatorKeysCodes\" (matChipInputTokenEnd)=\"add($event)\"\n #trigger=\"matAutocompleteTrigger\" (click)=\"trigger.openPanel()\">\n</mat-chip-list>\n<mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event)\">\n <mat-option *ngFor=\"let tag of filteredTags\" [value]=\"tag.id\">\n {{tag.title}}\n </mat-option>\n</mat-autocomplete>",
3555
+ providers: [{ provide: MatFormFieldControl, useExisting: TechlifyTaggerTagFormFieldComponent_1 }],
3556
+ styles: [".mat-relative-icon{font-size:20px;position:relative;right:7px;top:-3px}"]
3557
+ },] }
3558
+ ];
3559
+ TechlifyTaggerTagFormFieldComponent.ctorParameters = () => [
3560
+ { type: FocusMonitor },
3561
+ { type: ElementRef },
3562
+ { type: HttpService },
3563
+ { type: MatFormField, decorators: [{ type: Optional }, { type: Inject, args: [MAT_FORM_FIELD,] }] },
3564
+ { type: NgControl, decorators: [{ type: Optional }, { type: Self }] }
3565
+ ];
3566
+ TechlifyTaggerTagFormFieldComponent.propDecorators = {
3567
+ tagInput: [{ type: ViewChild, args: ['tagInput',] }],
3568
+ config: [{ type: Input }],
3569
+ modelType: [{ type: Input }],
3570
+ modelId: [{ type: Input }],
3571
+ allTags: [{ type: Input }],
3572
+ categories: [{ type: Input }],
3573
+ defaultCreateCategory: [{ type: Input }],
3574
+ required: [{ type: Input }],
3575
+ disabled: [{ type: Input }],
3576
+ value: [{ type: Input }],
3577
+ placeholder: [{ type: Input }]
3578
+ };
3579
+ TechlifyTaggerTagFormFieldComponent = TechlifyTaggerTagFormFieldComponent_1 = __decorate([
3580
+ UntilDestroy()
3581
+ ], TechlifyTaggerTagFormFieldComponent);
3582
+
3583
+ class TechlifyTaggerTagFormFieldModule {
3584
+ }
3585
+ TechlifyTaggerTagFormFieldModule.decorators = [
3586
+ { type: NgModule, args: [{
3587
+ declarations: [
3588
+ TechlifyTaggerTagFormFieldComponent
3589
+ ],
3211
3590
  imports: [
3212
3591
  CommonModule,
3213
- ReactiveFormsModule,
3214
- InfiniteScrollModule,
3215
- FlexLayoutModule,
3216
- ActionPopupModule,
3217
3592
  MaterialModule,
3218
- ReadMoreModule
3219
- ],
3220
- exports: [
3221
- NoteListComponent
3593
+ FlexLayoutModule,
3594
+ MatAutocompleteModule,
3595
+ ReactiveFormsModule
3222
3596
  ],
3223
- entryComponents: [NoteFormComponent]
3597
+ exports: [TechlifyTaggerTagFormFieldComponent]
3224
3598
  },] }
3225
3599
  ];
3226
3600
 
@@ -3245,28 +3619,136 @@ SearchableSelectorModule.decorators = [
3245
3619
  },] }
3246
3620
  ];
3247
3621
 
3248
- class UtilityModule {
3622
+ class EntityFilesViewAllModule {
3249
3623
  }
3250
- UtilityModule.decorators = [
3624
+ EntityFilesViewAllModule.decorators = [
3251
3625
  { type: NgModule, args: [{
3626
+ declarations: [EntityFileFormComponent, EntityFilesViewAllComponent],
3252
3627
  imports: [
3253
3628
  CommonModule,
3254
3629
  FormsModule,
3630
+ ReactiveFormsModule,
3631
+ FlexLayoutModule,
3632
+ FileDropperModule,
3633
+ DocumentViewerModule,
3634
+ InfiniteScrollModule,
3635
+ ActionPopupModule,
3636
+ MaterialModule,
3637
+ TechlifyTaggerTagFormFieldModule,
3638
+ SearchableSelectorModule
3255
3639
  ],
3256
- declarations: [
3257
- NumItemsSelector, NumberSelector,
3640
+ exports: [
3641
+ EntityFilesViewAllComponent
3258
3642
  ],
3259
- exports: [NumItemsSelector, NumberSelector]
3260
- },] }
3261
- ];
3262
-
3263
- const routes = [];
3264
- class TimelineFilterRoutingModule {
3265
- }
3266
- TimelineFilterRoutingModule.decorators = [
3267
- { type: NgModule, args: [{
3268
- imports: [RouterModule.forChild(routes)],
3269
- exports: [RouterModule]
3643
+ entryComponents: [EntityFileFormComponent]
3644
+ },] }
3645
+ ];
3646
+
3647
+ class ReadMoreComponent {
3648
+ constructor() {
3649
+ this.maxLength = 100;
3650
+ this.hideToggle = true;
3651
+ this.isCollapsed = true;
3652
+ }
3653
+ ngOnInit() {
3654
+ this.determineView();
3655
+ }
3656
+ toggleView() {
3657
+ this.isCollapsed = !this.isCollapsed;
3658
+ this.determineView();
3659
+ }
3660
+ determineView() {
3661
+ if (!this.text || this.text.length <= this.maxLength) {
3662
+ this.currentText = this.text;
3663
+ this.isCollapsed = false;
3664
+ this.hideToggle = true;
3665
+ return;
3666
+ }
3667
+ this.hideToggle = false;
3668
+ if (this.isCollapsed == true) {
3669
+ this.currentText = this.text.substring(0, this.maxLength) + "...";
3670
+ }
3671
+ else if (this.isCollapsed == false) {
3672
+ this.currentText = this.text;
3673
+ }
3674
+ }
3675
+ }
3676
+ ReadMoreComponent.decorators = [
3677
+ { type: Component, args: [{
3678
+ selector: "app-read-more",
3679
+ template: "<div [innerHTML]=\"currentText\"></div>\n<a href=\"javascript:;\" *ngIf=\"!hideToggle\" class=\"primary-color hoverable\" (click)=\"toggleView()\">Read\n {{ isCollapsed ? \"more\" : \"less\" }}</a>",
3680
+ styles: ["div.collapsed{height:250px;overflow:hidden}.primary-color{color:#009fdd!important}"]
3681
+ },] }
3682
+ ];
3683
+ ReadMoreComponent.ctorParameters = () => [];
3684
+ ReadMoreComponent.propDecorators = {
3685
+ text: [{ type: Input }],
3686
+ maxLength: [{ type: Input }]
3687
+ };
3688
+
3689
+ class ReadMoreModule {
3690
+ }
3691
+ ReadMoreModule.decorators = [
3692
+ { type: NgModule, args: [{
3693
+ declarations: [ReadMoreComponent],
3694
+ imports: [
3695
+ CommonModule,
3696
+ MaterialModule,
3697
+ FlexLayoutModule
3698
+ ],
3699
+ exports: [
3700
+ ReadMoreComponent
3701
+ ]
3702
+ },] }
3703
+ ];
3704
+
3705
+ class NoteModule {
3706
+ }
3707
+ NoteModule.decorators = [
3708
+ { type: NgModule, args: [{
3709
+ declarations: [
3710
+ NoteListComponent,
3711
+ NoteFormComponent,
3712
+ CommentFormComponent,
3713
+ ],
3714
+ imports: [
3715
+ CommonModule,
3716
+ ReactiveFormsModule,
3717
+ InfiniteScrollModule,
3718
+ FlexLayoutModule,
3719
+ ActionPopupModule,
3720
+ MaterialModule,
3721
+ ReadMoreModule
3722
+ ],
3723
+ exports: [
3724
+ NoteListComponent
3725
+ ],
3726
+ entryComponents: [NoteFormComponent]
3727
+ },] }
3728
+ ];
3729
+
3730
+ class UtilityModule {
3731
+ }
3732
+ UtilityModule.decorators = [
3733
+ { type: NgModule, args: [{
3734
+ imports: [
3735
+ CommonModule,
3736
+ FormsModule,
3737
+ ],
3738
+ declarations: [
3739
+ NumItemsSelector, NumberSelector,
3740
+ ],
3741
+ exports: [NumItemsSelector, NumberSelector]
3742
+ },] }
3743
+ ];
3744
+
3745
+ const routes = [];
3746
+ class TimelineFilterRoutingModule {
3747
+ }
3748
+ TimelineFilterRoutingModule.decorators = [
3749
+ { type: NgModule, args: [{
3750
+ imports: [RouterModule.forChild(routes)],
3751
+ exports: [RouterModule]
3270
3752
  },] }
3271
3753
  ];
3272
3754
 
@@ -6087,295 +6569,6 @@ LoginHistoryForUserModule.decorators = [
6087
6569
  },] }
6088
6570
  ];
6089
6571
 
6090
- class TechlifyTaggerTagFormConfigModel {
6091
- constructor() {
6092
- this.selectable = true;
6093
- this.removable = true;
6094
- this.separatorKeysCodes = [ENTER, COMMA];
6095
- this.placeholder = 'New Tag..';
6096
- this.apiUrl = 'api/techlify-tagger-tags';
6097
- this.createApiUrl = 'api/techlify-tagger-tags';
6098
- this.isCreateable = true;
6099
- this.isCacheTags = false;
6100
- this.isSingle = false;
6101
- }
6102
- }
6103
-
6104
- var TechlifyTaggerTagFormFieldComponent_1;
6105
- let TechlifyTaggerTagFormFieldComponent = TechlifyTaggerTagFormFieldComponent_1 = class TechlifyTaggerTagFormFieldComponent {
6106
- constructor(_focusMonitor, _elementRef, httpService, _formField, ngControl) {
6107
- this._focusMonitor = _focusMonitor;
6108
- this._elementRef = _elementRef;
6109
- this.httpService = httpService;
6110
- this._formField = _formField;
6111
- this.ngControl = ngControl;
6112
- this.stateChanges = new Subject();
6113
- this.focused = false;
6114
- this.controlType = 'techlify-tagger-form-field';
6115
- this.id = `techlify-tagger-form-field-${TechlifyTaggerTagFormFieldComponent_1.nextId++}`;
6116
- this.onChange = (_) => { };
6117
- this.onTouched = () => { };
6118
- this.tagInputCtrl = new FormControl();
6119
- /**Pass the configuration for Techlify Tagger */
6120
- this.config = new TechlifyTaggerTagFormConfigModel();
6121
- /**Pass the default list of tags */
6122
- this._allTags = [];
6123
- /**Pass the Categories to filter for a model */
6124
- this.categories = [];
6125
- this._required = false;
6126
- this._disabled = false;
6127
- this._value = [];
6128
- this.tagInputCtrl.valueChanges
6129
- .subscribe(filterValue => {
6130
- this.filterString = filterValue;
6131
- });
6132
- //Set Focus Monitor
6133
- _focusMonitor.monitor(_elementRef, true).subscribe(origin => {
6134
- if (this.focused && !origin) {
6135
- this.onTouched();
6136
- }
6137
- this.focused = !!origin;
6138
- this.stateChanges.next();
6139
- });
6140
- if (this.ngControl != null) {
6141
- this.ngControl.valueAccessor = this;
6142
- }
6143
- }
6144
- get allTags() {
6145
- return this._allTags;
6146
- }
6147
- set allTags(value) {
6148
- this._allTags = value;
6149
- }
6150
- get tags() {
6151
- return this.allTags.filter(x => this.value.some(y => y == x.id));
6152
- }
6153
- //Default Getter and Setters for a Form Field Implementation
6154
- get empty() {
6155
- return this.value.length == 0;
6156
- }
6157
- get shouldLabelFloat() {
6158
- return this.focused || !this.empty || this.tagInputCtrl.value;
6159
- }
6160
- get required() {
6161
- return this._required;
6162
- }
6163
- set required(value) {
6164
- this._required = coerceBooleanProperty(value);
6165
- this.stateChanges.next();
6166
- }
6167
- get disabled() {
6168
- return this._disabled;
6169
- }
6170
- set disabled(value) {
6171
- this._disabled = coerceBooleanProperty(value);
6172
- this._disabled ? this.tagInputCtrl.disable() : this.tagInputCtrl.enable();
6173
- this.stateChanges.next();
6174
- }
6175
- get value() {
6176
- return this._value;
6177
- }
6178
- set value(tagIds) {
6179
- this._value = tagIds || [];
6180
- this.stateChanges.next();
6181
- }
6182
- get errorState() {
6183
- return this.tagInputCtrl.dirty && this.required && (this.value.length == 0);
6184
- }
6185
- get placeholder() {
6186
- return this._placeholder;
6187
- }
6188
- set placeholder(value) {
6189
- this._placeholder = value;
6190
- this.stateChanges.next();
6191
- }
6192
- ngOnInit() {
6193
- }
6194
- ngOnChanges(changes) {
6195
- //API to load all tags for the model type
6196
- if (this.allTags.length == 0) {
6197
- this.httpService
6198
- .cache(!this.config.isCacheTags)
6199
- .get(this.config.apiUrl, {
6200
- params: {
6201
- categories: this.categories.join(','),
6202
- perPage: '1000'
6203
- }
6204
- }).pipe(debounceTime(500), untilDestroyed(this)).subscribe((result) => {
6205
- this.allTags = result.data;
6206
- });
6207
- }
6208
- //API to load only the selected tags for the model
6209
- if (this.modelId && this.value.length == 0) {
6210
- //Model Id is passed and no tags are present, so we query db for the avilable tags for the model ID.
6211
- this.httpService
6212
- .cache(!this.config.isCacheTags)
6213
- .get(this.config.apiUrl, {
6214
- params: {
6215
- categories: this.categories.join(','),
6216
- model_type: this.modelType,
6217
- model_id: this.modelId,
6218
- perPage: '1000'
6219
- }
6220
- }).pipe(debounceTime(500), untilDestroyed(this)).subscribe((result) => {
6221
- this.value = ((result === null || result === void 0 ? void 0 : result.data) || []).map((x) => x.id);
6222
- this._handleInput();
6223
- });
6224
- }
6225
- }
6226
- init() {
6227
- if (this.modelId && this.allTags.length == 0) {
6228
- //Model Id is passed and no tags are passed, so we query db for the avilable tags for the model ID.
6229
- this.httpService
6230
- .cache(!this.config.isCacheTags)
6231
- .get(this.config.apiUrl, {
6232
- params: {
6233
- categories: this.categories.join(','),
6234
- model_type: this.modelType,
6235
- model_id: this.modelId
6236
- }
6237
- }).pipe(untilDestroyed(this)).subscribe((result) => {
6238
- this.allTags = result.data;
6239
- });
6240
- }
6241
- }
6242
- get filteredTags() {
6243
- return this._filter();
6244
- }
6245
- setDescribedByIds(ids) {
6246
- // Just a empty implementation for Mat Form Field Interface
6247
- }
6248
- onContainerClick() {
6249
- // Just a empty implementation for Mat Form Field Interface
6250
- }
6251
- add(event) {
6252
- return __awaiter(this, void 0, void 0, function* () {
6253
- const value = (event.value || '').trim();
6254
- // Add our tag
6255
- // Validate for single mode
6256
- if (!this.config.isSingle || (this.value.length === 0)) {
6257
- if (value && this.config.isCreateable) {
6258
- const tags = this.allTags;
6259
- let tag = tags.find((item) => item.title.toLowerCase() == value.toLowerCase());
6260
- if (!tag) {
6261
- //No tag present in the list
6262
- try {
6263
- const result = yield this.httpService.post(this.config.createApiUrl, {
6264
- title: value,
6265
- description: value,
6266
- category_title: (this.categories.length > 0) ? (this.defaultCreateCategory ? this.defaultCreateCategory : this.categories[0]) : ''
6267
- }).toPromise();
6268
- tag = result.item;
6269
- }
6270
- catch (error) {
6271
- return;
6272
- }
6273
- this.allTags.push(tag);
6274
- }
6275
- else {
6276
- //Optionally clean the existing value, to avoid duplicate
6277
- this.remove(tag);
6278
- }
6279
- this.value.push(tag.id);
6280
- this._handleInput();
6281
- }
6282
- }
6283
- // Clear the input value
6284
- event.input.value = '';
6285
- this.tagInputCtrl.setValue(null);
6286
- });
6287
- }
6288
- remove(tag) {
6289
- this.value = this.value.filter(x => x !== tag.id);
6290
- this._handleInput();
6291
- }
6292
- selected(event) {
6293
- // Validate for single mode
6294
- if (!this.config.isSingle || (this.value.length === 0)) {
6295
- //Clean the existing value, to avoid duplicate
6296
- this.remove({ id: event.option.value });
6297
- this.value.push(event.option.value);
6298
- this._handleInput();
6299
- }
6300
- this.tagInput.nativeElement.value = '';
6301
- this.tagInputCtrl.setValue(null);
6302
- }
6303
- _filter() {
6304
- const filterValue = this.filterString ? this.filterString.toString().toLowerCase() : null;
6305
- const availableTags = this.allTags.filter((tag) => !this.value.some((item) => item == tag.id));
6306
- return filterValue ? availableTags.filter((tag) => tag.title.toLowerCase().includes(filterValue)) : availableTags;
6307
- }
6308
- writeValue(tagIds) {
6309
- this.value = tagIds || [];
6310
- }
6311
- registerOnChange(fn) {
6312
- this.onChange = fn;
6313
- }
6314
- registerOnTouched(fn) {
6315
- this.onTouched = fn;
6316
- }
6317
- setDisabledState(isDisabled) {
6318
- this.disabled = isDisabled;
6319
- }
6320
- _handleInput() {
6321
- this.onChange(this.value);
6322
- }
6323
- ngOnDestroy() {
6324
- this.stateChanges.complete();
6325
- this._focusMonitor.stopMonitoring(this._elementRef);
6326
- }
6327
- };
6328
- TechlifyTaggerTagFormFieldComponent.nextId = 0;
6329
- TechlifyTaggerTagFormFieldComponent.decorators = [
6330
- { type: Component, args: [{
6331
- selector: 'app-techlify-tagger-tag-form-field',
6332
- template: "<mat-chip-list #chipList aria-label=\"Tag Selection\">\n <mat-chip *ngFor=\"let tag of tags\" [selectable]=\"config.selectable\" [removable]=\"config.removable\"\n (removed)=\"remove(tag)\">\n {{tag.title}}\n <button matChipRemove *ngIf=\"config.removable\" class=\"border-0\">\n <mat-icon class=\"mat-relative-icon\">cancel</mat-icon>\n </button>\n </mat-chip>\n <input placeholder=\"{{config.isCreateable? config.placeholder:''}}\" #tagInput [formControl]=\"tagInputCtrl\"\n [matAutocomplete]=\"auto\" [matChipInputFor]=\"chipList\"\n [matChipInputSeparatorKeyCodes]=\"config.separatorKeysCodes\" (matChipInputTokenEnd)=\"add($event)\"\n #trigger=\"matAutocompleteTrigger\" (click)=\"trigger.openPanel()\">\n</mat-chip-list>\n<mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event)\">\n <mat-option *ngFor=\"let tag of filteredTags\" [value]=\"tag.id\">\n {{tag.title}}\n </mat-option>\n</mat-autocomplete>",
6333
- providers: [{ provide: MatFormFieldControl, useExisting: TechlifyTaggerTagFormFieldComponent_1 }],
6334
- styles: [".mat-relative-icon{font-size:20px;position:relative;right:7px;top:-3px}"]
6335
- },] }
6336
- ];
6337
- TechlifyTaggerTagFormFieldComponent.ctorParameters = () => [
6338
- { type: FocusMonitor },
6339
- { type: ElementRef },
6340
- { type: HttpService },
6341
- { type: MatFormField, decorators: [{ type: Optional }, { type: Inject, args: [MAT_FORM_FIELD,] }] },
6342
- { type: NgControl, decorators: [{ type: Optional }, { type: Self }] }
6343
- ];
6344
- TechlifyTaggerTagFormFieldComponent.propDecorators = {
6345
- tagInput: [{ type: ViewChild, args: ['tagInput',] }],
6346
- config: [{ type: Input }],
6347
- modelType: [{ type: Input }],
6348
- modelId: [{ type: Input }],
6349
- allTags: [{ type: Input }],
6350
- categories: [{ type: Input }],
6351
- defaultCreateCategory: [{ type: Input }],
6352
- required: [{ type: Input }],
6353
- disabled: [{ type: Input }],
6354
- value: [{ type: Input }],
6355
- placeholder: [{ type: Input }]
6356
- };
6357
- TechlifyTaggerTagFormFieldComponent = TechlifyTaggerTagFormFieldComponent_1 = __decorate([
6358
- UntilDestroy()
6359
- ], TechlifyTaggerTagFormFieldComponent);
6360
-
6361
- class TechlifyTaggerTagFormFieldModule {
6362
- }
6363
- TechlifyTaggerTagFormFieldModule.decorators = [
6364
- { type: NgModule, args: [{
6365
- declarations: [
6366
- TechlifyTaggerTagFormFieldComponent
6367
- ],
6368
- imports: [
6369
- CommonModule,
6370
- MaterialModule,
6371
- FlexLayoutModule,
6372
- MatAutocompleteModule,
6373
- ReactiveFormsModule
6374
- ],
6375
- exports: [TechlifyTaggerTagFormFieldComponent]
6376
- },] }
6377
- ];
6378
-
6379
6572
  var TechlifyTaggerTagSelectorComponent_1;
6380
6573
  let TechlifyTaggerTagSelectorComponent = TechlifyTaggerTagSelectorComponent_1 = class TechlifyTaggerTagSelectorComponent {
6381
6574
  constructor(_focusMonitor, _elementRef, httpService, _formField, ngControl) {
@@ -6875,5 +7068,5 @@ TechlifyFeatureModule.decorators = [
6875
7068
  * Generated bundle index. Do not edit.
6876
7069
  */
6877
7070
 
6878
- export { ActionPopup, ActionPopupComponent, ActionPopupModule, AlertService, ApiPrefixInterceptor, AuditLogForModelComponent, AuditLogForModelModule, AuditLogForModelRoutingModule, AuditLogListComponent, AuditLogListFilterComponent, AuditLogListFilterModule, AuditLogListFilterRoutingModule, AuditLogListModule, AuditLogListRoutingModule, AuditLogModule, AuditLogRoutingModule, AuditLogViewComponent, AuditLogViewModelComponent, AuditLogViewModelModule, AuditLogViewModelRoutingModule, AuditLogViewModule, AuditLogViewRoutingModule, AuditLogsViewModelComponent, AuditLogsViewModelModule, AuditLogsViewModelRoutingModule, AuthenticationGuard, AuthenticationService, CacheInterceptor, CommentFormComponent, ConfigService, CoreModule, CredentialsService, DataManager, DataTable, DataTableComponent, DataTableModule, DateUtils, DateValidator, DocumentViewerComponent, DocumentViewerModule, EmailSubscriptionForUserComponent, EmailSubscriptionForUserModule, EmailSubscriptionForUserRoutingModule, EmailSubscriptionModule, EmailSubscriptionRoutingModule, EmailSubscriptionTypeFormComponent, EmailSubscriptionTypeFormModule, EmailSubscriptionTypeFormRoutingModule, EmailSubscriptionTypeListComponent, EmailSubscriptionTypeListModule, EmailSubscriptionTypeListRoutingModule, EmailSubscriptionTypeModule, EmailSubscriptionTypeRoutingModule, EmailSubscriptionUserFormComponent, EmailSubscriptionUserFormModule, EmailSubscriptionUserFormRoutingModule, EmailSubscriptionUserListComponent, EmailSubscriptionUserListFilterComponent, EmailSubscriptionUserListFilterModule, EmailSubscriptionUserListFilterRoutingModule, EmailSubscriptionUserListModule, EmailSubscriptionUserListRoutingModule, EmailSubscriptionUserModule, EmailSubscriptionUserRoutingModule, EntityFileFormComponent, EntityFilesViewAllComponent, EntityFilesViewAllModule, ErrorHandlerInterceptor, ErrorHandlerService, ErrorSnackComponent, ExportExcelButtonComponent, ExportExcelModule, FileDropperComponent, FileDropperConfig, FileDropperModule, FormValidatorService, HTTP_DYNAMIC_INTERCEPTORS, HttpCacheService, HttpService, ImportCsvComponent, ImportCsvModule, LoaderComponent, LoaderModule, LogLevel, Logger, LoginHistoryForUserComponent, LoginHistoryForUserModule, LoginHistoryForUserRoutingModule, MatSelectInfiniteScrollDirective, MaterialModule, NoteFormComponent, NoteListComponent, NoteModule, NumItemsSelector, NumberSelector, PageEvent, ReadMoreComponent, ReadMoreModule, RouteReusableStrategy, SearchableSelectorComponent, SearchableSelectorModule, SnackModule, StorageService, SuccessSnackComponent, TechlifyConfig, TechlifyFeatureEnabledDirective, TechlifyFeatureListingComponent, TechlifyFeatureModule, TechlifyFeatureRoutes, TechlifyTaggerTagFormConfigModel, TechlifyTaggerTagFormFieldComponent, TechlifyTaggerTagFormFieldModule, TechlifyTaggerTagSelectorComponent, TechlifyTaggerTagSelectorModule, TechlifyUpdateHistoryModule, TechlifyUpdateModule, Timeline, TimelineFilterComponent, TimelineFilterModule, TokenInterceptor, UpdateNotifierComponent, UpdateNotifierModule, UtilityModule, ViewerConfig, calculateTimeline, esfur, estlr, esulr, SnackModule as ɵa, SuccessSnackComponent as ɵb, NumberSelector as ɵba, TimelineFilterComponent as ɵbb, TimelineFilterRoutingModule as ɵbc, LoaderComponent as ɵbd, EmailSubscriptionUserFormComponent as ɵbe, EmailSubscriptionUserListComponent as ɵbf, AuthenticationGuard as ɵbg, EmailSubscriptionUserListFilterComponent as ɵbh, EmailSubscriptionTypeFormComponent as ɵbi, EmailSubscriptionTypeListComponent as ɵbj, EmailSubscriptionForUserComponent as ɵbk, TechlifyUpdatesListComponent as ɵbl, TechlifyUpdateService as ɵbm, TechlifyUpdateRoutingModule as ɵbn, TechlifyUpdateFormModule as ɵbo, TechlifyUpdateFormComponent as ɵbp, TechlifyUpdateHistoryRoutingModule as ɵbq, TechlifyUpdateHistoryComponent as ɵbr, UpdateNotifierSnackComponent as ɵbs, UpdateViewModule as ɵbt, UpdateViewComponent as ɵbu, DataManager as ɵbv, ErrorHandlerService as ɵbw, FieldMappingComponent as ɵbx, FailedItemsListComponent as ɵby, ImportHistoryListComponent as ɵbz, ErrorSnackComponent as ɵc, ImportSuccessComponent as ɵca, DataImportComponent as ɵcb, StorageService as ɵcc, TechlifyFeatureService as ɵcd, OnOffSwitchComponent as ɵce, HTTP_DYNAMIC_INTERCEPTORS as ɵd, HttpService as ɵe, RouteReusableStrategy as ɵf, ActionPopupComponent as ɵg, ActionPopup as ɵh, DataTableComponent as ɵi, DocumentViewerComponent as ɵj, EntityFileFormComponent as ɵk, FormValidatorService as ɵl, EntityFileService as ɵm, AlertService as ɵn, EntityFilesViewAllComponent as ɵo, FileDropperComponent as ɵp, NoteListComponent as ɵq, NoteService as ɵr, NoteFormComponent as ɵs, CommentFormComponent as ɵt, CredentialsService as ɵu, ConfigService as ɵv, TechlifyConfig as ɵw, SearchableSelectorComponent as ɵx, MatSelectInfiniteScrollDirective as ɵy, NumItemsSelector as ɵz };
7071
+ export { ActionPopup, ActionPopupComponent, ActionPopupModule, AlertService, ApiPrefixInterceptor, AuditLogForModelComponent, AuditLogForModelModule, AuditLogForModelRoutingModule, AuditLogListComponent, AuditLogListFilterComponent, AuditLogListFilterModule, AuditLogListFilterRoutingModule, AuditLogListModule, AuditLogListRoutingModule, AuditLogModule, AuditLogRoutingModule, AuditLogViewComponent, AuditLogViewModelComponent, AuditLogViewModelModule, AuditLogViewModelRoutingModule, AuditLogViewModule, AuditLogViewRoutingModule, AuditLogsViewModelComponent, AuditLogsViewModelModule, AuditLogsViewModelRoutingModule, AuthenticationGuard, AuthenticationService, CacheInterceptor, CommentFormComponent, ConfigService, CoreModule, CredentialsService, DataManager, DataTable, DataTableComponent, DataTableModule, DateUtils, DateValidator, DocumentViewerComponent, DocumentViewerModule, EmailSubscriptionForUserComponent, EmailSubscriptionForUserModule, EmailSubscriptionForUserRoutingModule, EmailSubscriptionModule, EmailSubscriptionRoutingModule, EmailSubscriptionTypeFormComponent, EmailSubscriptionTypeFormModule, EmailSubscriptionTypeFormRoutingModule, EmailSubscriptionTypeListComponent, EmailSubscriptionTypeListModule, EmailSubscriptionTypeListRoutingModule, EmailSubscriptionTypeModule, EmailSubscriptionTypeRoutingModule, EmailSubscriptionUserFormComponent, EmailSubscriptionUserFormModule, EmailSubscriptionUserFormRoutingModule, EmailSubscriptionUserListComponent, EmailSubscriptionUserListFilterComponent, EmailSubscriptionUserListFilterModule, EmailSubscriptionUserListFilterRoutingModule, EmailSubscriptionUserListModule, EmailSubscriptionUserListRoutingModule, EmailSubscriptionUserModule, EmailSubscriptionUserRoutingModule, EntityFileFormComponent, EntityFilesViewAllComponent, EntityFilesViewAllModule, ErrorHandlerInterceptor, ErrorHandlerService, ErrorSnackComponent, ExportExcelButtonComponent, ExportExcelModule, FileDropperComponent, FileDropperConfig, FileDropperModule, FormValidatorService, HTTP_DYNAMIC_INTERCEPTORS, HttpCacheService, HttpService, ImportCsvComponent, ImportCsvModule, LoaderComponent, LoaderModule, LogLevel, Logger, LoginHistoryForUserComponent, LoginHistoryForUserModule, LoginHistoryForUserRoutingModule, MatSelectInfiniteScrollDirective, MaterialModule, NoteFormComponent, NoteListComponent, NoteModule, NumItemsSelector, NumberSelector, PageEvent, ReadMoreComponent, ReadMoreModule, RouteReusableStrategy, SearchableSelectorComponent, SearchableSelectorModule, SnackModule, StorageService, SuccessSnackComponent, TechlifyConfig, TechlifyFeatureEnabledDirective, TechlifyFeatureListingComponent, TechlifyFeatureModule, TechlifyFeatureRoutes, TechlifyFormComponentInterface, TechlifyListingControllerInterface, TechlifyServiceBaseClass, TechlifyTaggerTagFormConfigModel, TechlifyTaggerTagFormFieldComponent, TechlifyTaggerTagFormFieldModule, TechlifyTaggerTagSelectorComponent, TechlifyTaggerTagSelectorModule, TechlifyUpdateHistoryModule, TechlifyUpdateModule, Timeline, TimelineFilterComponent, TimelineFilterModule, TokenInterceptor, UpdateNotifierComponent, UpdateNotifierModule, UtilityModule, ViewerConfig, calculateTimeline, esfur, estlr, esulr, SnackModule as ɵa, SuccessSnackComponent as ɵb, NumberSelector as ɵba, TimelineFilterComponent as ɵbb, TimelineFilterRoutingModule as ɵbc, LoaderComponent as ɵbd, EmailSubscriptionUserFormComponent as ɵbe, EmailSubscriptionUserListComponent as ɵbf, AuthenticationGuard as ɵbg, EmailSubscriptionUserListFilterComponent as ɵbh, EmailSubscriptionTypeFormComponent as ɵbi, EmailSubscriptionTypeListComponent as ɵbj, EmailSubscriptionForUserComponent as ɵbk, TechlifyUpdatesListComponent as ɵbl, TechlifyUpdateService as ɵbm, TechlifyUpdateRoutingModule as ɵbn, TechlifyUpdateFormModule as ɵbo, TechlifyUpdateFormComponent as ɵbp, TechlifyUpdateHistoryRoutingModule as ɵbq, TechlifyUpdateHistoryComponent as ɵbr, UpdateNotifierSnackComponent as ɵbs, UpdateViewModule as ɵbt, UpdateViewComponent as ɵbu, DataManager as ɵbv, ErrorHandlerService as ɵbw, FieldMappingComponent as ɵbx, FailedItemsListComponent as ɵby, ImportHistoryListComponent as ɵbz, ErrorSnackComponent as ɵc, ImportSuccessComponent as ɵca, DataImportComponent as ɵcb, StorageService as ɵcc, TechlifyFeatureService as ɵcd, OnOffSwitchComponent as ɵce, HTTP_DYNAMIC_INTERCEPTORS as ɵd, HttpService as ɵe, RouteReusableStrategy as ɵf, ActionPopupComponent as ɵg, ActionPopup as ɵh, DataTableComponent as ɵi, DocumentViewerComponent as ɵj, EntityFileFormComponent as ɵk, FormValidatorService as ɵl, EntityFileService as ɵm, AlertService as ɵn, EntityFilesViewAllComponent as ɵo, FileDropperComponent as ɵp, SearchableSelectorComponent as ɵq, MatSelectInfiniteScrollDirective as ɵr, NoteListComponent as ɵs, NoteService as ɵt, NoteFormComponent as ɵu, CommentFormComponent as ɵv, CredentialsService as ɵw, ConfigService as ɵx, TechlifyConfig as ɵy, NumItemsSelector as ɵz };
6879
7072
  //# sourceMappingURL=ngx-techlify-core.js.map