@trudb/tru-common-lib 0.0.450 → 0.0.451

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,20 +1,20 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Directive, Input, Component, NgModule, Injectable, Inject, HostListener, EventEmitter, ViewEncapsulation, Output, APP_INITIALIZER, InjectionToken } from '@angular/core';
3
- import { EntityAspect, BinaryPredicate, AndOrPredicate, breeze, MetadataStore, EntityManager, DataService, EntityQuery, FetchStrategy, EntityState } from 'breeze-client';
4
- import * as i1$3 from '@angular/common';
5
- import { CommonModule } from '@angular/common';
6
- import * as i7 from '@angular/forms';
7
- import { FormsModule, FormGroup, FormControl, Validators, ReactiveFormsModule } from '@angular/forms';
8
- import { BehaviorSubject, Subject, defer, from, of, Observable, skip, forkJoin, throwError } from 'rxjs';
2
+ import { Directive, Input, Injectable, Component, Inject, HostListener, NgModule, EventEmitter, ViewEncapsulation, Output, APP_INITIALIZER, InjectionToken } from '@angular/core';
3
+ import { EntityAspect, MetadataStore, EntityManager, DataService, EntityQuery, FetchStrategy, EntityState, BinaryPredicate, AndOrPredicate, breeze } from 'breeze-client';
4
+ import { BehaviorSubject, defer, from, of, Observable, Subject, skip, forkJoin, throwError } from 'rxjs';
9
5
  import * as _ from 'underscore';
10
- import moment from 'moment/moment';
11
- import * as i1 from '@angular/material/dialog';
12
- import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
13
6
  import * as i1$2 from '@angular/common/http';
14
7
  import { HttpClientModule, HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http';
8
+ import * as i1 from '@angular/material/dialog';
9
+ import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
10
+ import * as i7 from '@angular/forms';
11
+ import { FormsModule, FormGroup, FormControl, Validators, ReactiveFormsModule } from '@angular/forms';
15
12
  import * as i3 from '@angular/material/checkbox';
16
13
  import { MatCheckboxModule } from '@angular/material/checkbox';
17
14
  import * as i1$1 from 'ngx-toastr';
15
+ import * as i1$3 from '@angular/common';
16
+ import { CommonModule } from '@angular/common';
17
+ import moment from 'moment/moment';
18
18
  import * as i7$1 from 'ag-grid-angular';
19
19
  import { AgGridModule } from 'ag-grid-angular';
20
20
  import * as i2 from '@angular/material/icon';
@@ -238,1538 +238,1730 @@ class TruTableConfigBase {
238
238
  }
239
239
  }
240
240
 
241
- class TruDetailViewBase {
242
- constructor() { }
243
- }
244
- TruDetailViewBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDetailViewBase, deps: [], target: i0.ɵɵFactoryTarget.Component });
245
- TruDetailViewBase.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.1", type: TruDetailViewBase, selector: "tru-detail-view-base", ngImport: i0, template: "", styles: [""] });
246
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDetailViewBase, decorators: [{
247
- type: Component,
248
- args: [{ selector: 'tru-detail-view-base', template: "" }]
249
- }], ctorParameters: function () { return []; } });
250
-
251
- class DetailViewModule {
252
- }
253
- DetailViewModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: DetailViewModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
254
- DetailViewModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.1", ngImport: i0, type: DetailViewModule, declarations: [TruDetailViewBase], imports: [CommonModule, FormsModule], exports: [TruDetailViewBase] });
255
- DetailViewModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: DetailViewModule, imports: [CommonModule, FormsModule] });
256
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: DetailViewModule, decorators: [{
257
- type: NgModule,
258
- args: [{
259
- declarations: [TruDetailViewBase],
260
- imports: [CommonModule, FormsModule],
261
- exports: [TruDetailViewBase]
262
- }]
263
- }] });
264
-
265
- class TruDesktopViewConfig {
266
- onActive() {
267
- return this.active$;
268
- }
269
- active(value) {
270
- this.active$.next(value);
271
- }
241
+ class TruBreezeMetadataProvider {
272
242
  constructor() {
273
- this.active$ = new BehaviorSubject(true);
274
- this.entities = undefined;
275
- this.entityIndex = 0;
276
- this.isDirty = false;
277
- this.isEditing = false;
278
- this.isInvalid = false;
279
- this.componentName = '';
280
- this.openAsDetaiView = false;
243
+ this._metadata = {};
281
244
  }
282
- }
283
- ;
284
-
285
- class TruWindowEventArgs {
286
- constructor() {
287
- this.title = '';
288
- this.tableName = '';
289
- this.tablePluralName = '';
290
- this.tablePluralLabel = '';
291
- this.context = {};
292
- this.contentBottom = '23px';
293
- this.statusbarDirective = 'tru-statusbar';
294
- this.height = '450px';
295
- this.width = '900px';
296
- this.views = [{}];
297
- this.contextFilters = [];
245
+ get metadata() {
246
+ return this._metadata;
298
247
  }
299
- }
300
- TruWindowEventArgs.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventArgs, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
301
- TruWindowEventArgs.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventArgs, providedIn: 'root' });
302
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventArgs, decorators: [{
303
- type: Injectable,
304
- args: [{
305
- providedIn: 'root'
306
- }]
307
- }] });
308
-
309
- class TruContextFilters {
310
- constructor() {
311
- this.filters = [];
312
- this.valueFor = (tableName) => {
313
- let choice = this.filters.find(f => f.selectedChoice.table === tableName)?.selectedChoice;
314
- if (!choice)
315
- throw new Error('ContextFilterChoice not found. Possible invalid configuration.');
316
- return choice.ref;
317
- };
318
- this.label = () => {
319
- let label = '';
320
- //this.selectedContextFilterChoices.forEach((filter: TruContextFilterChoice) => {
321
- // label += filter.table + ': ' + filter.label + ' ';
322
- //});
323
- return label;
324
- };
248
+ set metadata(json) {
249
+ this._metadata = json;
325
250
  }
326
251
  }
327
- TruContextFilters.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruContextFilters, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
328
- TruContextFilters.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruContextFilters, providedIn: 'root' });
329
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruContextFilters, decorators: [{
252
+ TruBreezeMetadataProvider.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruBreezeMetadataProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
253
+ TruBreezeMetadataProvider.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruBreezeMetadataProvider, providedIn: 'root' });
254
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruBreezeMetadataProvider, decorators: [{
330
255
  type: Injectable,
331
256
  args: [{
332
257
  providedIn: 'root',
333
258
  }]
334
259
  }], ctorParameters: function () { return []; } });
335
260
 
336
- class TruWindowEventHandler {
261
+ class TruAppEnvironment {
337
262
  constructor() {
338
- this.open$ = new Subject();
339
- this.addView$ = new Subject();
340
- this.removeForwadViews$ = new Subject();
263
+ this._activeUserRef = new BehaviorSubject(3);
264
+ this._isSaving = new BehaviorSubject(false);
265
+ this._saveComplete = new BehaviorSubject(null);
266
+ this._revertComplete = new BehaviorSubject(null);
267
+ this._deleteComplete = new BehaviorSubject(null);
268
+ this.onSavingChanged$ = this._isSaving.asObservable();
269
+ this.onSaveComplete$ = this._saveComplete.asObservable();
270
+ this.onRevertComplete$ = this._revertComplete.asObservable();
271
+ this.onDeleteComplete$ = this._deleteComplete.asObservable();
272
+ this.saveComplete = (event) => {
273
+ this._saveComplete.next(event);
274
+ };
275
+ this.revertComplete = (event) => {
276
+ this._revertComplete.next(event);
277
+ };
278
+ this.deleteComplete = (event) => {
279
+ this._deleteComplete.next(event);
280
+ };
281
+ this.formatDeleteConfirmationMessage = (tableName, tablePluralLabel, count) => {
282
+ if (count === null)
283
+ return 'Are you sure you want to delete this ' + tableName + '?';
284
+ if (count === 1)
285
+ return 'Are you sure you want to delete 1 ' + tableName + '?';
286
+ return 'Are you sure you want to delete ' + count + ' ' + tablePluralLabel + '?';
287
+ };
288
+ this._appUri = '';
289
+ this._maxRecordCount = 0;
290
+ this.msgModifierKeyLabel = this.isMac ? 'Cmd' : 'Ctrl';
291
+ this.msgConfirmExitWithChangesPending = 'You have unsaved changes that will be lost.';
292
+ this.msgDeleteSuccessful = 'Delete succeeded';
293
+ this.msgSaveSuccessful = 'Save succeeded';
294
+ this.msgNoChangesToSave = 'No changes to save';
295
+ this.msgSaveInProgress = 'Save in progress';
296
+ this.msgInvalidData = 'Invalid data';
297
+ this.msgDirtyPreventsReadOnly = 'Save or revert before disabling editing';
298
+ this.msgDirtyPreventsNavigate = 'Save or revert before navigating';
299
+ this.msgDirtyPreventsClose = 'Save or revert before closing window';
300
+ this.msgDirtyPreventsDeleteExistingRecord = 'Save or revert before deleting';
301
+ this.msgNoDeleteAccess = 'Contact administrator about delete access';
302
+ this.msgCannotDeleteNewAndExistingRecords = 'Delete new or existing records - but not both';
303
+ this.msgDeleteReferencingRecordsFirst = 'Delete all referencing records first';
304
+ this.msgNoRecordsSelected = 'No Records selected';
341
305
  }
342
- onOpen() {
343
- return this.open$;
306
+ get appUri() {
307
+ return this._appUri;
344
308
  }
345
- open(windowEvent) {
346
- this.open$.next(windowEvent);
309
+ set appUri(uri) {
310
+ this._appUri = uri;
347
311
  }
348
- onAddView() {
349
- return this.addView$;
312
+ get activeUserRef() {
313
+ return this._activeUserRef.getValue();
350
314
  }
351
- addView(windowAddViewEvent) {
352
- this.addView$.next(windowAddViewEvent);
315
+ set activeUserRef(ref) {
316
+ this._activeUserRef.next(ref);
353
317
  }
354
- onRemoveForwardViews() {
355
- return this.removeForwadViews$;
318
+ get isSaving() {
319
+ return this._isSaving.getValue();
356
320
  }
357
- removeForwardViews() {
358
- this.removeForwadViews$.next(null);
321
+ set isSaving(isSaving) {
322
+ this._isSaving.next(isSaving);
323
+ }
324
+ get maxRecordCount() {
325
+ return this._maxRecordCount;
326
+ }
327
+ set maxRecordCount(maxRecordCount) {
328
+ this._maxRecordCount = maxRecordCount;
329
+ }
330
+ get isMac() {
331
+ return navigator.platform.toUpperCase().indexOf('MAC') >= 0;
359
332
  }
360
333
  }
361
- TruWindowEventHandler.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
362
- TruWindowEventHandler.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventHandler, providedIn: 'root' });
363
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventHandler, decorators: [{
364
- type: Injectable,
365
- args: [{
366
- providedIn: 'root'
367
- }]
368
- }] });
334
+ TruAppEnvironment.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruAppEnvironment, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
335
+ TruAppEnvironment.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruAppEnvironment });
336
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruAppEnvironment, decorators: [{
337
+ type: Injectable
338
+ }], ctorParameters: function () { return []; } });
369
339
 
370
- class TruDesktopManager {
371
- constructor(contextFilters, windowEventHandler) {
372
- this.contextFilters = contextFilters;
373
- this.windowEventHandler = windowEventHandler;
374
- this.getWindowEvent = (tableName, tablePluralName, tablePluralLabel, componentName, entities = [], openAsDetaiView = false) => {
375
- var windowEvent = new TruWindowEventArgs();
376
- windowEvent.tableName = tableName;
377
- windowEvent.tablePluralName = tablePluralName;
378
- windowEvent.tablePluralLabel = tablePluralLabel;
379
- windowEvent.contextFilters = this.contextFilters.filters;
380
- windowEvent.views = [
381
- {
382
- active: true,
383
- entities: entities,
384
- entityIndex: 0,
385
- isDirty: false,
386
- isEditing: false,
387
- isInvalid: false,
388
- openAsDetaiView: openAsDetaiView,
389
- componentName: componentName
390
- }
391
- ];
392
- return windowEvent;
393
- };
340
+ class TruBreezeContextFactory {
341
+ constructor(breezeMetadataProvider, environment) {
342
+ this.breezeMetadataProvider = breezeMetadataProvider;
343
+ this.environment = environment;
394
344
  /**
395
- * Opens a window for a directive.
396
- * @param {string} directiveName - name of the view directive.
397
- * @param {object} data - values to pass to the view.
398
- * @param {optional bool} showIfExists - if true and a view already exists for the
399
- * directive, then shows its window instead of creating a new one.
400
- */
401
- this.addWindow = (tableName, tablePluralName, tablePluralLabel, componentName, entities = [], openAsDetaiView = false, showNavigation = true, showIfExists) => {
402
- this.windowEventHandler.open(this.getWindowEvent(tableName, tablePluralName, tablePluralLabel, componentName, entities, openAsDetaiView));
345
+ * Maximum number of records to return from a query.
346
+ * @return {number}
347
+ */
348
+ this.servicePath = '';
349
+ this.metadataStore = new MetadataStore();
350
+ this.setUpMetadata = (metadata) => {
351
+ if (this.metadataStore.isEmpty())
352
+ return this.metadataStore.importMetadata(metadata);
353
+ return this.metadataStore;
403
354
  };
404
- this.windowTitlesByBaseText = {};
405
355
  /**
406
- * Returns a unique string for the base name of a window. At first, returns the input.
407
- * For second call with same base name, returns the name plus ' - 2' and so on. When
408
- * all of the titles for the base name are released, then the next title will have no
409
- * suffix.
410
- * @param {string} text - base name of a window.
411
- * @returns {object} - text: the unique text and release(): releases the name for
412
- * future windows.
413
- */
414
- this.getUniqueTitle = (text) => {
415
- var baseText = text;
416
- var titles = this.windowTitlesByBaseText[baseText];
417
- if (!titles) {
418
- this.windowTitlesByBaseText[baseText] = titles = {
419
- dispensedCount: 1,
420
- activeCount: 1
421
- };
422
- }
423
- else {
424
- ++titles.activeCount;
425
- text += ' - ' + (++titles.dispensedCount);
356
+ * Returns a new data context object.
357
+ * @return {object} - Breeze Manager
358
+ */
359
+ this.createContext = (tableName = null) => {
360
+ let entityManager = new EntityManager({
361
+ dataService: this.breezeDataService,
362
+ metadataStore: this.metadataStore
363
+ });
364
+ let breezeContext = new TruBreezeContext(entityManager);
365
+ /**
366
+ * Cache the active user's user record since it is required to be in the cache
367
+ * for some situations such as when create new record and the view displays the
368
+ * created user audit property. If it fails, the next context will try again.
369
+ * Of course, the already existing context(s) won't have the record cached, but
370
+ * it's a rather unlikely situation and it's non-fatal, so just let it fail.
371
+ */
372
+ var activeUserRecordExport;
373
+ if (activeUserRecordExport) {
374
+ entityManager.importEntities(activeUserRecordExport);
426
375
  }
427
- return {
428
- text: text,
429
- release: () => {
430
- if (titles.activeCount === 1)
431
- delete this.windowTitlesByBaseText[baseText];
432
- else {
433
- --titles.activeCount;
434
- }
435
- }
436
- };
376
+ return breezeContext;
437
377
  };
378
+ this.servicePath = environment.appUri + '/api/TruDB';
379
+ /**
380
+ * Note: hasServerMetadata is false to prevent the automatic query of the metadata from the server.
381
+ */
382
+ this.breezeDataService = new DataService({
383
+ serviceName: this.servicePath,
384
+ hasServerMetadata: false
385
+ });
438
386
  }
439
387
  }
440
- TruDesktopManager.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDesktopManager, deps: [{ token: TruContextFilters }, { token: TruWindowEventHandler }], target: i0.ɵɵFactoryTarget.Injectable });
441
- TruDesktopManager.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDesktopManager, providedIn: 'root' });
442
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDesktopManager, decorators: [{
388
+ TruBreezeContextFactory.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruBreezeContextFactory, deps: [{ token: TruBreezeMetadataProvider }, { token: TruAppEnvironment }], target: i0.ɵɵFactoryTarget.Injectable });
389
+ TruBreezeContextFactory.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruBreezeContextFactory, providedIn: 'root' });
390
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruBreezeContextFactory, decorators: [{
443
391
  type: Injectable,
444
392
  args: [{
445
393
  providedIn: 'root',
446
394
  }]
447
- }], ctorParameters: function () { return [{ type: TruContextFilters }, { type: TruWindowEventHandler }]; } });
448
-
449
- class TruSearchViewBase {
450
- constructor(desktopManager, truWindowEventHandler) {
451
- this.desktopManager = desktopManager;
452
- this.truWindowEventHandler = truWindowEventHandler;
453
- this.tableName = '';
454
- this.tablePluralName = '';
455
- this.tablePluralLabel = '';
456
- this.pkeyName = '';
457
- this.windowTitle = undefined;
458
- this.unsubscribes = [];
459
- this.expands = [];
460
- this.isSearching = false;
461
- this.entities = [];
462
- this.hasDetailView = true;
463
- this.searchPanelConfig = {
464
- side: 'right',
465
- active: true,
466
- open: true,
467
- modKeyLabel: '',
468
- size: 500,
469
- pinned: false
470
- };
471
- this.onPkeyCellDoubleClicked = (gridConfig) => {
472
- if (this.hasDetailView) {
473
- var truWindowAddViewEventArgs = new TruDesktopViewConfig();
474
- truWindowAddViewEventArgs.entities = gridConfig.api.getRenderedNodes().map((rowNode) => rowNode.data.$entity);
475
- truWindowAddViewEventArgs.entityIndex = gridConfig.rowIndex;
476
- truWindowAddViewEventArgs.componentName = this.tableName + 'DetailView';
477
- this.truWindowEventHandler.addView(truWindowAddViewEventArgs);
478
- this.view.active(false);
479
- }
480
- else {
481
- alert(this.tablePluralLabel + ' does not have a detail view.');
482
- }
483
- };
395
+ }], ctorParameters: function () { return [{ type: TruBreezeMetadataProvider }, { type: TruAppEnvironment }]; } });
396
+ class TruBreezeContext {
397
+ constructor(manager) {
398
+ this.manager = manager;
399
+ this._entityManager = manager;
484
400
  }
485
- setWindowTitle() {
486
- if (!this.windowTitle)
487
- this.windowTitle = this.desktopManager.getUniqueTitle(this.tablePluralLabel);
488
- this.view.window.title = this.windowTitle.text;
401
+ get createQuery() {
402
+ return (x) => { return new EntityQuery(x); };
489
403
  }
490
- releaseWindowTitle() {
491
- this.windowTitle?.release();
404
+ ;
405
+ get entityManager() {
406
+ return this._entityManager;
492
407
  }
493
- }
494
- TruSearchViewBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBase, deps: [{ token: TruDesktopManager }, { token: TruWindowEventHandler }], target: i0.ɵɵFactoryTarget.Component });
495
- TruSearchViewBase.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.1", type: TruSearchViewBase, selector: "tru-search-view-base", inputs: { view: "view" }, ngImport: i0, template: "", styles: [""] });
496
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBase, decorators: [{
497
- type: Component,
498
- args: [{ selector: 'tru-search-view-base', template: "" }]
499
- }], ctorParameters: function () { return [{ type: TruDesktopManager }, { type: TruWindowEventHandler }]; }, propDecorators: { view: [{
500
- type: Input
501
- }] } });
502
-
503
- class TruSearchViewBaseModule {
504
- }
505
- TruSearchViewBaseModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBaseModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
506
- TruSearchViewBaseModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBaseModule, declarations: [TruSearchViewBase], imports: [CommonModule, FormsModule], exports: [TruSearchViewBase] });
507
- TruSearchViewBaseModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBaseModule, imports: [CommonModule, FormsModule] });
508
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBaseModule, decorators: [{
509
- type: NgModule,
510
- args: [{
511
- declarations: [TruSearchViewBase],
512
- imports: [CommonModule, FormsModule],
513
- exports: [TruSearchViewBase]
514
- }]
515
- }] });
408
+ ;
409
+ }
516
410
 
