Skip to content

Commit

Permalink
Add change history to area search (#467)
Browse files Browse the repository at this point in the history
  • Loading branch information
henrinie-nc authored Mar 13, 2024
1 parent 9709134 commit ab36159
Show file tree
Hide file tree
Showing 10 changed files with 215 additions and 1 deletion.
130 changes: 130 additions & 0 deletions src/areaSearch/components/AreaSearchApplicationAuditLog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
//@flow
import React, {Fragment, PureComponent} from 'react';
import {connect} from 'react-redux';
import isEmpty from 'lodash/isEmpty';

import AuditLogTable from '$components/auditLog/AuditLogTable';
import Divider from '$components/content/Divider';
import Loader from '$components/loader/Loader';
import LoaderWrapper from '$components/loader/LoaderWrapper';
import Pagination from '$components/table/Pagination';
import TableWrapper from '$components/table/TableWrapper';
import Title from '$components/content/Title';
import {fetchAuditLogByAreaSearch} from '$src/auditLog/actions';
import {LIST_TABLE_PAGE_SIZE} from '$src/constants';
import {
AreaSearchFieldPaths,
AreaSearchFieldTitles,
} from '$src/areaSearch/enums';
import {getApiResponseCount, getApiResponseMaxPage, getApiResponseResults} from '$util/helpers';
import {getUiDataLeaseKey} from '$src/uiData/helpers';
import {getAuditLogByAreaSearch, getIsFetchingByAreaSearch} from '$src/auditLog/selectors';
import {getIsEditMode} from '$src/leases/selectors';

import type {AuditLogList} from '$src/auditLog/types';

type Props = {
auditLogList: AuditLogList,
fetchAuditLogByAreaSearch: Function,
isEditMode: boolean,
isFetching: boolean,
areaSearchId: string,
}

type State = {
activePage: number,
auditLogItems: Array<Object>,
auditLogList: AuditLogList,
count: number,
maxPage: number,
}

class AreaSearchApplicationAuditLog extends PureComponent<Props, State> {
state = {
activePage: 1,
auditLogItems: [],
auditLogList: {},
count: 0,
maxPage: 0,
}
componentDidMount() {
const {fetchAuditLogByAreaSearch, areaSearchId} = this.props;

fetchAuditLogByAreaSearch({
id: areaSearchId,
limit: LIST_TABLE_PAGE_SIZE,
});
}

static getDerivedStateFromProps(props: Props, state: State) {
const newState = {};

if(props.auditLogList !== state.auditLogList) {
newState.auditLogList = props.auditLogList;
newState.auditLogItems = getApiResponseResults(props.auditLogList);
newState.count = getApiResponseCount(props.auditLogList);
newState.maxPage = getApiResponseMaxPage(props.auditLogList, LIST_TABLE_PAGE_SIZE);
}

return !isEmpty(newState) ? newState : null;
}

handlePageClick = (page: number) => {
const {fetchAuditLogByAreaSearch, areaSearchId} = this.props;

this.setState({activePage: page}, () => {
const payload: any = {
id: areaSearchId,
limit: LIST_TABLE_PAGE_SIZE,
};

if(page > 1) {
payload.offset = (page - 1) * LIST_TABLE_PAGE_SIZE;
}

fetchAuditLogByAreaSearch(payload);
});
}

render() {
const {isEditMode, isFetching} = this.props;
const {activePage, auditLogItems, maxPage} = this.state;

return(
<Fragment>
<Title enableUiDataEdit={isEditMode} uiDataKey={getUiDataLeaseKey(AreaSearchFieldPaths.AUDIT_LOG)}>
{AreaSearchFieldTitles.AUDIT_LOG}
</Title>
<Divider />

<TableWrapper>
{isFetching &&
<LoaderWrapper className='relative-overlay-wrapper'><Loader isLoading={isFetching} /></LoaderWrapper>
}

<AuditLogTable
items={auditLogItems}
/>
<Pagination
activePage={activePage}
maxPage={maxPage}
onPageClick={this.handlePageClick}
/>
</TableWrapper>
</Fragment>
);
}
}

export default connect(
(state, props: Props) => {
return {
auditLogList: getAuditLogByAreaSearch(state, props.areaSearchId),
isEditMode: getIsEditMode(state),
isFetching: getIsFetchingByAreaSearch(state, props.areaSearchId),
};
},
{
fetchAuditLogByAreaSearch,
}
)(AreaSearchApplicationAuditLog);
3 changes: 2 additions & 1 deletion src/areaSearch/components/AreaSearchApplicationPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import ConfirmationModal from '$components/modal/ConfirmationModal';
import AreaSearchApplication from '$src/areaSearch/components/AreaSearchApplication';
import {withAreaSearchAttributes} from '$components/attributes/AreaSearchAttributes';
import AreaSearchApplicationEdit from '$src/areaSearch/components/AreaSearchApplicationEdit';
import AreaSearchApplicationAuditLog from '$src/areaSearch/components/AreaSearchApplicationAuditLog';
import {fetchApplicantInfoCheckAttributes, fetchFormAttributes} from '$src/application/actions';
import {
getFormAttributes,
Expand Down Expand Up @@ -503,7 +504,7 @@ class AreaSearchApplicationPage extends Component<Props, State> {

<TabPane>
<ContentContainer>
{'Muutoshistoria'}
<AreaSearchApplicationAuditLog areaSearchId={currentAreaSearch.id}/>
</ContentContainer>
</TabPane>

Expand Down
2 changes: 2 additions & 0 deletions src/areaSearch/enums.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
export const AreaSearchFieldPaths = {
INTENDED_USE: 'intended_use',
LESSOR: 'lessor',
AUDIT_LOG: 'audit_log',
};

export const AreaSearchFieldTitles = {
Expand All @@ -19,4 +20,5 @@ export const AreaSearchFieldTitles = {
DECLINE_REASON: 'Hylkäämisen syy',
PREPARER_NOTE: 'Käsittelytietojen huomautus',
STATUS_NOTES: 'Käsittelijän muistiinpanot',
AUDIT_LOG: 'Muutoshistoria',
};
1 change: 1 addition & 0 deletions src/areaSearch/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type AreaSearchState = {
};

export type AreaSearch = Object;
export type AreaSearchId = number;

export type FetchListAttributesAction = Action<'mvj/areaSearch/FETCH_LIST_ATTRIBUTES', void>;
export type ReceiveListAttributesAction = Action<'mvj/areaSearch/RECEIVE_LIST_ATTRIBUTES', Attributes>;
Expand Down
13 changes: 13 additions & 0 deletions src/auditLog/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {createAction} from 'redux-actions';

import type {ContactId} from '$src/contacts/types';
import type {LeaseId} from '$src/leases/types';
import type {AreaSearchId} from '$src/areaSearch/types';
import type {
AuditLogListMap,
FetchAuditLogByContactAction,
Expand All @@ -11,6 +12,9 @@ import type {
FetchAuditLogByLeaseAction,
ReceiveAuditLogByLeaseAction,
NotFoundByLeaseAction,
FetchAuditLogByAreaSearchAction,
ReceiveAuditLogByAreaSearchAction,
NotFoundByAreaSearchAction
} from '$src/auditLog/types';

export const fetchAuditLogByContact = (contactId: ContactId): FetchAuditLogByContactAction =>
Expand All @@ -30,3 +34,12 @@ export const receiveAuditLogByLease = (payload: AuditLogListMap): ReceiveAuditLo

export const notFoundByLease = (leaseId: LeaseId): NotFoundByLeaseAction =>
createAction('mvj/auditLog/NOT_FOUND_BY_LEASE')(leaseId);

export const fetchAuditLogByAreaSearch = (query: Object): FetchAuditLogByAreaSearchAction =>
createAction('mvj/auditLog/FETCH_BY_AREASEARCH')(query);

export const receiveAuditLogByAreaSearch = (payload: AuditLogListMap): ReceiveAuditLogByAreaSearchAction =>
createAction('mvj/auditLog/RECEIVE_BY_AREASEARCH')(payload);

export const notFoundByAreaSearch = (areaSearchId: AreaSearchId): NotFoundByAreaSearchAction =>
createAction('mvj/auditLog/NOT_FOUND_BY_AREASEARCH')(areaSearchId);
27 changes: 27 additions & 0 deletions src/auditLog/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import type {
FetchAuditLogByLeaseAction,
ReceiveAuditLogByLeaseAction,
NotFoundByLeaseAction,
FetchAuditLogByAreaSearchAction,
NotFoundByAreaSearchAction,
ReceiveAuditLogByAreaSearchAction,
} from '$src/auditLog/types';

const isFetchingByContactReducer: Reducer<AuditLogIsFetchingMap> = handleActions({
Expand Down Expand Up @@ -58,9 +61,33 @@ const auditLogByLeaseReducer: Reducer<AuditLogListMap> = handleActions({
}),
}, {});

const isFetchingByAreaSearchReducer: Reducer<AuditLogIsFetchingMap> = handleActions({
['mvj/auditLog/FETCH_BY_AREASEARCH']: (state: AuditLogIsFetchingMap, {payload}: FetchAuditLogByAreaSearchAction) => ({
...state,
[payload.id]: true,
}),
['mvj/auditLog/RECEIVE_BY_AREASEARCH']: (state: AuditLogIsFetchingMap, {payload}: ReceiveAuditLogByAreaSearchAction) => ({
...state,
...Object.keys(payload).reduce((obj, key) => ({...obj, [key]: false}), {}),
}),
['mvj/auditLog/NOT_FOUND_BY_AREASEARCH']: (state: AuditLogIsFetchingMap, {payload: areaSearchId}: NotFoundByAreaSearchAction) => ({
...state,
[areaSearchId]: false,
}),
}, {});

const auditLogByAreaSearchReducer: Reducer<AuditLogListMap> = handleActions({
['mvj/auditLog/RECEIVE_BY_AREASEARCH']: (state: AuditLogListMap, {payload}: ReceiveAuditLogByAreaSearchAction) => ({
...state,
...payload,
}),
}, {});

export default combineReducers<Object, any>({
byContact: auditLogByContactReducer,
byLease: auditLogByLeaseReducer,
byAreaSearch: auditLogByAreaSearchReducer,
isFetchingByContact: isFetchingByContactReducer,
isFetchingByLease: isFetchingByLeaseReducer,
isFetchingByAreaSearch: isFetchingByAreaSearchReducer,
});
26 changes: 26 additions & 0 deletions src/auditLog/saga.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
notFoundByContact,
receiveAuditLogByLease,
notFoundByLease,
receiveAuditLogByAreaSearch,
notFoundByAreaSearch,
} from './actions';
import {fetchAuditLog} from './requests';

Expand Down Expand Up @@ -56,11 +58,35 @@ function* fetchAuditLogByLeaseSaga({payload}): Generator<any, any, any> {
}
}

function* fetchAuditLogByAreaSearchSaga({payload}): Generator<any, any, any> {
try {
const {response: {status: statusCode}, bodyAsJson} = yield call(fetchAuditLog, {
...payload,
type: 'areasearch',
});

switch (statusCode) {
case 200:
yield put(receiveAuditLogByAreaSearch({[payload.id.toString()]: bodyAsJson}));
break;
default:
console.error('Failed to fetch areasearch audit log');
yield put(notFoundByAreaSearch(payload.id));
break;
}
} catch (error) {
console.error('Failed to fetch areasearch audit log with error "%s"', error);
yield put(notFoundByAreaSearch(payload.id));
yield put(receiveError(error));
}
}

export default function*(): Generator<any, any, any> {
yield all([
fork(function*(): Generator<any, any, any> {
yield takeLatest('mvj/auditLog/FETCH_BY_CONTACT', fetchAuditLogByContactSaga);
yield takeLatest('mvj/auditLog/FETCH_BY_LEASE', fetchAuditLogByLeaseSaga);
yield takeLatest('mvj/auditLog/FETCH_BY_AREASEARCH', fetchAuditLogByAreaSearchSaga);
}),
]);
}
6 changes: 6 additions & 0 deletions src/auditLog/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@ export const getIsFetchingByLease: Selector<boolean, string> = (state: RootState

export const getAuditLogByLease: Selector<boolean, string> = (state: RootState, leaseId: string): boolean =>
state.auditLog.byLease[leaseId];

export const getIsFetchingByAreaSearch: Selector<boolean, string> = (state: RootState, areaSearchId: string): boolean =>
state.auditLog.isFetchingByAreaSearch[areaSearchId];

export const getAuditLogByAreaSearch: Selector<boolean, string> = (state: RootState, areaSearchId: string): boolean =>
state.auditLog.byAreaSearch[areaSearchId];
2 changes: 2 additions & 0 deletions src/auditLog/spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ import type {AuditLogState} from './types';
const defaultState: AuditLogState = {
byContact: {},
byLease: {},
byAreaSearch: {},
isFetchingByContact: {},
isFetchingByLease: {},
isFetchingByAreaSearch: {},
};

// $FlowFixMe
Expand Down
6 changes: 6 additions & 0 deletions src/auditLog/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
import type {Action} from '../types';
import type {ContactId} from '$src/contacts/types';
import type {LeaseId} from '$src/leases/types';
import type {AreaSearchId} from '$src/areaSearch/types';

export type AuditLogState = {
byContact: AuditLogListMap,
byLease: AuditLogListMap,
byAreaSearch: AuditLogListMap,
isFetchingByContact: AuditLogIsFetchingMap,
isFetchingByLease: AuditLogIsFetchingMap,
isFetchingByAreaSearch: AuditLogIsFetchingMap,
}

export type AuditLogList = Object;
Expand All @@ -26,3 +29,6 @@ export type NotFoundByContactAction = Action<'mvj/auditLog/NOT_FOUND_BY_CONTACT'
export type FetchAuditLogByLeaseAction = Action<'mvj/auditLog/FETCH_BY_LEASE', Object>;
export type ReceiveAuditLogByLeaseAction = Action<'mvj/auditLog/RECEIVE_BY_LEASE', AuditLogListMap>;
export type NotFoundByLeaseAction = Action<'mvj/auditLog/NOT_FOUND_BY_LEASE', LeaseId>;
export type FetchAuditLogByAreaSearchAction = Action<'mvj/auditLog/FETCH_BY_AREASEARCH', Object>;
export type ReceiveAuditLogByAreaSearchAction = Action<'mvj/auditLog/RECEIVE_BY_AREASEARCH', AuditLogListMap>;
export type NotFoundByAreaSearchAction = Action<'mvj/auditLog/NOT_FOUND_BY_AREASEARCH', AreaSearchId>;

0 comments on commit ab36159

Please sign in to comment.