|
|
|
@ -24,7 +24,14 @@ import { UtilsService } from '@core/services/utils.service'; |
|
|
|
import { TranslateService } from '@ngx-translate/core'; |
|
|
|
import { DataKey, Datasource, DatasourceData, DatasourceType, WidgetConfig } from '@shared/models/widget.models'; |
|
|
|
import { IWidgetSubscription } from '@core/api/widget-api.models'; |
|
|
|
import { createLabelFromDatasource, isDefinedAndNotNull, isEqual, isNotEmptyStr, isUndefined } from '@core/utils'; |
|
|
|
import { |
|
|
|
createLabelFromDatasource, |
|
|
|
isBoolean, isDefined, |
|
|
|
isDefinedAndNotNull, |
|
|
|
isEqual, |
|
|
|
isNotEmptyStr, |
|
|
|
isUndefined |
|
|
|
} from '@core/utils'; |
|
|
|
import { EntityType } from '@shared/models/entity-type.models'; |
|
|
|
import * as _moment from 'moment'; |
|
|
|
import { FormBuilder, FormGroup, ValidatorFn, Validators } from '@angular/forms'; |
|
|
|
@ -35,6 +42,7 @@ import { forkJoin, Observable, Subject } from 'rxjs'; |
|
|
|
import { EntityId } from '@shared/models/id/entity-id'; |
|
|
|
import { ResizeObserver } from '@juggle/resize-observer'; |
|
|
|
import { takeUntil } from 'rxjs/operators'; |
|
|
|
import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; |
|
|
|
|
|
|
|
type FieldAlignment = 'row' | 'column'; |
|
|
|
|
|
|
|
@ -44,6 +52,9 @@ type MultipleInputWidgetDataKeyValueType = 'string' | 'double' | 'integer' | |
|
|
|
'dateTime' | 'date' | 'time' | 'select'; |
|
|
|
type MultipleInputWidgetDataKeyEditableType = 'editable' | 'disabled' | 'readonly'; |
|
|
|
|
|
|
|
type ConvertGetValueFunction = (value: any, ctx: WidgetContext) => any; |
|
|
|
type ConvertSetValueFunction = (value: any, originValue: any, ctx: WidgetContext) => any; |
|
|
|
|
|
|
|
interface MultipleInputWidgetSettings { |
|
|
|
widgetTitle: string; |
|
|
|
showActionButtons: boolean; |
|
|
|
@ -66,6 +77,7 @@ interface MultipleInputWidgetSelectOption { |
|
|
|
interface MultipleInputWidgetDataKeySettings { |
|
|
|
dataKeyType: MultipleInputWidgetDataKeyType; |
|
|
|
dataKeyValueType: MultipleInputWidgetDataKeyValueType; |
|
|
|
slideToggleLabelPosition?: 'after' | 'before'; |
|
|
|
selectOptions: MultipleInputWidgetSelectOption[]; |
|
|
|
required: boolean; |
|
|
|
isEditable: MultipleInputWidgetDataKeyEditableType; |
|
|
|
@ -78,10 +90,19 @@ interface MultipleInputWidgetDataKeySettings { |
|
|
|
invalidDateErrorMessage?: string; |
|
|
|
minValueErrorMessage?: string; |
|
|
|
maxValueErrorMessage?: string; |
|
|
|
useCustomIcon: boolean; |
|
|
|
icon: string; |
|
|
|
customIcon: string ; |
|
|
|
safeCustomIcon?: SafeUrl; |
|
|
|
inputTypeNumber?: boolean; |
|
|
|
readOnly?: boolean; |
|
|
|
disabledOnCondition?: boolean; |
|
|
|
useGetValueFunction?: boolean; |
|
|
|
getValueFunctionBody?: string; |
|
|
|
getValueFunction?: ConvertGetValueFunction; |
|
|
|
useSetValueFunction?: boolean; |
|
|
|
setValueFunctionBody?: string; |
|
|
|
setValueFunction?: ConvertSetValueFunction; |
|
|
|
} |
|
|
|
|
|
|
|
interface MultipleInputWidgetDataKey extends DataKey { |
|
|
|
@ -139,7 +160,8 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni |
|
|
|
private utils: UtilsService, |
|
|
|
private fb: FormBuilder, |
|
|
|
private attributeService: AttributeService, |
|
|
|
private translate: TranslateService) { |
|
|
|
private translate: TranslateService, |
|
|
|
private sanitizer: DomSanitizer) { |
|
|
|
super(store); |
|
|
|
} |
|
|
|
|
|
|
|
@ -265,6 +287,34 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
if (dataKey.settings.dataKeyValueType === 'booleanSwitch' && isUndefined(dataKey.settings.slideToggleLabelPosition)) { |
|
|
|
dataKey.settings.slideToggleLabelPosition = 'after'; |
|
|
|
} |
|
|
|
|
|
|
|
if (dataKey.settings.useCustomIcon && isDefinedAndNotNull(dataKey.settings.customIcon)) { |
|
|
|
dataKey.settings.safeCustomIcon = this.sanitizer.bypassSecurityTrustUrl(dataKey.settings.customIcon); |
|
|
|
} |
|
|
|
|
|
|
|
if (dataKey.settings.useGetValueFunction && dataKey.settings.getValueFunctionBody.length) { |
|
|
|
try { |
|
|
|
dataKey.settings.getValueFunction = |
|
|
|
new Function('value, ctx', dataKey.settings.getValueFunctionBody) as ConvertGetValueFunction; |
|
|
|
} catch (e) { |
|
|
|
console.warn(`Parse getValue function in key ${dataKey.label}`, e); |
|
|
|
dataKey.settings.getValueFunction = null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (dataKey.settings.useSetValueFunction && dataKey.settings.setValueFunctionBody.length) { |
|
|
|
try { |
|
|
|
dataKey.settings.setValueFunction = |
|
|
|
new Function('value, originValue, ctx', dataKey.settings.setValueFunctionBody) as ConvertSetValueFunction; |
|
|
|
} catch (e) { |
|
|
|
console.warn(`Parse setValue function in key ${dataKey.label}`, e); |
|
|
|
dataKey.settings.setValueFunction = null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
source.keys.push(dataKey); |
|
|
|
}); |
|
|
|
} else { |
|
|
|
@ -342,28 +392,41 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni |
|
|
|
source.keys.forEach((key) => { |
|
|
|
const keyData = data[dataIndex].data; |
|
|
|
if (keyData && keyData.length) { |
|
|
|
let value; |
|
|
|
let value = keyData[0][1]; |
|
|
|
const keyValue = this.getKeyValue(value, key.settings); |
|
|
|
switch (key.settings.dataKeyValueType) { |
|
|
|
case 'dateTime': |
|
|
|
case 'date': |
|
|
|
if (isDefinedAndNotNull(keyData[0][1]) && keyData[0][1] !== '') { |
|
|
|
value = _moment(keyData[0][1]).toDate(); |
|
|
|
if (isDefinedAndNotNull(keyValue) && keyValue !== '') { |
|
|
|
if (keyValue instanceof Date) { |
|
|
|
value = keyValue; |
|
|
|
} else { |
|
|
|
value = _moment(keyValue).toDate(); |
|
|
|
} |
|
|
|
} else { |
|
|
|
value = null; |
|
|
|
} |
|
|
|
break; |
|
|
|
case 'time': |
|
|
|
value = _moment().startOf('day').add(keyData[0][1], 'ms').toDate(); |
|
|
|
if (keyValue instanceof Date) { |
|
|
|
value = keyValue; |
|
|
|
} else { |
|
|
|
value = _moment().startOf('day').add(keyValue, 'ms').toDate(); |
|
|
|
} |
|
|
|
break; |
|
|
|
case 'booleanCheckbox': |
|
|
|
case 'booleanSwitch': |
|
|
|
value = (keyData[0][1] === 'true'); |
|
|
|
if (isBoolean(keyValue)) { |
|
|
|
value = keyValue; |
|
|
|
} else { |
|
|
|
value = (keyValue === 'true'); |
|
|
|
} |
|
|
|
break; |
|
|
|
case 'select': |
|
|
|
value = keyData[0][1].toString(); |
|
|
|
value = keyValue.toString(); |
|
|
|
break; |
|
|
|
default: |
|
|
|
value = keyData[0][1]; |
|
|
|
value = keyValue; |
|
|
|
} |
|
|
|
key.value = value; |
|
|
|
} |
|
|
|
@ -399,6 +462,18 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
private getKeyValue(data: any, keySetting: MultipleInputWidgetDataKeySettings) { |
|
|
|
if (isDefined(keySetting.getValueFunction)) { |
|
|
|
try { |
|
|
|
return keySetting.getValueFunction(data, this.ctx); |
|
|
|
} catch (e) { |
|
|
|
console.warn(`Call function getValue`, e); |
|
|
|
return data; |
|
|
|
} |
|
|
|
} |
|
|
|
return data; |
|
|
|
} |
|
|
|
|
|
|
|
private updateWidgetDisplaying() { |
|
|
|
this.changeAlignment = (this.ctx.$container && this.ctx.$container[0].offsetWidth < 620); |
|
|
|
} |
|
|
|
@ -493,7 +568,8 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni |
|
|
|
if (!this.settings.showActionButtons && !this.isSavingInProgress) { |
|
|
|
this.isSavingInProgress = true; |
|
|
|
const currentValue = this.multipleInputFormGroup.get(key.formId).value; |
|
|
|
if (!key.settings.required || (key.settings.required && isDefinedAndNotNull(currentValue) && isNotEmptyStr(currentValue.toString()))) { |
|
|
|
if (!key.settings.required || |
|
|
|
(key.settings.required && isDefinedAndNotNull(currentValue) && isNotEmptyStr(currentValue.toString()))) { |
|
|
|
const dataToSave: MultipleInputWidgetSource = { |
|
|
|
datasource: source.datasource, |
|
|
|
keys: [key] |
|
|
|
@ -523,8 +599,9 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni |
|
|
|
const sharedAttributes: AttributeData[] = []; |
|
|
|
const telemetry: AttributeData[] = []; |
|
|
|
for (const key of toSave.keys) { |
|
|
|
const currentValue = key.settings.dataKeyHidden ? key.value : this.multipleInputFormGroup.get(key.formId).value; |
|
|
|
let currentValue = key.settings.dataKeyHidden ? key.value : this.multipleInputFormGroup.get(key.formId).value; |
|
|
|
if (!isEqual(currentValue, key.value) || this.settings.updateAllValues) { |
|
|
|
currentValue = this.setKeyValue(currentValue, key, toSave); |
|
|
|
const attribute: AttributeData = { |
|
|
|
key: key.name, |
|
|
|
value: null |
|
|
|
@ -615,6 +692,21 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private setKeyValue(value: any, key: MultipleInputWidgetDataKey, source: MultipleInputWidgetSource) { |
|
|
|
if (isDefined(key.settings.setValueFunction)) { |
|
|
|
const currentDatasourceData = this.subscription.data |
|
|
|
.find(dsData => dsData.datasource === source.datasource && dsData.dataKey.name === key.name); |
|
|
|
const originValue = currentDatasourceData.data[0][1]; |
|
|
|
try { |
|
|
|
return key.settings.setValueFunction(value, originValue, this.ctx); |
|
|
|
} catch (e) { |
|
|
|
console.warn(`Call function setValue`, e); |
|
|
|
return value; |
|
|
|
} |
|
|
|
} |
|
|
|
return value; |
|
|
|
} |
|
|
|
|
|
|
|
public discardAll() { |
|
|
|
this.multipleInputFormGroup.reset(undefined, {emitEvent: false}); |
|
|
|
this.sources.forEach((source) => { |
|
|
|
|