@trudb/tru-common-lib 0.0.450 → 0.0.452

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,1729 @@ 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);
1131
+ class TruDetailViewBase {
1132
+ constructor(dataContext, textManager) {
1133
+ this.dataContext = dataContext;
1134
+ this.textManager = textManager;
1135
+ this.entities = [];
1136
+ this.recordLocation = null;
1137
+ this.disableNavigationToPreviousEntity = false;
1138
+ this.disableNavigationToNextEntity = false;
1139
+ this.navigationIndex = 0;
1140
+ this.onAddEntity = () => {
1141
+ let newEntity = this.dataContext.entityAccess().add(this.entityType);
1142
+ this.entities.splice(this.navigationIndex + 1, 0, newEntity);
1143
+ this.navigateTo(this.navigationIndex + 1);
1144
+ };
1145
+ this.onCloneEntity = () => {
1146
+ };
1147
+ this.onDeleteEntity = () => {
1148
+ let confirmMsg = this.textManager.fmtDeleteConfirmation(this.entityType.name);
1149
+ this.dataContext.delete([this.entity], confirmMsg, () => { return true; });
1150
+ };
1151
+ this.onFirstEntity = () => {
1152
+ this.navigateTo(0);
1153
+ };
1154
+ this.onPreviousEntity = () => {
1155
+ this.navigateTo(this.navigationIndex - 1);
1156
+ };
1157
+ this.onNextEntity = () => {
1158
+ this.navigateTo(this.navigationIndex + 1);
1159
+ };
1160
+ this.onLastEntity = () => {
1161
+ this.navigateTo(this.entities.length - 1);
1162
+ };
1163
+ this.navigateTo = (index) => {
1164
+ this.setNavigationIndex(index);
1165
+ this.setEntityDisplayValues(this.tableName);
1166
+ };
1167
+ }
1168
+ 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
+ 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';
1382
1182
  }
1383
1183
  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);