517
- class TruSearchViewControlEventHandler {
518
- constructor() {
519
- this.clear$ = new BehaviorSubject(null);
520
- this.default$ = new BehaviorSubject(null);
521
- }
522
- onSetDefaults() {
523
- return this.default$;
411
+ class TruConfirmDialog {
412
+ constructor(dialogRef, data) {
413
+ this.dialogRef = dialogRef;
414
+ this.data = data;
415
+ this.title = data.title;
416
+ this.message = data.message;
524
417
  }
525
- setDefaults() {
526
- this.default$.next(null);
418
+ ngOnInit() {
527
419
  }
528
- onClearValues() {
529
- return this.clear$;
420
+ onConfirm() {
421
+ this.dialogRef.close(true);
530
422
  }
531
- clearValues() {
532
- this.clear$.next(null);
423
+ onDismiss() {
424
+ this.dialogRef.close(false);
533
425
  }
534
426
  }
535
- TruSearchViewControlEventHandler.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewControlEventHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
536
- TruSearchViewControlEventHandlerprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewControlEventHandler });
537
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewControlEventHandler, decorators: [{
538
- type: Injectable
539
- }] });
540
-
541
- class TruSearchViewEventHandler {
542
- constructor() {
543
- this.search$ = new BehaviorSubject(null);
544
- this.filter$ = new BehaviorSubject(null);
545
- }
546
- search(query) {
547
- this.search$.next(query);
548
- }
549
- onSearch() {
550
- return this.search$.asObservable();
551
- }
552
- filter(query) {
553
- this.filter$.next(query);
554
- }
555
- onFilter() {
556
- return this.filter$.asObservable();
427
+ TruConfirmDialog.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruConfirmDialog, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
428
+ TruConfirmDialogcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.1", type: TruConfirmDialog, selector: "tru-confirm-dialog", ngImport: i0, template: "<h1 mat-dialog-title>\r\n {{title}}\r\n</h1>\r\n\r\n<div mat-dialog-content>\r\n <p>{{message}}</p>\r\n</div>\r\n\r\n<div mat-dialog-actions>\r\n <button mat-button (click)=\"onDismiss()\">No</button>\r\n <button mat-raised-button color=\"primary\" (click)=\"onConfirm()\">Yes</button>\r\n</div>\r\n", styles: [""] });
429
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruConfirmDialog, decorators: [{
430
+ type: Component,
431
+ args: [{ selector: 'tru-confirm-dialog', template: "<h1 mat-dialog-title>\r\n {{title}}\r\n</h1>\r\n\r\n<div mat-dialog-content>\r\n <p>{{message}}</p>\r\n</div>\r\n\r\n<div mat-dialog-actions>\r\n <button mat-button (click)=\"onDismiss()\">No</button>\r\n <button mat-raised-button color=\"primary\" (click)=\"onConfirm()\">Yes</button>\r\n</div>\r\n" }]
432
+ }], ctorParameters: function () { return [{ type: i1.MatDialogRef }, { type: TruConfirmDialog, decorators: [{
433
+ type: Inject,
434
+ args: [MAT_DIALOG_DATA]
435
+ }] }]; } });
436
+ class TruConfirmDialogConfig {
437
+ constructor(title, message) {
438
+ this.title = title;
439
+ this.message = message;
557
440
  }
558
- }
559
- TruSearchViewEventHandler.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewEventHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
560
- TruSearchViewEventHandler.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewEventHandler });
561
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewEventHandler, decorators: [{
562
- type: Injectable
563
- }] });
441
+ }
564
442
 
565
- class TruSearchResultViewBase {
566
- constructor(truWindowEventHandler) {
567
- this.truWindowEventHandler = truWindowEventHandler;
568
- this.tableName = '';
569
- this.tablePluralLabel = '';
570
- this.hasDetailView = true;
571
- this.searchPanelConfig = {
572
- side: 'right',
573
- active: true,
574
- open: true,
575
- modKeyLabel: '',
576
- size: 500,
577
- pinned: false
443
+ class TruExportDialog {
444
+ constructor(dialogRef, data) {
445
+ this.dialogRef = dialogRef;
446
+ this.data = data;
447
+ this.options = {
448
+ useGrid: false,
449
+ useNames: false,
450
+ useEmptyTags: false,
451
+ async: false
578
452
  };
579
- this.onPkeyCellDoubleClicked = (gridConfig) => {
580
- if (this.hasDetailView) {
581
- var truWindowAddViewEventArgs = new TruDesktopViewConfig();
582
- truWindowAddViewEventArgs.entities = gridConfig.api.getRenderedNodes().map((rowNode) => rowNode.data.$entity);
583
- truWindowAddViewEventArgs.entityIndex = gridConfig.rowIndex;
584
- truWindowAddViewEventArgs.componentName = this.tableName + 'DetailView';
585
- this.truWindowEventHandler.addView(truWindowAddViewEventArgs);
586
- }
587
- else {
588
- alert(this.tablePluralLabel + ' does not have a detail view.');
589
- }
453
+ this.onFormatForImportChecked = () => {
454
+ if (!this.options.useNames)
455
+ this.options.useEmptyTags = false;
590
456
  };
457
+ this.title = data.title;
591
458
  }
592
- ngOnInit() {
593
- this.tableName = this.view.window.tableName;
594
- this.tablePluralLabel = this.view.window.tablePluralLabel;
459
+ onConfirm() {
460
+ this.dialogRef.close(this.options);
461
+ }
462
+ onDismiss() {
463
+ this.dialogRef.close(false);
464
+ }
465
+ handleKeyboardEvent(event) {
466
+ if (event.keyCode == 27) {
467
+ this.dialogRef.close(false);
468
+ }
469
+ if (event.keyCode == 13) {
470
+ event.stopPropagation();
471
+ this.dialogRef.close(this.options);
472
+ }
595
473
  }
474
+ ngOnInit() { }
596
475
  }
597
- TruSearchResultViewBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBase, deps: [{ token: TruWindowEventHandler }], target: i0.ɵɵFactoryTarget.Component });
598
- TruSearchResultViewBase.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.1", type: TruSearchResultViewBase, selector: "tru-search-result-view-base", inputs: { view: "view" }, ngImport: i0, template: "", styles: [""] });
599
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBase, decorators: [{
600
- type: Component,
601
- args: [{ selector: 'tru-search-result-view-base', template: "" }]
602
- }], ctorParameters: function () { return [{ type: TruWindowEventHandler }]; }, propDecorators: { view: [{
603
- type: Input
604
- }] } });
476
+ TruExportDialog.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruExportDialog, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
477
+ TruExportDialog.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.1", type: TruExportDialog, selector: "tru-export-dialog", host: { listeners: { "document:keypress": "handleKeyboardEvent($event)" } }, ngImport: i0, template: "<h1 mat-dialog-title>\r\n {{title}}\r\n</h1>\r\n\r\n<div mat-dialog-content>\r\n <table>\r\n <tbody>\r\n <tr>\r\n <td class=\"export-dialog-checkbox-container\" title=\"To support importing the export file: use names instead of labels.\">\r\n <mat-checkbox \r\n [(ngModel)]=\"options.useNames\"\r\n (change)=\"onFormatForImportChecked()\"\r\n [labelPosition]=\"'after'\">\r\n Format for import\r\n </mat-checkbox>\r\n </td>\r\n </tr>\r\n <tr>\r\n <td class=\"export-dialog-checkbox-container\" title=\"Export only the rows in the grid. When unchecked, exports the results of a new search without limiting result count as is a normal search.\">\r\n <mat-checkbox \r\n [(ngModel)]=\"options.useGrid\"\r\n [labelPosition]=\"'after'\">\r\n Export grid rows\r\n </mat-checkbox>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n</div>\r\n\r\n<div mat-dialog-actions>\r\n <button mat-button (click)=\"onDismiss()\">No</button>\r\n <button mat-raised-button color=\"primary\" (click)=\"onConfirm()\">Yes</button>\r\n</div>\r\n", styles: [".mat-mdc-dialog-content{overflow:hidden}.export-dialog-checkbox-container{padding-bottom:5px;display:inline-block}\n"], dependencies: [{ kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }] });
478
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruExportDialog, decorators: [{
479
+ type: Component,
480
+ args: [{ selector: 'tru-export-dialog', template: "<h1 mat-dialog-title>\r\n {{title}}\r\n</h1>\r\n\r\n<div mat-dialog-content>\r\n <table>\r\n <tbody>\r\n <tr>\r\n <td class=\"export-dialog-checkbox-container\" title=\"To support importing the export file: use names instead of labels.\">\r\n <mat-checkbox \r\n [(ngModel)]=\"options.useNames\"\r\n (change)=\"onFormatForImportChecked()\"\r\n [labelPosition]=\"'after'\">\r\n Format for import\r\n </mat-checkbox>\r\n </td>\r\n </tr>\r\n <tr>\r\n <td class=\"export-dialog-checkbox-container\" title=\"Export only the rows in the grid. When unchecked, exports the results of a new search without limiting result count as is a normal search.\">\r\n <mat-checkbox \r\n [(ngModel)]=\"options.useGrid\"\r\n [labelPosition]=\"'after'\">\r\n Export grid rows\r\n </mat-checkbox>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n</div>\r\n\r\n<div mat-dialog-actions>\r\n <button mat-button (click)=\"onDismiss()\">No</button>\r\n <button mat-raised-button color=\"primary\" (click)=\"onConfirm()\">Yes</button>\r\n</div>\r\n", styles: [".mat-mdc-dialog-content{overflow:hidden}.export-dialog-checkbox-container{padding-bottom:5px;display:inline-block}\n"] }]
481
+ }], ctorParameters: function () { return [{ type: i1.MatDialogRef }, { type: TruExportDialog, decorators: [{
482
+ type: Inject,
483
+ args: [MAT_DIALOG_DATA]
484
+ }] }]; }, propDecorators: { handleKeyboardEvent: [{
485
+ type: HostListener,
486
+ args: ['document:keypress', ['$event']]
487
+ }] } });
488
+ class TruExportDialogConfig {
489
+ constructor(title) {
490
+ this.title = title;
491
+ }
492
+ }
605
493
 
606
- class TruSearchResultViewBaseModule {
494
+ class TruUiNotification {
495
+ constructor(toastr, dialog) {
496
+ this.toastr = toastr;
497
+ this.dialog = dialog;
498
+ this.showMessage = (popup, log, prefix, message, detail = null) => {
499
+ popup(message);
500
+ message = prefix + ': ' + message;
501
+ if (detail)
502
+ message += '\r\n' + detail;
503
+ this.log(message);
504
+ };
505
+ /**
506
+ * Shows as toast and logs to server an error message and optional detail information.
507
+ * @param {string} message - Displayed as toast.
508
+ * @param {string} [detail] - Logged to console.
509
+ */
510
+ this.error = (message, detail = null) => {
511
+ this.showMessage((message) => this._toastr.error(message), this.log, 'Error', message, detail);
512
+ };
513
+ /**
514
+ * Same as error() but for info message.
515
+ */
516
+ this.info = (message, detail = null) => {
517
+ this.showMessage((message) => this._toastr.info(message), this.log, 'Info', message, detail);
518
+ };
519
+ /**
520
+ * Same as error() but for success message.
521
+ */
522
+ this.success = (message, detail = null) => {
523
+ this.showMessage((message) => this._toastr.success(message), this.log, 'Success', message, detail);
524
+ };
525
+ /**
526
+ * Same as error() but for warning message.
527
+ */
528
+ this.warning = (message, detail = null) => {
529
+ this.showMessage((message) => this._toastr.warning(message), this.log, 'Warning', message, detail);
530
+ };
531
+ this.log = (message) => {
532
+ var console = window.console;
533
+ !!console && console.log && console.log.apply && console.log.apply(console, [message]);
534
+ };
535
+ this.showErrorDialog = (title, message) => {
536
+ };
537
+ this.showExportDialog = () => {
538
+ return new Promise((resolve, reject) => {
539
+ let dialogConfig = new TruExportDialogConfig('Export');
540
+ let dialogRef = this._dialog.open(TruExportDialog, {
541
+ disableClose: true,
542
+ minWidth: "200px",
543
+ maxWidth: "400px",
544
+ data: dialogConfig
545
+ });
546
+ dialogRef.afterClosed().subscribe(dialogResult => {
547
+ resolve(dialogResult);
548
+ });
549
+ });
550
+ };
551
+ this.confirm = (title, message) => {
552
+ return new Promise((resolve, reject) => {
553
+ let dialogConfig = new TruConfirmDialogConfig(title, message);
554
+ let dialogRef = this._dialog.open(TruConfirmDialog, {
555
+ disableClose: true,
556
+ minWidth: "200px",
557
+ maxWidth: "400px",
558
+ data: dialogConfig
559
+ });
560
+ dialogRef.afterClosed().subscribe(dialogResult => {
561
+ resolve(dialogResult);
562
+ });
563
+ });
564
+ };
565
+ this._toastr = toastr;
566
+ this._dialog = dialog;
567
+ }
607
568
  }
608
- TruSearchResultViewBaseModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBaseModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
609
- TruSearchResultViewBaseModulemod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBaseModule, declarations: [TruSearchResultViewBase], imports: [CommonModule, FormsModule], exports: [TruSearchResultViewBase] });
610
- TruSearchResultViewBaseModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBaseModule, imports: [CommonModule, FormsModule] });
611
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBaseModule, decorators: [{
612
- type: NgModule,
569
+ TruUiNotification.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruUiNotification, deps: [{ token: i1$1.ToastrService }, { token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Injectable });
570
+ TruUiNotificationprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruUiNotification, providedIn: 'root' });
571
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruUiNotification, decorators: [{
572
+ type: Injectable,
613
573
  args: [{
614
- declarations: [TruSearchResultViewBase],
615
- imports: [CommonModule, FormsModule],
616
- exports: [TruSearchResultViewBase]
574
+ providedIn: 'root',
617
575
  }]
618
- }] });
619
-
620
- class TruChoice {
621
- }
576
+ }], ctorParameters: function () { return [{ type: i1$1.ToastrService }, { type: i1.MatDialog }]; } });
622
577
 
