379 lines
15 KiB
JavaScript
379 lines
15 KiB
JavaScript
import { signedGet, isSuccess } from '@/api/client';
|
|
import { dropdownMap, fetchUserAttributes } from '@/api/dropdowns';
|
|
import {
|
|
DEFAULT_INTERVAL_VALUES,
|
|
INTERVAL_VALUES,
|
|
metricOptions,
|
|
parseCombinedMetrics,
|
|
splitHash,
|
|
stringifyCombinedMetrics,
|
|
toApiDate,
|
|
toDateInput,
|
|
VIEW_COMBINED_TYPES,
|
|
} from '@/helpers/metric';
|
|
|
|
function asArray(value) {
|
|
if (Array.isArray(value)) return value.filter((part) => part !== null && part !== undefined && part !== '');
|
|
return splitHash(value);
|
|
}
|
|
|
|
const metricviews = {
|
|
service: 'metric',
|
|
module: 'metric_view',
|
|
title: 'Metric View',
|
|
subtitle: 'Metric',
|
|
baseUrl: '/metricview',
|
|
listPath: '/metricviews',
|
|
defaultType: 'simple',
|
|
listFields: [
|
|
{ key: 'actions', title: 'Actions', buttons: ['edit', 'duplicate', 'delete'] },
|
|
{ key: 'name', title: 'Name', type: 'text' },
|
|
{ key: 'type', title: 'Type', type: 'text' },
|
|
{ key: 'roles', title: 'Roles', type: 'text' },
|
|
{ key: 'sort_order', title: 'Sort Order', type: 'number' },
|
|
{ key: 'validity_start', title: 'Validity start', type: 'date' },
|
|
{ key: 'validity_end', title: 'Validity end', type: 'date' },
|
|
{ key: 'agg_type', title: 'Aggregation type', type: 'text' },
|
|
{ key: 'status', title: 'Status', type: 'select' },
|
|
],
|
|
listButtons: [
|
|
{ title: 'Add A vs B', to: '/metricview/addnew?type=verses' },
|
|
{ title: 'Add Grouped', to: '/metricview/addnew?type=grouped' },
|
|
{ title: 'Add Simple', to: '/metricview/addnew?type=simple' },
|
|
],
|
|
mapItems: (items) =>
|
|
(items || []).map((item) => ({
|
|
...item,
|
|
roles: asArray(item.designations || item.roles).join(', '),
|
|
sort_order: item.sort_order ?? item.widget_sort_order ?? 0,
|
|
})),
|
|
formFields: async () => {
|
|
const [metrics, roles, contactRes, userAttrItems] = await Promise.all([
|
|
metricOptions(),
|
|
dropdownMap('ums', 'roles', (item) => item.name),
|
|
signedGet('contact', 'contactattribute/get_all'),
|
|
fetchUserAttributes(),
|
|
]);
|
|
const contactAttributes = {};
|
|
const contactItems = isSuccess(contactRes) ? contactRes.data?.items || [] : [];
|
|
contactItems.forEach((attr) => {
|
|
if (attr?.code) contactAttributes[attr.code] = attr.attribute || attr.code;
|
|
});
|
|
const userAttributes = {};
|
|
userAttrItems.forEach((attr) => {
|
|
if (!attr?.code || attr.status === 'disabled') return;
|
|
userAttributes[attr.code] = attr.attribute || attr.code;
|
|
});
|
|
const versesMetrics = { ...metrics, fixed: 'Fixed Value' };
|
|
return [
|
|
{ key: 'name', title: 'Name', type: 'text', required: true },
|
|
{
|
|
key: 'type',
|
|
title: 'Type',
|
|
type: 'select',
|
|
required: true,
|
|
values: { simple: 'Simple', grouped: 'Grouped', verses: 'A vs B' },
|
|
},
|
|
{ key: 'validity_start', title: 'Validity start', type: 'date', required: true },
|
|
{ key: 'validity_end', title: 'Validity end', type: 'date', required: true },
|
|
{ key: 'designations', title: 'Publish to Roles', type: 'multiselect', required: true, values: roles },
|
|
{ key: 'metric', title: 'Choose Metric', type: 'select', required: true, values: metrics, showIf: { type: 'simple' } },
|
|
{ key: 'display_unit', title: 'Display Unit', type: 'text', required: true, showIf: { type: 'simple' } },
|
|
{ key: 'metric_0', title: 'Choose Metric 1', type: 'select', required: true, values: metrics, showIf: { type: 'verses' } },
|
|
{ key: 'display_unit_0', title: 'Metric 1 Display Unit', type: 'text', required: true, showIf: { type: 'verses' } },
|
|
{ key: 'metric_1', title: 'Choose Metric 2', type: 'select', required: true, values: versesMetrics, showIf: { type: 'verses' } },
|
|
{ key: 'display_unit_1', title: 'Metric 2 Display Unit', type: 'text', required: true, showIf: { type: 'verses' } },
|
|
{ key: 'fixed_metric', title: 'Fixed Metric value if selected', type: 'text', required: true, showIf: { type: 'verses' } },
|
|
{ key: 'max_value_color', title: 'Max Value Color', type: 'color', showIf: { type: 'verses' } },
|
|
{ key: 'color_ranges', title: 'Color Ranges (%)', type: 'color_ranges', fullwidth: true, showIf: { type: 'verses' } },
|
|
{
|
|
key: 'list_chart_type',
|
|
title: 'List Chart Type',
|
|
type: 'select',
|
|
required: true,
|
|
showIf: { type: 'verses' },
|
|
values: {
|
|
donut: 'Donut',
|
|
progressbar: 'Progress Bar',
|
|
horizontal_barchart: 'Horizontal Bar Chart',
|
|
vertical_barchart: 'Vertical Bar Chart',
|
|
},
|
|
},
|
|
{
|
|
key: 'metrics',
|
|
title: 'Choose Metric',
|
|
type: 'mapping',
|
|
variant: 'grouped',
|
|
required: true,
|
|
fullwidth: true,
|
|
metrics,
|
|
showIf: { type: 'grouped' },
|
|
},
|
|
{ key: 'operation', title: 'Operation', type: 'select', required: true, values: { sum: 'Sum', avg: 'Avg', value_count: 'Count' } },
|
|
{
|
|
key: 'agg_type',
|
|
title: 'Aggregation Type',
|
|
type: 'select',
|
|
required: true,
|
|
values: { individual: 'Individual', team: 'Team' },
|
|
},
|
|
{
|
|
key: 'graphical_views',
|
|
title: 'Graphical views',
|
|
type: 'multiselect',
|
|
values: { progress: 'Progress', percentile: 'Percentile', pie: 'Pie chart', bar: 'Bar chart', line: 'Line chart' },
|
|
},
|
|
{
|
|
key: 'value_views',
|
|
title: 'Value views',
|
|
type: 'multiselect',
|
|
values: { value: 'Value' },
|
|
},
|
|
{
|
|
key: 'details_views',
|
|
title: 'Details views',
|
|
type: 'multiselect',
|
|
values: { tabular: 'Tabular', contacts: 'Doctor View', incremental: 'Incremental View' },
|
|
},
|
|
{
|
|
key: 'trend_views',
|
|
title: 'Trend views',
|
|
type: 'multiselect',
|
|
values: { bar: 'Bar chart', line: 'Line chart', tabular: 'Tabular' },
|
|
},
|
|
{
|
|
key: 'leaderboard_views',
|
|
title: 'My Team views',
|
|
type: 'multiselect',
|
|
values: { leaderboard: 'My Team View' },
|
|
},
|
|
{
|
|
key: 'scoreboard_views',
|
|
title: 'Leaderboard views',
|
|
type: 'multiselect',
|
|
values: { leaderboard: 'Leaderboard View' },
|
|
},
|
|
{
|
|
key: 'contacts_views',
|
|
title: 'Doctor views',
|
|
type: 'multiselect',
|
|
values: { contacts: 'Doctor View' },
|
|
},
|
|
{ key: 'doctor_view_name', title: 'Enter Doctor View Name', type: 'text' },
|
|
{ key: 'intervals', title: 'Intervals', type: 'multiselect', required: true, values: INTERVAL_VALUES },
|
|
{ key: 'default_interval', title: 'Default Interval', type: 'select', required: true, values: DEFAULT_INTERVAL_VALUES },
|
|
{
|
|
key: 'default_tab',
|
|
title: 'Default Tab',
|
|
type: 'select',
|
|
values: {
|
|
value: 'Value',
|
|
trend: 'Trend',
|
|
details: 'Detail',
|
|
leaderboard: 'My Team',
|
|
scoreboard: 'Leaderboard',
|
|
contacts: 'Doctor List',
|
|
incremental: 'Incremental',
|
|
},
|
|
},
|
|
{ key: 'widget_sort_order', title: 'Sort Order', type: 'number', required: true },
|
|
{ key: 'doctor_type', title: 'Doctor Type', type: 'text' },
|
|
{
|
|
key: 'combined_metrics',
|
|
title: 'Combined Metrics (if any)',
|
|
type: 'combined_metrics',
|
|
variant: 'view',
|
|
fullwidth: true,
|
|
metrics,
|
|
types: VIEW_COMBINED_TYPES,
|
|
},
|
|
{ key: 'report_roles', title: 'Data Report from Roles', type: 'multiselect', required: true, values: roles },
|
|
{ key: 'status', title: 'Status', type: 'select', required: true, values: { active: 'Active', disabled: 'Disabled' } },
|
|
{ key: 'show_positions', title: 'Show Positions', type: 'select', required: true, values: { yes: 'Yes', no: 'No' } },
|
|
{
|
|
key: 'show_positions_type',
|
|
title: 'Show Positions Type',
|
|
type: 'select',
|
|
required: true,
|
|
values: { all: 'All', loggedin: 'Logged In' },
|
|
},
|
|
{ key: 'contact_attributes', title: 'Include Doctor Attributes', type: 'multiselect', values: contactAttributes },
|
|
{
|
|
key: 'team_leaderboard_widget_roles',
|
|
title: 'Team Leaderboard Widget Roles',
|
|
type: 'multiselect',
|
|
values: roles,
|
|
},
|
|
{ key: 'show_user_attributes', title: 'Show User Attributes', type: 'yesno', required: true, default: 'no' },
|
|
{
|
|
key: 'user_attributes',
|
|
title: 'Include User Attributes',
|
|
type: 'multiselect',
|
|
values: userAttributes,
|
|
default: [],
|
|
},
|
|
{
|
|
key: 'stateheadwise_leaderboard',
|
|
title: 'Stateheadwise Leaderboard',
|
|
type: 'yesno',
|
|
required: true,
|
|
default: 'no',
|
|
},
|
|
];
|
|
},
|
|
beforeForm: (item) => {
|
|
const next = {
|
|
type: 'simple',
|
|
widget_sort_order: 0,
|
|
sort_order: 0,
|
|
show_positions: 'yes',
|
|
show_positions_type: 'all',
|
|
show_user_attributes: 'no',
|
|
user_attributes: [],
|
|
stateheadwise_leaderboard: 'no',
|
|
list_chart_type: 'progressbar',
|
|
value_views: ['value'],
|
|
default_tab: '',
|
|
team_leaderboard_widget_roles: [],
|
|
...item,
|
|
};
|
|
next.designations = asArray(next.designations);
|
|
next.report_roles = asArray(next.report_roles);
|
|
next.graphical_views = asArray(next.graphical_views);
|
|
next.details_views = asArray(next.details_views);
|
|
next.trend_views = asArray(next.trend_views);
|
|
next.leaderboard_views = asArray(next.leaderboard_views);
|
|
next.scoreboard_views = item && Object.prototype.hasOwnProperty.call(item, 'scoreboard_views')
|
|
? asArray(next.scoreboard_views)
|
|
: asArray(next.leaderboard_views);
|
|
next.value_views = item && Object.prototype.hasOwnProperty.call(item, 'value_views')
|
|
? asArray(next.value_views)
|
|
: ['value'];
|
|
next.contacts_views = asArray(next.contacts_views);
|
|
next.default_tab = next.default_tab || '';
|
|
next.intervals = asArray(next.intervals);
|
|
next.contact_attributes = asArray(next.contact_attributes);
|
|
next.team_leaderboard_widget_roles = asArray(
|
|
next.team_leaderboard_widget_roles || next.leaderboard_widget_roles || next.widget_roles,
|
|
);
|
|
next.show_user_attributes = ['yes', '1', 'true', true, 1].includes(next.show_user_attributes) ? 'yes' : 'no';
|
|
next.user_attributes = asArray(next.user_attributes);
|
|
if (next.user_attributes.length && next.show_user_attributes !== 'yes') {
|
|
next.show_user_attributes = 'yes';
|
|
}
|
|
next.stateheadwise_leaderboard = next.stateheadwise_leaderboard === 'yes' ? 'yes' : 'no';
|
|
next.combined_metrics = parseCombinedMetrics(next.combined_metrics);
|
|
next.validity_start = toDateInput(next.validity_start);
|
|
next.validity_end = toDateInput(next.validity_end);
|
|
if (next.sort_order === '' || next.sort_order == null) next.sort_order = next.widget_sort_order || 0;
|
|
if (next.widget_sort_order === '' || next.widget_sort_order == null) next.widget_sort_order = next.sort_order || 0;
|
|
if (next.show_positions) next.show_positions = String(next.show_positions).toLowerCase();
|
|
if (!Array.isArray(next.color_ranges)) next.color_ranges = [];
|
|
const metrics = Array.isArray(next.metrics) ? [...next.metrics] : [];
|
|
metrics.sort((a, b) => (Number(a?.sort_order) || 0) - (Number(b?.sort_order) || 0));
|
|
if (next.type === 'simple' && metrics[0]) {
|
|
next.metric = metrics[0].metric;
|
|
next.display_unit = metrics[0].display;
|
|
} else if (next.type === 'verses') {
|
|
next.metric_0 = metrics[0]?.metric || '';
|
|
next.display_unit_0 = metrics[0]?.display || '';
|
|
next.metric_1 = metrics[1]?.metric || '';
|
|
next.display_unit_1 = metrics[1]?.display || '';
|
|
if (!next.list_chart_type) next.list_chart_type = 'progressbar';
|
|
} else if (next.type === 'grouped') {
|
|
next.metrics = metrics.map((row) => ({
|
|
metric: row.metric || '',
|
|
display: row.display || '',
|
|
sort_order: row.sort_order ?? 0,
|
|
weight: row.weight ?? 1,
|
|
list_view: row.list_view || 'yes',
|
|
}));
|
|
}
|
|
return next;
|
|
},
|
|
beforeSave: (data) => {
|
|
const type = data.type || 'simple';
|
|
let metrics = [];
|
|
if (type === 'simple') {
|
|
metrics = [{ metric: data.metric, display: data.display_unit }];
|
|
} else if (type === 'verses') {
|
|
metrics = [
|
|
{ metric: data.metric_0, display: data.display_unit_0 },
|
|
{ metric: data.metric_1, display: data.display_unit_1 },
|
|
];
|
|
} else {
|
|
metrics = (data.metrics || [])
|
|
.filter((row) => row.metric)
|
|
.map((row) => ({
|
|
metric: row.metric,
|
|
display: row.display || '',
|
|
sort_order: Number(row.sort_order) || 0,
|
|
list_view: row.list_view || 'yes',
|
|
weight: row.weight === '' || row.weight == null ? 1 : Number(row.weight),
|
|
}));
|
|
}
|
|
const widgetSort = Number.parseInt(data.widget_sort_order, 10) || 0;
|
|
const payload = {
|
|
...data,
|
|
type,
|
|
metrics,
|
|
designations: asArray(data.designations),
|
|
report_roles: asArray(data.report_roles),
|
|
graphical_views: asArray(data.graphical_views),
|
|
details_views: asArray(data.details_views),
|
|
trend_views: asArray(data.trend_views),
|
|
leaderboard_views: asArray(data.leaderboard_views),
|
|
scoreboard_views: asArray(data.scoreboard_views),
|
|
value_views: asArray(data.value_views),
|
|
contacts_views: asArray(data.contacts_views),
|
|
default_tab: data.default_tab || '',
|
|
intervals: asArray(data.intervals),
|
|
contact_attributes: asArray(data.contact_attributes),
|
|
team_leaderboard_widget_roles: asArray(data.team_leaderboard_widget_roles),
|
|
show_user_attributes: data.show_user_attributes === 'yes' ? 'yes' : 'no',
|
|
user_attributes: asArray(data.user_attributes),
|
|
stateheadwise_leaderboard: data.stateheadwise_leaderboard === 'yes' ? 'yes' : 'no',
|
|
combined_metrics: stringifyCombinedMetrics(
|
|
(data.combined_metrics || [])
|
|
.filter((row) => row.type)
|
|
.map((row) => ({
|
|
type: row.type,
|
|
title: row.title || '',
|
|
fields: Array.isArray(row.fields) ? row.fields : [],
|
|
list_view: row.list_view || 'yes',
|
|
})),
|
|
),
|
|
widget_sort_order: widgetSort,
|
|
sort_order: widgetSort,
|
|
validity_start: toApiDate(data.validity_start),
|
|
validity_end: toApiDate(data.validity_end),
|
|
};
|
|
if (type === 'verses') {
|
|
payload.max_value_color = (data.max_value_color || '').trim();
|
|
payload.color_ranges = (data.color_ranges || [])
|
|
.filter((row) => row.min !== '' || row.max !== '' || row.color)
|
|
.map((row) => ({
|
|
min: Number(row.min) || 0,
|
|
max: Number(row.max) || 0,
|
|
color: row.color || '#000000',
|
|
}));
|
|
payload.list_chart_type = data.list_chart_type || 'progressbar';
|
|
} else {
|
|
delete payload.max_value_color;
|
|
delete payload.color_ranges;
|
|
delete payload.list_chart_type;
|
|
delete payload.fixed_metric;
|
|
}
|
|
delete payload.metric;
|
|
delete payload.display_unit;
|
|
delete payload.metric_0;
|
|
delete payload.display_unit_0;
|
|
delete payload.metric_1;
|
|
delete payload.display_unit_1;
|
|
if (payload.id === '' || payload.id == null) delete payload.id;
|
|
return payload;
|
|
},
|
|
};
|
|
|
|
export default metricviews;
|