1184
+ title += this.entity.HID;
1388
1185
  }
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
- })));
1186
+ recordIndex = (this.navigationIndex + 1).toString();
1187
+ }
1188
+ this.view.window.title = this.textManager.formatWindowTitle(title);
1189
+ this.recordLocation = recordIndex + ' of ' + this.entities.length;
1190
+ }
1191
+ }
1192
+ 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 });
1193
+ 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: [""] });
1194
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDetailViewBase, decorators: [{
1195
+ type: Component,
1196
+ args: [{ selector: 'tru-detail-view-base', template: "" }]
1197
+ }], ctorParameters: function () { return [{ type: TruDataContext }, { type: TruTextManager }]; }, propDecorators: { view: [{
1198
+ type: Input
1199
+ }] } });
1200
+
1201
+ class DetailViewModule {
1202
+ }
1203
+ DetailViewModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: DetailViewModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1204
+ DetailViewModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.1", ngImport: i0, type: DetailViewModule, declarations: [TruDetailViewBase], imports: [CommonModule, FormsModule], exports: [TruDetailViewBase] });
1205
+ DetailViewModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: DetailViewModule, imports: [CommonModule, FormsModule] });
1206
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: DetailViewModule, decorators: [{
1207
+ type: NgModule,
1208
+ args: [{
1209
+ declarations: [TruDetailViewBase],
1210
+ imports: [CommonModule, FormsModule],
1211
+ exports: [TruDetailViewBase]
1212
+ }]
1213
+ }] });
1214
+
1215
+ class TruDesktopViewConfig {
1216
+ onActive() {
1217
+ return this.active$;
1218
+ }
1219
+ active(value) {
1220
+ this.active$.next(value);
1221
+ }
1222
+ constructor() {
1223
+ this.active$ = new BehaviorSubject(true);
1224
+ this.entities = undefined;
1225
+ this.entityIndex = 0;
1226
+ this.isDirty = false;
1227
+ this.isEditing = false;
1228
+ this.isInvalid = false;
1229
+ this.componentName = '';
1230
+ this.openAsDetaiView = false;
1231
+ }
1232
+ }
1233
+ ;
1234
+
1235
+ class TruWindowEventArgs {
1236
+ constructor() {
1237
+ this.title = '';
1238
+ this.tableName = '';
1239
+ this.tablePluralName = '';
1240
+ this.tablePluralLabel = '';
1241
+ this.context = {};
1242
+ this.contentBottom = '23px';
1243
+ this.statusbarDirective = 'tru-statusbar';
1244
+ this.height = '450px';
1245
+ this.width = '900px';
1246
+ this.views = [{}];
1247
+ this.contextFilters = [];
1248
+ }
1249
+ }
1250
+ TruWindowEventArgs.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventArgs, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1251
+ TruWindowEventArgs.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventArgs, providedIn: 'root' });
1252
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventArgs, decorators: [{
1253
+ type: Injectable,
1254
+ args: [{
1255
+ providedIn: 'root'
1256
+ }]
1257
+ }] });
1258
+
1259
+ class TruContextFilters {
1260
+ constructor() {
1261
+ this.filters = [];
1262
+ this.valueFor = (tableName) => {
1263
+ let choice = this.filters.find(f => f.selectedChoice.table === tableName)?.selectedChoice;
1264
+ if (!choice)
1265
+ throw new Error('ContextFilterChoice not found. Possible invalid configuration.');
1266
+ return choice.ref;
1396
1267
  };
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));
1268
+ this.label = () => {
1269
+ let label = '';
1270
+ //this.selectedContextFilterChoices.forEach((filter: TruContextFilterChoice) => {
1271
+ // label += filter.table + ': ' + filter.label + ' ';
1272
+ //});
1273
+ return label;
1402
1274
  };
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);
1275
+ }
1276
+ }
1277
+ TruContextFilters.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruContextFilters, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1278
+ TruContextFilters.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruContextFilters, providedIn: 'root' });
1279
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruContextFilters, decorators: [{
1280
+ type: Injectable,
1281
+ args: [{
1282
+ providedIn: 'root',
1283
+ }]
1284
+ }], ctorParameters: function () { return []; } });
1285
+
1286
+ class TruWindowEventHandler {
1287
+ constructor() {
1288
+ this.open$ = new Subject();
1289
+ this.addView$ = new Subject();
1290
+ this.removeForwadViews$ = new Subject();
1291
+ }
1292
+ onOpen() {
1293
+ return this.open$;
1294
+ }
1295
+ open(windowEvent) {
1296
+ this.open$.next(windowEvent);
1297
+ }
1298
+ onAddView() {
1299
+ return this.addView$;
1300
+ }
1301
+ addView(windowAddViewEvent) {
1302
+ this.addView$.next(windowAddViewEvent);
1303
+ }
1304
+ onRemoveForwardViews() {
1305
+ return this.removeForwadViews$;
1306
+ }
1307
+ removeForwardViews() {
1308
+ this.removeForwadViews$.next(null);
1309
+ }
1310
+ }
1311
+ TruWindowEventHandler.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1312
+ TruWindowEventHandler.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventHandler, providedIn: 'root' });
1313
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruWindowEventHandler, decorators: [{
1314
+ type: Injectable,
1315
+ args: [{
1316
+ providedIn: 'root'
1317
+ }]
1318
+ }] });
1319
+
1320
+ class TruDesktopManager {
1321
+ constructor(contextFilters, windowEventHandler) {
1322
+ this.contextFilters = contextFilters;
1323
+ this.windowEventHandler = windowEventHandler;
1324
+ this.getWindowEvent = (tableName, tablePluralName, tablePluralLabel, componentName, entities = [], openAsDetaiView = false) => {
1325
+ var windowEvent = new TruWindowEventArgs();
1326
+ windowEvent.tableName = tableName;
1327
+ windowEvent.tablePluralName = tablePluralName;
1328
+ windowEvent.tablePluralLabel = tablePluralLabel;
1329
+ windowEvent.contextFilters = this.contextFilters.filters;
1330
+ windowEvent.views = [
1331
+ {
1332
+ active: true,
1333
+ entities: entities,
1334
+ entityIndex: 0,
1335
+ isDirty: false,
1336
+ isEditing: false,
1337
+ isInvalid: false,
1338
+ openAsDetaiView: openAsDetaiView,
1339
+ componentName: componentName
1340
+ }
1341
+ ];
1342
+ return windowEvent;
1408
1343
  };
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
- })));
1344
+ /**
1345
+ * Opens a window for a directive.
1346
+ * @param {string} directiveName - name of the view directive.
1347
+ * @param {object} data - values to pass to the view.
1348
+ * @param {optional bool} showIfExists - if true and a view already exists for the
1349
+ * directive, then shows its window instead of creating a new one.
1350
+ */
1351
+ this.addWindow = (tableName, tablePluralName, tablePluralLabel, componentName, entities = [], openAsDetaiView = false, showNavigation = true, showIfExists) => {
1352
+ this.windowEventHandler.open(this.getWindowEvent(tableName, tablePluralName, tablePluralLabel, componentName, entities, openAsDetaiView));
1353
+ };
1354
+ this.windowTitlesByBaseText = {};
1355
+ /**
1356
+ * Returns a unique string for the base name of a window. At first, returns the input.
1357
+ * For second call with same base name, returns the name plus ' - 2' and so on. When
1358
+ * all of the titles for the base name are released, then the next title will have no
1359
+ * suffix.
1360
+ * @param {string} text - base name of a window.
1361
+ * @returns {object} - text: the unique text and release(): releases the name for
1362
+ * future windows.
1363
+ */
1364
+ this.getUniqueTitle = (text) => {
1365
+ var baseText = text;
1366
+ var titles = this.windowTitlesByBaseText[baseText];
1367
+ if (!titles) {
1368
+ this.windowTitlesByBaseText[baseText] = titles = {
1369
+ dispensedCount: 1,
1370
+ activeCount: 1
1371
+ };
1420
1372
  }
1421
- return of(this.formatQueryChoices(query, this._entityManager.executeQueryLocally(query), pkeyName, null));
1373
+ else {
1374
+ ++titles.activeCount;
1375
+ text += ' - ' + (++titles.dispensedCount);
1376
+ }
1377
+ return {
1378
+ text: text,
1379
+ release: () => {
1380
+ if (titles.activeCount === 1)
1381
+ delete this.windowTitlesByBaseText[baseText];
1382
+ else {
1383
+ --titles.activeCount;
1384
+ }
1385
+ }
1386
+ };
1422
1387
  };
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;
1388
+ }
1389
+ }
1390
+ 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 });
1391
+ TruDesktopManager.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDesktopManager, providedIn: 'root' });
1392
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruDesktopManager, decorators: [{
1393
+ type: Injectable,
1394
+ args: [{
1395
+ providedIn: 'root',
1396
+ }]
1397
+ }], ctorParameters: function () { return [{ type: TruContextFilters }, { type: TruWindowEventHandler }]; } });
1398
+
1399
+ class TruSearchViewBase {
1400
+ constructor(desktopManager, truWindowEventHandler) {
1401
+ this.desktopManager = desktopManager;
1402
+ this.truWindowEventHandler = truWindowEventHandler;
1403
+ this.tableName = '';
1404
+ this.tablePluralName = '';
1405
+ this.tablePluralLabel = '';
1406
+ this.pkeyName = '';
1407
+ this.windowTitle = undefined;
1408
+ this.unsubscribes = [];
1409
+ this.expands = [];
1410
+ this.isSearching = false;
1411
+ this.entities = [];
1412
+ this.hasDetailView = true;
1413
+ this.searchPanelConfig = {
1414
+ side: 'right',
1415
+ active: true,
1416
+ open: true,
1417
+ modKeyLabel: '',
1418
+ size: 500,
1419
+ pinned: false
1466
1420
  };
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;
1421
+ this.onPkeyCellDoubleClicked = (gridConfig) => {
1422
+ if (this.hasDetailView) {
1423
+ var truWindowAddViewEventArgs = new TruDesktopViewConfig();
1424
+ truWindowAddViewEventArgs.entities = gridConfig.api.getRenderedNodes().map((rowNode) => rowNode.data.$entity);
1425
+ truWindowAddViewEventArgs.entityIndex = gridConfig.rowIndex;
1426
+ truWindowAddViewEventArgs.componentName = this.tableName + 'DetailView';
1427
+ this.truWindowEventHandler.addView(truWindowAddViewEventArgs);
1428
+ this.view.active(false);
1486
1429
  }
1487
1430
  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;
1494
- }
1495
- 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;
1511
- }
1512
- var value = data[name];
1513
- buffer.push(encodeURIComponent(name) +
1514
- '=' + encodeURIComponent(value == null ? '' : value));
1431
+ alert(this.tablePluralLabel + ' does not have a detail view.');
1515
1432
  }
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;
1551
1433
  };