623
- class TruContextFilter {
624
- constructor() {
625
- this.tooltip = undefined;
626
- this.choices = [];
627
- this.identify = (index, choice) => {
628
- return choice.ref;
578
+ class TruEntityAccessor {
579
+ constructor(http, appEnvironment, uiNotification) {
580
+ this.http = http;
581
+ this.appEnvironment = appEnvironment;
582
+ this.uiNotification = uiNotification;
583
+ this._maxRecordCount = 0;
584
+ this.getQueryServiceName = (entity) => {
585
+ return 'Query' + entity.name;
629
586
  };
630
- this.comparer = (o1, o2) => {
631
- return o1 && o2 ? o1.label === o2.label : o2 === o2;
587
+ this.warnIfMaxRecords = (entities, entityName) => {
588
+ if (entities.length >= this._maxRecordCount)
589
+ this.uiNotification.warning('[' + entityName + '] has more records available than supported');
632
590
  };
633
- this.onChange = (choice) => {
634
- this.selectedChoice = choice;
591
+ this.formatQueryChoices = (query, entities, pKeyName, hid = null) => {
592
+ if (query && query.orderByClause)
593
+ return _.map(entities, (entity) => { return { value: { $: entity[pKeyName] }, label: hid !== null ? hid : entity.HID }; });
594
+ else
595
+ return _.map(entities, (entity) => { return { value: { $: entity[pKeyName] }, label: hid !== null ? hid : entity.HID }; });
635
596
  };
636
- }
637
- }
638
-
639
- class TruContextFilterChoice {
640
- constructor(table, label, ref) {
641
- this.table = table;
642
- this.label = label;
643
- this.ref = ref;
644
- }
645
- }
646
-
647
- class TruFormulaEval {
648
- static isString(s) {
649
- return typeof s === 'string';
650
- }
651
- static isDate(v) {
652
- return Object.prototype.toString.call(v) === '[object Date]';
653
- }
654
- static toValue(value) {
655
- return value;
656
- }
657
- static toString(value) {
658
- //if (_.isBoolean(value))
659
- // return value ? 'TRUE' : 'FALSE';
660
- return value.toString();
661
- }
662
- static toDouble(value) {
663
- return Number(value);
664
- }
665
- static toInteger(value) {
666
- return Math.round(value);
667
- }
668
- static toBoolean(value) {
669
- if (_.isBoolean(value))
670
- return value;
671
- var number = Number(value);
672
- if (isNaN(number))
673
- return NaN;
674
- return number !== 0;
675
- }
676
- static toDate(value) {
677
- return value;
678
- }
679
- statictoDateTime(value) {
680
- return value;
681
- }
682
- /**
683
- * Exposed for testing.
684
- */
685
- static _calculate(f, left, right) {
686
- if (TruFormulaEval.isString(left))
687
- left = parseFloat(left);
688
- if (TruFormulaEval.isString(left))
689
- if (TruFormulaEval.isString(right))
690
- right = parseFloat(right);
691
- return f(left, right);
692
- }
693
- static _calculateDate(left, right, add) {
694
- if (add) {
695
- if (TruFormulaEval.isDate(left) && !TruFormulaEval.isDate(right)) {
696
- return moment(left).add(right, 'day').toDate();
697
- }
698
- if (!TruFormulaEval.isDate(left) && TruFormulaEval.isDate(right)) {
699
- return moment(right).add(left, 'day').toDate();
597
+ this.add = (entity, contextFilters = null) => {
598
+ let newEntity = this._entityManager.createEntity(entity.prototype.entityType);
599
+ return newEntity;
600
+ };
601
+ this.search = (entity, setupQuery = null, expands, global) => {
602
+ var query;
603
+ if (expands && expands.length) {
604
+ if (global)
605
+ query = this._breezeContext.createQuery(this.getQueryServiceName(entity)).expand(expands.join(', '));
606
+ else
607
+ query = this._breezeContext.createQuery(this.getQueryServiceName(entity)).expand(expands.join(', ')).top(this._maxRecordCount);
700
608
  }
701
- if (TruFormulaEval.isDate(left) && TruFormulaEval.isDate(right)) {
702
- moment(left).add(right).toDate();
609
+ else {
610
+ if (global)
611
+ query = this._breezeContext.createQuery(this.getQueryServiceName(entity));
612
+ else
613
+ query = this._breezeContext.createQuery(this.getQueryServiceName(entity)).top(this._maxRecordCount);
703
614
  }
704
- }
705
- else {
706
- if (TruFormulaEval.isDate(left) && !TruFormulaEval.isDate(right)) {
707
- return moment(left).subtract(right, 'day').toDate();
615
+ if (setupQuery != null)
616
+ query = setupQuery(query);
617
+ return defer(() => from(this._entityManager.executeQuery(query).then((queryData) => {
618
+ if (!global)
619
+ this.warnIfMaxRecords(queryData.results, entity.name);
620
+ return queryData.results;
621
+ })));
622
+ };
623
+ this.searchCacheOnly = (entity, setupQuery = null, expands = null) => {
624
+ var query = this._breezeContext.createQuery(this.getQueryServiceName(entity));
625
+ if (setupQuery)
626
+ query = setupQuery(query);
627
+ return of(this._entityManager.executeQueryLocally(query));
628
+ };
629
+ this.searchCacheOnlySynchronously = (entity, setupQuery = null, expands = null) => {
630
+ var query = this._breezeContext.createQuery(this.getQueryServiceName(entity));
631
+ if (setupQuery)
632
+ query = setupQuery(query);
633
+ return this._entityManager.executeQueryLocally(query);
634
+ };
635
+ this.searchQueryChoices = (entity, setupQuery = null, hid = null, goToServer = false, ref = undefined) => {
636
+ const pkeyName = entity.name + 'Ref';
637
+ let query = this._breezeContext.createQuery(this.getQueryServiceName(entity));
638
+ if (setupQuery)
639
+ query = setupQuery(query) ?? query;
640
+ if (ref)
641
+ query = query.where(entity.name + 'Ref', '==', ref);
642
+ if (goToServer) {
643
+ return defer(() => from(this._entityManager.executeQuery(query).then((queryData) => {
644
+ return this.formatQueryChoices(query, queryData.results, pkeyName, null);
645
+ })));
708
646
  }
709
- if (!TruFormulaEval.isDate(left) && TruFormulaEval.isDate(right)) {
710
- return moment(right).subtract(left, 'day').toDate();
711
- }
712
- if (TruFormulaEval.isDate(left) && TruFormulaEval.isDate(right)) {
713
- //var m = moment(left).diff(right, 'days'); //Integer value, but Excel uses decimal for date time
714
- var m = moment(left).diff(moment(right)) / 86400000; //divide by miliseconds in a day, decimal answer 1.0 = 1 day, 0.5 = 12 hours
715
- return m;
647
+ return of(this.formatQueryChoices(query, this._entityManager.executeQueryLocally(query), pkeyName, null));
648
+ };
649
+ this.searchByRef = (entity, ref) => {
650
+ const pkeyName = entity.name + 'Ref';
651
+ var queryOptions = this._entityManager.queryOptions.using({
652
+ fetchStrategy: FetchStrategy.FromServer
653
+ });
654
+ var query = this._breezeContext.createQuery(this.getQueryServiceName(entity)).where(entity.name + 'Ref', '==', ref).using(queryOptions);
655
+ return defer(() => from(this._entityManager.executeQuery(query).then((queryData) => {
656
+ return this.formatQueryChoices(query, queryData.results, pkeyName, null);
657
+ })));
658
+ };
659
+ this.searchByRefPreferedCache = (entity, ref) => {
660
+ let cachedEntity = this.searchByRefCacheOnly(entity, ref);
661
+ if (cachedEntity) {
662
+ var queryOptions = this._entityManager.queryOptions.using({
663
+ fetchStrategy: FetchStrategy.FromLocalCache
664
+ });
665
+ var query = this._breezeContext.createQuery(this.getQueryServiceName(entity)).where(entity.name + 'Ref', '==', ref).using(queryOptions);
666
+ return defer(() => from(this._entityManager.executeQuery(query).then((queryData) => {
667
+ return queryData.results[0];
668
+ })));
716
669
  }
717
- }
718
- return null;
719
- }
720
- static add(left, right) {
721
- if (left === null || left === undefined || right === null || right === undefined)
722
- return undefined;
723
- if (TruFormulaEval.isDate(left) || TruFormulaEval.isDate(right))
724
- return TruFormulaEval._calculateDate(left, right, true);
725
- return TruFormulaEval._calculate(function (l, r) { return l + r; }, left, right);
726
- }
727
- static subtract(left, right) {
728
- if (left === null || left === undefined || right === null || right === undefined)
729
- return undefined;
730
- if (TruFormulaEval.isDate(left) || TruFormulaEval.isDate(right))
731
- return TruFormulaEval._calculateDate(left, right, true);
732
- return TruFormulaEval._calculate(function (l, r) { return l - r; }, left, right);
733
- }
734
- static multiply(left, right) {
735
- if (left === null || left === undefined || right === null || right === undefined)
736
- return undefined;
737
- return TruFormulaEval._calculate(function (l, r) { return l * r; }, left, right);
738
- }
739
- static divide(left, right) {
740
- if (left === null || left === undefined || right === null || right === undefined)
741
- return undefined;
742
- return TruFormulaEval._calculate(function (l, r) { return l / r; }, left, right);
743
- }
744
- static power(left, right) {
745
- if (left === null || left === undefined || right === null || right === undefined)
746
- return undefined;
747
- return TruFormulaEval._calculate(Math.pow, left, right);
748
- }
749
- static concatenate(left, right) {
750
- if (_.isBoolean(left))
751
- left = left ? 'TRUE' : 'FALSE';
752
- else if (!TruFormulaEval.isString(left))
753
- //NOTE: only need to convert left to string since concat() will coerce parameters
754
- left = left.toString();
755
- if (_.isBoolean(right))
756
- right = right ? 'TRUE' : 'FALSE';
757
- return left.concat(right);
758
- }
759
- static equal(left, right) {
760
- return left === right;
761
- }
762
- static notEqual(left, right) {
763
- return left !== right;
764
- }
765
- static lessThan(left, right) {
766
- if (typeof (left) !== typeof (right))
767
- return !TruFormulaEval.compareResultForMismatchedParams[typeof (left) + typeof (right)];
768
- return left < right;
769
- }
770
- static greaterThan(left, right) {
771
- if (typeof (left) !== typeof (right))
772
- return TruFormulaEval.compareResultForMismatchedParams[typeof (left) + typeof (right)];
773
- return left > right;
774
- }
775
- static lessThanOrEqual(left, right) {
776
- if (typeof (left) !== typeof (right))
777
- return !TruFormulaEval.compareResultForMismatchedParams[typeof (left) + typeof (right)];
778
- return left <= right;
779
- }
780
- static greaterThanOrEqual(left, right) {
781
- if (typeof (left) !== typeof (right))
782
- return TruFormulaEval.compareResultForMismatchedParams[typeof (left) + typeof (right)];
783
- return left >= right;
784
- }
785
- static negate(operand) {
786
- return -operand;
787
- }
788
- static percent(operand) {
789
- return operand / 100.0;
790
- }
791
- }
792
- TruFormulaEval.compareResultForMismatchedParams = {
793
- booleanstring: true,
794
- booleannumber: true,
795
- stringnumber: true,
796
- stringboolean: false,
797
- numberstring: false,
798
- numberboolean: false
799
- };
800
-
801
- class TruPredicate {
802
- constructor(field, operator, value, propertyQueryPath, overQuoted = false) {
803
- this._breezePredicate = null;
804
- this.handleOperator = (fieldOrPredicate, oper, operator, value) => {
805
- var breezePredicate;
806
- if (Array.isArray(fieldOrPredicate)) {
807
- breezePredicate = new TruPredicate(fieldOrPredicate[0], fieldOrPredicate[1], fieldOrPredicate[2], []);
670
+ else {
671
+ var queryOptions = this._entityManager.queryOptions.using({
672
+ fetchStrategy: FetchStrategy.FromServer
673
+ });
674
+ var query = this._breezeContext.createQuery(this.getQueryServiceName(entity)).where(entity.name + 'Ref', '==', ref).using(queryOptions);
675
+ return defer(() => from(this._entityManager.executeQuery(query).then((queryData) => {
676
+ return queryData.results[0];
677
+ })));
808
678
  }
809
- else if (fieldOrPredicate.constructor === TruPredicate || fieldOrPredicate.constructor === BinaryPredicate || fieldOrPredicate.constructor === AndOrPredicate) {
810
- breezePredicate = fieldOrPredicate;
679
+ };
680
+ this.searchByRefCacheOnly = (entity, ref, includeDeleted = false) => {
681
+ if (!includeDeleted)
682
+ includeDeleted = false;
683
+ var queryOptions = this._entityManager.queryOptions.using({
684
+ includeDeleted: includeDeleted,
685
+ fetchStrategy: FetchStrategy.FromLocalCache
686
+ });
687
+ var query = this._breezeContext.createQuery(this.getQueryServiceName(entity)).where(entity.name + 'Ref', '==', ref).using(queryOptions);
688
+ var result = this._entityManager.executeQueryLocally(query)[0];
689
+ if (result)
690
+ return result;
691
+ return null;
692
+ };
693
+ this.export = (entity, gridSpec, setupQuery, entityRefs, options) => {
694
+ options = options || {};
695
+ var args = {
696
+ runAsync: false,
697
+ useNames: false,
698
+ useEmptyTags: false,
699
+ entityRefs: null,
700
+ entityTypeName: entity.name,
701
+ gridSpec: gridSpec
702
+ };
703
+ if (options.async)
704
+ args.runAsync = true;
705
+ if (options.useNames)
706
+ args.useNames = true;
707
+ if (options.useEmptyTags)
708
+ args.useEmptyTags = true;
709
+ var queryText;
710
+ if (options.useGrid) {
711
+ args.entityRefs = entityRefs;
811
712
  }
812
713
  else {
813
- throw new TypeError('Unexpected parameter type <' + fieldOrPredicate.constructor + '>.');
714
+ var query = this._breezeContext.createQuery('noname');
715
+ if (setupQuery)
716
+ query = setupQuery(query);
717
+ if (query === null) {
718
+ this.uiNotification.warning('No records selected by query');
719
+ return;
720
+ }
721
+ else {
722
+ queryText = query._toUri(this._entityManager);
723
+ queryText = queryText.split('?')[1];
724
+ }
814
725
  }
815
- breezePredicate = oper(breezePredicate);
816
- return new TruPredicate(breezePredicate, null, null, null);
726
+ var argsText = this.formatAsUrlParameters(args);
727
+ if (queryText)
728
+ argsText += '&' + queryText;
729
+ this.uiNotification.info(args.runAsync ? 'Queuing export...' : 'Exporting...');
730
+ this.downloadFromUrl('ExportEntities', argsText);
817
731
  };
818
- this.and = (fieldOrPredicate, operator, value) => {
819
- var that = this;
820
- return this.handleOperator(fieldOrPredicate, function (p) { return that._breezePredicate.and(p); }, operator, value);
732
+ this.formatAsUrlParameters = (data) => {
733
+ var buffer = [];
734
+ for (var name in data) {
735
+ if (!data.hasOwnProperty(name)) {
736
+ continue;
737
+ }
738
+ var value = data[name];
739
+ buffer.push(encodeURIComponent(name) +
740
+ '=' + encodeURIComponent(value == null ? '' : value));
741
+ }
742
+ var source = buffer.join('&')
743
+ .replace(/%20/g, '+');
744
+ return (source);
821
745
  };
822
- this.or = (fieldOrPredicate, operator, value) => {
823
- var that = this;
824
- return this.handleOperator(fieldOrPredicate, function (p) { return that._breezePredicate.and(p); }, operator, value);
746
+ this.downloadFromUrl = (url, data) => {
747
+ if (data)
748
+ data = this.formatAsUrlParameters(data);
749
+ const body = { title: 'download request' };
750
+ const headers = { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' };
751
+ this.http.post(url, body, { headers }).subscribe((response) => {
752
+ this.saveDownloadedFile(response);
753
+ });
825
754
  };
826
- this.not = () => {
827
- var breezePredicate = this._breezePredicate.not();
828
- return new TruPredicate(breezePredicate, null, null, null);
755
+ this.saveDownloadedFile = (response) => {
756
+ var headers = response.headers;
757
+ var contentDisposition = headers('content-disposition');
758
+ if (!contentDisposition)
759
+ return; // NOTE: cannot save without header info
760
+ var filename = this.extractFilenameFromContentDisposition(contentDisposition);
761
+ var blob = new Blob([response.data], { type: headers('content-type') });
762
+ var link = document.createElement('a');
763
+ link.href = URL.createObjectURL(blob);
764
+ link.setAttribute('download', filename);
765
+ link.click();
766
+ link.remove();
829
767
  };
830
- if (typeof field === 'string') {
831
- var args = propertyQueryPath?.slice(0);
832
- args[args.length - 1] += field;
833
- args.push(operator);
834
- args.push(value);
835
- this._breezePredicate = new breeze.Predicate(args);
836
- this._breezePredicate.overQuoted = overQuoted;
837
- }
838
- else if (arguments[0].constructor === TruPredicate || arguments[0].constructor === BinaryPredicate || arguments[0].constructor === AndOrPredicate) {
839
- this._breezePredicate = arguments[0];
840
- }
841
- else {
842
- throw new TypeError('Unexpected parameter type <' + arguments[0].constructor + '>.');
843
- }
768
+ this.extractFilenameFromContentDisposition = (text) => {
769
+ var parts = _.map(text.split(';'), function (part) { return part.trim(); });
770
+ var prefix = 'filename=';
771
+ var filenamePart = _.find(parts, function (part) { return part.substring(0, prefix.length) === prefix; });
772
+ if (!filenamePart)
773
+ return 'file';
774
+ var filename = filenamePart.substring(prefix.length);
775
+ filename = filename.replace(/"/g, '');
776
+ return filename;
777
+ };
778
+ this._maxRecordCount = this.appEnvironment.maxRecordCount;
844
779
  }
845
- }
846
-
847
- class TruPropertyConfigForeignKey extends TruPropertyConfigBase {
848
- constructor() {
849
- super();
850
- this.table = undefined;
851
- this.foreignTableName = undefined;
852
- this.choicesQuery = undefined;
853
- }
854
- }
855
-
856
- class TruPropertyConfigCloudFile extends TruPropertyConfigForeignKey {
857
- constructor() { super(); }
858
- }
859
-
860
- class TruPropertyConfigDate extends TruPropertyConfigBase {
861
- constructor() {
862
- super();
863
- this.minimumValue = undefined;
864
- this.maximumValue = undefined;
865
- }
866
- }
867
-
868
- class TruPropertyConfigDecimal extends TruPropertyConfigBase {
869
- constructor() {
870
- super();
871
- this.decimalPlaces = undefined;
872
- this.totalDigits = undefined;
873
- this.minimumValue = undefined;
874
- this.maximumValue = undefined;
875
- }
876
- }
877
-
878
- class TruPropertyConfigFile extends TruPropertyConfigBase {
879
- constructor() {
880
- super();
881
- this.maxSize = undefined;
882
- }
883
- }
884
-
885
- class TruPropertyConfigInteger extends TruPropertyConfigBase {
886
- constructor() {
887
- super();
888
- this.minimumValue = undefined;
889
- this.maximumValue = undefined;
890
- }
891
- }
892
-
893
- class TruPropertyConfigText extends TruPropertyConfigBase {
894
- constructor() {
895
- super();
896
- this.maxLength = undefined;
897
- this.minLength = undefined;
898
- this.unbounded = undefined;
899
- }
900
- }
901
-
902
- class TruPropertyConfigPassword extends TruPropertyConfigText {
903
- constructor() {
904
- super();
905
- this.encryptionType = undefined;
906
- }
907
- }
908
-
909
- class TruPropertyConfigPercentage extends TruPropertyConfigBase {
910
- constructor() {
911
- super();
912
- this.minimumValue = undefined;
913
- this.maximumValue = undefined;
914
- }
915
- }
916
-
917
- class TruPropertyConfigScientific extends TruPropertyConfigBase {
918
- constructor() {
919
- super();
920
- this.minimumValue = undefined;
921
- this.maximumValue = undefined;
922
- }
923
- }
924
-
925
- class TruPropertyConfigTextChoices extends TruPropertyConfigText {
926
- constructor() {
927
- super();
928
- this.choices = {};
929
- }
930
- }
931
-
932
- class TruPropertyConfigUsaAddress extends TruPropertyConfigBase {
933
- constructor() {
934
- super();
935
- this.requireZipPlusFour = undefined;
936
- }
937
- }
938
-
939
- class TruPropertyConfigZipCode extends TruPropertyConfigBase {
940
- constructor() {
941
- super();
942
- this.requireZipPlusFour = undefined;
780
+ set context(dataContext) {
781
+ this._breezeContext = dataContext.breezeContext;
782
+ this._entityManager = dataContext.entityManager;
943
783
  }
944
- }
784
+ }
785
+ TruEntityAccessor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruEntityAccessor, deps: [{ token: i1$2.HttpClient }, { token: TruAppEnvironment }, { token: TruUiNotification }], target: i0.ɵɵFactoryTarget.Injectable });
786
+ TruEntityAccessor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruEntityAccessor });
787
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruEntityAccessor, decorators: [{
788
+ type: Injectable
789
+ }], ctorParameters: function () { return [{ type: i1$2.HttpClient }, { type: TruAppEnvironment }, { type: TruUiNotification }]; } });
945
790
 
946
- class TruQueryPredicateManager {
947
- constructor(propertyQueryPath, predicateName, predicateMap) {
948
- this._predicate = null;
949
- this._propertyQueryPath = [];
950
- this._predicateName = '';
951
- this._predicateMap = {};
952
- this.setPredicate = (queryPredicate) => {
953
- if (this._predicate !== queryPredicate && this._predicateMap !== null) {
954
- this._predicate = queryPredicate;
955
- this._predicateMap[this._predicateName] = this._predicate === null ? null : this._predicate;
956
- }
791
+ class TruDataContext {
792
+ constructor(breezeContextFactory, appEnvironment, entityAccessor, uiNotification) {
793
+ this.breezeContextFactory = breezeContextFactory;
794
+ this.appEnvironment = appEnvironment;
795
+ this.entityAccessor = entityAccessor;
796
+ this.uiNotification = uiNotification;
797
+ this._pendingDeleteEntities = [];
798
+ this._pendingCascadeDeleteEntities = [];
799
+ this.validationChangeDetection = new Observable((observer) => {
800
+ this.entityManager.validationErrorsChanged.subscribe(entities => {
801
+ observer.next(entities);
802
+ });
803
+ });
804
+ this.getValidationErrors = (entities = null) => {
805
+ entities = entities || this.entityManager.getChanges();
806
+ var errorsPerEntity = entities.map((entity) => {
807
+ var errors = entity.entityAspect.getValidationErrors();
808
+ errors = errors.map((err) => {
809
+ return {
810
+ entity: entity,
811
+ errorMessage: err.errorMessage,
812
+ property: err.property
813
+ };
814
+ });
815
+ return errors;
816
+ });
817
+ return of(errorsPerEntity);
957
818
  };
958
- /**
959
- * Returns the query predicate.
960
- */
961
- this.get = () => {
962
- return this._predicate;
819
+ this.formatValidationErrors = (entities = null) => {
820
+ let errors = this.getValidationErrors(entities);
821
+ let formattedErrors = new Array();
822
+ errors.subscribe(errorsArray => {
823
+ formattedErrors.push(errorsArray.map((e) => {
824
+ if (e.propertyName) {
825
+ return e.entity.entityType.defaultResourceName + '.' + e.propertyName + ': ' + e.errorMessage;
826
+ }
827
+ var mergeData = JSON.parse(e.entity.Merge_Data);
828
+ if (mergeData &&
829
+ mergeData.constructor === Object &&
830
+ Object.entries(mergeData).length > 0 &&
831
+ mergeData[e.property.name]) {
832
+ return mergeData[e.property.name].modifiedBy + ' changed ' + e.property.name + ' to ' + mergeData[e.property.name].value + '. Accept or Decline the change. ';
833
+ }
834
+ var propertyName = e.property.name ? e.property.name : '[Unknown Property]';
835
+ return e.entity.entityType.defaultResourceName + '.' + propertyName + ': has invalid data.';
836
+ }));
837
+ });
838
+ return formattedErrors;
963
839
  };
964
- /**
965
- * Clears the query predicate.
966
- */
967
- this.clear = () => {
968
- this.setPredicate(null);
840
+ this.findCachedCascadeDeleteDescendants = (entity) => {
841
+ let descendants = [];
842
+ let type = entity.entityType;
843
+ let typeName = type.defaultResourceName;
844
+ let entityChildrenNames = JSON.parse(JSON.stringify('Replace with: ModelNavigationProperties.value'))[typeName];
845
+ Object.entries(entityChildrenNames)
846
+ .forEach(([k, v]) => {
847
+ let property = entity[k];
848
+ property.forEach((child) => {
849
+ if (typeof v === 'object' && v.doesCascadeDelete && child.entityAspect.entityState !== EntityState.Added) {
850
+ throw new Error('Delete of selected item is not possible due to related child that is not setup for cascade delete. Delete children items first.');
851
+ }
852
+ descendants = descendants.concat(this.findCachedCascadeDeleteDescendants(child));
853
+ });
854
+ descendants = property.concat(descendants);
855
+ });
856
+ return descendants;
969
857
  };
970
- /**
971
- * Returns a new query predicate.
972
- *
973
- * @param {string} field - Name of the storage field relative to the intent property.
974
- * @param {string} operator - Name of the predicate operator.
975
- * @param {*} value - Literal value.
976
- */
977
- this.create = (field, operator, value, overQuoted = false) => {
978
- return new TruPredicate(field, operator, value, this._propertyQueryPath, overQuoted)._breezePredicate;
858
+ this.markCachedDescendantsForDelete = (entities) => {
859
+ var cascadeDeleteDescendantsPerEntity = entities.map((entity) => { return this.findCachedCascadeDeleteDescendants(entity); }, entities);
860
+ var cascadeDeleteDescendants = cascadeDeleteDescendantsPerEntity.reduce((memo, i) => { return memo.concat(i); });
861
+ cascadeDeleteDescendants.forEach((entity) => { this.entityManager.detachEntity(entity); });
862
+ this._pendingDeleteEntities = this._pendingDeleteEntities.concat(entities);
863
+ let combined = this._pendingCascadeDeleteEntities.concat(cascadeDeleteDescendants);
864
+ this._pendingCascadeDeleteEntities = combined.filter((n, i) => combined.indexOf(n) === i);
979
865
  };
980
- this.set = (fieldOrPredicate, operator, value, overQuoted = false) => {
981
- var predicate;
982
- if (fieldOrPredicate.constructor === TruPredicate)
983
- predicate = fieldOrPredicate;
984
- else
985
- predicate = this.create(fieldOrPredicate, operator, value, overQuoted);
986
- this.setPredicate(predicate);
866
+ this.markForDelete = (entities) => {
867
+ if (entities.length > 0) {
868
+ this.markCachedDescendantsForDelete(entities);
869
+ entities.forEach((entity) => {
870
+ entity.entityAspect.setDeleted();
871
+ //entity._associatedDataCached = false;
872
+ });
873
+ }
987
874
  };
988
- this._propertyQueryPath = propertyQueryPath;
989
- this._predicateName = predicateName;
990
- this._predicateMap = predicateMap;
991
- }
992
- }
993
-
994
- class TruConfirmDialog {
995
- constructor(dialogRef, data) {
996
- this.dialogRef = dialogRef;
997
- this.data = data;
998
- this.title = data.title;
999
- this.message = data.message;
1000
- }
1001
- ngOnInit() {
1002
- }
1003
- onConfirm() {
1004
- this.dialogRef.close(true);
1005
- }
1006
- onDismiss() {
1007
- this.dialogRef.close(false);
1008
- }
1009
- }
1010
- TruConfirmDialog.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruConfirmDialog, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
1011
- TruConfirmDialog.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.1", type: TruConfirmDialog, selector: "tru-confirm-dialog", ngImport: i0, template: "<h1 mat-dialog-title>\r\n {{title}}\r\n</h1>\r\n\r\n<div mat-dialog-content>\r\n <p>{{message}}</p>\r\n</div>\r\n\r\n<div mat-dialog-actions>\r\n <button mat-button (click)=\"onDismiss()\">No</button>\r\n <button mat-raised-button color=\"primary\" (click)=\"onConfirm()\">Yes</button>\r\n</div>\r\n", styles: [""] });
1012
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruConfirmDialog, decorators: [{
1013
- type: Component,
1014
- args: [{ selector: 'tru-confirm-dialog', template: "<h1 mat-dialog-title>\r\n {{title}}\r\n</h1>\r\n\r\n<div mat-dialog-content>\r\n <p>{{message}}</p>\r\n</div>\r\n\r\n<div mat-dialog-actions>\r\n <button mat-button (click)=\"onDismiss()\">No</button>\r\n <button mat-raised-button color=\"primary\" (click)=\"onConfirm()\">Yes</button>\r\n</div>\r\n" }]
1015
- }], ctorParameters: function () { return [{ type: i1.MatDialogRef }, { type: TruConfirmDialog, decorators: [{
1016
- type: Inject,
1017
- args: [MAT_DIALOG_DATA]
1018
- }] }]; } });
1019
- class TruConfirmDialogConfig {
1020
- constructor(title, message) {
1021
- this.title = title;
1022
- this.message = message;
1023
- }
1024
- }
1025
-
1026
- class TruConfirmDialogModule {
1027
- }
1028
- TruConfirmDialogModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruConfirmDialogModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1029
- TruConfirmDialogModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.1", ngImport: i0, type: TruConfirmDialogModule, declarations: [TruConfirmDialog], imports: [CommonModule, FormsModule], exports: [TruConfirmDialog] });
1030
- TruConfirmDialogModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruConfirmDialogModule, imports: [CommonModule, FormsModule] });
1031
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruConfirmDialogModule, decorators: [{
1032
- type: NgModule,
1033
- args: [{
1034
- declarations: [TruConfirmDialog],
1035
- imports: [CommonModule, FormsModule],
1036
- exports: [TruConfirmDialog]
1037
- }]
1038
- }] });
1039
-
1040
- var TruDataGridTypes;
1041
- (function (TruDataGridTypes) {
1042
- TruDataGridTypes[TruDataGridTypes["Search"] = 0] = "Search";
1043
- TruDataGridTypes[TruDataGridTypes["Detail"] = 1] = "Detail";
1044
- TruDataGridTypes[TruDataGridTypes["DetailManyToMany"] = 2] = "DetailManyToMany";
1045
- })(TruDataGridTypes || (TruDataGridTypes = {}));
1046
-
1047
- class TruBreezeMetadataProvider {
1048
- constructor() {
1049
- this._metadata = {};
1050
- }
1051
- get metadata() {
1052
- return this._metadata;
1053
- }
1054
- set metadata(json) {
1055
- this._metadata = json;
1056
- }
1057
- }
1058
- TruBreezeMetadataProvider.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruBreezeMetadataProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1059
- TruBreezeMetadataProvider.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruBreezeMetadataProvider, providedIn: 'root' });
1060
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruBreezeMetadataProvider, decorators: [{
1061
- type: Injectable,
1062
- args: [{
1063
- providedIn: 'root',
1064
- }]
1065
- }], ctorParameters: function () { return []; } });
1066
-
1067
- class TruAppEnvironment {
1068
- constructor() {
1069
- this._activeUserRef = new BehaviorSubject(3);
1070
- this._isSaving = new BehaviorSubject(false);
1071
- this._saveComplete = new BehaviorSubject(null);
1072
- this._revertComplete = new BehaviorSubject(null);
1073
- this._deleteComplete = new BehaviorSubject(null);
1074
- this.onSavingChanged$ = this._isSaving.asObservable();
1075
- this.onSaveComplete$ = this._saveComplete.asObservable();
1076
- this.onRevertComplete$ = this._revertComplete.asObservable();
1077
- this.onDeleteComplete$ = this._deleteComplete.asObservable();
1078
- this.saveComplete = (event) => {
1079
- this._saveComplete.next(event);
875
+ this.hasChanges = (entityTypes = []) => {
876
+ if (entityTypes.length)
877
+ return this._breezeContext.entityManager.getChanges(entityTypes);
878
+ return this._breezeContext.entityManager.getChanges();
1080
879
  };
1081
- this.revertComplete = (event) => {
1082
- this._revertComplete.next(event);
880
+ this.entityAccess = () => {
881
+ return this.entityAccessor;
1083
882
  };
1084
- this.deleteComplete = (event) => {
1085
- this._deleteComplete.next(event);
883
+ this.exportCahce = () => {
884
+ console.log(this._breezeContext.entityManager.exportEntities());
1086
885
  };
1087
- this.formatDeleteConfirmationMessage = (tableName, tablePluralLabel, count) => {
1088
- if (count === null)
1089
- return 'Are you sure you want to delete this ' + tableName + '?';
1090
- if (count === 1)
1091
- return 'Are you sure you want to delete 1 ' + tableName + '?';
1092
- return 'Are you sure you want to delete ' + count + ' ' + tablePluralLabel + '?';
886
+ this.save = (entities = null, deleteOperation = false) => {
887
+ return new Promise((resolve, reject) => {
888
+ if (this.appEnvironment.isSaving) {
889
+ this.uiNotification.error(this.appEnvironment.msgSaveInProgress);
890
+ resolve();
891
+ return;
892
+ }
893
+ var validationErrorMessages = this.formatValidationErrors(entities);
894
+ if (validationErrorMessages.length > 0) {
895
+ //this.uiNotification.error(this.appEnvironment.msgInvalidData, validationErrorMessages);
896
+ resolve();
897
+ return;
898
+ }
899
+ if (!this.hasChanges().length) {
900
+ this.uiNotification.warning(this.appEnvironment.msgNoChangesToSave);
901
+ resolve();
902
+ return;
903
+ }
904
+ this.appEnvironment.isSaving = true;
905
+ this.entityManager.saveChanges().then(() => {
906
+ if (!deleteOperation) {
907
+ this.uiNotification.success(this.appEnvironment.msgSaveSuccessful);
908
+ this.appEnvironment.saveComplete({ successful: true });
909
+ }
910
+ resolve();
911
+ }).catch((e) => {
912
+ this.appEnvironment.saveComplete({ successful: false });
913
+ reject(e);
914
+ }).finally(() => {
915
+ this.appEnvironment.isSaving = false;
916
+ });
917
+ });
1093
918
  };
1094
- this._appUri = '';
1095
- this._maxRecordCount = 0;
1096
- this.msgModifierKeyLabel = this.isMac ? 'Cmd' : 'Ctrl';
1097
- this.msgConfirmExitWithChangesPending = 'You have unsaved changes that will be lost.';
1098
- this.msgDeleteSuccessful = 'Delete succeeded';
1099
- this.msgSaveSuccessful = 'Save succeeded';
1100
- this.msgNoChangesToSave = 'No changes to save';
1101
- this.msgSaveInProgress = 'Save in progress';
1102
- this.msgInvalidData = 'Invalid data';
1103
- this.msgDirtyPreventsReadOnly = 'Save or revert before disabling editing';
1104
- this.msgDirtyPreventsNavigate = 'Save or revert before navigating';
1105
- this.msgDirtyPreventsClose = 'Save or revert before closing window';
1106
- this.msgDirtyPreventsDeleteExistingRecord = 'Save or revert before deleting';
1107
- this.msgNoDeleteAccess = 'Contact administrator about delete access';
1108
- this.msgCannotDeleteNewAndExistingRecords = 'Delete new or existing records - but not both';
1109
- this.msgDeleteReferencingRecordsFirst = 'Delete all referencing records first';
1110
- this.msgNoRecordsSelected = 'No Records selected';
1111
- }
1112
- get appUri() {
1113
- return this._appUri;
1114
- }
1115
- set appUri(uri) {
1116
- this._appUri = uri;
1117
- }
1118
- get activeUserRef() {
1119
- return this._activeUserRef.getValue();
1120
- }
1121
- set activeUserRef(ref) {
1122
- this._activeUserRef.next(ref);
1123
- }
1124
- get isSaving() {
1125
- return this._isSaving.getValue();
1126
- }
1127
- set isSaving(isSaving) {
1128
- this._isSaving.next(isSaving);
1129
- }
1130
- get maxRecordCount() {
1131
- return this._maxRecordCount;
919
+ this.revert = () => {
920
+ this.uiNotification.confirm('Confirm Action', 'Revert ' + this.hasChanges().length + ' changed record(s)?').then((confirm) => {
921
+ if (confirm) {
922
+ this.entityManager.rejectChanges();
923
+ this.appEnvironment.revertComplete({ successful: true });
924
+ }
925
+ });
926
+ };
927
+ this.revertWithoutPrompt = () => {
928
+ this.revert();
929
+ this.appEnvironment.revertComplete({ successful: true });
930
+ };
931
+ this.delete = (entities, confirmMsg, onSuccess = undefined) => {
932
+ var newEntities = [];
933
+ var existingEntities = [];
934
+ entities.forEach(function (e) {
935
+ if (e.entityAspect.entityState.isAdded())
936
+ newEntities.push(e);
937
+ else
938
+ existingEntities.push(e);
939
+ });
940
+ if (newEntities.length && existingEntities.length) {
941
+ this.uiNotification.warning(this.appEnvironment.msgCannotDeleteNewAndExistingRecords);
942
+ return;
943
+ }
944
+ if (existingEntities.length) {
945
+ if (this.hasChanges().length) {
946
+ this.uiNotification.warning(this.appEnvironment.msgDirtyPreventsDeleteExistingRecord);
947
+ return;
948
+ }
949
+ }
950
+ this.uiNotification.confirm('Confirm Action', confirmMsg).then((confirm) => {
951
+ if (confirm) {
952
+ if (newEntities.length) {
953
+ newEntities.forEach((entity) => {
954
+ entity.entityAspect.clearValidationErrors();
955
+ });
956
+ this.markForDelete(newEntities);
957
+ if (onSuccess)
958
+ onSuccess();
959
+ return;
960
+ }
961
+ try {
962
+ this.markForDelete(existingEntities);
963
+ }
964
+ catch (exception) {
965
+ this.uiNotification.error(exception.message);
966
+ return;
967
+ }
968
+ this.save(null, true).then(() => {
969
+ var entitiesDeleted = this._pendingDeleteEntities.concat(this._pendingCascadeDeleteEntities);
970
+ this.appEnvironment.deleteComplete({ successful: true, entities: entitiesDeleted });
971
+ if (entitiesDeleted.length) {
972
+ this._pendingCascadeDeleteEntities = [];
973
+ this._pendingDeleteEntities = [];
974
+ }
975
+ this.uiNotification.success(this.appEnvironment.msgDeleteSuccessful);
976
+ if (onSuccess)
977
+ onSuccess(true);
978
+ }).catch((error) => {
979
+ this.revert();
980
+ }).finally(() => { });
981
+ }
982
+ });
983
+ };
984
+ this._breezeContext = this.breezeContextFactory.createContext();
985
+ this.entityAccessor.context = this;
1132
986
  }
1133
- set maxRecordCount(maxRecordCount) {
1134
- this._maxRecordCount = maxRecordCount;
987
+ get breezeContext() {
988
+ return this._breezeContext;
1135
989
  }
1136
- get isMac() {
1137
- return navigator.platform.toUpperCase().indexOf('MAC') >= 0;
990
+ get entityManager() {
991
+ return this._breezeContext.entityManager;
1138
992
  }
1139
993
  }
1140
- TruAppEnvironment.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruAppEnvironment, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1141
- TruAppEnvironment.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruAppEnvironment });
1142
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruAppEnvironment, decorators: [{
994
+ TruDataContext.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDataContext, deps: [{ token: TruBreezeContextFactory }, { token: TruAppEnvironment }, { token: TruEntityAccessor }, { token: TruUiNotification }], target: i0.ɵɵFactoryTarget.Injectable });
995
+ TruDataContext.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDataContext });
996
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDataContext, decorators: [{
1143
997
  type: Injectable
1144
- }], ctorParameters: function () { return []; } });
998
+ }], ctorParameters: function () { return [{ type: TruBreezeContextFactory }, { type: TruAppEnvironment }, { type: TruEntityAccessor }, { type: TruUiNotification }]; } });
1145
999
 
1146
- class TruBreezeContextFactory {
1147
- constructor(breezeMetadataProvider, environment) {
1148
- this.breezeMetadataProvider = breezeMetadataProvider;
1149
- this.environment = environment;
1000
+ class TruTextManager {
1001
+ constructor() {
1150
1002
  /**
1151
- * Maximum number of records to return from a query.
1152
- * @return {number}
1003
+ * If text.length exceeds length, then returns a string that is the first length chars
1004
+ * of text plus suffix. Otherwise, returns text.
1005
+ * @param {string} text
1006
+ * @param {number} length
1007
+ * @param {string} suffix
1008
+ * @return {string}
1153
1009
  */
1154
- this.servicePath = '';
1155
- this.metadataStore = new MetadataStore();
1156
- this.setUpMetadata = (metadata) => {
1157
- if (this.metadataStore.isEmpty())
1158
- return this.metadataStore.importMetadata(metadata);
1159
- return this.metadataStore;
1010
+ this.truncate = (text, length, suffix) => {
1011
+ return text.length > length ? text.substr(0, length) + suffix : text.toString();
1012
+ };
1013
+ this.isMac = () => {
1014
+ return navigator.platform.toUpperCase().indexOf('MAC') >= 0;
1160
1015
  };
1161
1016
  /**
1162
- * Returns a new data context object.
1163
- * @return {object} - Breeze Manager
1164
- */
1165
- this.createContext = (tableName = null) => {
1166
- let entityManager = new EntityManager({
1167
- dataService: this.breezeDataService,
1168
- metadataStore: this.metadataStore
1169
- });
1170
- let breezeContext = new TruBreezeContext(entityManager);
1171
- /**
1172
- * Cache the active user's user record since it is required to be in the cache
1173
- * for some situations such as when create new record and the view displays the
1174
- * created user audit property. If it fails, the next context will try again.
1175
- * Of course, the already existing context(s) won't have the record cached, but
1176
- * it's a rather unlikely situation and it's non-fatal, so just let it fail.
1177
- */
1178
- var activeUserRecordExport;
1179
- if (activeUserRecordExport) {
1180
- entityManager.importEntities(activeUserRecordExport);
1181
- }
1182
- return breezeContext;
1017
+ * Formats the text to use for the window title.
1018
+ * @param {string} text
1019
+ * @return {string} - Window title.
1020
+ */
1021
+ this.formatWindowTitle = (text) => {
1022
+ return this.truncate(text, 60, '...');
1183
1023
  };
1184
- this.servicePath = environment.appUri + '/api/TruDB';
1185
1024
  /**
1186
- * Note: hasServerMetadata is false to prevent the automatic query of the metadata from the server.
1025
+ * Returns a message indicating that an entity or entities were deleted in another view.
1026
+ * @param {string} entityTypeLabel - Description of the entity type.
1027
+ * @param [{string}] entityTypePluralLabel - Description of more than one of the entity type.
1028
+ * @param [{number}] count - Number of entities.
1187
1029
  */
1188
- this.breezeDataService = new DataService({
1189
- serviceName: this.servicePath,
1190
- hasServerMetadata: false
1191
- });
1192
- }
1193
- }
1194
- TruBreezeContextFactory.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruBreezeContextFactory, deps: [{ token: TruBreezeMetadataProvider }, { token: TruAppEnvironment }], target: i0.ɵɵFactoryTarget.Injectable });
1195
- TruBreezeContextFactory.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruBreezeContextFactory, providedIn: 'root' });
1196
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruBreezeContextFactory, decorators: [{
1197
- type: Injectable,
1198
- args: [{
1199
- providedIn: 'root',
1200
- }]
1201
- }], ctorParameters: function () { return [{ type: TruBreezeMetadataProvider }, { type: TruAppEnvironment }]; } });
1202
- class TruBreezeContext {
1203
- constructor(manager) {
1204
- this.manager = manager;
1205
- this._entityManager = manager;
1206
- }
1207
- get createQuery() {
1208
- return (x) => { return new EntityQuery(x); };
1209
- }
1210
- ;
1211
- get entityManager() {
1212
- return this._entityManager;
1213
- }
1214
- ;
1215
- }
1216
-
1217
- class TruExportDialog {
1218
- constructor(dialogRef, data) {
1219
- this.dialogRef = dialogRef;
1220
- this.data = data;
1221
- this.options = {
1222
- useGrid: false,
1223
- useNames: false,
1224
- useEmptyTags: false,
1225
- async: false
1226
- };
1227
- this.onFormatForImportChecked = () => {
1228
- if (!this.options.useNames)
1229
- this.options.useEmptyTags = false;
1230
- };
1231
- this.title = data.title;
1232
- }
1233
- onConfirm() {
1234
- this.dialogRef.close(this.options);
1235
- }
1236
- onDismiss() {
1237
- this.dialogRef.close(false);
1238
- }
1239
- handleKeyboardEvent(event) {
1240
- if (event.keyCode == 27) {
1241
- this.dialogRef.close(false);
1242
- }
1243
- if (event.keyCode == 13) {
1244
- event.stopPropagation();
1245
- this.dialogRef.close(this.options);
1246
- }
1247
- }
1248
- ngOnInit() { }
1249
- }
1250
- TruExportDialog.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruExportDialog, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
1251
- TruExportDialog.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.1", type: TruExportDialog, selector: "tru-export-dialog", host: { listeners: { "document:keypress": "handleKeyboardEvent($event)" } }, ngImport: i0, template: "<h1 mat-dialog-title>\r\n {{title}}\r\n</h1>\r\n\r\n<div mat-dialog-content>\r\n <table>\r\n <tbody>\r\n <tr>\r\n <td class=\"export-dialog-checkbox-container\" title=\"To support importing the export file: use names instead of labels.\">\r\n <mat-checkbox \r\n [(ngModel)]=\"options.useNames\"\r\n (change)=\"onFormatForImportChecked()\"\r\n [labelPosition]=\"'after'\">\r\n Format for import\r\n </mat-checkbox>\r\n </td>\r\n </tr>\r\n <tr>\r\n <td class=\"export-dialog-checkbox-container\" title=\"Export only the rows in the grid. When unchecked, exports the results of a new search without limiting result count as is a normal search.\">\r\n <mat-checkbox \r\n [(ngModel)]=\"options.useGrid\"\r\n [labelPosition]=\"'after'\">\r\n Export grid rows\r\n </mat-checkbox>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n</div>\r\n\r\n<div mat-dialog-actions>\r\n <button mat-button (click)=\"onDismiss()\">No</button>\r\n <button mat-raised-button color=\"primary\" (click)=\"onConfirm()\">Yes</button>\r\n</div>\r\n", styles: [".mat-mdc-dialog-content{overflow:hidden}.export-dialog-checkbox-container{padding-bottom:5px;display:inline-block}\n"], dependencies: [{ kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }] });
1252
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruExportDialog, decorators: [{
1253
- type: Component,
1254
- args: [{ selector: 'tru-export-dialog', template: "<h1 mat-dialog-title>\r\n {{title}}\r\n</h1>\r\n\r\n<div mat-dialog-content>\r\n <table>\r\n <tbody>\r\n <tr>\r\n <td class=\"export-dialog-checkbox-container\" title=\"To support importing the export file: use names instead of labels.\">\r\n <mat-checkbox \r\n [(ngModel)]=\"options.useNames\"\r\n (change)=\"onFormatForImportChecked()\"\r\n [labelPosition]=\"'after'\">\r\n Format for import\r\n </mat-checkbox>\r\n </td>\r\n </tr>\r\n <tr>\r\n <td class=\"export-dialog-checkbox-container\" title=\"Export only the rows in the grid. When unchecked, exports the results of a new search without limiting result count as is a normal search.\">\r\n <mat-checkbox \r\n [(ngModel)]=\"options.useGrid\"\r\n [labelPosition]=\"'after'\">\r\n Export grid rows\r\n </mat-checkbox>\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n</div>\r\n\r\n<div mat-dialog-actions>\r\n <button mat-button (click)=\"onDismiss()\">No</button>\r\n <button mat-raised-button color=\"primary\" (click)=\"onConfirm()\">Yes</button>\r\n</div>\r\n", styles: [".mat-mdc-dialog-content{overflow:hidden}.export-dialog-checkbox-container{padding-bottom:5px;display:inline-block}\n"] }]
1255
- }], ctorParameters: function () { return [{ type: i1.MatDialogRef }, { type: TruExportDialog, decorators: [{
1256
- type: Inject,
1257
- args: [MAT_DIALOG_DATA]
1258
- }] }]; }, propDecorators: { handleKeyboardEvent: [{
1259
- type: HostListener,
1260
- args: ['document:keypress', ['$event']]
1261
- }] } });
1262
- class TruExportDialogConfig {
1263
- constructor(title) {
1264
- this.title = title;
1265
- }
1266
- }
1267
-
1268
- class TruUiNotification {
1269
- constructor(toastr, dialog) {
1270
- this.toastr = toastr;
1271
- this.dialog = dialog;
1272
- this.showMessage = (popup, log, prefix, message, detail = null) => {
1273
- popup(message);
1274
- message = prefix + ': ' + message;
1275
- if (detail)
1276
- message += '\r\n' + detail;
1277
- this.log(message);
1030
+ this.fmtEntityDeletedInOtherView = (entityTypeLabel, entityTypePluralLabel, count) => {
1031
+ if (!count || count === 1)
1032
+ return entityTypeLabel + ' deleted in another view';
1033
+ return count + ' ' + entityTypePluralLabel + ' deleted in another view';
1278
1034
  };
1279
1035
  /**
1280
- * Shows as toast and logs to server an error message and optional detail information.
1281
- * @param {string} message - Displayed as toast.
1282
- * @param {string} [detail] - Logged to console.
1283
- */
1284
- this.error = (message, detail = null) => {
1285
- this.showMessage((message) => this._toastr.error(message), this.log, 'Error', message, detail);
1036
+ * Returns a message used to confirm deletion of an entity or entities.
1037
+ * @param {string} entityTypeLabel - Description of the entity type.
1038
+ * @param [{string}] entityTypePluralLabel - Description of more than one of the entity type.
1039
+ * @param [{number}] count - Number of entities.
1040
+ */
1041
+ this.fmtDeleteConfirmation = (entityTypeLabel, entityTypePluralLabel = null, count = null) => {
1042
+ if (count === null)
1043
+ return 'Are you sure you want to delete this ' + entityTypeLabel + '?';
1044
+ if (count === 1)
1045
+ return 'Are you sure you want to delete 1 ' + entityTypeLabel + '?';
1046
+ return 'Are you sure you want to delete ' + count + ' ' + entityTypePluralLabel + '?';
1286
1047
  };
1287
1048
  /**
1288
- * Same as error() but for info message.
1289
- */
1290
- this.info = (message, detail = null) => {
1291
- this.showMessage((message) => this._toastr.info(message), this.log, 'Info', message, detail);
1049
+ * Returns a message formatted from an error object.
1050
+ * @param {error|string} error
1051
+ * @returns {string}
1052
+ */
1053
+ this.fmtErrorToShow = (error) => {
1054
+ if (typeof error === 'string')
1055
+ error = new Error(error);
1056
+ var lines = [];
1057
+ lines.push(error.message);
1058
+ var exception = error.detail;
1059
+ while (exception) {
1060
+ var message = exception.ExceptionMessage;
1061
+ if (!_.contains(lines, message))
1062
+ lines.push(message);
1063
+ exception = exception.InnerException;
1064
+ }
1065
+ if (error.entityErrors) {
1066
+ error.entityErrors.forEach((entityError) => {
1067
+ lines.push('Entity <' + entityError.propertyName + '>: ' + entityError.errorMessage);
1068
+ });
1069
+ }
1070
+ if (error.stack)
1071
+ lines.push(error.stack);
1072
+ var text = lines.join('\r\n\r\n');
1073
+ if (!text)
1074
+ text = _.map(error, (value, key) => { return key + ': ' + value; }).join('\r\n');
1075
+ return text;
1292
1076
  };
1293
1077
  /**
1294
- * Same as error() but for success message.
1078
+ * Returns a message formatted from an exception object.
1079
+ * @param {object} exception
1080
+ * @returns {string}
1295
1081
  */
1296
- this.success = (message, detail = null) => {
1297
- this.showMessage((message) => this._toastr.success(message), this.log, 'Success', message, detail);
1082
+ this.fmtExceptionToShow = (exception) => {
1083
+ var lines = [];
1084
+ while (exception) {
1085
+ var message = exception.Message;
1086
+ if (!_.contains(lines, message))
1087
+ lines.push(message);
1088
+ exception = exception.InnerException;
1089
+ }
1090
+ return lines.join('\r\n\r\n');
1298
1091
  };
1299
1092
  /**
1300
- * Same as error() but for warning message.
1093
+ * Returns a message for a data error type.
1094
+ * @param {string} typeName
1095
+ * @returns {string}
1301
1096
  */
1302
- this.warning = (message, detail = null) => {
1303
- this.showMessage((message) => this._toastr.warning(message), this.log, 'Warning', message, detail);
1304
- };
1305
- this.log = (message) => {
1306
- var console = window.console;
1307
- !!console && console.log && console.log.apply && console.log.apply(console, [message]);
1308
- };
1309
- this.showErrorDialog = (title, message) => {
1310
- };
1311
- this.showExportDialog = () => {
1312
- return new Promise((resolve, reject) => {
1313
- let dialogConfig = new TruExportDialogConfig('Export');
1314
- let dialogRef = this._dialog.open(TruExportDialog, {
1315
- disableClose: true,
1316
- minWidth: "200px",
1317
- maxWidth: "400px",
1318
- data: dialogConfig
1319
- });
1320
- dialogRef.afterClosed().subscribe(dialogResult => {
1321
- resolve(dialogResult);
1322
- });
1323
- });
1324
- };
1325
- this.confirm = (title, message) => {
1326
- return new Promise((resolve, reject) => {
1327
- let dialogConfig = new TruConfirmDialogConfig(title, message);
1328
- let dialogRef = this._dialog.open(TruConfirmDialog, {
1329
- disableClose: true,
1330
- minWidth: "200px",
1331
- maxWidth: "400px",
1332
- data: dialogConfig
1333
- });
1334
- dialogRef.afterClosed().subscribe(dialogResult => {
1335
- resolve(dialogResult);
1336
- });
1337
- });
1097
+ this.fmtDataError = (typeName) => {
1098
+ if (typeName.indexOf('OptimisticLockViolation') >= 0)
1099
+ return 'The record was edited already, by another user. Please reload and attempt your edit again.';
1100
+ if (typeName.indexOf('DataConstraintViolation') >= 0)
1101
+ return 'Foreign key constraint violation';
1102
+ if (typeName.indexOf('DuplicateKeyError') >= 0)
1103
+ return 'Duplicate key error';
1104
+ return typeName;
1338
1105
  };
1339
- this._toastr = toastr;
1340
- this._dialog = dialog;
1106
+ this.msgModifierKeyLabel = this.isMac() ? 'Cmd' : 'Ctrl';
1107
+ this.msgConfirmExitWithChangesPending = 'You have unsaved changes that will be lost.';
1108
+ this.msgDeleteSuccessful = 'Delete succeeded';
1109
+ this.msgSaveSuccessful = 'Save succeeded';
1110
+ this.msgNoChangesToSave = 'No changes to save';
1111
+ this.msgSaveInProgress = 'Save in progress';
1112
+ this.msgInvalidData = 'Invalid data';
1113
+ this.msgDirtyPreventsReadOnly = 'Save or revert before disabling editing';
1114
+ this.msgDirtyPreventsNavigate = 'Save or revert before navigating';
1115
+ this.msgDirtyPreventsClose = 'Save or revert before closing window';
1116
+ this.msgDirtyPreventsDeleteExistingRecord = 'Save or revert before deleting';
1117
+ this.msgNoDeleteAccess = 'Contact administrator about delete access';
1118
+ this.msgCannotDeleteNewAndExistingRecords = 'Delete new or existing records - but not both';
1119
+ this.msgDeleteReferencingRecordsFirst = 'Delete all referencing records first';
1341
1120
  }
1342
1121
  }
1343
- TruUiNotification.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruUiNotification, deps: [{ token: i1$1.ToastrService }, { token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Injectable });
1344
- TruUiNotification.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruUiNotification, providedIn: 'root' });
1345
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruUiNotification, decorators: [{
1122
+ TruTextManager.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruTextManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1123
+ TruTextManager.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruTextManager, providedIn: 'root' });
1124
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruTextManager, decorators: [{
1346
1125
  type: Injectable,
1347
1126
  args: [{
1348
1127
  providedIn: 'root',
1349
1128
  }]
1350
- }], ctorParameters: function () { return [{ type: i1$1.ToastrService }, { type: i1.MatDialog }]; } });
1129
+ }], ctorParameters: function () { return []; } });
1351
1130
 
