@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
163 lines (158 loc) • 6.74 kB
JavaScript
import { gettext } from '@c8y/ngx-components/gettext';
import { DynamicComponentErrorStrategy, DynamicDatapointsResolver, hookWidget } from '@c8y/ngx-components';
import { defaultWidgetIds } from '@c8y/ngx-components/widgets/definitions';
import { importConfigWithTargets, exportConfigWithTargets } from '@c8y/ngx-components/widgets/import-export-config';
import { hookWidgetConfig } from '@c8y/ngx-components/context-dashboard';
import { FormGroup } from '@angular/forms';
const AT_LEAST_ONE_ACTIVE_ERROR_KEY = 'noActiveDataPoint';
function atLeastOneDataPointActive(dataPointsControlNames) {
const validatorFn = (formGroup) => {
if (!(formGroup instanceof FormGroup))
return null;
const errorKey = AT_LEAST_ONE_ACTIVE_ERROR_KEY;
let anyActive = false;
for (const controlName of dataPointsControlNames) {
const control = formGroup.get(controlName);
const value = control?.value;
if (Array.isArray(value) && value.some(item => item?.__active)) {
anyActive = true;
break;
}
}
// If none are active
if (!anyActive) {
// Set error on all specified controls
for (const controlName of dataPointsControlNames) {
const control = formGroup.get(controlName);
if (control) {
const errors = { ...(control.errors || {}) };
errors[errorKey] = true;
control.setErrors(errors);
}
}
// Set error on the group
return { [errorKey]: true };
}
else {
// Remove error from all specified controls if present
for (const controlName of dataPointsControlNames) {
const control = formGroup.get(controlName);
if (control?.errors?.[errorKey]) {
const errors = { ...control.errors };
delete errors[errorKey];
control.setErrors(Object.keys(errors).length ? errors : null);
}
}
// Validation passes for the group
return null;
}
};
// Attach metadata to the validator function
validatorFn.controlNames = dataPointsControlNames;
return validatorFn;
}
const DEFAULT_FORM_CONFIG = {
showRedRange: true,
showYellowRange: true,
showRange: true,
selectableChartRenderTypes: []
};
const DATAPOINTS_GAUGE_CONTROL_NAME = 'datapointsGauge';
const DATAPOINTS_LABELS_CONTROL_NAME = 'datapointsLabels';
const MISSING_RANGE_ERROR_KEY = 'gaugeDatapointMissingRange';
function gaugeDatapointHasRange(controlName) {
const validatorFn = (formGroup) => {
if (!(formGroup instanceof FormGroup))
return null;
const control = formGroup.get(controlName);
const datapoints = control?.value;
if (!Array.isArray(datapoints))
return null;
const activeGauge = datapoints.find(dp => dp?.__active);
if (!activeGauge)
return null;
const min = Number(activeGauge.min);
const max = Number(activeGauge.max);
const hasRange = Number.isFinite(min) && Number.isFinite(max) && min !== max;
return hasRange ? null : { [MISSING_RANGE_ERROR_KEY]: true };
};
validatorFn.controlNames = [controlName];
return validatorFn;
}
const minActiveDataPointError = {
[AT_LEAST_ONE_ACTIVE_ERROR_KEY]: gettext('At least 1 data point must be selected and active for the gauge or the labels.')
};
const gaugeRangeError = {
[MISSING_RANGE_ERROR_KEY]: gettext('The gauge data point has no min/max range configured. The gauge bar will not display correctly.')
};
const infoGaugeWidgetDefinition = {
id: defaultWidgetIds.INFO_GAUGE,
label: gettext('Info gauge'),
description: gettext('Radial gauge and multiple label and value pairs for data points'),
loadComponent: () => import('@c8y/ngx-components/widgets/implementations/info-gauge').then(m => m.InfoGaugeWidgetViewComponent),
loadConfigComponent: () => import('@c8y/ngx-components/widgets/implementations/info-gauge').then(m => m.InfoGaugeWidgetConfigComponent),
previewImage: 'c8y-style-assets/info-gauge-widget-pr.png',
resolve: {
datapointsLabels: DynamicDatapointsResolver,
datapointsGauge: DynamicDatapointsResolver
},
errorStrategy: DynamicComponentErrorStrategy.OVERLAY_ERROR,
data: {
schema: () => import('c8y-schema-loader?interfaceName=InfoGaugeWidgetConfig&type=widget-config!@c8y/ngx-components/widgets/implementations/info-gauge'),
export: exportConfigWithTargets,
import: importConfigWithTargets,
settings: {
noNewWidgets: false,
widgetDefaults: {
_width: 6,
_height: 5
},
ng1: {
options: {
noDeviceTarget: true,
groupsSelectable: false
}
}
}
}
};
const infoGaugeWidgetProviders = [
hookWidget(infoGaugeWidgetDefinition),
hookWidgetConfig({
widgetId: defaultWidgetIds.INFO_GAUGE,
label: gettext('Gauge`display`'),
loadComponent: () => import('@c8y/ngx-components/datapoint-selector').then(m => m.WidgetDatapointsSelectorComponent),
initialState: {
minActiveCount: 0,
defaultFormOptions: DEFAULT_FORM_CONFIG,
controlName: DATAPOINTS_GAUGE_CONTROL_NAME
},
expanded: true,
validators: [
atLeastOneDataPointActive([DATAPOINTS_GAUGE_CONTROL_NAME, DATAPOINTS_LABELS_CONTROL_NAME]),
gaugeDatapointHasRange(DATAPOINTS_GAUGE_CONTROL_NAME)
],
validationErrors: { ...minActiveDataPointError, ...gaugeRangeError },
priority: 80
}),
hookWidgetConfig({
widgetId: defaultWidgetIds.INFO_GAUGE,
label: gettext('Multiple label and value pairs'),
loadComponent: () => import('@c8y/ngx-components/datapoint-selector').then(m => m.WidgetDatapointsSelectorComponent),
initialState: {
minActiveCount: 0,
defaultFormOptions: DEFAULT_FORM_CONFIG,
controlName: DATAPOINTS_LABELS_CONTROL_NAME
},
validators: [
atLeastOneDataPointActive([DATAPOINTS_GAUGE_CONTROL_NAME, DATAPOINTS_LABELS_CONTROL_NAME])
],
validationErrors: minActiveDataPointError,
priority: 80
})
];
/**
* Generated bundle index. Do not edit.
*/
export { infoGaugeWidgetDefinition, infoGaugeWidgetProviders };
//# sourceMappingURL=c8y-ngx-components-widgets-definitions-info-gauge.mjs.map