@acorex/layout 5.1.5 → 5.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. package/karma.conf.js +32 -0
  2. package/ng-package.json +9 -0
  3. package/package.json +11 -31
  4. package/src/lib/widget-board/editors/widget-size-editor/widget-size.editor.html +6 -0
  5. package/src/lib/widget-board/editors/widget-size-editor/widget-size.editor.ts +55 -0
  6. package/src/lib/widget-board/editors/widget-size-editor/widget-size.module.ts +19 -0
  7. package/src/lib/widget-board/widget-board.component.html +7 -0
  8. package/src/lib/widget-board/widget-board.component.scss +198 -0
  9. package/src/lib/widget-board/widget-board.component.ts +514 -0
  10. package/src/lib/widget-board/widget-board.module.ts +74 -0
  11. package/src/lib/widget-board/widget-config.component.html +16 -0
  12. package/src/lib/widget-board/widget-config.component.ts +99 -0
  13. package/src/lib/widget-board/widget-host.component.html +30 -0
  14. package/src/lib/widget-board/widget-host.component.ts +350 -0
  15. package/src/lib/widget-board/widget-save.component.html +43 -0
  16. package/src/lib/widget-board/widget-save.component.ts +88 -0
  17. package/src/lib/widget-board/widget.class.ts +179 -0
  18. package/{public-api.d.ts → src/public-api.ts} +0 -0
  19. package/src/test.ts +28 -0
  20. package/tsconfig.lib.json +23 -0
  21. package/tsconfig.lib.prod.json +6 -0
  22. package/tsconfig.spec.json +17 -0
  23. package/tslint.json +17 -0
  24. package/acorex-layout.d.ts +0 -5
  25. package/esm2020/acorex-layout.mjs +0 -5
  26. package/esm2020/lib/widget-board/editors/widget-size-editor/widget-size.editor.mjs +0 -46
  27. package/esm2020/lib/widget-board/editors/widget-size-editor/widget-size.module.mjs +0 -21
  28. package/esm2020/lib/widget-board/widget-board.component.mjs +0 -444
  29. package/esm2020/lib/widget-board/widget-board.module.mjs +0 -111
  30. package/esm2020/lib/widget-board/widget-config.component.mjs +0 -82
  31. package/esm2020/lib/widget-board/widget-host.component.mjs +0 -295
  32. package/esm2020/lib/widget-board/widget-save.component.mjs +0 -79
  33. package/esm2020/lib/widget-board/widget.class.mjs +0 -127
  34. package/esm2020/public-api.mjs +0 -7
  35. package/fesm2015/acorex-layout.mjs +0 -1174
  36. package/fesm2015/acorex-layout.mjs.map +0 -1
  37. package/fesm2020/acorex-layout.mjs +0 -1167
  38. package/fesm2020/acorex-layout.mjs.map +0 -1
  39. package/lib/widget-board/editors/widget-size-editor/widget-size.editor.d.ts +0 -19
  40. package/lib/widget-board/editors/widget-size-editor/widget-size.module.d.ts +0 -10
  41. package/lib/widget-board/widget-board.component.d.ts +0 -62
  42. package/lib/widget-board/widget-board.module.d.ts +0 -18
  43. package/lib/widget-board/widget-config.component.d.ts +0 -23
  44. package/lib/widget-board/widget-host.component.d.ts +0 -52
  45. package/lib/widget-board/widget-save.component.d.ts +0 -19
  46. package/lib/widget-board/widget.class.d.ts +0 -57