1552
- this._maxRecordCount = this.appEnvironment.maxRecordCount;
1553
1434
  }
1554
- set context(dataContext) {
1555
- this._breezeContext = dataContext.breezeContext;
1556
- this._entityManager = dataContext.entityManager;
1435
+ setWindowTitle() {
1436
+ if (!this.windowTitle)
1437
+ this.windowTitle = this.desktopManager.getUniqueTitle(this.tablePluralLabel);
1438
+ this.view.window.title = this.windowTitle.text;
1439
+ }
1440
+ releaseWindowTitle() {
1441
+ this.windowTitle?.release();
1557
1442
  }
1558
1443
  }
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
- TruEntityAccessorprov = 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: [{
1444
+ 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 });
1445
+ TruSearchViewBasecmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.1", type: TruSearchViewBase, selector: "tru-search-view-base", inputs: { view: "view" }, ngImport: i0, template: "", styles: [""] });
1446
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBase, decorators: [{
1447
+ type: Component,
1448
+ args: [{ selector: 'tru-search-view-base', template: "" }]
1449
+ }], ctorParameters: function () { return [{ type: TruDesktopManager }, { type: TruWindowEventHandler }]; }, propDecorators: { view: [{
1450
+ type: Input
1451
+ }] } });
1452
+
1453
+ class TruSearchViewBaseModule {
1454
+ }
1455
+ TruSearchViewBaseModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBaseModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1456
+ TruSearchViewBaseModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBaseModule, declarations: [TruSearchViewBase], imports: [CommonModule, FormsModule], exports: [TruSearchViewBase] });
1457
+ TruSearchViewBaseModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBaseModule, imports: [CommonModule, FormsModule] });
1458
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewBaseModule, decorators: [{
1459
+ type: NgModule,
1460
+ args: [{
1461
+ declarations: [TruSearchViewBase],
1462
+ imports: [CommonModule, FormsModule],
1463
+ exports: [TruSearchViewBase]
1464
+ }]
1465
+ }] });
1466
+
1467
+ class TruSearchViewControlEventHandler {
1468
+ constructor() {
1469
+ this.clear$ = new BehaviorSubject(null);
1470
+ this.default$ = new BehaviorSubject(null);
1471
+ }
1472
+ onSetDefaults() {
1473
+ return this.default$;
1474
+ }
1475
+ setDefaults() {
1476
+ this.default$.next(null);
1477
+ }
1478
+ onClearValues() {
1479
+ return this.clear$;
1480
+ }
1481
+ clearValues() {
1482
+ this.clear$.next(null);
1483
+ }
1484
+ }
1485
+ TruSearchViewControlEventHandler.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewControlEventHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1486
+ TruSearchViewControlEventHandler.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewControlEventHandler });
1487
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewControlEventHandler, decorators: [{
1562
1488
  type: Injectable
1563
- }], ctorParameters: function () { return [{ type: i1$2.HttpClient }, { type: TruAppEnvironment }, { type: TruUiNotification }]; } });
1489
+ }] });
1564
1490
 
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);
1592
- };
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;
1491
+ class TruSearchViewEventHandler {
1492
+ constructor() {
1493
+ this.search$ = new BehaviorSubject(null);
1494
+ this.filter$ = new BehaviorSubject(null);
1495
+ }
1496
+ search(query) {
1497
+ this.search$.next(query);
1498
+ }
1499
+ onSearch() {
1500
+ return this.search$.asObservable();
1501
+ }
1502
+ filter(query) {
1503
+ this.filter$.next(query);
1504
+ }
1505
+ onFilter() {
1506
+ return this.filter$.asObservable();
1507
+ }
1508
+ }
1509
+ TruSearchViewEventHandler.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewEventHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1510
+ TruSearchViewEventHandler.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewEventHandler });
1511
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchViewEventHandler, decorators: [{
1512
+ type: Injectable
1513
+ }] });
1514
+
1515
+ class TruSearchResultViewBase {
1516
+ constructor(truWindowEventHandler) {
1517
+ this.truWindowEventHandler = truWindowEventHandler;
1518
+ this.tableName = '';
1519
+ this.tablePluralLabel = '';
1520
+ this.hasDetailView = true;
1521
+ this.searchPanelConfig = {
1522
+ side: 'right',
1523
+ active: true,
1524
+ open: true,
1525
+ modKeyLabel: '',
1526
+ size: 500,
1527
+ pinned: false
1613
1528
  };
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;
1529
+ this.onPkeyCellDoubleClicked = (gridConfig) => {
1530
+ if (this.hasDetailView) {
1531
+ var truWindowAddViewEventArgs = new TruDesktopViewConfig();
1532
+ truWindowAddViewEventArgs.entities = gridConfig.api.getRenderedNodes().map((rowNode) => rowNode.data.$entity);
1533
+ truWindowAddViewEventArgs.entityIndex = gridConfig.rowIndex;
1534
+ truWindowAddViewEventArgs.componentName = this.tableName + 'DetailView';
1535
+ this.truWindowEventHandler.addView(truWindowAddViewEventArgs);
1536
+ }
1537
+ else {
1538
+ alert(this.tablePluralLabel + ' does not have a detail view.');
1539
+ }
1631
1540
  };
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);
1541
+ }
1542
+ ngOnInit() {
1543
+ this.tableName = this.view.window.tableName;
1544
+ this.tablePluralLabel = this.view.window.tablePluralLabel;
1545
+ }
1546
+ }
1547
+ TruSearchResultViewBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBase, deps: [{ token: TruWindowEventHandler }], target: i0.ɵɵFactoryTarget.Component });
1548
+ 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: [""] });
1549
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBase, decorators: [{
1550
+ type: Component,
1551
+ args: [{ selector: 'tru-search-result-view-base', template: "" }]
1552
+ }], ctorParameters: function () { return [{ type: TruWindowEventHandler }]; }, propDecorators: { view: [{
1553
+ type: Input
1554
+ }] } });
1555
+
1556
+ class TruSearchResultViewBaseModule {
1557
+ }
1558
+ TruSearchResultViewBaseModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBaseModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1559
+ TruSearchResultViewBaseModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBaseModule, declarations: [TruSearchResultViewBase], imports: [CommonModule, FormsModule], exports: [TruSearchResultViewBase] });
1560
+ TruSearchResultViewBaseModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBaseModule, imports: [CommonModule, FormsModule] });
1561
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruSearchResultViewBaseModule, decorators: [{
1562
+ type: NgModule,
1563
+ args: [{
1564
+ declarations: [TruSearchResultViewBase],
1565
+ imports: [CommonModule, FormsModule],
1566
+ exports: [TruSearchResultViewBase]
1567
+ }]
1568
+ }] });
1569
+
1570
+ class TruChoice {
1571
+ }
1572
+
1573
+ class TruContextFilter {
1574
+ constructor() {
1575
+ this.tooltip = undefined;
1576
+ this.choices = [];
1577
+ this.identify = (index, choice) => {
1578
+ return choice.ref;
1639
1579
  };
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
- });
1580
+ this.comparer = (o1, o2) => {
1581
+ return o1 && o2 ? o1.label === o2.label : o2 === o2;
1582
+ };
1583
+ this.onChange = (choice) => {
1584
+ this.selectedChoice = choice;
1585
+ };
1586
+ }
1587
+ }
1588
+
1589
+ class TruContextFilterChoice {
1590
+ constructor(table, label, ref) {
1591
+ this.table = table;
1592
+ this.label = label;
1593
+ this.ref = ref;
1594
+ }
1595
+ }
1596
+
1597
+ class TruFormulaEval {
1598
+ static isString(s) {
1599
+ return typeof s === 'string';
1600
+ }
1601
+ static isDate(v) {
1602
+ return Object.prototype.toString.call(v) === '[object Date]';
1603
+ }
1604
+ static toValue(value) {
1605
+ return value;
1606
+ }
1607
+ static toString(value) {
1608
+ //if (_.isBoolean(value))
1609
+ // return value ? 'TRUE' : 'FALSE';
1610
+ return value.toString();
1611
+ }
1612
+ static toDouble(value) {
1613
+ return Number(value);
1614
+ }
1615
+ static toInteger(value) {
1616
+ return Math.round(value);
1617
+ }
1618
+ static toBoolean(value) {
1619
+ if (_.isBoolean(value))
1620
+ return value;
1621
+ var number = Number(value);
1622
+ if (isNaN(number))
1623
+ return NaN;
1624
+ return number !== 0;
1625
+ }
1626
+ static toDate(value) {
1627
+ return value;
1628
+ }
1629
+ statictoDateTime(value) {
1630
+ return value;
1631
+ }
1632
+ /**
1633
+ * Exposed for testing.
1634
+ */
1635
+ static _calculate(f, left, right) {
1636
+ if (TruFormulaEval.isString(left))
1637
+ left = parseFloat(left);
1638
+ if (TruFormulaEval.isString(left))
1639
+ if (TruFormulaEval.isString(right))
1640
+ right = parseFloat(right);
1641
+ return f(left, right);
1642
+ }
1643
+ static _calculateDate(left, right, add) {
1644
+ if (add) {
1645
+ if (TruFormulaEval.isDate(left) && !TruFormulaEval.isDate(right)) {
1646
+ return moment(left).add(right, 'day').toDate();
1647
+ }
1648
+ if (!TruFormulaEval.isDate(left) && TruFormulaEval.isDate(right)) {
1649
+ return moment(right).add(left, 'day').toDate();
1650
+ }
1651
+ if (TruFormulaEval.isDate(left) && TruFormulaEval.isDate(right)) {
1652
+ moment(left).add(right).toDate();
1653
+ }
1654
+ }
1655
+ else {
1656
+ if (TruFormulaEval.isDate(left) && !TruFormulaEval.isDate(right)) {
1657
+ return moment(left).subtract(right, 'day').toDate();
1658
+ }
1659
+ if (!TruFormulaEval.isDate(left) && TruFormulaEval.isDate(right)) {
1660
+ return moment(right).subtract(left, 'day').toDate();
1661
+ }
1662
+ if (TruFormulaEval.isDate(left) && TruFormulaEval.isDate(right)) {
1663
+ //var m = moment(left).diff(right, 'days'); //Integer value, but Excel uses decimal for date time
1664
+ var m = moment(left).diff(moment(right)) / 86400000; //divide by miliseconds in a day, decimal answer 1.0 = 1 day, 0.5 = 12 hours
1665
+ return m;
1647
1666
  }
1667
+ }
1668
+ return null;
1669
+ }
1670
+ static add(left, right) {
1671
+ if (left === null || left === undefined || right === null || right === undefined)
1672
+ return undefined;
1673
+ if (TruFormulaEval.isDate(left) || TruFormulaEval.isDate(right))
1674
+ return TruFormulaEval._calculateDate(left, right, true);
1675
+ return TruFormulaEval._calculate(function (l, r) { return l + r; }, left, right);
1676
+ }
1677
+ static subtract(left, right) {
1678
+ if (left === null || left === undefined || right === null || right === undefined)
1679
+ return undefined;
1680
+ if (TruFormulaEval.isDate(left) || TruFormulaEval.isDate(right))
1681
+ return TruFormulaEval._calculateDate(left, right, true);
1682
+ return TruFormulaEval._calculate(function (l, r) { return l - r; }, left, right);
1683
+ }
1684
+ static multiply(left, right) {
1685
+ if (left === null || left === undefined || right === null || right === undefined)
1686
+ return undefined;
1687
+ return TruFormulaEval._calculate(function (l, r) { return l * r; }, left, right);
1688
+ }
1689
+ static divide(left, right) {
1690
+ if (left === null || left === undefined || right === null || right === undefined)
1691
+ return undefined;
1692
+ return TruFormulaEval._calculate(function (l, r) { return l / r; }, left, right);
1693
+ }
1694
+ static power(left, right) {
1695
+ if (left === null || left === undefined || right === null || right === undefined)
1696
+ return undefined;
1697
+ return TruFormulaEval._calculate(Math.pow, left, right);
1698
+ }
1699
+ static concatenate(left, right) {
1700
+ if (_.isBoolean(left))
1701
+ left = left ? 'TRUE' : 'FALSE';
1702
+ else if (!TruFormulaEval.isString(left))
1703
+ //NOTE: only need to convert left to string since concat() will coerce parameters
1704
+ left = left.toString();
1705
+ if (_.isBoolean(right))
1706
+ right = right ? 'TRUE' : 'FALSE';
1707
+ return left.concat(right);
1708
+ }
1709
+ static equal(left, right) {
1710
+ return left === right;
1711
+ }
1712
+ static notEqual(left, right) {
1713
+ return left !== right;
1714
+ }
1715
+ static lessThan(left, right) {
1716
+ if (typeof (left) !== typeof (right))
1717
+ return !TruFormulaEval.compareResultForMismatchedParams[typeof (left) + typeof (right)];
1718
+ return left < right;
1719
+ }
1720
+ static greaterThan(left, right) {
1721
+ if (typeof (left) !== typeof (right))
1722
+ return TruFormulaEval.compareResultForMismatchedParams[typeof (left) + typeof (right)];
1723
+ return left > right;
1724
+ }
1725
+ static lessThanOrEqual(left, right) {
1726
+ if (typeof (left) !== typeof (right))
1727
+ return !TruFormulaEval.compareResultForMismatchedParams[typeof (left) + typeof (right)];
1728
+ return left <= right;
1729
+ }
1730
+ static greaterThanOrEqual(left, right) {
1731
+ if (typeof (left) !== typeof (right))
1732
+ return TruFormulaEval.compareResultForMismatchedParams[typeof (left) + typeof (right)];
1733
+ return left >= right;
1734
+ }
1735
+ static negate(operand) {
1736
+ return -operand;
1737
+ }
1738
+ static percent(operand) {
1739
+ return operand / 100.0;
1740
+ }
1741
+ }
1742
+ TruFormulaEval.compareResultForMismatchedParams = {
1743
+ booleanstring: true,
1744
+ booleannumber: true,
1745
+ stringnumber: true,
1746
+ stringboolean: false,
1747
+ numberstring: false,
1748
+ numberboolean: false
1749
+ };
1750
+
1751
+ class TruPredicate {
1752
+ constructor(field, operator, value, propertyQueryPath, overQuoted = false) {
1753
+ this._breezePredicate = null;
1754
+ this.handleOperator = (fieldOrPredicate, oper, operator, value) => {
1755
+ var breezePredicate;
1756
+ if (Array.isArray(fieldOrPredicate)) {
1757
+ breezePredicate = new TruPredicate(fieldOrPredicate[0], fieldOrPredicate[1], fieldOrPredicate[2], []);
1758
+ }
1759
+ else if (fieldOrPredicate.constructor === TruPredicate || fieldOrPredicate.constructor === BinaryPredicate || fieldOrPredicate.constructor === AndOrPredicate) {
1760
+ breezePredicate = fieldOrPredicate;
1761
+ }
1762
+ else {
1763
+ throw new TypeError('Unexpected parameter type <' + fieldOrPredicate.constructor + '>.');
1764
+ }
1765
+ breezePredicate = oper(breezePredicate);
1766
+ return new TruPredicate(breezePredicate, null, null, null);
1648
1767
  };
1649
- this.hasChanges = (entityTypes = []) => {
1650
- if (entityTypes.length)
1651
- return this._breezeContext.entityManager.getChanges(entityTypes);
1652
- return this._breezeContext.entityManager.getChanges();
1768
+ this.and = (fieldOrPredicate, operator, value) => {
1769
+ var that = this;
1770
+ return this.handleOperator(fieldOrPredicate, function (p) { return that._breezePredicate.and(p); }, operator, value);
1653
1771
  };
1654
- this.entityAccess = () => {
1655
- return this.entityAccessor;
1772
+ this.or = (fieldOrPredicate, operator, value) => {
1773
+ var that = this;
1774
+ return this.handleOperator(fieldOrPredicate, function (p) { return that._breezePredicate.and(p); }, operator, value);
1656
1775
  };
1657
- this.exportCahce = () => {
1658
- console.log(this._breezeContext.entityManager.exportEntities());
1776
+ this.not = () => {
1777
+ var breezePredicate = this._breezePredicate.not();
1778
+ return new TruPredicate(breezePredicate, null, null, null);
1659
1779
  };
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
- });
1780
+ if (typeof field === 'string') {
1781
+ var args = propertyQueryPath?.slice(0);
1782
+ args[args.length - 1] += field;
1783
+ args.push(operator);
1784
+ args.push(value);
1785
+ this._breezePredicate = new breeze.Predicate(args);
1786
+ this._breezePredicate.overQuoted = overQuoted;
1787
+ }
1788
+ else if (arguments[0].constructor === TruPredicate || arguments[0].constructor === BinaryPredicate || arguments[0].constructor === AndOrPredicate) {
1789
+ this._breezePredicate = arguments[0];
1790
+ }
1791
+ else {
1792
+ throw new TypeError('Unexpected parameter type <' + arguments[0].constructor + '>.');
1793
+ }
1794
+ }
1795
+ }
1796
+
1797
+ class TruPropertyConfigForeignKey extends TruPropertyConfigBase {
1798
+ constructor() {
1799
+ super();
1800
+ this.table = undefined;
1801
+ this.foreignTableName = undefined;
1802
+ this.choicesQuery = undefined;
1803
+ }
1804
+ }
1805
+
1806
+ class TruPropertyConfigCloudFile extends TruPropertyConfigForeignKey {
1807
+ constructor() { super(); }
1808
+ }
1809
+
1810
+ class TruPropertyConfigDate extends TruPropertyConfigBase {
1811
+ constructor() {
1812
+ super();
1813
+ this.minimumValue = undefined;
1814
+ this.maximumValue = undefined;
1815
+ }
1816
+ }
1817
+
1818
+ class TruPropertyConfigDecimal extends TruPropertyConfigBase {
1819
+ constructor() {
1820
+ super();
1821
+ this.decimalPlaces = undefined;
1822
+ this.totalDigits = undefined;
1823
+ this.minimumValue = undefined;
1824
+ this.maximumValue = undefined;
1825
+ }
1826
+ }
1827
+
1828
+ class TruPropertyConfigFile extends TruPropertyConfigBase {
1829
+ constructor() {
1830
+ super();
1831
+ this.maxSize = undefined;
1832
+ }
1833
+ }
1834
+
1835
+ class TruPropertyConfigInteger extends TruPropertyConfigBase {
1836
+ constructor() {
1837
+ super();
1838
+ this.minimumValue = undefined;
1839
+ this.maximumValue = undefined;
1840
+ }
1841
+ }
1842
+
1843
+ class TruPropertyConfigText extends TruPropertyConfigBase {
1844
+ constructor() {
1845
+ super();
1846
+ this.maxLength = undefined;
1847
+ this.minLength = undefined;
1848
+ this.unbounded = undefined;
1849
+ }
1850
+ }
1851
+
1852
+ class TruPropertyConfigPassword extends TruPropertyConfigText {
1853
+ constructor() {
1854
+ super();
1855
+ this.encryptionType = undefined;
1856
+ }
1857
+ }
1858
+
1859
+ class TruPropertyConfigPercentage extends TruPropertyConfigBase {
1860
+ constructor() {
1861
+ super();
1862
+ this.minimumValue = undefined;
1863
+ this.maximumValue = undefined;
1864
+ }
1865
+ }
1866
+
1867
+ class TruPropertyConfigScientific extends TruPropertyConfigBase {
1868
+ constructor() {
1869
+ super();
1870
+ this.minimumValue = undefined;
1871
+ this.maximumValue = undefined;
1872
+ }
1873
+ }
1874
+
1875
+ class TruPropertyConfigTextChoices extends TruPropertyConfigText {
1876
+ constructor() {
1877
+ super();
1878
+ this.choices = {};
1879
+ }
1880
+ }
1881
+
1882
+ class TruPropertyConfigUsaAddress extends TruPropertyConfigBase {
1883
+ constructor() {
1884
+ super();
1885
+ this.requireZipPlusFour = undefined;
1886
+ }
1887
+ }
1888
+
1889
+ class TruPropertyConfigZipCode extends TruPropertyConfigBase {
1890
+ constructor() {
1891
+ super();
1892
+ this.requireZipPlusFour = undefined;
1893
+ }
1894
+ }
1895
+
1896
+ class TruQueryPredicateManager {
1897
+ constructor(propertyQueryPath, predicateName, predicateMap) {
1898
+ this._predicate = null;
1899
+ this._propertyQueryPath = [];
1900
+ this._predicateName = '';
1901
+ this._predicateMap = {};
1902
+ this.setPredicate = (queryPredicate) => {
1903
+ if (this._predicate !== queryPredicate && this._predicateMap !== null) {
1904
+ this._predicate = queryPredicate;
1905
+ this._predicateMap[this._predicateName] = this._predicate === null ? null : this._predicate;
1906
+ }
1907
+ };
1908
+ /**
1909
+ * Returns the query predicate.
1910
+ */
1911
+ this.get = () => {
1912
+ return this._predicate;
1692
1913
  };
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
- });
1914
+ /**
1915
+ * Clears the query predicate.
1916
+ */
1917
+ this.clear = () => {
1918
+ this.setPredicate(null);
1700
1919
  };
1701
- this.revertWithoutPrompt = () => {
1702
- this.revert();
1703
- this.appEnvironment.revertComplete({ successful: true });
1920
+ /**
1921
+ * Returns a new query predicate.
1922
+ *
1923
+ * @param {string} field - Name of the storage field relative to the intent property.
1924
+ * @param {string} operator - Name of the predicate operator.
1925
+ * @param {*} value - Literal value.
1926
+ */
1927
+ this.create = (field, operator, value, overQuoted = false) => {
1928
+ return new TruPredicate(field, operator, value, this._propertyQueryPath, overQuoted)._breezePredicate;
1704
1929
  };
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
- });
1930
+ this.set = (fieldOrPredicate, operator, value, overQuoted = false) => {
1931
+ var predicate;
1932
+ if (fieldOrPredicate.constructor === TruPredicate)
1933
+ predicate = fieldOrPredicate;
1934
+ else
1935
+ predicate = this.create(fieldOrPredicate, operator, value, overQuoted);
1936
+ this.setPredicate(predicate);
1757
1937
  };
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;
1938
+ this._propertyQueryPath = propertyQueryPath;
1939
+ this._predicateName = predicateName;
1940
+ this._predicateMap = predicateMap;
1766
1941
  }
