Reestruturação dos arquivos e pastas do código da extensão
This commit is contained in:
944
src/content/manage-time-controller.js
Normal file
944
src/content/manage-time-controller.js
Normal file
@@ -0,0 +1,944 @@
|
||||
(() => {
|
||||
function create(dependencies) {
|
||||
const {
|
||||
appState,
|
||||
COMCIP_REQUEST,
|
||||
comcipRepository,
|
||||
readCachedTaskTypePayload,
|
||||
writeCachedTaskTypePayload,
|
||||
getStoredTimeManagementSelectedDate,
|
||||
setStoredTimeManagementSelectedDate,
|
||||
renderModal,
|
||||
cleanString,
|
||||
normalizeString,
|
||||
getDateInputValue,
|
||||
parseDatePreservingDateOnly,
|
||||
getFieldValue,
|
||||
extractArray,
|
||||
getErrorMessage,
|
||||
cssEscape,
|
||||
getTimeManagementRows,
|
||||
isTimeManagementSaveEnabled,
|
||||
getTimeManagementPendingChanges,
|
||||
createTimeManagementSavePayload,
|
||||
isNonServiceRequestSrNumber,
|
||||
normalizeInfoWeekResponse,
|
||||
normalizeTimeManagementServiceRequests,
|
||||
mergeTimeManagementServiceRequests,
|
||||
normalizeTimeManagementEntryRows,
|
||||
normalizeTimeManagementEntryRowSelection,
|
||||
getActivityRequestSrNumbers,
|
||||
normalizeActivityRequest,
|
||||
normalizeTaskTypeRequest,
|
||||
getTimeManagementTaskTypeOptions,
|
||||
getTimeManagementActivityOptions,
|
||||
findTimeManagementServiceRequest,
|
||||
findOptionValue,
|
||||
} = dependencies;
|
||||
|
||||
let requestCounter = 0;
|
||||
|
||||
function toggleTimeManagementDatePicker() {
|
||||
const selectedDate = getTimeManagementSelectedDate();
|
||||
const pickerDate = parseDatePreservingDateOnly(selectedDate);
|
||||
const fallback = Number.isNaN(pickerDate.getTime()) ? new Date() : pickerDate;
|
||||
|
||||
appState.timeManagementDatePicker = {
|
||||
isOpen: !appState.timeManagementDatePicker.isOpen,
|
||||
year: fallback.getFullYear(),
|
||||
month: fallback.getMonth(),
|
||||
};
|
||||
renderModal();
|
||||
}
|
||||
|
||||
function shiftTimeManagementDatePickerMonth(delta) {
|
||||
const picker = appState.timeManagementDatePicker;
|
||||
const nextDate = new Date(picker.year, picker.month + delta, 1);
|
||||
|
||||
appState.timeManagementDatePicker = {
|
||||
isOpen: true,
|
||||
year: nextDate.getFullYear(),
|
||||
month: nextDate.getMonth(),
|
||||
};
|
||||
renderModal();
|
||||
}
|
||||
|
||||
async function selectTimeManagementDate(selectedDate) {
|
||||
appState.timeManagementDatePicker = {
|
||||
...appState.timeManagementDatePicker,
|
||||
isOpen: false,
|
||||
};
|
||||
await loadTimeManagementData(selectedDate);
|
||||
}
|
||||
|
||||
async function shiftTimeManagementDateByWeeks(delta) {
|
||||
const selectedDate = getTimeManagementSelectedDate();
|
||||
const parsedDate = parseDatePreservingDateOnly(selectedDate);
|
||||
const baseDate = Number.isNaN(parsedDate.getTime())
|
||||
? new Date()
|
||||
: parsedDate;
|
||||
|
||||
baseDate.setDate(baseDate.getDate() + (Number(delta) || 0) * 7);
|
||||
appState.timeManagementDatePicker = {
|
||||
...appState.timeManagementDatePicker,
|
||||
isOpen: false,
|
||||
};
|
||||
await loadTimeManagementData(getDateInputValue(baseDate));
|
||||
}
|
||||
|
||||
function getTimeManagementSelectedDate() {
|
||||
return appState.timeManagementModal?.selectedDate || getDateInputValue(new Date());
|
||||
}
|
||||
|
||||
async function openTimeManagementModal() {
|
||||
const selectedDate = getStoredTimeManagementSelectedDate();
|
||||
|
||||
appState.timeManagementModal = createTimeManagementLoadingState(selectedDate);
|
||||
renderModal();
|
||||
await loadTimeManagementData(selectedDate);
|
||||
}
|
||||
|
||||
async function loadTimeManagementData(selectedDate) {
|
||||
const normalizedDate = cleanString(selectedDate) || getDateInputValue(new Date());
|
||||
const requestId = `${Date.now()}-${++requestCounter}`;
|
||||
|
||||
setStoredTimeManagementSelectedDate(normalizedDate);
|
||||
appState.timeManagementDatePicker = {
|
||||
...appState.timeManagementDatePicker,
|
||||
isOpen: false,
|
||||
};
|
||||
appState.timeManagementModal = {
|
||||
...(appState.timeManagementModal || {}),
|
||||
requestId,
|
||||
selectedDate: normalizedDate,
|
||||
status: "loading",
|
||||
errorMessage: "",
|
||||
};
|
||||
renderModal();
|
||||
|
||||
try {
|
||||
const resourcePartyId = getCurrentUserResourcePartyId();
|
||||
const taskTypePromise = fetchTaskTypeRequest();
|
||||
|
||||
if (!resourcePartyId) {
|
||||
throw new Error("resourceCurrentUser.resourcePartyId nao esta disponivel.");
|
||||
}
|
||||
|
||||
const weekInfoPayload = await comcipRepository.fetchInfoWeekRequest(
|
||||
normalizedDate
|
||||
);
|
||||
const weekDays = normalizeInfoWeekResponse(weekInfoPayload);
|
||||
const weekId = cleanString(weekDays[0]?.weekId);
|
||||
|
||||
if (!weekId) {
|
||||
throw new Error("WeekId nao encontrado no retorno de infoWeekRequest.");
|
||||
}
|
||||
|
||||
const timeEntryWeekUrl = comcipRepository.buildTimeEntryWeekUrl(
|
||||
resourcePartyId,
|
||||
weekId
|
||||
);
|
||||
const [srPayload, taskTypePayload, timeEntryWeekPayload] = await Promise.all([
|
||||
comcipRepository.fetchActiveServiceRequests(resourcePartyId, weekId),
|
||||
taskTypePromise,
|
||||
comcipRepository.fetchTimeEntryWeek(timeEntryWeekUrl),
|
||||
]);
|
||||
const timeEntryRows = normalizeTimeManagementEntryRows(
|
||||
timeEntryWeekPayload,
|
||||
weekDays
|
||||
);
|
||||
const serviceRequests = mergeTimeManagementServiceRequests(
|
||||
normalizeTimeManagementServiceRequests(srPayload),
|
||||
timeEntryRows
|
||||
);
|
||||
const activitySrNumbers = getActivityRequestSrNumbers(
|
||||
srPayload,
|
||||
serviceRequests
|
||||
);
|
||||
const activityRequest = await fetchCachedActivityRequest(activitySrNumbers);
|
||||
const activityRequestUrl = activityRequest.url;
|
||||
const activityPayload = activityRequest.payload;
|
||||
const activityOptionsBySr = normalizeActivityRequest(
|
||||
activityPayload,
|
||||
serviceRequests
|
||||
);
|
||||
const taskTypes = normalizeTaskTypeRequest(taskTypePayload);
|
||||
const rows = timeEntryRows;
|
||||
const selectedSrNumber = rows[0]?.selectedSrNumber || "";
|
||||
const normalizedRows = rows.map((row, index) =>
|
||||
normalizeTimeManagementEntryRowSelection(
|
||||
row,
|
||||
index,
|
||||
activityOptionsBySr,
|
||||
taskTypes
|
||||
)
|
||||
);
|
||||
|
||||
if (appState.timeManagementModal?.requestId !== requestId) {
|
||||
return;
|
||||
}
|
||||
|
||||
appState.timeManagementModal = {
|
||||
requestId,
|
||||
selectedDate: normalizedDate,
|
||||
status: "ready",
|
||||
errorMessage: "",
|
||||
weekId,
|
||||
weekDays,
|
||||
serviceRequests,
|
||||
selectedSrNumber,
|
||||
activityOptionsBySr,
|
||||
activityRequestUrl,
|
||||
activityRequestPayload: activityPayload,
|
||||
timeEntryRows: normalizedRows,
|
||||
selectedActivityValue: normalizedRows[0]?.selectedActivityValue || "",
|
||||
taskTypes,
|
||||
selectedTaskTypeValue: normalizedRows[0]?.selectedTaskTypeValue || "",
|
||||
highlightRowId: "",
|
||||
deletedTimeEntryIds: [],
|
||||
isSaving: false,
|
||||
saveErrorMessage: "",
|
||||
};
|
||||
renderModal();
|
||||
} catch (error) {
|
||||
if (appState.timeManagementModal?.requestId !== requestId) {
|
||||
return;
|
||||
}
|
||||
|
||||
appState.timeManagementModal = {
|
||||
...(appState.timeManagementModal || {}),
|
||||
requestId,
|
||||
selectedDate: normalizedDate,
|
||||
status: "error",
|
||||
errorMessage: getErrorMessage(error),
|
||||
};
|
||||
renderModal();
|
||||
}
|
||||
}
|
||||
|
||||
function createTimeManagementLoadingState(selectedDate) {
|
||||
return {
|
||||
requestId: "",
|
||||
selectedDate,
|
||||
status: "loading",
|
||||
errorMessage: "",
|
||||
weekId: "",
|
||||
weekDays: [],
|
||||
serviceRequests: [],
|
||||
selectedSrNumber: "",
|
||||
activityOptionsBySr: {},
|
||||
activityRequestUrl: "",
|
||||
activityRequestPayload: null,
|
||||
selectedActivityValue: "",
|
||||
taskTypes: [],
|
||||
selectedTaskTypeValue: "",
|
||||
timeEntryRows: [],
|
||||
highlightRowId: "",
|
||||
deletedTimeEntryIds: [],
|
||||
isSaving: false,
|
||||
saveErrorMessage: "",
|
||||
};
|
||||
}
|
||||
|
||||
function createBlankTimeManagementEntryRow(srNumber = "", source = "blank") {
|
||||
return {
|
||||
id: `row-${Date.now()}-${Math.random().toString(16).slice(2)}`,
|
||||
timeEntryId: "",
|
||||
selectedSrNumber: cleanString(srNumber),
|
||||
selectedActivityValue: "",
|
||||
selectedTaskTypeValue: "",
|
||||
dayHours: {},
|
||||
source,
|
||||
originalSignature: "",
|
||||
};
|
||||
}
|
||||
|
||||
function addTimeManagementEntryRow(type) {
|
||||
if (!appState.timeManagementModal) {
|
||||
return;
|
||||
}
|
||||
|
||||
const existingDuplicateRow = findExistingTimeManagementDuplicateRow(
|
||||
appState.timeManagementModal,
|
||||
type
|
||||
);
|
||||
|
||||
if (existingDuplicateRow) {
|
||||
highlightTimeManagementDuplicateRow(existingDuplicateRow.id);
|
||||
return;
|
||||
}
|
||||
|
||||
const srNumber = type === "non-service" ? "non-service-sr" : "";
|
||||
const nextRow = createBlankTimeManagementEntryRow(srNumber, "manual");
|
||||
const nextRows = [
|
||||
...getTimeManagementRows(appState.timeManagementModal),
|
||||
nextRow,
|
||||
];
|
||||
|
||||
appState.timeManagementModal = {
|
||||
...appState.timeManagementModal,
|
||||
timeEntryRows: nextRows,
|
||||
highlightRowId: "",
|
||||
saveErrorMessage: "",
|
||||
};
|
||||
appState.pendingFocusSelector = getTimeManagementComboboxFocusSelector(
|
||||
nextRow.id,
|
||||
type === "non-service" ? "taskType" : "sr"
|
||||
);
|
||||
renderModal();
|
||||
}
|
||||
|
||||
function removeTimeManagementEntryRow(rowId) {
|
||||
if (!appState.timeManagementModal) {
|
||||
return;
|
||||
}
|
||||
|
||||
const normalizedRowId = cleanString(rowId);
|
||||
const rows = getTimeManagementRows(appState.timeManagementModal);
|
||||
const removedRow = rows.find(
|
||||
(row) => cleanString(row?.id) === normalizedRowId
|
||||
);
|
||||
const removedTimeEntryId = cleanString(removedRow?.timeEntryId);
|
||||
const nextRows = rows.filter(
|
||||
(row) => cleanString(row?.id) !== normalizedRowId
|
||||
);
|
||||
const deletedTimeEntryIds = removedTimeEntryId
|
||||
? Array.from(
|
||||
new Set([
|
||||
...(appState.timeManagementModal.deletedTimeEntryIds || []),
|
||||
removedTimeEntryId,
|
||||
])
|
||||
)
|
||||
: appState.timeManagementModal.deletedTimeEntryIds || [];
|
||||
|
||||
appState.timeManagementModal = {
|
||||
...appState.timeManagementModal,
|
||||
timeEntryRows: nextRows,
|
||||
selectedSrNumber: nextRows[0]?.selectedSrNumber || "",
|
||||
selectedActivityValue: nextRows[0]?.selectedActivityValue || "",
|
||||
selectedTaskTypeValue: nextRows[0]?.selectedTaskTypeValue || "",
|
||||
highlightRowId: "",
|
||||
deletedTimeEntryIds,
|
||||
saveErrorMessage: "",
|
||||
};
|
||||
appState.pendingFocusSelector = getTimeManagementPostDeleteFocusSelector(
|
||||
nextRows,
|
||||
rows,
|
||||
normalizedRowId
|
||||
);
|
||||
renderModal();
|
||||
}
|
||||
|
||||
function getTimeManagementComboboxFocusSelector(rowId, field) {
|
||||
return `.arch-panel-extension-combobox input[data-row-id="${cssEscape(rowId)}"][data-combobox-field="${cssEscape(field)}"]`;
|
||||
}
|
||||
|
||||
function getTimeManagementPostDeleteFocusSelector(
|
||||
nextRows,
|
||||
previousRows,
|
||||
removedRowId
|
||||
) {
|
||||
if (!nextRows.length) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const removedIndex = previousRows.findIndex(
|
||||
(row) => cleanString(row?.id) === cleanString(removedRowId)
|
||||
);
|
||||
const focusIndex = Math.min(Math.max(removedIndex, 0), nextRows.length - 1);
|
||||
const focusRow = nextRows[focusIndex];
|
||||
|
||||
return focusRow?.id
|
||||
? `.arch-panel-extension-time-management-delete[data-row-id="${cssEscape(focusRow.id)}"]`
|
||||
: "";
|
||||
}
|
||||
|
||||
function getTimeManagementRowById(modal, rowId) {
|
||||
const rows = getTimeManagementRows(modal);
|
||||
const normalizedRowId = cleanString(rowId);
|
||||
|
||||
return (
|
||||
rows.find((row) => cleanString(row?.id) === normalizedRowId) ||
|
||||
rows[0] ||
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
function updateTimeManagementRows(modal, rowId, nextRow) {
|
||||
const rows = getTimeManagementRows(modal);
|
||||
const normalizedRowId = cleanString(rowId || nextRow?.id);
|
||||
|
||||
return rows.map((row, index) => {
|
||||
const isTarget = normalizedRowId
|
||||
? cleanString(row?.id) === normalizedRowId
|
||||
: index === 0;
|
||||
|
||||
return isTarget
|
||||
? {
|
||||
...row,
|
||||
...nextRow,
|
||||
id: row?.id || nextRow?.id || `row-${index + 1}`,
|
||||
}
|
||||
: row;
|
||||
});
|
||||
}
|
||||
|
||||
function updateTimeManagementSelectedSr(srNumber, rowId = "") {
|
||||
if (!appState.timeManagementModal) {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetRow = getTimeManagementRowById(appState.timeManagementModal, rowId);
|
||||
const selectedServiceRequest = findTimeManagementServiceRequest(
|
||||
appState.timeManagementModal,
|
||||
srNumber
|
||||
);
|
||||
const selectedSrNumber =
|
||||
selectedServiceRequest?.srNumber || cleanString(srNumber);
|
||||
const duplicateRow = findDuplicateTimeManagementSrRow(
|
||||
appState.timeManagementModal,
|
||||
selectedSrNumber,
|
||||
rowId
|
||||
);
|
||||
|
||||
if (duplicateRow) {
|
||||
highlightTimeManagementDuplicateRow(duplicateRow.id);
|
||||
return;
|
||||
}
|
||||
|
||||
const nextRow = {
|
||||
...(targetRow || createBlankTimeManagementEntryRow()),
|
||||
selectedSrNumber,
|
||||
selectedActivityValue: "",
|
||||
selectedTaskTypeValue: "",
|
||||
};
|
||||
const nextRows = updateTimeManagementRows(
|
||||
appState.timeManagementModal,
|
||||
rowId,
|
||||
nextRow
|
||||
);
|
||||
|
||||
appState.timeManagementModal = {
|
||||
...appState.timeManagementModal,
|
||||
timeEntryRows: nextRows,
|
||||
selectedSrNumber: nextRows[0]?.selectedSrNumber || selectedSrNumber,
|
||||
selectedActivityValue: nextRows[0]?.selectedActivityValue || "",
|
||||
selectedTaskTypeValue: nextRows[0]?.selectedTaskTypeValue || "",
|
||||
highlightRowId: "",
|
||||
saveErrorMessage: "",
|
||||
};
|
||||
renderModal();
|
||||
}
|
||||
|
||||
function updateTimeManagementField(fieldName, inputValue, rowId = "") {
|
||||
if (!appState.timeManagementModal) {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetRow = getTimeManagementRowById(appState.timeManagementModal, rowId);
|
||||
const normalizedInput = cleanString(inputValue);
|
||||
let value = normalizedInput;
|
||||
|
||||
if (fieldName === "selectedActivityValue") {
|
||||
const options = getTimeManagementActivityOptions(
|
||||
appState.timeManagementModal,
|
||||
targetRow?.selectedSrNumber || appState.timeManagementModal.selectedSrNumber
|
||||
);
|
||||
value = findOptionValue(options, normalizedInput) || normalizedInput;
|
||||
}
|
||||
|
||||
if (fieldName === "selectedTaskTypeValue") {
|
||||
const options = getTimeManagementTaskTypeOptions(
|
||||
appState.timeManagementModal,
|
||||
targetRow?.selectedSrNumber || appState.timeManagementModal.selectedSrNumber
|
||||
);
|
||||
value = findOptionValue(options, normalizedInput) || normalizedInput;
|
||||
|
||||
const duplicateRow = findDuplicateTimeManagementNonServiceTaskTypeRow(
|
||||
appState.timeManagementModal,
|
||||
value,
|
||||
rowId
|
||||
);
|
||||
|
||||
if (duplicateRow) {
|
||||
highlightTimeManagementDuplicateRow(duplicateRow.id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const nextRows = updateTimeManagementRows(appState.timeManagementModal, rowId, {
|
||||
...(targetRow || createBlankTimeManagementEntryRow()),
|
||||
[fieldName]: value,
|
||||
});
|
||||
|
||||
appState.timeManagementModal = {
|
||||
...appState.timeManagementModal,
|
||||
timeEntryRows: nextRows,
|
||||
[fieldName]: value,
|
||||
highlightRowId: "",
|
||||
saveErrorMessage: "",
|
||||
};
|
||||
}
|
||||
|
||||
function findDuplicateTimeManagementSrRow(modal, srNumber, currentRowId = "") {
|
||||
const normalizedSrNumber = normalizeString(srNumber);
|
||||
const normalizedCurrentRowId = cleanString(currentRowId);
|
||||
|
||||
if (!normalizedSrNumber || isNonServiceRequestSrNumber(srNumber)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
getTimeManagementRows(modal).find((row) => {
|
||||
return (
|
||||
cleanString(row?.id) !== normalizedCurrentRowId &&
|
||||
normalizeString(row?.selectedSrNumber) === normalizedSrNumber
|
||||
);
|
||||
}) || null
|
||||
);
|
||||
}
|
||||
|
||||
function findExistingTimeManagementDuplicateRow(modal, type) {
|
||||
const seen = new Map();
|
||||
|
||||
for (const row of getTimeManagementRows(modal)) {
|
||||
const rowId = cleanString(row?.id);
|
||||
let key = "";
|
||||
|
||||
if (type === "non-service") {
|
||||
if (!isNonServiceRequestSrNumber(row?.selectedSrNumber)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
key = normalizeString(row?.selectedTaskTypeValue);
|
||||
} else {
|
||||
if (isNonServiceRequestSrNumber(row?.selectedSrNumber)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
key = normalizeString(row?.selectedSrNumber);
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (seen.has(key)) {
|
||||
return (
|
||||
getTimeManagementRows(modal).find(
|
||||
(candidate) => cleanString(candidate?.id) === seen.get(key)
|
||||
) || row
|
||||
);
|
||||
}
|
||||
|
||||
seen.set(key, rowId);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function findDuplicateTimeManagementNonServiceTaskTypeRow(
|
||||
modal,
|
||||
taskTypeValue,
|
||||
currentRowId = ""
|
||||
) {
|
||||
const normalizedTaskTypeValue = normalizeString(taskTypeValue);
|
||||
const normalizedCurrentRowId = cleanString(currentRowId);
|
||||
|
||||
if (!normalizedTaskTypeValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const currentRow = getTimeManagementRowById(modal, currentRowId);
|
||||
|
||||
if (!isNonServiceRequestSrNumber(currentRow?.selectedSrNumber)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
getTimeManagementRows(modal).find((row) => {
|
||||
return (
|
||||
cleanString(row?.id) !== normalizedCurrentRowId &&
|
||||
isNonServiceRequestSrNumber(row?.selectedSrNumber) &&
|
||||
normalizeString(row?.selectedTaskTypeValue) === normalizedTaskTypeValue
|
||||
);
|
||||
}) || null
|
||||
);
|
||||
}
|
||||
|
||||
function highlightTimeManagementDuplicateRow(rowId) {
|
||||
const normalizedRowId = cleanString(rowId);
|
||||
|
||||
if (!appState.timeManagementModal || !normalizedRowId) {
|
||||
return;
|
||||
}
|
||||
|
||||
appState.pendingTimeManagementHighlightRowId = normalizedRowId;
|
||||
appState.timeManagementModal = {
|
||||
...appState.timeManagementModal,
|
||||
highlightRowId: normalizedRowId,
|
||||
};
|
||||
renderModal();
|
||||
}
|
||||
|
||||
function updateTimeManagementDayHours(rowId, dateKey, inputValue) {
|
||||
if (!appState.timeManagementModal) {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetRow = getTimeManagementRowById(appState.timeManagementModal, rowId);
|
||||
const nextRow = {
|
||||
...(targetRow || createBlankTimeManagementEntryRow()),
|
||||
dayHours: {
|
||||
...(targetRow?.dayHours || {}),
|
||||
[cleanString(dateKey)]: cleanString(inputValue),
|
||||
},
|
||||
};
|
||||
|
||||
appState.timeManagementModal = {
|
||||
...appState.timeManagementModal,
|
||||
timeEntryRows: updateTimeManagementRows(
|
||||
appState.timeManagementModal,
|
||||
rowId,
|
||||
nextRow
|
||||
),
|
||||
highlightRowId: "",
|
||||
saveErrorMessage: "",
|
||||
};
|
||||
renderModal();
|
||||
}
|
||||
|
||||
async function saveTimeManagementChanges() {
|
||||
const modal = appState.timeManagementModal;
|
||||
|
||||
if (!modal || modal.isSaving || !isTimeManagementSaveEnabled(modal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
appState.timeManagementModal = {
|
||||
...modal,
|
||||
isSaving: true,
|
||||
saveErrorMessage: "",
|
||||
};
|
||||
renderModal();
|
||||
|
||||
try {
|
||||
const resourceId = getCurrentUserResourcePartyId();
|
||||
const weekId = cleanString(modal.weekId);
|
||||
|
||||
if (!resourceId) {
|
||||
throw new Error("resourceCurrentUser.resourcePartyId nao esta disponivel.");
|
||||
}
|
||||
|
||||
if (!weekId) {
|
||||
throw new Error("WeekId nao encontrado para gravacao do apontamento.");
|
||||
}
|
||||
|
||||
const changes = getTimeManagementPendingChanges(modal);
|
||||
const baseUrl = COMCIP_REQUEST.timeEntriesUrl;
|
||||
const updatedPayload = changes.updatedRows.map((row) =>
|
||||
createTimeManagementSavePayload(row, modal.weekDays, weekId, resourceId, {
|
||||
includeId: true,
|
||||
})
|
||||
);
|
||||
const newPayload = changes.newRows.map((row) =>
|
||||
createTimeManagementSavePayload(row, modal.weekDays, weekId, resourceId)
|
||||
);
|
||||
|
||||
for (const timeEntryId of changes.deletedIds) {
|
||||
await comcipRepository.mutateComcipPayload(
|
||||
"DELETE",
|
||||
`${baseUrl}/${encodeURIComponent(timeEntryId)}`,
|
||||
null,
|
||||
"timeEntryDelete"
|
||||
);
|
||||
}
|
||||
|
||||
if (updatedPayload.length) {
|
||||
await comcipRepository.mutateComcipPayload(
|
||||
"PUT",
|
||||
baseUrl,
|
||||
updatedPayload,
|
||||
"timeEntryUpdate"
|
||||
);
|
||||
}
|
||||
|
||||
if (newPayload.length) {
|
||||
await comcipRepository.mutateComcipPayload(
|
||||
"POST",
|
||||
baseUrl,
|
||||
newPayload,
|
||||
"timeEntryCreate"
|
||||
);
|
||||
}
|
||||
|
||||
await loadTimeManagementData(
|
||||
modal.selectedDate || getDateInputValue(new Date())
|
||||
);
|
||||
} catch (error) {
|
||||
appState.timeManagementModal = {
|
||||
...(appState.timeManagementModal || modal),
|
||||
isSaving: false,
|
||||
saveErrorMessage: getErrorMessage(error),
|
||||
};
|
||||
renderModal();
|
||||
}
|
||||
}
|
||||
|
||||
function selectTimeManagementComboboxOption(field, value, rowId = "") {
|
||||
if (field === "sr") {
|
||||
updateTimeManagementSelectedSr(value || "", rowId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (field === "activity") {
|
||||
updateTimeManagementField("selectedActivityValue", value || "", rowId);
|
||||
renderModal();
|
||||
return;
|
||||
}
|
||||
|
||||
if (field === "taskType") {
|
||||
updateTimeManagementField("selectedTaskTypeValue", value || "", rowId);
|
||||
renderModal();
|
||||
}
|
||||
}
|
||||
|
||||
function filterTimeManagementCombobox(input) {
|
||||
const query = normalizeString(input.value);
|
||||
const combobox = input.closest(".arch-panel-extension-combobox");
|
||||
|
||||
if (!combobox) {
|
||||
return;
|
||||
}
|
||||
|
||||
const options = Array.from(
|
||||
combobox.querySelectorAll(".arch-panel-extension-combobox-option")
|
||||
);
|
||||
|
||||
for (const option of options) {
|
||||
const searchText = normalizeString(option.getAttribute("data-search") || "");
|
||||
option.hidden = Boolean(query) && !searchText.includes(query);
|
||||
}
|
||||
|
||||
setActiveTimeManagementComboboxOption(
|
||||
combobox,
|
||||
getVisibleTimeManagementComboboxOptions(combobox).find((option) =>
|
||||
option.classList.contains("is-selected")
|
||||
) || getVisibleTimeManagementComboboxOptions(combobox)[0]
|
||||
);
|
||||
}
|
||||
|
||||
function handleTimeManagementComboboxKeydown(event, input) {
|
||||
const combobox = input.closest(".arch-panel-extension-combobox");
|
||||
|
||||
if (!combobox) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.key === "Escape") {
|
||||
clearActiveTimeManagementComboboxOption(combobox);
|
||||
input.blur();
|
||||
return;
|
||||
}
|
||||
|
||||
const visibleOptions = getVisibleTimeManagementComboboxOptions(combobox);
|
||||
|
||||
if (!visibleOptions.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if (event.key === "Enter") {
|
||||
const activeOption =
|
||||
visibleOptions.find((option) => option.classList.contains("is-active")) ||
|
||||
visibleOptions[0];
|
||||
activeOption.click();
|
||||
return;
|
||||
}
|
||||
|
||||
const activeIndex = visibleOptions.findIndex((option) =>
|
||||
option.classList.contains("is-active")
|
||||
);
|
||||
const selectedIndex = visibleOptions.findIndex((option) =>
|
||||
option.classList.contains("is-selected")
|
||||
);
|
||||
const baseIndex = activeIndex >= 0 ? activeIndex : selectedIndex;
|
||||
let nextIndex = 0;
|
||||
|
||||
if (event.key === "ArrowDown") {
|
||||
nextIndex = baseIndex >= 0 ? baseIndex + 1 : 0;
|
||||
} else if (event.key === "ArrowUp") {
|
||||
nextIndex = baseIndex >= 0 ? baseIndex - 1 : visibleOptions.length - 1;
|
||||
} else if (event.key === "Home") {
|
||||
nextIndex = 0;
|
||||
} else if (event.key === "End") {
|
||||
nextIndex = visibleOptions.length - 1;
|
||||
}
|
||||
|
||||
if (nextIndex < 0) {
|
||||
nextIndex = visibleOptions.length - 1;
|
||||
} else if (nextIndex >= visibleOptions.length) {
|
||||
nextIndex = 0;
|
||||
}
|
||||
|
||||
setActiveTimeManagementComboboxOption(combobox, visibleOptions[nextIndex]);
|
||||
}
|
||||
|
||||
function getVisibleTimeManagementComboboxOptions(combobox) {
|
||||
return Array.from(
|
||||
combobox.querySelectorAll(".arch-panel-extension-combobox-option")
|
||||
).filter((option) => !option.hidden);
|
||||
}
|
||||
|
||||
function setActiveTimeManagementComboboxOption(combobox, option) {
|
||||
clearActiveTimeManagementComboboxOption(combobox);
|
||||
|
||||
if (!option) {
|
||||
return;
|
||||
}
|
||||
|
||||
option.classList.add("is-active");
|
||||
combobox
|
||||
.querySelector("input[data-combobox-field]")
|
||||
?.setAttribute("aria-activedescendant", option.id || "");
|
||||
option.scrollIntoView({ block: "nearest" });
|
||||
}
|
||||
|
||||
function clearActiveTimeManagementComboboxOption(combobox) {
|
||||
combobox
|
||||
.querySelectorAll(".arch-panel-extension-combobox-option.is-active")
|
||||
.forEach((option) => option.classList.remove("is-active"));
|
||||
combobox
|
||||
.querySelector("input[data-combobox-field]")
|
||||
?.removeAttribute("aria-activedescendant");
|
||||
}
|
||||
|
||||
async function fetchCachedActivityRequest(srNumbers) {
|
||||
const cacheKey = getActivityRequestCacheKey(srNumbers);
|
||||
|
||||
if (!cacheKey) {
|
||||
return {
|
||||
url: "",
|
||||
payload: null,
|
||||
};
|
||||
}
|
||||
|
||||
const cachedRequest = appState.timeManagementActivityCache.get(cacheKey);
|
||||
|
||||
if (cachedRequest?.payload) {
|
||||
return cachedRequest;
|
||||
}
|
||||
|
||||
if (cachedRequest?.promise) {
|
||||
return cachedRequest.promise;
|
||||
}
|
||||
|
||||
const requestPromise = comcipRepository
|
||||
.fetchActivityRequest(srNumbers)
|
||||
.then((result) => {
|
||||
appState.timeManagementActivityCache.set(cacheKey, {
|
||||
url: result.url,
|
||||
payload: result.payload,
|
||||
});
|
||||
|
||||
return result;
|
||||
})
|
||||
.catch((error) => {
|
||||
appState.timeManagementActivityCache.delete(cacheKey);
|
||||
throw error;
|
||||
});
|
||||
|
||||
appState.timeManagementActivityCache.set(cacheKey, {
|
||||
promise: requestPromise,
|
||||
});
|
||||
|
||||
return requestPromise;
|
||||
}
|
||||
|
||||
function getActivityRequestCacheKey(srNumbers) {
|
||||
const normalizedSrNumbers = (srNumbers || [])
|
||||
.map((srNumber) => cleanString(srNumber).toUpperCase())
|
||||
.filter((srNumber) => /^SR\d+$/i.test(srNumber))
|
||||
.sort();
|
||||
|
||||
return normalizedSrNumbers.join("|");
|
||||
}
|
||||
|
||||
async function fetchTaskTypeRequest() {
|
||||
if (appState.taskTypeCache.promise) {
|
||||
return appState.taskTypeCache.promise;
|
||||
}
|
||||
|
||||
appState.taskTypeCache.promise = (async () => {
|
||||
return readCachedTaskTypePayload().catch(() => null);
|
||||
})().finally(() => {
|
||||
appState.taskTypeCache.promise = null;
|
||||
});
|
||||
|
||||
return appState.taskTypeCache.promise;
|
||||
}
|
||||
|
||||
async function refreshTaskTypeCache() {
|
||||
const payload = await comcipRepository.fetchTaskTypePayload();
|
||||
await writeCachedTaskTypePayload(payload);
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
function getCurrentUserResourcePartyId() {
|
||||
const resourceCurrentUser = appState.dataset?.resourceCurrentUser;
|
||||
const directResourcePartyId = cleanString(
|
||||
getFieldValue(resourceCurrentUser, [
|
||||
"resourcePartyId",
|
||||
"ResourcePartyId",
|
||||
"ResourcePartyID",
|
||||
"partyId",
|
||||
"PartyId",
|
||||
])
|
||||
);
|
||||
|
||||
if (directResourcePartyId) {
|
||||
return directResourcePartyId;
|
||||
}
|
||||
|
||||
const candidates = Array.isArray(resourceCurrentUser)
|
||||
? resourceCurrentUser
|
||||
: extractArray(resourceCurrentUser, ["items", "data", "results", "content"]);
|
||||
const source = candidates[0] || resourceCurrentUser;
|
||||
|
||||
return cleanString(
|
||||
getFieldValue(source, [
|
||||
"resourcePartyId",
|
||||
"ResourcePartyId",
|
||||
"ResourcePartyID",
|
||||
"partyId",
|
||||
"PartyId",
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
return Object.freeze({
|
||||
toggleTimeManagementDatePicker,
|
||||
shiftTimeManagementDatePickerMonth,
|
||||
selectTimeManagementDate,
|
||||
shiftTimeManagementDateByWeeks,
|
||||
openTimeManagementModal,
|
||||
loadTimeManagementData,
|
||||
addTimeManagementEntryRow,
|
||||
removeTimeManagementEntryRow,
|
||||
updateTimeManagementSelectedSr,
|
||||
updateTimeManagementField,
|
||||
updateTimeManagementDayHours,
|
||||
saveTimeManagementChanges,
|
||||
selectTimeManagementComboboxOption,
|
||||
filterTimeManagementCombobox,
|
||||
handleTimeManagementComboboxKeydown,
|
||||
refreshTaskTypeCache,
|
||||
});
|
||||
}
|
||||
|
||||
globalThis.ArchPanelManageTimeController = Object.freeze({
|
||||
create,
|
||||
});
|
||||
})();
|
||||
Reference in New Issue
Block a user