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