1352
- class TruEntityAccessor {
1353
- constructor(http, appEnvironment, uiNotification) {
1354
- this.http = http;
1355
- this.appEnvironment = appEnvironment;
1356
- this.uiNotification = uiNotification;
1357
- this._maxRecordCount = 0;
1358
- this.getQueryServiceName = (entity) => {
1359
- return 'Query' + entity.name;
1360
- };
1361
- this.warnIfMaxRecords = (entities, entityName) => {
1362
- if (entities.length >= this._maxRecordCount)
1363
- this.uiNotification.warning('[' + entityName + '] has more records available than supported');
1364
- };
1365
- this.formatQueryChoices = (query, entities, pKeyName, hid = null) => {
1366
- if (query && query.orderByClause)
1367
- return _.map(entities, (entity) => { return { value: { $: entity[pKeyName] }, label: hid !== null ? hid : entity.HID }; });
1368
- else
1369
- return _.map(entities, (entity) => { return { value: { $: entity[pKeyName] }, label: hid !== null ? hid : entity.HID }; });
1370
- };
1371
- this.add = (entity, contextFilters = null) => {
1372
- let newEntity = this._entityManager.createEntity(entity.prototype.entityType);
1373
- return newEntity;
1374
- };
1375
- this.search = (entity, setupQuery = null, expands, global) => {
1376
- var query;
1377
- if (expands && expands.length) {
1378
- if (global)
1379
- query = this._breezeContext.createQuery(this.getQueryServiceName(entity)).expand(expands.join(', '));
1380
- else
1381
- query = this._breezeContext.createQuery(this.getQueryServiceName(entity)).expand(expands.join(', ')).top(this._maxRecordCount);
1382
- }
1383
- else {
1384
- if (global)
1385
- query = this._breezeContext.createQuery(this.getQueryServiceName(entity));
1386
- else
1387
- query = this._breezeContext.createQuery(this.getQueryServiceName(entity)).top(this._maxRecordCount);
1388
- }
1389
- if (setupQuery != null)
1390
- query = setupQuery(query);
1391
- return defer(() => from(this._entityManager.executeQuery(query).then((queryData) => {
1392
- if (!global)
1393
- this.warnIfMaxRecords(queryData.results, entity.name);
1394
- return queryData.results;
1395
- })));
1396
- };
1397
- this.searchCacheOnly = (entity, setupQuery = null, expands = null) => {
1398
- var query = this._breezeContext.createQuery(this.getQueryServiceName(entity));
1399
- if (setupQuery)
1400
- query = setupQuery(query);
1401
- return of(this._entityManager.executeQueryLocally(query));
1402
- };
1403
- this.searchCacheOnlySynchronously = (entity, setupQuery = null, expands = null) => {
1404
- var query = this._breezeContext.createQuery(this.getQueryServiceName(entity));
1405
- if (setupQuery)
1406
- query = setupQuery(query);
1407
- return this._entityManager.executeQueryLocally(query);
1408
- };
1409
- this.searchQueryChoices = (entity, setupQuery = null, hid = null, goToServer = false, ref = undefined) => {
1410
- const pkeyName = entity.name + 'Ref';
1411
- let query = this._breezeContext.createQuery(this.getQueryServiceName(entity));
1412
- if (setupQuery)
1413
- query = setupQuery(query) ?? query;
1414
- if (ref)
1415
- query = query.where(entity.name + 'Ref', '==', ref);
1416
- if (goToServer) {
1417
- return defer(() => from(this._entityManager.executeQuery(query).then((queryData) => {
1418
- return this.formatQueryChoices(query, queryData.results, pkeyName, null);
1419
- })));
1420
- }
1421
- return of(this.formatQueryChoices(query, this._entityManager.executeQueryLocally(query), pkeyName, null));
1422
- };
1423
- this.searchByRef = (entity, ref) => {
1424
- const pkeyName = entity.name + 'Ref';
1425
- var queryOptions = this._entityManager.queryOptions.using({
1426
- fetchStrategy: FetchStrategy.FromServer
1427
- });
1428
- var query = this._breezeContext.createQuery(this.getQueryServiceName(entity)).where(entity.name + 'Ref', '==', ref).using(queryOptions);
1429
- return defer(() => from(this._entityManager.executeQuery(query).then((queryData) => {
1430
- return this.formatQueryChoices(query, queryData.results, pkeyName, null);
1431
- })));
1432
- };
1433
- this.searchByRefPreferedCache = (entity, ref) => {
1434
- let cachedEntity = this.searchByRefCacheOnly(entity, ref);
1435
- if (cachedEntity) {
1436
- var queryOptions = this._entityManager.queryOptions.using({
1437
- fetchStrategy: FetchStrategy.FromLocalCache
1438
- });
1439
- var query = this._breezeContext.createQuery(this.getQueryServiceName(entity)).where(entity.name + 'Ref', '==', ref).using(queryOptions);
1440
- return defer(() => from(this._entityManager.executeQuery(query).then((queryData) => {
1441
- return queryData.results[0];
1442
- })));
1443
- }
1444
- else {
1445
- var queryOptions = this._entityManager.queryOptions.using({
1446
- fetchStrategy: FetchStrategy.FromServer
1447
- });
1448
- var query = this._breezeContext.createQuery(this.getQueryServiceName(entity)).where(entity.name + 'Ref', '==', ref).using(queryOptions);
1449
- return defer(() => from(this._entityManager.executeQuery(query).then((queryData) => {
1450
- return queryData.results[0];
1451
- })));
1452
- }
1453
- };
1454
- this.searchByRefCacheOnly = (entity, ref, includeDeleted = false) => {
1455
- if (!includeDeleted)
1456
- includeDeleted = false;
1457
- var queryOptions = this._entityManager.queryOptions.using({
1458
- includeDeleted: includeDeleted,
1459
- fetchStrategy: FetchStrategy.FromLocalCache
1460
- });
1461
- var query = this._breezeContext.createQuery(this.getQueryServiceName(entity)).where(entity.name + 'Ref', '==', ref).using(queryOptions);
1462
- var result = this._entityManager.executeQueryLocally(query)[0];
1463
- if (result)
1464
- return result;
1465
- return null;
1466
- };
1467
- this.export = (entity, gridSpec, setupQuery, entityRefs, options) => {
1468
- options = options || {};
1469
- var args = {
1470
- runAsync: false,
1471
- useNames: false,
1472
- useEmptyTags: false,
1473
- entityRefs: null,
1474
- entityTypeName: entity.name,
1475
- gridSpec: gridSpec
1476
- };
1477
- if (options.async)
1478
- args.runAsync = true;
1479
- if (options.useNames)
1480
- args.useNames = true;
1481
- if (options.useEmptyTags)
1482
- args.useEmptyTags = true;
1483
- var queryText;
1484
- if (options.useGrid) {
1485
- args.entityRefs = entityRefs;
1486
- }
1487
- else {
1488
- var query = this._breezeContext.createQuery('noname');
1489
- if (setupQuery)
1490
- query = setupQuery(query);
1491
- if (query === null) {
1492
- this.uiNotification.warning('No records selected by query');
1493
- return;
1131
+ class TruDetailViewBase {
1132
+ constructor(dataContext, textManager) {
1133
+ this.dataContext = dataContext;
1134
+ this.textManager = textManager;
1135
+ this.tableName = '';
1136
+ this.entities = [];
1137
+ this.recordLocation = null;
1138
+ this.disableNavigationToPreviousEntity = false;
1139
+ this.disableNavigationToNextEntity = false;
1140
+ this.navigationIndex = 0;
1141
+ this.onAddEntity = () => {
1142
+ let newEntity = this.dataContext.entityAccess().add(this.entityType);
1143
+ this.entities.splice(this.navigationIndex + 1, 0, newEntity);
1144
+ this.navigateTo(this.navigationIndex + 1);
1145
+ };
1146
+ this.onCloneEntity = () => {
1147
+ };
1148
+ this.onDeleteEntity = () => {
1149
+ let confirmMsg = this.textManager.fmtDeleteConfirmation(this.entityType.name);
1150
+ this.dataContext.delete([this.entity], confirmMsg, () => { return true; });
1151
+ };
1152
+ this.onFirstEntity = () => {
1153
+ this.navigateTo(0);
1154
+ };
1155
+ this.onPreviousEntity = () => {
1156
+ this.navigateTo(this.navigationIndex - 1);
1157
+ };
1158
+ this.onNextEntity = () => {
1159
+ this.navigateTo(this.navigationIndex + 1);
1160
+ };
1161
+ this.onLastEntity = () => {
1162
+ this.navigateTo(this.entities.length - 1);
1163
+ };
1164
+ this.navigateTo = (index) => {
1165
+ this.setNavigationIndex(index);
1166
+ this.setEntityDisplayValues(this.tableName);
1167
+ };
1168
+ this.setNavigationIndex = (index) => {
1169
+ this.navigationIndex = index;
1170
+ this.disableNavigationToPreviousEntity = index === 0;
1171
+ this.disableNavigationToNextEntity = index === this.entities.length - 1;
1172
+ this.entity = this.entities[this.navigationIndex];
1173
+ };
1174
+ this.setEntityDisplayValues = (tableName) => {
1175
+ let title = '';
1176
+ let recordIndex = '?';
1177
+ let entity = this.entities[this.navigationIndex];
1178
+ if (entity) {
1179
+ title = tableName + ' - ';
1180
+ if (entity.entityAspect.entityState.isAdded()) {
1181
+ title += 'New Record';
1494
1182
  }
1495
1183
  else {
1496
- queryText = query._toUri(this._entityManager);
1497
- queryText = queryText.split('?')[1];
1498
- }
1499
- }
1500
- var argsText = this.formatAsUrlParameters(args);
1501
- if (queryText)
1502
- argsText += '&' + queryText;
1503
- this.uiNotification.info(args.runAsync ? 'Queuing export...' : 'Exporting...');
1504
- this.downloadFromUrl('ExportEntities', argsText);
1505
- };
1506
- this.formatAsUrlParameters = (data) => {
1507
- var buffer = [];
1508
- for (var name in data) {
1509
- if (!data.hasOwnProperty(name)) {
1510
- continue;
1184
+ title += this.entity.HID;
1511
1185
  }
1512
- var value = data[name];
1513
- buffer.push(encodeURIComponent(name) +
1514
- '=' + encodeURIComponent(value == null ? '' : value));
1186
+ recordIndex = (this.navigationIndex + 1).toString();
1515
1187
  }
1516
- var source = buffer.join('&')
1517
- .replace(/%20/g, '+');
1518
- return (source);
1519
- };
1520
- this.downloadFromUrl = (url, data) => {
1521
- if (data)
1522
- data = this.formatAsUrlParameters(data);
1523
- const body = { title: 'download request' };
1524
- const headers = { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' };
1525
- this.http.post(url, body, { headers }).subscribe((response) => {
1526
- this.saveDownloadedFile(response);
1527
- });
1528
- };
1529
- this.saveDownloadedFile = (response) => {
1530
- var headers = response.headers;
1531
- var contentDisposition = headers('content-disposition');
1532
- if (!contentDisposition)
1533
- return; // NOTE: cannot save without header info
1534
- var filename = this.extractFilenameFromContentDisposition(contentDisposition);
1535
- var blob = new Blob([response.data], { type: headers('content-type') });
1536
- var link = document.createElement('a');
1537
- link.href = URL.createObjectURL(blob);
1538
- link.setAttribute('download', filename);
1539
- link.click();
1540
- link.remove();
1541
- };
1542
- this.extractFilenameFromContentDisposition = (text) => {
1543
- var parts = _.map(text.split(';'), function (part) { return part.trim(); });
1544
- var prefix = 'filename=';
1545
- var filenamePart = _.find(parts, function (part) { return part.substring(0, prefix.length) === prefix; });
1546
- if (!filenamePart)
1547
- return 'file';
1548
- var filename = filenamePart.substring(prefix.length);
1549
- filename = filename.replace(/"/g, '');
1550
- return filename;
1188
+ this.view.window.title = this.textManager.formatWindowTitle(title);
1189
+ this.recordLocation = recordIndex + ' of ' + this.entities.length;
1551
1190
  };
1552
- this._maxRecordCount = this.appEnvironment.maxRecordCount;
1553
1191
  }
1554
- set context(dataContext) {
1555
- this._breezeContext = dataContext.breezeContext;
1556
- this._entityManager = dataContext.entityManager;
1192
+ }
1193
+ TruDetailViewBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDetailViewBase, deps: [{ token: TruDataContext }, { token: TruTextManager }], target: i0.ɵɵFactoryTarget.Component });
1194
+ TruDetailViewBase.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.1", type: TruDetailViewBase, selector: "tru-detail-view-base", inputs: { view: "view" }, ngImport: i0, template: "", styles: [""] });
1195
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDetailViewBase, decorators: [{
1196
+ type: Component,
1197
+ args: [{ selector: 'tru-detail-view-base', template: "" }]
1198
+ }], ctorParameters: function () { return [{ type: TruDataContext }, { type: TruTextManager }]; }, propDecorators: { view: [{
1199
+ type: Input
1200
+ }] } });
1201
+
1202
+ class DetailViewModule {
1203
+ }
1204
+ DetailViewModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: DetailViewModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1205
+ DetailViewModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.1", ngImport: i0, type: DetailViewModule, declarations: [TruDetailViewBase], imports: [CommonModule, FormsModule], exports: [TruDetailViewBase] });
1206
+ DetailViewModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: DetailViewModule, imports: [CommonModule, FormsModule] });
1207
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: DetailViewModule, decorators: [{
1208
+ type: NgModule,
1209
+ args: [{
1210
+ declarations: [TruDetailViewBase],
1211
+ imports: [CommonModule, FormsModule],
1212
+ exports: [TruDetailViewBase]
1213
+ }]
1214
+ }] });
1215
+
1216
+ class TruDesktopViewConfig {
1217
+ onActive() {
1218
+ return this.active$;
1219
+ }
1220
+ active(value) {
1221
+ this.active$.next(value);
1222
+ }
1223
+ constructor() {
1224
+ this.active$ = new BehaviorSubject(true);
1225
+ this.entities = undefined;
1226
+ this.entityIndex = 0;
1227
+ this.isDirty = false;
1228
+ this.isEditing = false;
1229
+ this.isInvalid = false;
1230
+ this.componentName = '';
1231
+ this.openAsDetaiView = false;
1557
1232
  }
1558
1233
  }
