421 lines
16 KiB
JavaScript
421 lines
16 KiB
JavaScript
import { signedGet, isSuccess } from '@/api/client';
|
|
import { dropdownMap } from '@/api/dropdowns';
|
|
import { metricOptions, toDateInput } from '@/helpers/metric';
|
|
|
|
const STATUS = { active: 'Active', disabled: 'Disabled' };
|
|
const YES_NO = { yes: 'Yes', no: 'No' };
|
|
const MANAGER_LEVELS = {
|
|
l1manager: 'L1 Manager',
|
|
l2manager: 'L2 Manager',
|
|
l3manager: 'L3 Manager',
|
|
l4manager: 'L4 Manager',
|
|
};
|
|
const DAYS = {
|
|
MON: 'Monday',
|
|
TUE: 'Tuesday',
|
|
WED: 'Wednesday',
|
|
THU: 'Thursday',
|
|
FRI: 'Friday',
|
|
SAT: 'Saturday',
|
|
SUN: 'Sunday',
|
|
};
|
|
|
|
function dateOptions() {
|
|
const values = { L: 'Last day of month' };
|
|
for (let day = 1; day <= 31; day += 1) values[String(day)] = String(day);
|
|
return values;
|
|
}
|
|
|
|
function toBool(value) {
|
|
if (value === true || value === 1) return true;
|
|
return ['yes', '1', 'true'].includes(String(value ?? '').toLowerCase());
|
|
}
|
|
|
|
function fromBool(value) {
|
|
return toBool(value) ? 'yes' : 'no';
|
|
}
|
|
|
|
function toStringList(value) {
|
|
if (value == null || value === '') return [];
|
|
if (Array.isArray(value)) return value.map(String).filter((part) => part !== '');
|
|
if (typeof value === 'object') return Object.values(value).map(String);
|
|
return [String(value)];
|
|
}
|
|
|
|
function titleMap(items) {
|
|
const values = {};
|
|
(items || []).forEach((item) => {
|
|
if (item?.id) values[item.id] = item.title || item.name || item.id;
|
|
});
|
|
return values;
|
|
}
|
|
|
|
async function getAllItems(service, path) {
|
|
const response = await signedGet(service, path);
|
|
return isSuccess(response) ? response.data?.items || [] : [];
|
|
}
|
|
|
|
function newMilestoneId() {
|
|
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
return crypto.randomUUID();
|
|
}
|
|
return `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
}
|
|
|
|
function flattenMetrics(metrics) {
|
|
if (!Array.isArray(metrics)) return [];
|
|
return metrics.map((row) => {
|
|
const metric = row && typeof row === 'object' ? row : {};
|
|
return {
|
|
metric: metric.metric || '',
|
|
display: metric.display || '',
|
|
weight: metric.weight ?? 1,
|
|
target: metric.target ?? '',
|
|
};
|
|
});
|
|
}
|
|
|
|
function firstBadge(value) {
|
|
if (Array.isArray(value)) return value[0] || '';
|
|
return value || '';
|
|
}
|
|
|
|
function flattenMilestoneCards(milestones) {
|
|
if (!Array.isArray(milestones)) return [];
|
|
return milestones.map((row) => {
|
|
const card = row && typeof row === 'object' ? row : {};
|
|
const target = card.target && typeof card.target === 'object' ? card.target : {};
|
|
const actions = card.actions && typeof card.actions === 'object' ? card.actions : {};
|
|
const appreciation = Array.isArray(actions.send_appreciation)
|
|
? actions.send_appreciation[0] || {}
|
|
: actions.send_appreciation || {};
|
|
return {
|
|
milestone_id: card.milestone_id || '',
|
|
target_title: target.target_title ?? '',
|
|
target: target.value ?? (typeof card.target === 'number' || typeof card.target === 'string' ? card.target : ''),
|
|
repeat_target: card.repeat_target ? '1' : '0',
|
|
roles: toStringList(card.roles),
|
|
reporting_roles: toStringList(card.reporting_roles),
|
|
user_notification: Boolean(actions.user_notification),
|
|
user_email: Boolean(actions.user_email),
|
|
manager_notification: toStringList(actions.manager_notification),
|
|
manager_email: toStringList(actions.manager_email),
|
|
send_badge: firstBadge(actions.send_badge),
|
|
appreciation_category: appreciation.category_id || '',
|
|
appreciation_image: appreciation.image_id || '',
|
|
appreciation_message: appreciation.message || '',
|
|
};
|
|
});
|
|
}
|
|
|
|
function mapMetricsForSave(rows) {
|
|
return (Array.isArray(rows) ? rows : [])
|
|
.filter((row) => row?.metric)
|
|
.map((row) => ({
|
|
metric: row.metric,
|
|
display: row.display || '',
|
|
weight: row.weight !== '' && row.weight != null ? String(row.weight) : '1',
|
|
target: row.target !== '' && row.target != null ? String(row.target) : '',
|
|
}));
|
|
}
|
|
|
|
function mapMilestonesForSave(rows) {
|
|
return (Array.isArray(rows) ? rows : []).map((row) => ({
|
|
milestone_id: row.milestone_id || newMilestoneId(),
|
|
target: {
|
|
value: Number(row.target || 0),
|
|
target_title: row.target_title || '',
|
|
},
|
|
repeat_target: String(row.repeat_target) === '1',
|
|
roles: toStringList(row.roles),
|
|
reporting_roles: toStringList(row.reporting_roles),
|
|
actions: {
|
|
user_notification: Boolean(row.user_notification),
|
|
user_email: Boolean(row.user_email),
|
|
manager_notification: toStringList(row.manager_notification),
|
|
manager_email: toStringList(row.manager_email),
|
|
send_badge: row.send_badge ? [row.send_badge] : [],
|
|
send_appreciation: [
|
|
{
|
|
category_id: row.appreciation_category || null,
|
|
image_id: row.appreciation_image || null,
|
|
message: row.appreciation_message || null,
|
|
},
|
|
],
|
|
},
|
|
}));
|
|
}
|
|
|
|
const milestones = {
|
|
service: 'formreminders',
|
|
module: 'milestones',
|
|
title: 'Milestone',
|
|
subtitle: 'Recognition',
|
|
baseUrl: '/milestone',
|
|
listPath: '/milestones',
|
|
listFields: [
|
|
{ key: 'actions', title: 'Actions', buttons: ['edit', 'delete'] },
|
|
{ key: 'title', title: 'Name', type: 'text' },
|
|
{ key: 'status', title: 'Status', type: 'select' },
|
|
],
|
|
formFields: async () => {
|
|
const [metrics, roles, badges, categories, images, userAttrRes] = await Promise.all([
|
|
metricOptions(),
|
|
dropdownMap('ums', 'roles', (item) => item.name),
|
|
getAllItems('recognition', 'badge_list/get_all').then(titleMap),
|
|
getAllItems('recognition', 'appreciation_category/get_all').then(titleMap),
|
|
getAllItems('recognition', 'appreciation_image/get_all').then((items) => {
|
|
const values = {};
|
|
items.forEach((item) => {
|
|
if (item?.id) values[item.id] = { title: item.title || item.id, image: item.image || '' };
|
|
});
|
|
return values;
|
|
}),
|
|
signedGet('ums', 'userattribute/get_all'),
|
|
]);
|
|
const userAttributes = {};
|
|
const userAttrItems = isSuccess(userAttrRes) ? userAttrRes.data?.items || [] : [];
|
|
userAttrItems.forEach((attr) => {
|
|
if (!attr?.code || attr.status === 'disabled') return;
|
|
userAttributes[attr.code] = attr.attribute || attr.code;
|
|
});
|
|
return [
|
|
{ key: 'title', title: 'Title', type: 'text', required: true },
|
|
{ key: 'interval_start_date', title: 'Interval Start Date', type: 'date', required: true },
|
|
{ key: 'interval_end_date', title: 'Interval End Date', type: 'date', required: true },
|
|
{
|
|
key: 'period',
|
|
title: 'Period',
|
|
type: 'select',
|
|
required: true,
|
|
values: {
|
|
daily: 'Daily',
|
|
weekly: 'Weekly',
|
|
monthly: 'Monthly',
|
|
yearly: 'Yearly',
|
|
overall: 'Overall',
|
|
custom: 'Custom',
|
|
},
|
|
},
|
|
{ key: 'custom_start_date', title: 'Custom Start Date', type: 'date', showIf: { period: 'custom' } },
|
|
{ key: 'custom_end_date', title: 'Custom End Date', type: 'date', showIf: { period: 'custom' } },
|
|
{ key: 'status', title: 'Status', type: 'select', required: true, values: STATUS },
|
|
{ key: 'show_positions', title: 'Show Positions', type: 'select', required: true, values: YES_NO },
|
|
{
|
|
key: 'show_positions_type',
|
|
title: 'Show Positions Type',
|
|
type: 'select',
|
|
required: true,
|
|
values: { all: 'All', loggedin: 'Logged In' },
|
|
},
|
|
{ key: 'show_units_export', title: 'Show Units Export', type: 'select', required: true, values: YES_NO, default: 'yes' },
|
|
{ key: 'show_user_attributes', title: 'Show User Attributes', type: 'select', required: true, values: YES_NO, default: 'no' },
|
|
{
|
|
key: 'user_attributes',
|
|
title: 'Include User Attributes',
|
|
type: 'multiselect',
|
|
values: userAttributes,
|
|
default: [],
|
|
showIf: { show_user_attributes: 'yes' },
|
|
},
|
|
{ key: 'show_normal_metrics', title: 'Show Normal Metrics', type: 'select', required: true, values: YES_NO, default: 'yes' },
|
|
{ key: 'show_combined_metrics', title: 'Show Combined Metrics', type: 'select', required: true, values: YES_NO, default: 'yes' },
|
|
{ key: 'manager_details', title: 'Manager Details', type: 'multiselect', values: MANAGER_LEVELS, default: ['l1manager'] },
|
|
{ key: 'total_units_name', title: 'Total Units Name', type: 'text', default: '' },
|
|
{ key: 'send_report', title: 'Send Report', type: 'select', required: true, values: YES_NO },
|
|
{
|
|
key: 'performance_period',
|
|
title: 'Performance Period',
|
|
type: 'select',
|
|
values: { daily: 'Daily', weekly: 'Weekly', monthly: 'Monthly' },
|
|
showIf: { send_report: 'yes' },
|
|
},
|
|
{
|
|
key: 'days_or_dates',
|
|
title: 'Days or Dates',
|
|
type: 'radio',
|
|
fullwidth: true,
|
|
values: { days: 'Days', dates: 'Dates' },
|
|
showIf: { send_report: 'yes' },
|
|
},
|
|
{
|
|
key: 'days',
|
|
title: 'Days',
|
|
type: 'checkbox',
|
|
fullwidth: true,
|
|
values: DAYS,
|
|
showIf: { send_report: 'yes', days_or_dates: 'days' },
|
|
},
|
|
{
|
|
key: 'dates',
|
|
title: 'Dates',
|
|
type: 'multiselect',
|
|
values: dateOptions(),
|
|
showIf: { send_report: 'yes', days_or_dates: 'dates' },
|
|
},
|
|
{ key: 'send_time', title: 'Send Time', type: 'text', showIf: { send_report: 'yes' } },
|
|
{
|
|
key: 'send_report_roles',
|
|
title: 'Send Report Roles',
|
|
type: 'multiselect',
|
|
values: roles,
|
|
showIf: { send_report: 'yes' },
|
|
},
|
|
{
|
|
key: 'report_roles',
|
|
title: 'Report Roles',
|
|
type: 'multiselect',
|
|
values: roles,
|
|
showIf: { send_report: 'yes' },
|
|
},
|
|
{
|
|
key: 'send_user_performance',
|
|
title: 'Send User Performance',
|
|
type: 'select',
|
|
values: YES_NO,
|
|
showIf: { send_report: 'yes' },
|
|
},
|
|
{
|
|
key: 'ai_action_items',
|
|
title: 'AI Action Items',
|
|
type: 'select',
|
|
values: YES_NO,
|
|
showIf: { send_report: 'yes' },
|
|
},
|
|
{
|
|
key: 'send_pending_users',
|
|
title: 'Send Pending Users',
|
|
type: 'select',
|
|
values: YES_NO,
|
|
showIf: { send_report: 'yes' },
|
|
},
|
|
{
|
|
key: 'show_target_average',
|
|
title: 'Show Target Average',
|
|
type: 'select',
|
|
values: YES_NO,
|
|
showIf: { send_report: 'yes' },
|
|
},
|
|
{
|
|
key: 'show_overall_average',
|
|
title: 'Show Overall Average',
|
|
type: 'select',
|
|
values: YES_NO,
|
|
showIf: { send_report: 'yes' },
|
|
},
|
|
{
|
|
key: 'metrics',
|
|
title: 'Metric Mapping',
|
|
type: 'mapping',
|
|
variant: 'milestone_metrics',
|
|
required: true,
|
|
metrics,
|
|
fullwidth: true,
|
|
},
|
|
{
|
|
key: 'milestones',
|
|
title: 'Milestone',
|
|
type: 'milestonemapping',
|
|
required: true,
|
|
roles,
|
|
badges,
|
|
appreciationCategories: categories,
|
|
appreciationImages: images,
|
|
fullwidth: true,
|
|
},
|
|
];
|
|
},
|
|
beforeForm: (item) => {
|
|
const next = { ...item };
|
|
if (next.interval) {
|
|
const [start, end] = String(next.interval).split('_');
|
|
next.interval_start_date = toDateInput(start);
|
|
next.interval_end_date = toDateInput(end);
|
|
} else {
|
|
next.interval_start_date = toDateInput(next.interval_start_date);
|
|
next.interval_end_date = toDateInput(next.interval_end_date);
|
|
}
|
|
next.custom_start_date = toDateInput(next.custom_start_date);
|
|
next.custom_end_date = toDateInput(next.custom_end_date);
|
|
next.metrics = flattenMetrics(next.metrics);
|
|
next.milestones = flattenMilestoneCards(next.milestones);
|
|
|
|
const reportConfig = next.report_config && typeof next.report_config === 'object' ? next.report_config : {};
|
|
next.days_or_dates = reportConfig.days_or_dates || 'days';
|
|
next.days = toStringList(reportConfig.days);
|
|
next.dates = toStringList(reportConfig.dates).map(String);
|
|
next.send_time = reportConfig.send_time || '';
|
|
next.performance_period = reportConfig.performance_period || '';
|
|
next.send_report_roles = toStringList(reportConfig.send_report_roles);
|
|
next.report_roles = toStringList(reportConfig.report_roles);
|
|
next.send_user_performance = fromBool(reportConfig.send_user_performance ?? false);
|
|
next.ai_action_items = fromBool(reportConfig.ai_action_items ?? false);
|
|
next.send_pending_users = fromBool(reportConfig.send_pending_users ?? false);
|
|
next.show_target_average = fromBool(reportConfig.show_target_average ?? false);
|
|
next.show_overall_average = fromBool(reportConfig.show_overall_average ?? false);
|
|
next.send_report = fromBool(next.send_report ?? false);
|
|
next.show_units_export = next.show_units_export || 'yes';
|
|
next.show_user_attributes = next.show_user_attributes === 'yes' ? 'yes' : 'no';
|
|
next.user_attributes = toStringList(next.user_attributes);
|
|
next.show_normal_metrics = next.show_normal_metrics || 'yes';
|
|
next.show_combined_metrics = next.show_combined_metrics || 'yes';
|
|
next.manager_details = toStringList(next.manager_details);
|
|
if (!next.manager_details.length) next.manager_details = ['l1manager'];
|
|
next.total_units_name = next.total_units_name || '';
|
|
return next;
|
|
},
|
|
beforeSave: (data) => {
|
|
const payload = { ...data };
|
|
const start = toDateInput(payload.interval_start_date);
|
|
const end = toDateInput(payload.interval_end_date);
|
|
payload.interval = start && end ? `${start}_${end}` : '';
|
|
payload.custom_start_date = payload.period === 'custom' ? toDateInput(payload.custom_start_date) : '';
|
|
payload.custom_end_date = payload.period === 'custom' ? toDateInput(payload.custom_end_date) : '';
|
|
payload.metrics = mapMetricsForSave(payload.metrics);
|
|
payload.milestones = mapMilestonesForSave(payload.milestones);
|
|
|
|
const daysOrDates = payload.days_or_dates || 'days';
|
|
payload.show_units_export = payload.show_units_export || 'yes';
|
|
payload.show_user_attributes = payload.show_user_attributes === 'yes' ? 'yes' : 'no';
|
|
payload.user_attributes = toStringList(payload.user_attributes);
|
|
payload.show_normal_metrics = payload.show_normal_metrics || 'yes';
|
|
payload.show_combined_metrics = payload.show_combined_metrics || 'yes';
|
|
payload.manager_details = toStringList(payload.manager_details);
|
|
if (!payload.manager_details.length) payload.manager_details = ['l1manager'];
|
|
payload.total_units_name = payload.total_units_name || '';
|
|
payload.send_report = toBool(payload.send_report ?? 'no');
|
|
payload.report_config = {
|
|
days_or_dates: daysOrDates,
|
|
days: daysOrDates === 'days' ? toStringList(payload.days) : [],
|
|
dates: daysOrDates === 'dates' ? toStringList(payload.dates) : [],
|
|
send_time: payload.send_time || '13:00',
|
|
performance_period: payload.performance_period || 'monthly',
|
|
send_report_roles: toStringList(payload.send_report_roles),
|
|
report_roles: toStringList(payload.report_roles),
|
|
send_user_performance: toBool(payload.send_user_performance ?? 'no'),
|
|
ai_action_items: toBool(payload.ai_action_items ?? 'no'),
|
|
send_pending_users: toBool(payload.send_pending_users ?? 'no'),
|
|
show_target_average: toBool(payload.show_target_average ?? 'no'),
|
|
show_overall_average: toBool(payload.show_overall_average ?? 'no'),
|
|
};
|
|
|
|
delete payload.interval_start_date;
|
|
delete payload.interval_end_date;
|
|
delete payload.days_or_dates;
|
|
delete payload.days;
|
|
delete payload.dates;
|
|
delete payload.send_time;
|
|
delete payload.performance_period;
|
|
delete payload.send_report_roles;
|
|
delete payload.report_roles;
|
|
delete payload.send_user_performance;
|
|
delete payload.ai_action_items;
|
|
delete payload.send_pending_users;
|
|
delete payload.show_target_average;
|
|
delete payload.show_overall_average;
|
|
return payload;
|
|
},
|
|
};
|
|
|
|
export default milestones;
|