1942
+ }
1943
+
1944
+ class TruConfirmDialogModule {
1767
1945
  }
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 }]; } });
1946
+ TruConfirmDialogModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruConfirmDialogModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1947
+ TruConfirmDialogModulemod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.1", ngImport: i0, type: TruConfirmDialogModule, declarations: [TruConfirmDialog], imports: [CommonModule, FormsModule], exports: [TruConfirmDialog] });
1948
+ TruConfirmDialogModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruConfirmDialogModule, imports: [CommonModule, FormsModule] });
1949
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImport: i0, type: TruConfirmDialogModule, decorators: [{
1950
+ type: NgModule,
1951
+ args: [{
1952
+ declarations: [TruConfirmDialog],
1953
+ imports: [CommonModule, FormsModule],
1954
+ exports: [TruConfirmDialog]
1955
+ }]
1956
+ }] });
1957
+
1958
+ var TruDataGridTypes;
1959
+ (function (TruDataGridTypes) {
1960
+ TruDataGridTypes[TruDataGridTypes["Search"] = 0] = "Search";
1961
+ TruDataGridTypes[TruDataGridTypes["Detail"] = 1] = "Detail";
1962
+ TruDataGridTypes[TruDataGridTypes["DetailManyToMany"] = 2] = "DetailManyToMany";
1963
+ })(TruDataGridTypes || (TruDataGridTypes = {}));
1773
1964
 
1774
1965
  class TruSearchResultViewManager {
1775
1966
  constructor() { }
@@ -5523,137 +5714,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.1", ngImpor
5523
5714
  }]
5524
5715
  }], ctorParameters: function () { return []; } });
5525
5716
 
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
5717
  class TruUser {
5658
5718
  constructor() {
5659
5719
  this._ref = -1;