@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
JavaScript
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