Files
ncd-fe/packages/pl-fe/src/reducers/admin.ts
2025-02-25 01:56:50 +01:00

134 lines
4.3 KiB
TypeScript

import omit from 'lodash/omit';
import { create } from 'mutative';
import {
ADMIN_CONFIG_FETCH_SUCCESS,
ADMIN_CONFIG_UPDATE_SUCCESS,
ADMIN_REPORTS_FETCH_SUCCESS,
ADMIN_REPORT_PATCH_SUCCESS,
ADMIN_USERS_FETCH_SUCCESS,
ADMIN_USER_DELETE_SUCCESS,
ADMIN_USER_APPROVE_SUCCESS,
ADMIN_USER_REJECT_SUCCESS,
type AdminActions,
} from 'pl-fe/actions/admin';
import { normalizeAdminReport, type AdminReport as MinifiedReport } from 'pl-fe/normalizers/admin-report';
import type { AdminAccount, AdminGetAccountsParams, AdminReport } from 'pl-api';
import type { Config } from 'pl-fe/utils/config-db';
interface State {
reports: Record<string, MinifiedReport>;
openReports: Array<string>;
users: Record<string, MinifiedUser>;
latestUsers: Array<string>;
awaitingApproval: Array<string>;
configs: Array<Config>;
needsReboot: boolean;
}
const initialState: State = {
reports: {},
openReports: [],
users: {},
latestUsers: [],
awaitingApproval: [],
configs: [],
needsReboot: false,
};
const toIds = (items: any[]) => items.map(item => item.id);
const maybeImportUnapproved = (state: State, users: Array<AdminAccount>, params?: AdminGetAccountsParams) => {
if (params?.origin === 'local' && params.status === 'pending') {
const newIds = toIds(users);
state.awaitingApproval = [...new Set([...state.awaitingApproval, ...newIds])];
} else {
return state;
}
};
const maybeImportLatest = (state: State, users: Array<AdminAccount>, params?: AdminGetAccountsParams) => {
if (params?.origin === 'local' && params.status === 'active') {
const newIds = toIds(users);
state.latestUsers = newIds;
}
};
const minifyUser = (user: AdminAccount) => omit(user, ['account']);
type MinifiedUser = ReturnType<typeof minifyUser>;
const importUsers = (state: State, users: Array<AdminAccount>, params?: AdminGetAccountsParams) => {
maybeImportUnapproved(state, users, params);
maybeImportLatest(state, users, params);
users.forEach(user => {
const normalizedUser = minifyUser(user);
state.users[user.id] = normalizedUser;
});
};
const deleteUser = (state: State, accountId: string) => {
state.awaitingApproval = state.awaitingApproval.filter(id => id !== accountId);
delete state.users[accountId];
};
const approveUser = (state: State, user: AdminAccount) => {
const normalizedUser = minifyUser(user);
state.awaitingApproval = state.awaitingApproval.filter(id => id !== user.id);
state.users[user.id] = normalizedUser;
};
const importReports = (state: State, reports: Array<AdminReport>) => {
reports.forEach(report => {
const minifiedReport = normalizeAdminReport(report);
if (!minifiedReport.action_taken) {
state.openReports = [...new Set([...state.openReports, report.id])];
}
state.reports[report.id] = minifiedReport;
});
};
const handleReportDiffs = (state: State, report: AdminReport) => {
// Note: the reports here aren't full report objects
// hence the need for a new function.
switch (report.action_taken) {
case false:
state.openReports = [...new Set([...state.openReports, report.id])];
break;
default:
state.openReports = state.openReports.filter(id => id !== report.id);
}
};
const importConfigs = (state: State, configs: any) => {
state.configs = configs;
};
const admin = (state = initialState, action: AdminActions): State => {
switch (action.type) {
case ADMIN_CONFIG_FETCH_SUCCESS:
case ADMIN_CONFIG_UPDATE_SUCCESS:
return create(state, (draft) => importConfigs(draft, action.configs));
case ADMIN_REPORTS_FETCH_SUCCESS:
return create(state, (draft) => importReports(draft, action.reports));
case ADMIN_REPORT_PATCH_SUCCESS:
return create(state, (draft) => handleReportDiffs(draft, action.report));
case ADMIN_USERS_FETCH_SUCCESS:
return create(state, (draft) => importUsers(draft, action.users, action.params));
case ADMIN_USER_DELETE_SUCCESS:
return create(state, (draft) => deleteUser(draft, action.accountId));
case ADMIN_USER_APPROVE_SUCCESS:
return create(state, (draft) => approveUser(draft, action.user));
case ADMIN_USER_REJECT_SUCCESS:
return create(state, (draft) => {
draft.awaitingApproval = draft.awaitingApproval.filter(value => value !== action.accountId);
});
default:
return state;
}
};
export { admin as default };