1559
- TruEntityAccessor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruEntityAccessor, deps: [{ token: i1$2.HttpClient }, { token: TruAppEnvironment }, { token: TruUiNotification }], target: i0.ɵɵFactoryTarget.Injectable });
1560
- TruEntityAccessor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruEntityAccessor });
1561
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruEntityAccessor, decorators: [{
1562
- type: Injectable
1563
- }], ctorParameters: function () { return [{ type: i1$2.HttpClient }, { type: TruAppEnvironment }, { type: TruUiNotification }]; } });
1234
+ ;
1564
1235
 
1565
- class TruDataContext {
1566
- constructor(breezeContextFactory, appEnvironment, entityAccessor, uiNotification) {
1567
- this.breezeContextFactory = breezeContextFactory;
1568
- this.appEnvironment = appEnvironment;
1569
- this.entityAccessor = entityAccessor;
1570
- this.uiNotification = uiNotification;
1571
- this._pendingDeleteEntities = [];
1572
- this._pendingCascadeDeleteEntities = [];
1573
- this.validationChangeDetection = new Observable((observer) => {
1574
- this.entityManager.validationErrorsChanged.subscribe(entities => {
1575
- observer.next(entities);
1576
- });
1577
- });
1578
- this.getValidationErrors = (entities = null) => {
1579
- entities = entities || this.entityManager.getChanges();
1580
- var errorsPerEntity = entities.map((entity) => {
1581
- var errors = entity.entityAspect.getValidationErrors();
1582
- errors = errors.map((err) => {
1583
- return {
1584
- entity: entity,
1585
- errorMessage: err.errorMessage,
1586
- property: err.property
1587
- };
1588
- });
1589
- return errors;
1590
- });
1591
- return of(errorsPerEntity);
1236
+ class TruWindowEventArgs {
1237
+ constructor() {
1238
+ this.title = '';
1239
+ this.tableName = '';
1240
+ this.tablePluralName = '';
1241
+ this.tablePluralLabel = '';
1242
+ this.context = {};
1243
+ this.contentBottom = '23px';
1244
+ this.statusbarDirective = 'tru-statusbar';
1245
+ this.height = '450px';
1246
+ this.width = '900px';
1247
+ this.views = [{}];
1248
+ this.contextFilters = [];
1249
+ }
1250
+ }
1251
+ TruWindowEventArgs.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventArgs, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1252
+ TruWindowEventArgs.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventArgs, providedIn: 'root' });
1253
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventArgs, decorators: [{
1254
+ type: Injectable,
1255
+ args: [{
1256
+ providedIn: 'root'
1257
+ }]
1258
+ }] });
1259
+
1260
+ class TruContextFilters {
1261
+ constructor() {
1262
+ this.filters = [];
1263
+ this.valueFor = (tableName) => {
1264
+ let choice = this.filters.find(f => f.selectedChoice.table === tableName)?.selectedChoice;
1265
+ if (!choice)
1266
+ throw new Error('ContextFilterChoice not found. Possible invalid configuration.');
1267
+ return choice.ref;
1592
1268
  };
1593
- this.formatValidationErrors = (entities = null) => {
1594
- let errors = this.getValidationErrors(entities);
1595
- let formattedErrors = new Array();
1596
- errors.subscribe(errorsArray => {
1597
- formattedErrors.push(errorsArray.map((e) => {
1598
- if (e.propertyName) {
1599
- return e.entity.entityType.defaultResourceName + '.' + e.propertyName + ': ' + e.errorMessage;
1600
- }
1601
- var mergeData = JSON.parse(e.entity.Merge_Data);
1602
- if (mergeData &&
1603
- mergeData.constructor === Object &&
1604
- Object.entries(mergeData).length > 0 &&
1605
- mergeData[e.property.name]) {
1606
- return mergeData[e.property.name].modifiedBy + ' changed ' + e.property.name + ' to ' + mergeData[e.property.name].value + '. Accept or Decline the change. ';
1607
- }
1608
- var propertyName = e.property.name ? e.property.name : '[Unknown Property]';
1609
- return e.entity.entityType.defaultResourceName + '.' + propertyName + ': has invalid data.';
1610
- }));
1611
- });
1612
- return formattedErrors;
1269
+ this.label = () => {
1270
+ let label = '';
1271
+ //this.selectedContextFilterChoices.forEach((filter: TruContextFilterChoice) => {
1272
+ // label += filter.table + ': ' + filter.label + ' ';
1273
+ //});
1274
+ return label;
1613
1275
  };
1614
- this.findCachedCascadeDeleteDescendants = (entity) => {
1615
- let descendants = [];
1616
- let type = entity.entityType;
1617
- let typeName = type.defaultResourceName;
1618
- let entityChildrenNames = JSON.parse(JSON.stringify('Replace with: ModelNavigationProperties.value'))[typeName];
1619
- Object.entries(entityChildrenNames)
1620
- .forEach(([k, v]) => {
1621
- let property = entity[k];
1622
- property.forEach((child) => {
1623
- if (typeof v === 'object' && v.doesCascadeDelete && child.entityAspect.entityState !== EntityState.Added) {
1624
- throw new Error('Delete of selected item is not possible due to related child that is not setup for cascade delete. Delete children items first.');
1625
- }
1626
- descendants = descendants.concat(this.findCachedCascadeDeleteDescendants(child));
1627
- });
1628
- descendants = property.concat(descendants);
1629
- });
1630
- return descendants;
1276
+ }
1277
+ }
1278
+ TruContextFilters.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruContextFilters, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1279
+ TruContextFilters.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruContextFilters, providedIn: 'root' });
1280
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruContextFilters, decorators: [{
1281
+ type: Injectable,
1282
+ args: [{
1283
+ providedIn: 'root',
1284
+ }]
1285
+ }], ctorParameters: function () { return []; } });
1286
+
1287
+ class TruWindowEventHandler {
1288
+ constructor() {
1289
+ this.open$ = new Subject();
1290
+ this.addView$ = new Subject();
1291
+ this.removeForwadViews$ = new Subject();
1292
+ }
1293
+ onOpen() {
1294
+ return this.open$;
1295
+ }
1296
+ open(windowEvent) {
1297
+ this.open$.next(windowEvent);
1298
+ }
1299
+ onAddView() {
1300
+ return this.addView$;
1301
+ }
1302
+ addView(windowAddViewEvent) {
1303
+ this.addView$.next(windowAddViewEvent);
1304
+ }
1305
+ onRemoveForwardViews() {
1306
+ return this.removeForwadViews$;
1307
+ }
1308
+ removeForwardViews() {
1309
+ this.removeForwadViews$.next(null);
1310
+ }
1311
+ }
1312
+ TruWindowEventHandler.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1313
+ TruWindowEventHandler.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventHandler, providedIn: 'root' });
1314
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventHandler, decorators: [{
1315
+ type: Injectable,
1316
+ args: [{
1317
+ providedIn: 'root'
1318
+ }]
1319
+ }] });
1320
+
1321
+ class TruDesktopManager {
1322
+ constructor(contextFilters, windowEventHandler) {
1323
+ this.contextFilters = contextFilters;
1324
+ this.windowEventHandler = windowEventHandler;
1325
+ this.getWindowEvent = (tableName, tablePluralName, tablePluralLabel, componentName, entities = [], openAsDetaiView = false) => {
1326
+ var windowEvent = new TruWindowEventArgs();
1327
+ windowEvent.tableName = tableName;
1328
+ windowEvent.tablePluralName = tablePluralName;
1329
+ windowEvent.tablePluralLabel = tablePluralLabel;
1330
+ windowEvent.contextFilters = this.contextFilters.filters;
1331
+ windowEvent.views = [
1332
+ {
1333
+ active: true,
1334
+ entities: entities,
1335
+ entityIndex: 0,
1336
+ isDirty: false,
1337
+ isEditing: false,
1338
+ isInvalid: false,
1339
+ openAsDetaiView: openAsDetaiView,
1340
+ componentName: componentName
1341
+ }
1342
+ ];
1343
+ return windowEvent;
1631
1344
  };
1632
- this.markCachedDescendantsForDelete = (entities) => {
1633
- var cascadeDeleteDescendantsPerEntity = entities.map((entity) => { return this.findCachedCascadeDeleteDescendants(entity); }, entities);
1634
- var cascadeDeleteDescendants = cascadeDeleteDescendantsPerEntity.reduce((memo, i) => { return memo.concat(i); });
1635
- cascadeDeleteDescendants.forEach((entity) => { this.entityManager.detachEntity(entity); });
1636
- this._pendingDeleteEntities = this._pendingDeleteEntities.concat(entities);
1637
- let combined = this._pendingCascadeDeleteEntities.concat(cascadeDeleteDescendants);
1638
- this._pendingCascadeDeleteEntities = combined.filter((n, i) => combined.indexOf(n) === i);
1345
+ /**
1346
+ * Opens a window for a directive.
1347
+ * @param {string} directiveName - name of the view directive.
1348
+ * @param {object} data - values to pass to the view.
1349
+ * @param {optional bool} showIfExists - if true and a view already exists for the
1350
+ * directive, then shows its window instead of creating a new one.
1351
+ */
1352
+ this.addWindow = (tableName, tablePluralName, tablePluralLabel, componentName, entities = [], openAsDetaiView = false, showNavigation = true, showIfExists) => {
1353
+ this.windowEventHandler.open(this.getWindowEvent(tableName, tablePluralName, tablePluralLabel, componentName, entities, openAsDetaiView));
1639
1354
  };
1640
- this.markForDelete = (entities) => {
1641
- if (entities.length > 0) {
1642
- this.markCachedDescendantsForDelete(entities);
1643
- entities.forEach((entity) => {
1644
- entity.entityAspect.setDeleted();
1645
- //entity._associatedDataCached = false;
1646
- });
1355
+ this.windowTitlesByBaseText = {};
1356
+ /**
1357
+ * Returns a unique string for the base name of a window. At first, returns the input.
1358
+ * For second call with same base name, returns the name plus ' - 2' and so on. When
1359
+ * all of the titles for the base name are released, then the next title will have no
1360
+ * suffix.
1361
+ * @param {string} text - base name of a window.
1362
+ * @returns {object} - text: the unique text and release(): releases the name for
1363
+ * future windows.
1364
+ */
1365
+ this.getUniqueTitle = (text) => {
1366
+ var baseText = text;
1367
+ var titles = this.windowTitlesByBaseText[baseText];
1368
+ if (!titles) {
1369
+ this.windowTitlesByBaseText[baseText] = titles = {
1370
+ dispensedCount: 1,
1371
+ activeCount: 1
1372
+ };
1647
1373
  }
1374
+ else {
1375
+ ++titles.activeCount;
1376
+ text += ' - ' + (++titles.dispensedCount);
1377
+ }
1378
+ return {
1379
+ text: text,
1380
+ release: () => {
1381
+ if (titles.activeCount === 1)
1382
+ delete this.windowTitlesByBaseText[baseText];
1383
+ else {
1384
+ --titles.activeCount;
1385
+ }
1386
+ }
1387
+ };
1648
1388
  };
1649
- this.hasChanges = (entityTypes = []) => {
1650
- if (entityTypes.length)
1651
- return this._breezeContext.entityManager.getChanges(entityTypes);
1652
- return this._breezeContext.entityManager.getChanges();
1653
- };
1654
- this.entityAccess = () => {
1655
- return this.entityAccessor;
1656
- };
1657
- this.exportCahce = () => {
1658
- console.log(this._breezeContext.entityManager.exportEntities());
1389
+ }
1390
+ }
1391
+ TruDesktopManager.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDesktopManager, deps: [{ token: TruContextFilters }, { token: TruWindowEventHandler }], target: i0.ɵɵFactoryTarget.Injectable });
1392
+ TruDesktopManager.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDesktopManager, providedIn: 'root' });
1393
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDesktopManager, decorators: [{
1394
+ type: Injectable,
1395
+ args: [{
1396
+ providedIn: 'root',
1397
+ }]
1398
+ }], ctorParameters: function () { return [{ type: TruContextFilters }, { type: TruWindowEventHandler }]; } });
1399
+
1400
+ class TruSearchViewBase {
1401
+ constructor(desktopManager, truWindowEventHandler) {
1402
+ this.desktopManager = desktopManager;
1403
+ this.truWindowEventHandler = truWindowEventHandler;
1404
+ this.tableName = '';
1405
+ this.tablePluralName = '';
1406
+ this.tablePluralLabel = '';
1407
+ this.pkeyName = '';
1408
+ this.windowTitle = undefined;
1409
+ this.unsubscribes = [];
1410
+ this.expands = [];
1411
+ this.isSearching = false;
1412
+ this.entities = [];
1413
+ this.hasDetailView = true;
1414
+ this.searchPanelConfig = {
1415
+ side: 'right',
1416
+ active: true,
1417
+ open: true,
1418
+ modKeyLabel: '',
1419
+ size: 500,
1420
+ pinned: false
1659
1421
  };
1660
- this.save = (entities = null, deleteOperation = false) => {
1661
- return new Promise((resolve, reject) => {
1662
- if (this.appEnvironment.isSaving) {
1663
- this.uiNotification.error(this.appEnvironment.msgSaveInProgress);
1664
- resolve();
1665
- return;
1666
- }
1667
- var validationErrorMessages = this.formatValidationErrors(entities);
1668
- if (validationErrorMessages.length > 0) {
1669
- //this.uiNotification.error(this.appEnvironment.msgInvalidData, validationErrorMessages);
1670
- resolve();
1671
- return;
1672
- }
1673
- if (!this.hasChanges().length) {
1674
- this.uiNotification.warning(this.appEnvironment.msgNoChangesToSave);
1675
- resolve();
1676
- return;
1677
- }
1678
- this.appEnvironment.isSaving = true;
1679
- this.entityManager.saveChanges().then(() => {
1680
- if (!deleteOperation) {
1681
- this.uiNotification.success(this.appEnvironment.msgSaveSuccessful);
1682
- this.appEnvironment.saveComplete({ successful: true });
1683
- }
1684
- resolve();
1685
- }).catch((e) => {
1686
- this.appEnvironment.saveComplete({ successful: false });
1687
- reject(e);
1688
- }).finally(() => {
1689
- this.appEnvironment.isSaving = false;
1690
- });
1691
- });
1422
+ this.onPkeyCellDoubleClicked = (gridConfig) => {
1423
+ if (this.hasDetailView) {
1424
+ var truWindowAddViewEventArgs = new TruDesktopViewConfig();
1425
+ truWindowAddViewEventArgs.entities = gridConfig.api.getRenderedNodes().map((rowNode) => rowNode.data.$entity);
1426
+ truWindowAddViewEventArgs.entityIndex = gridConfig.rowIndex;
1427
+ truWindowAddViewEventArgs.componentName = this.tableName + 'DetailView';
1428
+ this.truWindowEventHandler.addView(truWindowAddViewEventArgs);
1429
+ this.view.active(false);
1430
+ }
1431
+ else {
1432
+ alert(this.tablePluralLabel + ' does not have a detail view.');
1433
+ }
1434
+ };
1435
+ }
1436
+ setWindowTitle() {
1437
+ if (!this.windowTitle)
1438
+ this.windowTitle = this.desktopManager.getUniqueTitle(this.tablePluralLabel);
1439
+ this.view.window.title = this.windowTitle.text;
1440
+ }
1441
+ releaseWindowTitle() {
1442
+ this.windowTitle?.release();
1443
+ }
1444
+ }
1445
+ TruSearchViewBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBase, deps: [{ token: TruDesktopManager }, { token: TruWindowEventHandler }], target: i0.ɵɵFactoryTarget.Component });
1446
+ TruSearchViewBase.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.1", type: TruSearchViewBase, selector: "tru-search-view-base", inputs: { view: "view" }, ngImport: i0, template: "", styles: [""] });
1447
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBase, decorators: [{
1448
+ type: Component,
1449
+ args: [{ selector: 'tru-search-view-base', template: "" }]
1450
+ }], ctorParameters: function () { return [{ type: TruDesktopManager }, { type: TruWindowEventHandler }]; }, propDecorators: { view: [{
1451
+ type: Input
1452
+ }] } });
1453
+
1454
+ class TruSearchViewBaseModule {
1455
+ }
1456
+ TruSearchViewBaseModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBaseModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1457
+ TruSearchViewBaseModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBaseModule, declarations: [TruSearchViewBase], imports: [CommonModule, FormsModule], exports: [TruSearchViewBase] });
1458
+ TruSearchViewBaseModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBaseModule, imports: [CommonModule, FormsModule] });
1459
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBaseModule, decorators: [{
1460
+ type: NgModule,
1461
+ args: [{
1462
+ declarations: [TruSearchViewBase],
1463
+ imports: [CommonModule, FormsModule],
1464
+ exports: [TruSearchViewBase]
1465
+ }]
1466
+ }] });
1467
+
1468
+ class TruSearchViewControlEventHandler {
1469
+ constructor() {
1470
+ this.clear$ = new BehaviorSubject(null);
1471
+ this.default$ = new BehaviorSubject(null);
1472
+ }
1473
+ onSetDefaults() {
1474
+ return this.default$;
1475
+ }
1476
+ setDefaults() {
1477
+ this.default$.next(null);
1478
+ }
1479
+ onClearValues() {
1480
+ return this.clear$;
1481
+ }
1482
+ clearValues() {
1483
+ this.clear$.next(null);
1484
+ }
1485
+ }
1486
+ TruSearchViewControlEventHandler.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewControlEventHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1487
+ TruSearchViewControlEventHandler.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewControlEventHandler });
1488
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewControlEventHandler, decorators: [{
1489
+ type: Injectable
1490
+ }] });
1491
+
1492
+ class TruSearchViewEventHandler {
1493
+ constructor() {
1494
+ this.search$ = new BehaviorSubject(null);
1495
+ this.filter$ = new BehaviorSubject(null);
1496
+ }
1497
+ search(query) {
1498
+ this.search$.next(query);
1499
+ }
1500
+ onSearch() {
1501
+ return this.search$.asObservable();
1502
+ }
1503
+ filter(query) {
1504
+ this.filter$.next(query);
1505
+ }
1506
+ onFilter() {
1507
+ return this.filter$.asObservable();
1508
+ }
1509
+ }
1510
+ TruSearchViewEventHandler.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewEventHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1511
+ TruSearchViewEventHandler.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewEventHandler });
1512
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewEventHandler, decorators: [{
1513
+ type: Injectable
1514
+ }] });
1515
+
1516
+ class TruSearchResultViewBase {
1517
+ constructor(truWindowEventHandler) {
1518
+ this.truWindowEventHandler = truWindowEventHandler;
1519
+ this.tableName = '';
1520
+ this.tablePluralLabel = '';
1521
+ this.hasDetailView = true;
1522
+ this.searchPanelConfig = {
1523
+ side: 'right',
1524
+ active: true,
1525
+ open: true,
1526
+ modKeyLabel: '',
1527
+ size: 500,
1528
+ pinned: false
1529
+ };
1530
+ this.onPkeyCellDoubleClicked = (gridConfig) => {
1531
+ if (this.hasDetailView) {
1532
+ var truWindowAddViewEventArgs = new TruDesktopViewConfig();
1533
+ truWindowAddViewEventArgs.entities = gridConfig.api.getRenderedNodes().map((rowNode) => rowNode.data.$entity);
1534
+ truWindowAddViewEventArgs.entityIndex = gridConfig.rowIndex;
1535
+ truWindowAddViewEventArgs.componentName = this.tableName + 'DetailView';
1536
+ this.truWindowEventHandler.addView(truWindowAddViewEventArgs);
1537
+ }
1538
+ else {
1539
+ alert(this.tablePluralLabel + ' does not have a detail view.');
1540
+ }
1541
+ };
1542
+ }
1543
+ ngOnInit() {
1544
+ this.tableName = this.view.window.tableName;
1545
+ this.tablePluralLabel = this.view.window.tablePluralLabel;
1546
+ }
1547
+ }
1548
+ TruSearchResultViewBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBase, deps: [{ token: TruWindowEventHandler }], target: i0.ɵɵFactoryTarget.Component });
1549
+ TruSearchResultViewBase.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.1", type: TruSearchResultViewBase, selector: "tru-search-result-view-base", inputs: { view: "view" }, ngImport: i0, template: "", styles: [""] });
1550
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBase, decorators: [{
1551
+ type: Component,
1552
+ args: [{ selector: 'tru-search-result-view-base', template: "" }]
1553
+ }], ctorParameters: function () { return [{ type: TruWindowEventHandler }]; }, propDecorators: { view: [{
1554
+ type: Input
1555
+ }] } });
1556
+
1557
+ class TruSearchResultViewBaseModule {
1558
+ }
1559
+ TruSearchResultViewBaseModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBaseModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1560
+ TruSearchResultViewBaseModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBaseModule, declarations: [TruSearchResultViewBase], imports: [CommonModule, FormsModule], exports: [TruSearchResultViewBase] });
1561
+ TruSearchResultViewBaseModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBaseModule, imports: [CommonModule, FormsModule] });
1562
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBaseModule, decorators: [{
1563
+ type: NgModule,
1564
+ args: [{
1565
+ declarations: [TruSearchResultViewBase],
1566
+ imports: [CommonModule, FormsModule],
1567
+ exports: [TruSearchResultViewBase]
1568
+ }]
1569
+ }] });
1570
+
1571
+ class TruChoice {
1572
+ }
1573
+
1574
+ class TruContextFilter {
1575
+ constructor() {
1576
+ this.tooltip = undefined;
1577
+ this.choices = [];
1578
+ this.identify = (index, choice) => {
1579
+ return choice.ref;
1580
+ };
1581
+ this.comparer = (o1, o2) => {
1582
+ return o1 && o2 ? o1.label === o2.label : o2 === o2;
1583
+ };
1584
+ this.onChange = (choice) => {
1585
+ this.selectedChoice = choice;
1586
+ };
1587
+ }
1588
+ }
1589
+
1590
+ class TruContextFilterChoice {
1591
+ constructor(table, label, ref) {
1592
+ this.table = table;
1593
+ this.label = label;
1594
+ this.ref = ref;
1595
+ }
1596
+ }
1597
+
1598
+ class TruFormulaEval {
1599
+ static isString(s) {
1600
+ return typeof s === 'string';
1601
+ }
1602
+ static isDate(v) {
1603
+ return Object.prototype.toString.call(v) === '[object Date]';
1604
+ }
1605
+ static toValue(value) {
1606
+ return value;
1607
+ }
1608
+ static toString(value) {
1609
+ //if (_.isBoolean(value))
1610
+ // return value ? 'TRUE' : 'FALSE';
1611
+ return value.toString();
1612
+ }
1613
+ static toDouble(value) {
1614
+ return Number(value);
1615
+ }
1616
+ static toInteger(value) {
1617
+ return Math.round(value);
1618
+ }
1619
+ static toBoolean(value) {
1620
+ if (_.isBoolean(value))
1621
+ return value;
1622
+ var number = Number(value);
1623
+ if (isNaN(number))
1624
+ return NaN;
1625
+ return number !== 0;
1626
+ }
1627
+ static toDate(value) {
1628
+ return value;
1629
+ }
1630
+ statictoDateTime(value) {
1631
+ return value;
1632
+ }
1633
+ /**
1634
+ * Exposed for testing.
1635
+ */
1636
+ static _calculate(f, left, right) {
1637
+ if (TruFormulaEval.isString(left))
1638
+ left = parseFloat(left);
1639
+ if (TruFormulaEval.isString(left))
1640
+ if (TruFormulaEval.isString(right))
1641
+ right = parseFloat(right);
1642
+ return f(left, right);
1643
+ }
1644
+ static _calculateDate(left, right, add) {
1645
+ if (add) {
1646
+ if (TruFormulaEval.isDate(left) && !TruFormulaEval.isDate(right)) {
1647
+ return moment(left).add(right, 'day').toDate();
1648
+ }
1649
+ if (!TruFormulaEval.isDate(left) && TruFormulaEval.isDate(right)) {
1650
+ return moment(right).add(left, 'day').toDate();
1651
+ }
1652
+ if (TruFormulaEval.isDate(left) && TruFormulaEval.isDate(right)) {
1653
+ moment(left).add(right).toDate();
1654
+ }
1655
+ }
1656
+ else {
1657
+ if (TruFormulaEval.isDate(left) && !TruFormulaEval.isDate(right)) {
1658
+ return moment(left).subtract(right, 'day').toDate();
1659
+ }
1660
+ if (!TruFormulaEval.isDate(left) && TruFormulaEval.isDate(right)) {
1661
+ return moment(right).subtract(left, 'day').toDate();
1662
+ }
1663
+ if (TruFormulaEval.isDate(left) && TruFormulaEval.isDate(right)) {
1664
+ //var m = moment(left).diff(right, 'days'); //Integer value, but Excel uses decimal for date time
1665
+ var m = moment(left).diff(moment(right)) / 86400000; //divide by miliseconds in a day, decimal answer 1.0 = 1 day, 0.5 = 12 hours
1666
+ return m;
1667
+ }
1668
+ }
1669
+ return null;
1670
+ }
1671
+ static add(left, right) {
1672
+ if (left === null || left === undefined || right === null || right === undefined)
1673
+ return undefined;
1674
+ if (TruFormulaEval.isDate(left) || TruFormulaEval.isDate(right))
1675
+ return TruFormulaEval._calculateDate(left, right, true);
1676
+ return TruFormulaEval._calculate(function (l, r) { return l + r; }, left, right);
1677
+ }
1678
+ static subtract(left, right) {
1679
+ if (left === null || left === undefined || right === null || right === undefined)
1680
+ return undefined;
1681
+ if (TruFormulaEval.isDate(left) || TruFormulaEval.isDate(right))
1682
+ return TruFormulaEval._calculateDate(left, right, true);
1683
+ return TruFormulaEval._calculate(function (l, r) { return l - r; }, left, right);
1684
+ }
1685
+ static multiply(left, right) {
1686
+ if (left === null || left === undefined || right === null || right === undefined)
1687
+ return undefined;
1688
+ return TruFormulaEval._calculate(function (l, r) { return l * r; }, left, right);
1689
+ }
1690
+ static divide(left, right) {
1691
+ if (left === null || left === undefined || right === null || right === undefined)
1692
+ return undefined;
1693
+ return TruFormulaEval._calculate(function (l, r) { return l / r; }, left, right);
1694
+ }
1695
+ static power(left, right) {
1696
+ if (left === null || left === undefined || right === null || right === undefined)
1697
+ return undefined;
1698
+ return TruFormulaEval._calculate(Math.pow, left, right);
1699
+ }
1700
+ static concatenate(left, right) {
1701
+ if (_.isBoolean(left))
1702
+ left = left ? 'TRUE' : 'FALSE';
1703
+ else if (!TruFormulaEval.isString(left))
1704
+ //NOTE: only need to convert left to string since concat() will coerce parameters
1705
+ left = left.toString();
1706
+ if (_.isBoolean(right))
1707
+ right = right ? 'TRUE' : 'FALSE';
1708
+ return left.concat(right);
1709
+ }
1710
+ static equal(left, right) {
1711
+ return left === right;
1712
+ }
1713
+ static notEqual(left, right) {
1714
+ return left !== right;
1715
+ }
1716
+ static lessThan(left, right) {
1717
+ if (typeof (left) !== typeof (right))
1718
+ return !TruFormulaEval.compareResultForMismatchedParams[typeof (left) + typeof (right)];
1719
+ return left < right;
1720
+ }
1721
+ static greaterThan(left, right) {
1722
+ if (typeof (left) !== typeof (right))
1723
+ return TruFormulaEval.compareResultForMismatchedParams[typeof (left) + typeof (right)];
1724
+ return left > right;
1725
+ }
1726
+ static lessThanOrEqual(left, right) {
1727
+ if (typeof (left) !== typeof (right))
1728
+ return !TruFormulaEval.compareResultForMismatchedParams[typeof (left) + typeof (right)];
1729
+ return left <= right;
1730
+ }
1731
+ static greaterThanOrEqual(left, right) {
1732
+ if (typeof (left) !== typeof (right))
1733
+ return TruFormulaEval.compareResultForMismatchedParams[typeof (left) + typeof (right)];
1734
+ return left >= right;
1735
+ }
1736
+ static negate(operand) {
1737
+ return -operand;
1738
+ }
1739
+ static percent(operand) {
1740
+ return operand / 100.0;
1741
+ }
1742
+ }
1743
+ TruFormulaEval.compareResultForMismatchedParams = {
1744
+ booleanstring: true,
1745
+ booleannumber: true,
1746
+ stringnumber: true,
1747
+ stringboolean: false,
1748
+ numberstring: false,
1749
+ numberboolean: false
1750
+ };
1751
+
1752
+ class TruPredicate {
1753
+ constructor(field, operator, value, propertyQueryPath, overQuoted = false) {
1754
+ this._breezePredicate = null;
1755
+ this.handleOperator = (fieldOrPredicate, oper, operator, value) => {
1756
+ var breezePredicate;
1757
+ if (Array.isArray(fieldOrPredicate)) {
1758
+ breezePredicate = new TruPredicate(fieldOrPredicate[0], fieldOrPredicate[1], fieldOrPredicate[2], []);
1759
+ }
1760
+ else if (fieldOrPredicate.constructor === TruPredicate || fieldOrPredicate.constructor === BinaryPredicate || fieldOrPredicate.constructor === AndOrPredicate) {
1761
+ breezePredicate = fieldOrPredicate;
1762
+ }
1763
+ else {
1764
+ throw new TypeError('Unexpected parameter type <' + fieldOrPredicate.constructor + '>.');
1765
+ }
1766
+ breezePredicate = oper(breezePredicate);
1767
+ return new TruPredicate(breezePredicate, null, null, null);
1768
+ };
1769
+ this.and = (fieldOrPredicate, operator, value) => {
1770
+ var that = this;
1771
+ return this.handleOperator(fieldOrPredicate, function (p) { return that._breezePredicate.and(p); }, operator, value);
1772
+ };
1773
+ this.or = (fieldOrPredicate, operator, value) => {
1774
+ var that = this;
1775
+ return this.handleOperator(fieldOrPredicate, function (p) { return that._breezePredicate.and(p); }, operator, value);
1776
+ };
1777
+ this.not = () => {
1778
+ var breezePredicate = this._breezePredicate.not();
1779
+ return new TruPredicate(breezePredicate, null, null, null);
1780
+ };
1781
+ if (typeof field === 'string') {
1782
+ var args = propertyQueryPath?.slice(0);
1783
+ args[args.length - 1] += field;
1784
+ args.push(operator);
1785
+ args.push(value);
1786
+ this._breezePredicate = new breeze.Predicate(args);
1787
+ this._breezePredicate.overQuoted = overQuoted;
1788
+ }
1789
+ else if (arguments[0].constructor === TruPredicate || arguments[0].constructor === BinaryPredicate || arguments[0].constructor === AndOrPredicate) {
1790
+ this._breezePredicate = arguments[0];
1791
+ }
1792
+ else {
1793
+ throw new TypeError('Unexpected parameter type <' + arguments[0].constructor + '>.');
1794
+ }
1795
+ }
1796
+ }
1797
+
1798
+ class TruPropertyConfigForeignKey extends TruPropertyConfigBase {
1799
+ constructor() {
1800
+ super();
1801
+ this.table = undefined;
1802
+ this.foreignTableName = undefined;
1803
+ this.choicesQuery = undefined;
1804
+ }
1805
+ }
1806
+
1807
+ class TruPropertyConfigCloudFile extends TruPropertyConfigForeignKey {
1808
+ constructor() { super(); }
1809
+ }
1810
+
1811
+ class TruPropertyConfigDate extends TruPropertyConfigBase {
1812
+ constructor() {
1813
+ super();
1814
+ this.minimumValue = undefined;
1815
+ this.maximumValue = undefined;
1816
+ }
1817
+ }
1818
+
1819
+ class TruPropertyConfigDecimal extends TruPropertyConfigBase {
1820
+ constructor() {
1821
+ super();
1822
+ this.decimalPlaces = undefined;
1823
+ this.totalDigits = undefined;
1824
+ this.minimumValue = undefined;
1825
+ this.maximumValue = undefined;
1826
+ }
1827
+ }
1828
+
1829
+ class TruPropertyConfigFile extends TruPropertyConfigBase {
1830
+ constructor() {
1831
+ super();
1832
+ this.maxSize = undefined;
1833
+ }
1834
+ }
1835
+
1836
+ class TruPropertyConfigInteger extends TruPropertyConfigBase {
1837
+ constructor() {
1838
+ super();
1839
+ this.minimumValue = undefined;
1840
+ this.maximumValue = undefined;
1841
+ }
1842
+ }
1843
+
1844
+ class TruPropertyConfigText extends TruPropertyConfigBase {
1845
+ constructor() {
1846
+ super();
1847
+ this.maxLength = undefined;
1848
+ this.minLength = undefined;
1849
+ this.unbounded = undefined;
1850
+ }
1851
+ }
1852
+
1853
+ class TruPropertyConfigPassword extends TruPropertyConfigText {
1854
+ constructor() {
1855
+ super();
1856
+ this.encryptionType = undefined;
1857
+ }
1858
+ }
1859
+
1860
+ class TruPropertyConfigPercentage extends TruPropertyConfigBase {
1861
+ constructor() {
1862
+ super();
1863
+ this.minimumValue = undefined;
1864
+ this.maximumValue = undefined;
1865
+ }
1866
+ }
1867
+
1868
+ class TruPropertyConfigScientific extends TruPropertyConfigBase {
1869
+ constructor() {
1870
+ super();
1871
+ this.minimumValue = undefined;
1872
+ this.maximumValue = undefined;
1873
+ }
1874
+ }
1875
+
1876
+ class TruPropertyConfigTextChoices extends TruPropertyConfigText {
1877
+ constructor() {
1878
+ super();
1879
+ this.choices = {};
1880
+ }
1881
+ }
1882
+
1883
+ class TruPropertyConfigUsaAddress extends TruPropertyConfigBase {
1884
+ constructor() {
1885
+ super();
1886
+ this.requireZipPlusFour = undefined;
1887
+ }
1888
+ }
1889
+
1890
+ class TruPropertyConfigZipCode extends TruPropertyConfigBase {
1891
+ constructor() {
1892
+ super();
1893
+ this.requireZipPlusFour = undefined;
1894
+ }
1895
+ }
1896
+
1897
+ class TruQueryPredicateManager {
1898
+ constructor(propertyQueryPath, predicateName, predicateMap) {
1899
+ this._predicate = null;
1900
+ this._propertyQueryPath = [];
1901
+ this._predicateName = '';
1902
+ this._predicateMap = {};
1903
+ this.setPredicate = (queryPredicate) => {
1904
+ if (this._predicate !== queryPredicate && this._predicateMap !== null) {
1905
+ this._predicate = queryPredicate;
1906
+ this._predicateMap[this._predicateName] = this._predicate === null ? null : this._predicate;
1907
+ }
1908
+ };
1909
+ /**
1910
+ * Returns the query predicate.
1911
+ */
1912
+ this.get = () => {
1913
+ return this._predicate;
1692
1914
  };
1693
- this.revert = () => {
1694
- this.uiNotification.confirm('Confirm Action', 'Revert ' + this.hasChanges().length + ' changed record(s)?').then((confirm) => {
1695
- if (confirm) {
1696
- this.entityManager.rejectChanges();
1697
- this.appEnvironment.revertComplete({ successful: true });
1698
- }
1699
- });
1915
+ /**
1916
+ * Clears the query predicate.
1917
+ */
1918
+ this.clear = () => {
1919
+ this.setPredicate(null);
1700
1920
  };
1701
- this.revertWithoutPrompt = () => {
1702
- this.revert();
1703
- this.appEnvironment.revertComplete({ successful: true });
1921
+ /**
1922
+ * Returns a new query predicate.
1923
+ *
1924
+ * @param {string} field - Name of the storage field relative to the intent property.
1925
+ * @param {string} operator - Name of the predicate operator.
1926
+ * @param {*} value - Literal value.
1927
+ */
1928
+ this.create = (field, operator, value, overQuoted = false) => {
1929
+ return new TruPredicate(field, operator, value, this._propertyQueryPath, overQuoted)._breezePredicate;
1704
1930
  };
1705
- this.delete = (entities, confirmMsg, onSuccess = undefined) => {
1706
- var newEntities = [];
1707
- var existingEntities = [];
1708
- entities.forEach(function (e) {
1709
- if (e.entityAspect.entityState.isAdded())
1710
- newEntities.push(e);
1711
- else
1712
- existingEntities.push(e);
1713
- });
1714
- if (newEntities.length && existingEntities.length) {
1715
- this.uiNotification.warning(this.appEnvironment.msgCannotDeleteNewAndExistingRecords);
1716
- return;
1717
- }
1718
- if (existingEntities.length) {
1719
- if (this.hasChanges().length) {
1720
- this.uiNotification.warning(this.appEnvironment.msgDirtyPreventsDeleteExistingRecord);
1721
- return;
1722
- }
1723
- }
1724
- this.uiNotification.confirm('Confirm Action', confirmMsg).then((confirm) => {
1725
- if (confirm) {
1726
- if (newEntities.length) {
1727
- newEntities.forEach((entity) => {
1728
- entity.entityAspect.clearValidationErrors();
1729
- });
1730
- this.markForDelete(newEntities);
1731
- if (onSuccess)
1732
- onSuccess();
1733
- return;
1734
- }
1735
- try {
1736
- this.markForDelete(existingEntities);
1737
- }
1738
- catch (exception) {
1739
- this.uiNotification.error(exception.message);
1740
- return;
1741
- }
1742
- this.save(null, true).then(() => {
1743
- var entitiesDeleted = this._pendingDeleteEntities.concat(this._pendingCascadeDeleteEntities);
1744
- this.appEnvironment.deleteComplete({ successful: true, entities: entitiesDeleted });
1745
- if (entitiesDeleted.length) {
1746
- this._pendingCascadeDeleteEntities = [];
1747
- this._pendingDeleteEntities = [];
1748
- }
1749
- this.uiNotification.success(this.appEnvironment.msgDeleteSuccessful);
1750
- if (onSuccess)
1751
- onSuccess(true);
1752
- }).catch((error) => {
1753
- this.revert();
1754
- }).finally(() => { });
1755
- }
1756
- });
1931
+ this.set = (fieldOrPredicate, operator, value, overQuoted = false) => {
1932
+ var predicate;
1933
+ if (fieldOrPredicate.constructor === TruPredicate)
1934
+ predicate = fieldOrPredicate;
1935
+ else
1936
+ predicate = this.create(fieldOrPredicate, operator, value, overQuoted);
1937
+ this.setPredicate(predicate);
1757
1938
  };
1758
- this._breezeContext = this.breezeContextFactory.createContext();
1759
- this.entityAccessor.context = this;
1760
- }
1761
- get breezeContext() {
1762
- return this._breezeContext;
1763
- }
1764
- get entityManager() {
1765
- return this._breezeContext.entityManager;
1939
+ this._propertyQueryPath = propertyQueryPath;
1940
+ this._predicateName = predicateName;
1941
+ this._predicateMap = predicateMap;
1766
1942
  }
1943
+ }
1944
+
1945
+ class TruConfirmDialogModule {
1767
1946
  }
1768
- TruDataContext.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDataContext, deps: [{ token: TruBreezeContextFactory }, { token: TruAppEnvironment }, { token: TruEntityAccessor }, { token: TruUiNotification }], target: i0.ɵɵFactoryTarget.Injectable });
1769
- TruDataContextprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDataContext });
1770
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDataContext, decorators: [{
1771
- type: Injectable
1772
- }], ctorParameters: function () { return [{ type: TruBreezeContextFactory }, { type: TruAppEnvironment }, { type: TruEntityAccessor }, { type: TruUiNotification }]; } });
1947
+ TruConfirmDialogModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruConfirmDialogModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1948
+ TruConfirmDialogModulemod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.1", ngImport: i0, type: TruConfirmDialogModule, declarations: [TruConfirmDialog], imports: [CommonModule, FormsModule], exports: [TruConfirmDialog] });
1949
+ TruConfirmDialogModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruConfirmDialogModule, imports: [CommonModule, FormsModule] });
1950
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruConfirmDialogModule, decorators: [{
1951
+ type: NgModule,
1952
+ args: [{
1953
+ declarations: [TruConfirmDialog],
1954
+ imports: [CommonModule, FormsModule],
1955
+ exports: [TruConfirmDialog]
1956
+ }]
1957
+ }] });
1958
+
1959
+ var TruDataGridTypes;
1960
+ (function (TruDataGridTypes) {
1961
+ TruDataGridTypes[TruDataGridTypes["Search"] = 0] = "Search";
1962
+ TruDataGridTypes[TruDataGridTypes["Detail"] = 1] = "Detail";
1963
+ TruDataGridTypes[TruDataGridTypes["DetailManyToMany"] = 2] = "DetailManyToMany";
1964
+ })(TruDataGridTypes || (TruDataGridTypes = {}));
1773
1965
 