@@ -0,0 +1,30 @@
1
+ <div class='widget-container'>
2
+ <div class="widget-config-overlay" *ngIf="!isConfigured" (click)="handleConfig($event)">
3
+ <div class="widget-title">{{config.title}}</div>
4
+ <div class="widget-config-box">
5
+ <div class="config-title">{{ 'widget-board.configure' | trans}}</div>
6
+ <div class="config-icon" *ngIf="!readonly"><i class="fas fa-cogs fa-5x" aria-hidden="true"></i></div>
7
+ </div>
8
+ </div>
9
+ <div class='widget-edit-overlay' >
10
+ <div class='widget-edit-menu'>
11
+ <button class="widget-edit-menu-button" (click)="handleConfig($event)"
12
+ (mousedown)="$event.stopPropagation()" *ngIf="_hasProps" (mouseup)="$event.stopPropagation()">
13
+ <i class="far fa-cogs" aria-hidden="true"></i>
14
+ </button>
15
+ <button class="widget-edit-menu-button" (click)="remove($event)" (mousedown)="$event.stopPropagation()"
16
+ (mouseup)="$event.stopPropagation()">
17
+ <i class="far fa-times" aria-hidden="true"></i>
18
+ </button>
19
+ </div>
20
+
21
+ </div>
22
+ <div class="widget-options-menu" *ngIf="_hasMenu && !readonly">
23
+ <ax-menu [items]='configMenuItem' direction="horizontal"></ax-menu>
24
+ </div>
25
+ <!-- <ax-loading-panel [visible]="isBusy">
26
+ </ax-loading-panel> -->
27
+ <div class="widget-content">
28
+ <ng-container #vc></ng-container>
29
+ </div>
30
+ </div>
@@ -0,0 +1,350 @@
1
+ import {
2
+ Component,
3
+ ViewEncapsulation, Input,
4
+ ElementRef, HostBinding, ComponentFactoryResolver, ViewChild,
5
+ ViewContainerRef, Output, EventEmitter, ChangeDetectionStrategy,
6
+ ChangeDetectorRef, ComponentRef
7
+ } from '@angular/core';
8
+ import { AXWidgetConfig, AXWidgetComponent, AXWidgetConfigChanged, AXWidgetConfigSavedEvent } from './widget.class';
9
+ import { AXObjectUtil, AXRenderService } from '@acorex/core';
10
+ import { AXPopupService, AXPropertyDecorators, AXPropertyDecorator, AXLoadingService } from '@acorex/components';
11
+ import { AXWidgetConfigComponent } from './widget-config.component';
12
+ import { AXMenuItem } from '@acorex/core';
13
+ import { AXTranslator } from '@acorex/core';
14
+ import { AXWidgetSaveComponent } from './widget-save.component';
15
+
16
+
17
+
18
+
19
+
20
+ @Component({
21
+ selector: 'ax-widget-host',
22
+ templateUrl: "./widget-host.component.html",
23
+ host: { class: 'ax widget-host', tabindex: '0' },
24
+ encapsulation: ViewEncapsulation.None,
25
+ changeDetection: ChangeDetectionStrategy.OnPush
26
+ })
27
+
28
+ export class AXWidgetHostComponent {
29
+
30
+ private _widget: AXWidgetComponent;
31
+ public get widget(): AXWidgetComponent {
32
+ return this._widget;
33
+ }
34
+
35
+ _hasProps: boolean = false;
36
+
37
+
38
+ _hasMenu: boolean = false;
39
+
40
+ @Input()
41
+ provideValue: (e: any) => any;
42
+
43
+
44
+ get element(): HTMLDivElement {
45
+ return this.ref.nativeElement;
46
+ }
47
+
48
+
49
+ configMenuItem: AXMenuItem[] = [
50
+ {
51
+ icon: 'far fa-ellipsis-h',
52
+ items: []
53
+ }
54
+ ];
55
+
56
+
57
+ @Output()
58
+ onRemove: EventEmitter<AXWidgetHostComponent> = new EventEmitter<AXWidgetHostComponent>();
59
+
60
+ @Output()
61
+ onConfigChanged: EventEmitter<AXWidgetConfigChanged> = new EventEmitter<AXWidgetConfigChanged>();
62
+
63
+
64
+ @Output()
65
+ onResized: EventEmitter<AXWidgetConfigChanged> = new EventEmitter<AXWidgetConfigChanged>();
66
+
67
+ @Output()
68
+ onSave: EventEmitter<AXWidgetConfigSavedEvent> = new EventEmitter<AXWidgetConfigSavedEvent>();
69
+
70
+ @Input()
71
+ config: AXWidgetConfig;
72
+
73
+ @ViewChild('vc', { read: ViewContainerRef })
74
+ vc: ViewContainerRef;
75
+
76
+
77
+
78
+ @Input()
79
+ readonly: boolean = false;
80
+
81
+ private componentRef: ComponentRef<any>;
82
+ //private isLoading: boolean = true;
83
+
84
+ // get isBusy() {
85
+ // return this._widget?.isBusy || this.isLoading;
86
+ // }
87
+
88
+
89
+ private _loadingId: number;
90
+
91
+ private _isLoading: boolean = false;
92
+ public get isLoading(): boolean {
93
+ return this._isLoading;
94
+ }
95
+ public set isLoading(v: boolean) {
96
+ this._isLoading = v;
97
+ if (this._loadingId && !v) {
98
+ this.loadingService.hide(this._loadingId);
99
+ this._loadingId = null;
100
+ }
101
+ if (v) {
102
+ this._loadingId = this.loadingService.show(this.ref.nativeElement);
103
+ }
104
+ }
105
+
106
+
107
+ get isConfigured(): boolean {
108
+ return this._widget?.isConfigured || false;
109
+ }
110
+
111
+
112
+ constructor(
113
+ private ref: ElementRef<HTMLDivElement>,
114
+ private componentFactoryResolver: ComponentFactoryResolver,
115
+ private rendererService: AXRenderService,
116
+ private cdr: ChangeDetectorRef,
117
+ private popup: AXPopupService,
118
+ private loadingService: AXLoadingService
119
+
120
+ ) {
121
+
122
+ }
123
+
124
+
125
+ ngOnInit() {
126
+ this.isLoading = true;
127
+ }
128
+
129
+
130
+ async ngAfterViewInit() {
131
+ let component: any;
132
+ if (typeof this.config.component === 'string') {
133
+ const route = await this.rendererService.findLoadedComponentByRoute(this.config.component, 20);
134
+ component = route?.component;
135
+ }
136
+ else if (typeof this.config.component === 'function') {
137
+ component = this.config.component;
138
+ }
139
+ if (component == null) {
140
+ console.error(`Invalid Widget Component!`, this.config);
141
+ this.onRemove.emit(this);
142
+ return;
143
+ }
144
+
145
+ const widgetFactory = this.componentFactoryResolver.resolveComponentFactory(component);
146
+ this.componentRef = this.vc.createComponent(widgetFactory);
147
+ this._widget = this.componentRef.instance as AXWidgetComponent;
148
+ this._widget.provideValue = this.provideValue;
149
+ if (this._widget.onBusyChanged) {
150
+ this._widget.onBusyChanged.subscribe((d) => {
151
+ if (!this._widget.widgetSize) {
152
+ this._widget.setValue('widgetSize', [this.sizeX, this.sizeY]);
153
+ }
154
+ else {
155
+ this.setSizeFromOptions();
156
+ }
157
+ this.isLoading = d.value;
158
+ this.cdr.detectChanges();
159
+ });
160
+ }
161
+ if (this._widget.onConfiguredChanged) {
162
+ this._widget.onConfiguredChanged.subscribe(() => {
163
+ this.setSizeFromOptions();
164
+ });
165
+ }
166
+ //
167
+ if (this.config.options) {
168
+ Object.assign(this._widget, this.config.options);
169
+ }
170
+ this._hasProps = AXPropertyDecorators.getProperties(this._widget).length > 0;
171
+
172
+ this.isLoading = false;
173
+ this.config['__meta__'].instance = this;
174
+ this._widget['__meta__'] = {};
175
+ this._widget['__meta__'].config = this.config;
176
+ //
177
+ this.configMenuItem[0].items.push({
178
+ name: 'refresh',
179
+ icon: 'far fa-undo',
180
+ text: AXTranslator.get('common.refresh'),
181
+ onClick: () => {
182
+ this?.widget?.refresh();
183
+ }
184
+ });
185
+ //
186
+ if (this._hasProps) {
187
+ this.configMenuItem[0].items.push({
188
+ name: 'configs',
189
+ icon: 'far fa-cogs',
190
+ text: AXTranslator.get('common.configs'),
191
+ onClick: () => {
192
+ this.openConfigDialog();
193
+ }
194
+ });
195
+ }
196
+ this.configMenuItem[0].items.push({
197
+ name: 'save',
198
+ icon: 'far fa-save',
199
+ text: AXTranslator.get('common.save-as'),
200
+ onClick: () => {
201
+ this.openSaveDialog();
202
+ }
203
+ });
204
+ if (true) {
205
+ this.configMenuItem[0].items.push({
206
+ name: 'remove',
207
+ icon: 'far fa-times',
208
+ style: 'ax danger blank',
209
+ text: AXTranslator.get('common.remove'),
210
+ onClick: () => {
211
+ this.onRemove.emit(this);
212
+ }
213
+ });
214
+ }
215
+ this._hasMenu = this.configMenuItem[0].items.length > 0;
216
+ this.cdr.detectChanges();
217
+ }
218
+
219
+ @HostBinding('attr.data-size-x')
220
+ @Input()
221
+ sizeX: number = 1;
222
+
223
+ @HostBinding('attr.data-size-y')
224
+ @Input()
225
+ sizeY: number = 1;
226
+
227
+ @HostBinding('attr.data-col')
228
+ @Input()
229
+ col: number = 1;
230
+
231
+
232
+ @HostBinding('attr.data-row')
233
+ @Input()
234
+ row: number = 1;
235
+
236
+
237
+ private setSizeFromOptions() {
238
+ this._widget.getValue('widgetSize').then(c => {
239
+ const oldSizeX = this.sizeX;
240
+ const oldSizeY = this.sizeY;
241
+ if (c && Array.isArray(c) && (oldSizeX !== c[0] || oldSizeY !== c[1])) {
242
+ this.config.sizeX = this.sizeX = c[0];
243
+ this.config.sizeY = this.sizeY = c[1];
244
+ this.onResized.emit({
245
+ component: this._widget,
246
+ config: this.config
247
+ });
248
+ }
249
+ this.cdr.detectChanges();
250
+ });
251
+ }
252
+
253
+ remove(e: MouseEvent) {
254
+ e.preventDefault();
255
+ e.stopPropagation();
256
+ if (!this.readonly)
257
+ this.onRemove.emit(this);
258
+ return false;
259
+ }
260
+
261
+ handleConfig(e: MouseEvent) {
262
+ e.preventDefault();
263
+ e.stopPropagation();
264
+ if (!this.readonly)
265
+ this.openConfigDialog();
266
+ return false;
267
+ }
268
+
269
+ private openConfigDialog() {
270
+ const ppp = this.getMergedProps();
271
+ this.popup.open(AXWidgetConfigComponent, {
272
+ title: AXTranslator.get('common.configs'),
273
+ size: 'sm',
274
+ data: {
275
+ props: ppp.map(c => ({ property: c.options, value: this._widget[c.options.name] })),
276
+ widget: this.widget
277
+ }
278
+ }).then(c => {
279
+ if (c.data) {
280
+ if (!this.config.options) {
281
+ this.config.options = {};
282
+ }
283
+ c.data.forEach(p => {
284
+ this._widget.setValue(p.property.name, p.value);
285
+ this.config.options[p.property.name] = p.value;
286
+ });
287
+ this.emitConfigChanged();
288
+ this._widget.redraw();
289
+ this.cdr.detectChanges();
290
+ }
291
+ });
292
+ }
293
+
294
+ private openSaveDialog() {
295
+ const ppp = this.getMergedProps();
296
+ this.popup.open(AXWidgetSaveComponent, {
297
+ title: AXTranslator.get('common.save-as'),
298
+ size: 'sm',
299
+ data: {
300
+ config: this.config,
301
+ props: ppp.map(c => ({ property: c.options, value: this._widget[c.options.name] }))
302
+ }
303
+ }).then(c => {
304
+ if (c.data) {
305
+ this.onSave.emit({
306
+ component: this._widget,
307
+ data: c.data
308
+ });
309
+ }
310
+ });
311
+ }
312
+
313
+
314
+
315
+ handleOptionClick(e: MouseEvent) {
316
+ e.preventDefault();
317
+ e.stopPropagation();
318
+ this.openConfigDialog();
319
+ return false;
320
+ }
321
+
322
+ ngOnDestroy() {
323
+ this.vc.clear();
324
+ if (this.componentRef) {
325
+ this.componentRef.destroy();
326
+ }
327
+ }
328
+
329
+ private getMergedProps(): AXPropertyDecorator[] {
330
+ const ppp = AXObjectUtil.deepCopy(AXPropertyDecorators.getProperties(this._widget)) as AXPropertyDecorator[];
331
+ for (const key in this.config.props) {
332
+ if (Object.prototype.hasOwnProperty.call(this.config.props, key)) {
333
+ const newP = this.config.props[key];
334
+ const existPropDec = ppp.find(p => p.property === key);
335
+ if (existPropDec) {
336
+ Object.assign(existPropDec.options, newP);
337
+ }
338
+ }
339
+ }
340
+ return ppp;
341
+ }
342
+
343
+ private emitConfigChanged() {
344
+ this.onConfigChanged.emit({
345
+ component: this._widget,
346
+ config: this.config
347
+ });
348
+ }
349
+
350
+ }
@@ -0,0 +1,43 @@
1
+ <ax-page>
2
+ <ax-page-content>
3
+ <div class="container">
4
+ <div class="row">
5
+ <div class="col-12">
6
+ <ax-form-group>
7
+ <ax-label>{{'common.title' | trans}}</ax-label>
8
+ <ax-text-box [(value)]="data.title"></ax-text-box>
9
+ </ax-form-group>
10
+ </div>
11
+ </div>
12
+ <div class="row">
13
+ <div class="col-12">
14
+ <ax-form-group>
15
+ <ax-label>{{'common.description' | trans}}</ax-label>
16
+ <ax-text-area [(value)]="data.description"></ax-text-area>
17
+ </ax-form-group>
18
+ </div>
19
+ </div>
20
+ <!-- <div class="row">
21
+ <div class="col-12">
22
+ <ax-form-group>
23
+ <ax-label>{{'common.uniquename' | trans}}</ax-label>
24
+ <ax-text-box></ax-text-box>
25
+ </ax-form-group>
26
+ </div>
27
+ </div> -->
28
+ <div class="row" style="margin-block-end: var(--ax-size-md);margin-block-start: var(--ax-size-md);">
29
+ <div class="col-12">
30
+ <ax-fieldset caption="{{'widget-board.configurable-props' | trans}}">
31
+ <div class="row" *ngFor="let prop of displayProps">
32
+ <div class="col-12" style="margin-block-end: var(--ax-size-sm)">
33
+ <ax-check-box [(value)]="prop.allow" label="{{ prop.title | trans }}">
34
+
35
+ </ax-check-box>
36
+ </div>
37
+ </div>
38
+ </ax-fieldset>
39
+ </div>
40
+ </div>
41
+ </div>
42
+ </ax-page-content>
43
+ </ax-page>
@@ -0,0 +1,88 @@
1
+ import {
2
+ Component,
3
+ ViewEncapsulation,
4
+ ChangeDetectionStrategy,
5
+
6
+ } from '@angular/core';
7
+ import { AXWidgetConfig, AXWidgetSaveAsData } from './widget.class';
8
+ import { AXButtonItem, AXHtmlUtil, AXObjectUtil, AXTranslator } from '@acorex/core';
9
+ import { AXPropertyConfig, AXMenuItemClickEvent, AXBasePopupPageComponent } from '@acorex/components';
10
+
11
+
12
+
13
+ @Component({
14
+ templateUrl: "./widget-save.component.html",
15
+ encapsulation: ViewEncapsulation.None,
16
+ changeDetection: ChangeDetectionStrategy.OnPush,
17
+ })
18
+ export class AXWidgetSaveComponent extends AXBasePopupPageComponent {
19
+ config: AXWidgetConfig;
20
+ props: AXPropertyConfig[] = [];
21
+ displayProps: { name: string, title: string, allow: boolean }[];
22
+
23
+ data: AXWidgetSaveAsData;
24
+
25
+ getFooterButtons(): AXButtonItem[] {
26
+ return [
27
+ {
28
+ name: 'okay',
29
+ submitBehavior: true,
30
+ text: AXTranslator.get('common.confirm'),
31
+ style: 'ax success'
32
+ },
33
+ {
34
+ name: 'cancel',
35
+ cancelBehavior: true,
36
+ text: AXTranslator.get('common.cancel'),
37
+ style: 'ax light'
38
+ }
39
+ ];
40
+ }
41
+
42
+ ngOnInit() {
43
+ const titleProp = this.props.find(c => c.property.name === 'title' || c.property.name === 'name');
44
+ const title = titleProp?.value || this.config.title;
45
+ const pp: any = {};
46
+ this.props?.forEach(c => {
47
+ pp[c.property.name] = c.property;
48
+ });
49
+ this.data = {
50
+ component: this.config.component,
51
+ title,
52
+ uniqueName: `${this.config.uniqueName}-${AXHtmlUtil.getUID()}`,
53
+ options: AXObjectUtil.deepJSONClone(this.config.options),
54
+ props: AXObjectUtil.deepJSONClone(pp)
55
+ };
56
+ this.displayProps = this.props
57
+ .filter(c => c.property.visible !== false)
58
+ .sort((a, b) => a.property.order - b.property.order)
59
+ .map(c => ({
60
+ name: c.property.name,
61
+ title: c.property.title,
62
+ allow: true
63
+ }));
64
+ }
65
+
66
+
67
+
68
+ onFooterButtonClick(e: AXMenuItemClickEvent) {
69
+ if (e.name === 'cancel') {
70
+ this.close();
71
+ }
72
+ if (e.name === 'okay') {
73
+ this.props.forEach(p => {
74
+ const pp = this.displayProps.find(c => c.name === p.property.name);
75
+ if (pp == null || !pp.allow) {
76
+ let ppp = this.data.props[p.property.name];
77
+ if (ppp) {
78
+ ppp.visible = false;
79
+ }
80
+ else {
81
+ ppp = { visible: false };
82
+ }
83
+ }
84
+ });
85
+ this.close(this.data);
86
+ }
87
+ }
88
+ }
@@ -0,0 +1,179 @@
1
+ import { EventEmitter, Injectable } from '@angular/core';
2
+ import { AXValueEvent, AXBaseEvent, propertyEditor, AXDataEvent } from '@acorex/components';
3
+ import { AXHtmlUtil, AXTranslator } from '@acorex/core';
4
+
5
+ export interface AXWidgetConfig {
6
+ uniqueName: string;
7
+ component: any;
8
+ title: string;
9
+ sizeX: number;
10
+ sizeY: number;
11
+ col?: number;
12
+ row?: number;
13
+ options?: any;
14
+ props?: any;
15
+ readonly?: boolean;
16
+ }
17
+
18
+ export interface AXWidgetConfigChanged extends AXBaseEvent {
19
+ config: AXWidgetConfig;
20
+ }
21
+
22
+
23
+
24
+ export interface AXWidgetBoardConfigChanged extends AXBaseEvent {
25
+
26
+ }
27
+
28
+ export interface AXWidgetConfigSavedEvent extends AXDataEvent<AXWidgetSaveAsData> {
29
+
30
+ }
31
+
32
+
33
+ export interface AXWidgetSaveAsData {
34
+ title?: string;
35
+ description?: string;
36
+ icon?: string;
37
+ group?: string;
38
+ //
39
+ uniqueName: string;
40
+ component: any;
41
+ options?: any;
42
+ props?: any;
43
+ }
44
+
45
+ // @dynamic
46
+ // TODO: Add Angular decorator.
47
+ @Injectable()
48
+ export abstract class AXWidgetComponent {
49
+
50
+ readonly uid: string = AXHtmlUtil.getUID();
51
+ provideValue: (e: any) => any;
52
+
53
+ onBusyChanged: EventEmitter<AXValueEvent<boolean>> = new EventEmitter<AXValueEvent<boolean>>();
54
+
55
+ private _isBusy: boolean = true;
56
+ public get isBusy(): boolean {
57
+ return this._isBusy;
58
+ }
59
+ public set isBusy(v: boolean) {
60
+ if (v !== this._isBusy) {
61
+ const eventData: AXValueEvent<boolean> = {
62
+ component: this,
63
+ oldValue: this._isBusy,
64
+ value: v
65
+ };
66
+ this._isBusy = v;
67
+ this.onBusyChanged.emit(eventData);
68
+ }
69
+ }
70
+
71
+ @propertyEditor({
72
+ editorClass: 'ax/editors/widget-size',
73
+ title: 'common.size',
74
+ visible: false,
75
+ order: -99,
76
+ })
77
+ widgetSize: number[];
78
+
79
+ @propertyEditor({
80
+ editorClass: 'ax/editors/select',
81
+ title: 'common.refresh-rate',
82
+ visible: true,
83
+ order: -98,
84
+ editorOptions: {
85
+ items: () => {
86
+ return [1, 2, 3, 5, 10, 20, 30, 60].map(c => ({
87
+ id: 60000 * c,
88
+ text: AXTranslator.get('dateTime.duration.format_minute').replace('{0}', c.toString())
89
+ }));
90
+ },
91
+ allowNull: false,
92
+ allowSearch: false,
93
+ selectionDataMode: 'value',
94
+ selectionMode: 'single',
95
+ valueField: 'id',
96
+ }
97
+ })
98
+ refreshRate: any = [{
99
+ id: 60000 * 5,
100
+ text: AXTranslator.get('dateTime.duration.format_minute').replace('{0}', '5')
101
+ }];
102
+
103
+ // ???
104
+ getRefreshRate() {
105
+ return Array.isArray(this.refreshRate) && this.refreshRate.length ? this.refreshRate[0].id : this.refreshRate;
106
+ }
107
+
108
+ private intervalId: number;
109
+
110
+ constructor() {
111
+ this.onConfiguredChanged.subscribe(() => {
112
+ if (this.isConfigured === true && this.getRefreshRate()) {
113
+ this.restartRefreshTimer();
114
+ }
115
+ else {
116
+ this.stopRefreshTimer();
117
+ }
118
+ });
119
+ }
120
+
121
+
122
+ private startRefreshTimer() {
123
+ this.intervalId = window.setInterval(this.refresh.bind(this), this.getRefreshRate());
124
+ }
125
+
126
+ private stopRefreshTimer() {
127
+ window.clearInterval(this.intervalId);
128
+ }
129
+
130
+ private restartRefreshTimer() {
131
+ this.stopRefreshTimer();
132
+ this.startRefreshTimer();
133
+ }
134
+
135
+ ngOnDestroy() {
136
+ this.stopRefreshTimer();
137
+ }
138
+
139
+ public redraw() {
140
+
141
+ }
142
+
143
+ public refresh() {
144
+ this.restartRefreshTimer();
145
+ }
146
+
147
+ onConfiguredChanged: EventEmitter<void> = new EventEmitter<void>();
148
+
149
+ get isConfigured(): boolean {
150
+ return true;
151
+ }
152
+
153
+ public setValue(name: string, value?: any) {
154
+ this[name] = value;
155
+ this.onConfiguredChanged.emit();
156
+ }
157
+
158
+ public getValue(name: string): Promise<any> {
159
+ const val = this[name];
160
+ const config = this['__meta__'].config;
161
+ const runtime = config.props[name]?.runtime;
162
+ if (runtime && this.provideValue) {
163
+ const res = this.provideValue({
164
+ name,
165
+ value: val,
166
+ uniqueName: config.uniqueName,
167
+ options: config.options,
168
+ });
169
+ if (this.provideValue instanceof Promise) {
170
+ return res;
171
+ }
172
+ else {
173
+ return Promise.resolve(res);
174
+ }
175
+ }
176
+ return Promise.resolve(val);
177
+ }
178
+
179
+ }
File without changes