UNPKG

@ministryofjustice/hmpps-digital-prison-reporting-frontend

Version:

The Digital Prison Reporting Frontend contains templates and code to help display data effectively in UI applications.

218 lines (215 loc) 8.74 kB
import { RequestStatus } from '../../../../types/UserReports.js'; import { ReportStoreService } from '../../../../services/reportStoreService.js'; import { getDpdPathSuffix } from '../../../../utils/urlHelper.js'; import logger from '../../../../utils/logger.js'; class RequestedReportService extends ReportStoreService { constructor(userDataStore) { super(userDataStore); } async addReport(userId, reportStateData) { const userConfig = await this.getState(userId); userConfig.requestedReports.unshift(reportStateData); await this.saveState(userId, userConfig); } async removeReport(executionId, userId) { const userConfig = await this.getState(userId); const index = this.findIndexByExecutionId(executionId, userConfig.requestedReports); if (index === -1) return; userConfig.requestedReports.splice(index, 1); await this.saveState(userId, userConfig); } async getReportByExecutionId(id, userId) { const userConfig = await this.getState(userId); return userConfig.requestedReports.find(report => report.executionId === id); } async getReportByTableId(id, userId) { const userConfig = await this.getState(userId); return userConfig.requestedReports.find(report => report.tableId === id); } async getAllReports(userId) { const userConfig = await this.getState(userId); return userConfig.requestedReports; } async updateLastViewed(id, userId) { const userConfig = await this.getState(userId); const index = this.findIndexByExecutionId(id, userConfig.requestedReports); if (index === -1) { return; } const report = userConfig.requestedReports[index]; report.timestamp.lastViewed = new Date(); userConfig.requestedReports[index] = report; await this.saveState(userId, userConfig); } async updateStatus(id, userId, status, errorMessage) { const userConfig = await this.getState(userId); const index = this.findIndexByExecutionId(id, userConfig.requestedReports); if (index === -1) { return; } let report = userConfig.requestedReports[index]; if (report) report = this.updateDataByStatus(report, status, errorMessage); userConfig.requestedReports[index] = report; await this.saveState(userId, userConfig); } async setToExpired(id, userId) { const userConfig = await this.getState(userId); const index = this.findIndexByExecutionId(id, userConfig.requestedReports); if (index === -1) { return; } await this.saveExpiredState(userConfig, index, userId); } async setToExpiredByTableId(id, userId) { const userConfig = await this.getState(userId); const index = this.findIndexByTableId(id, userConfig.recentlyViewedReports); if (index !== -1) { await this.saveExpiredState(userConfig, index, userId); } else { logger.info(`Unable to expire requested report - ${id} not found in state`); } } async saveExpiredState(userConfig, index, userId) { const report = userConfig.requestedReports[index]; if (!report || report.status === RequestStatus.EXPIRED) { return; } const updated = { ...report, status: RequestStatus.EXPIRED, timestamp: { ...report.timestamp, expired: new Date(), }, }; userConfig.requestedReports[index] = updated; await this.saveState(userId, userConfig); } /** * Removes old stale data from requested reports * - When a report is viewed it is given a lastViewed ts. * - If the requested data has a lastViewed ts and * - has no corresponding viewed entry * - then that requested data is stale and can be removed * * @param {string} userId * @param {StoredReportData[]} viewedReports * @memberof RequestedReportService */ async cleanList(userId, viewedReports) { const userConfig = await this.getState(userId); const allRequested = userConfig.requestedReports; const viewedRequestedReports = allRequested.filter(requestedReport => { return requestedReport.timestamp.lastViewed !== undefined; }); let count = 0; await Promise.all(viewedRequestedReports.map(async (viewedRequestReport) => { const { executionId } = viewedRequestReport; const viewedReport = viewedReports.find(report => { const { executionId: viewedExecutionId } = report; return viewedExecutionId && viewedExecutionId === executionId; }); if (!viewedReport && executionId) { await this.removeReport(executionId, userId); count += 1; } })); if (count > 0) logger.info(`RequestedReports: Removed ${count} stale reports from list`); } setReportUrl(report) { const { tableId, url, dpdPathFromQuery, dataProductDefinitionsPath, type } = report; let pathname; let fullUrl; if (url && url.polling?.pathname) { let reportUrlArr = Array.from(new Array(2)); reportUrlArr = url.polling.pathname.replace('/request-report', '/view-report/async').split('/'); reportUrlArr[reportUrlArr.length - 2] = tableId; reportUrlArr[reportUrlArr.length - 1] = type; const reportUrl = reportUrlArr.join('/'); const search = url.report?.search ? url.report.search : ''; const dpdPath = dataProductDefinitionsPath && dpdPathFromQuery ? `${getDpdPathSuffix(dataProductDefinitionsPath)}` : ''; const searchPath = search || dpdPath; pathname = `${reportUrl}${searchPath}`; fullUrl = `${url.origin}${pathname}`; } return { pathname, fullUrl, }; } updateDataByStatus(report, status, errorMessage) { const ts = new Date(); if (status) report.status = status; switch (status) { case RequestStatus.FAILED: report.timestamp.failed = ts; if (errorMessage) report.errorMessage = errorMessage; break; case RequestStatus.EXPIRED: report.timestamp.expired = ts; break; case RequestStatus.ABORTED: report.timestamp.aborted = ts; break; case RequestStatus.FINISHED: { report.timestamp.completed = ts; if (report.url) { report.url.report = { ...report.url.report, ...this.setReportUrl(report), }; } break; } case RequestStatus.SUBMITTED: report.timestamp.requested = ts; break; case RequestStatus.STARTED: case RequestStatus.PICKED: break; default: report.timestamp.lastViewed = ts; break; } return report; } /** * Remove duplicate report from state * * @param {RequestedReport[]} reports * @return {*} {RequestedReport[]} * @memberof RequestedReportService */ removeDuplicateRequestedReports = async (userId) => { const reports = await this.getAllReports(userId); if (reports.length < 2) { return []; } // Get the newest report const latest = reports[0]; const latestFilters = latest.url?.request?.search?.trim() ?? ''; const duplicates = reports.slice(1).filter(report => { if (!report.executionId) { return false; } const sameReport = report.reportId === latest.reportId && report.id === latest.id; if (!sameReport) { return false; } const reportFilters = report.url?.request?.search?.trim() ?? ''; return report.executionId === latest.executionId || reportFilters === latestFilters; }); await Promise.all(duplicates.map(({ executionId }) => { return this.removeReport(executionId || '', userId); })); return duplicates.map(({ executionId }) => executionId || ''); }; } export { RequestedReportService, RequestedReportService as default }; //# sourceMappingURL=service.js.map