1774
1966
  class TruSearchResultViewManager {
1775
1967
  constructor() { }
@@ -5523,137 +5715,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImpor
5523
5715
  }]
5524
5716
  }], ctorParameters: function () { return []; } });
5525
5717
 
5526
- class TruTextManager {
5527
- constructor() {
5528
- /**
5529
- * If text.length exceeds length, then returns a string that is the first length chars
5530
- * of text plus suffix. Otherwise, returns text.
5531
- * @param {string} text
5532
- * @param {number} length
5533
- * @param {string} suffix
5534
- * @return {string}
5535
- */
5536
- this.truncate = (text, length, suffix) => {
5537
- return text.length > length ? text.substr(0, length) + suffix : text.toString();
5538
- };
5539
- this.isMac = () => {
5540
- return navigator.platform.toUpperCase().indexOf('MAC') >= 0;
5541
- };
5542
- /**
5543
- * Formats the text to use for the window title.
5544
- * @param {string} text
5545
- * @return {string} - Window title.
5546
- */
5547
- this.formatWindowTitle = (text) => {
5548
- return this.truncate(text, 60, '...');
5549
- };
5550
- /**
5551
- * Returns a message indicating that an entity or entities were deleted in another view.
5552
- * @param {string} entityTypeLabel - Description of the entity type.
5553
- * @param [{string}] entityTypePluralLabel - Description of more than one of the entity type.
5554
- * @param [{number}] count - Number of entities.
5555
- */
5556
- this.fmtEntityDeletedInOtherView = (entityTypeLabel, entityTypePluralLabel, count) => {
5557
- if (!count || count === 1)
5558
- return entityTypeLabel + ' deleted in another view';
5559
- return count + ' ' + entityTypePluralLabel + ' deleted in another view';
5560
- };
5561
- /**
5562
- * Returns a message used to confirm deletion of an entity or entities.
5563
- * @param {string} entityTypeLabel - Description of the entity type.
5564
- * @param [{string}] entityTypePluralLabel - Description of more than one of the entity type.
5565
- * @param [{number}] count - Number of entities.
5566
- */
5567
- this.fmtDeleteConfirmation = (entityTypeLabel, entityTypePluralLabel = null, count = null) => {
5568
- if (count === null)
5569
- return 'Are you sure you want to delete this ' + entityTypeLabel + '?';
5570
- if (count === 1)
5571
- return 'Are you sure you want to delete 1 ' + entityTypeLabel + '?';
5572
- return 'Are you sure you want to delete ' + count + ' ' + entityTypePluralLabel + '?';
5573
- };
5574
- /**
5575
- * Returns a message formatted from an error object.
5576
- * @param {error|string} error
5577
- * @returns {string}
5578
- */
5579
- this.fmtErrorToShow = (error) => {
5580
- if (typeof error === 'string')
5581
- error = new Error(error);
5582
- var lines = [];
5583
- lines.push(error.message);
5584
- var exception = error.detail;
5585
- while (exception) {
5586
- var message = exception.ExceptionMessage;
5587
- if (!_.contains(lines, message))
5588
- lines.push(message);
5589
- exception = exception.InnerException;
5590
- }
5591
- if (error.entityErrors) {
5592
- error.entityErrors.forEach((entityError) => {
5593
- lines.push('Entity <' + entityError.propertyName + '>: ' + entityError.errorMessage);
5594
- });
5595
- }
5596
- if (error.stack)
5597
- lines.push(error.stack);
5598
- var text = lines.join('\r\n\r\n');
5599
- if (!text)
5600
- text = _.map(error, (value, key) => { return key + ': ' + value; }).join('\r\n');
5601
- return text;
5602
- };
5603
- /**
5604
- * Returns a message formatted from an exception object.
5605
- * @param {object} exception
5606
- * @returns {string}
5607
- */
5608
- this.fmtExceptionToShow = (exception) => {
5609
- var lines = [];
5610
- while (exception) {
5611
- var message = exception.Message;
5612
- if (!_.contains(lines, message))
5613
- lines.push(message);
5614
- exception = exception.InnerException;
5615
- }
5616
- return lines.join('\r\n\r\n');
5617
- };
5618
- /**
5619
- * Returns a message for a data error type.
5620
- * @param {string} typeName
5621
- * @returns {string}
5622
- */
5623
- this.fmtDataError = (typeName) => {
5624
- if (typeName.indexOf('OptimisticLockViolation') >= 0)
5625
- return 'The record was edited already, by another user. Please reload and attempt your edit again.';
5626
- if (typeName.indexOf('DataConstraintViolation') >= 0)
5627
- return 'Foreign key constraint violation';
5628
- if (typeName.indexOf('DuplicateKeyError') >= 0)
5629
- return 'Duplicate key error';
5630
- return typeName;
5631
- };
5632
- this.msgModifierKeyLabel = this.isMac() ? 'Cmd' : 'Ctrl';
5633
- this.msgConfirmExitWithChangesPending = 'You have unsaved changes that will be lost.';
5634
- this.msgDeleteSuccessful = 'Delete succeeded';
5635
- this.msgSaveSuccessful = 'Save succeeded';
5636
- this.msgNoChangesToSave = 'No changes to save';
5637
- this.msgSaveInProgress = 'Save in progress';
5638
- this.msgInvalidData = 'Invalid data';
5639
- this.msgDirtyPreventsReadOnly = 'Save or revert before disabling editing';
5640
- this.msgDirtyPreventsNavigate = 'Save or revert before navigating';
5641
- this.msgDirtyPreventsClose = 'Save or revert before closing window';
5642
- this.msgDirtyPreventsDeleteExistingRecord = 'Save or revert before deleting';
5643
- this.msgNoDeleteAccess = 'Contact administrator about delete access';
5644
- this.msgCannotDeleteNewAndExistingRecords = 'Delete new or existing records - but not both';
5645
- this.msgDeleteReferencingRecordsFirst = 'Delete all referencing records first';
5646
- }
5647
- }
5648
- TruTextManager.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruTextManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
5649
- TruTextManager.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruTextManager, providedIn: 'root' });
5650
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruTextManager, decorators: [{
5651
- type: Injectable,
5652
- args: [{
5653
- providedIn: 'root',
5654
- }]
5655
- }], ctorParameters: function () { return []; } });
5656
-
5657
5718
  class TruUser {
5658
5719
  constructor() {
5659
5720
  this._ref = -1;