Skip to content

Commit

Permalink
Merge pull request #442 from City-of-Helsinki/area-search-list-export
Browse files Browse the repository at this point in the history
Area search list export
  • Loading branch information
EmiliaMakelaVincit authored Sep 25, 2023
2 parents 4b22c8d + 76a5de1 commit c1331ee
Show file tree
Hide file tree
Showing 9 changed files with 332 additions and 13 deletions.
123 changes: 115 additions & 8 deletions src/areaSearch/components/AreaSearchApplicationListPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import flowRight from 'lodash/flowRight';
import isArray from 'lodash/isArray';
import {connect} from 'react-redux';
import {Row, Column} from 'react-foundation';
import {initialize} from 'redux-form';
import {formValueSelector, initialize, reduxForm} from 'redux-form';
import {withRouter} from 'react-router';
import debounce from 'lodash/debounce';

import AuthorizationError from '$components/authorization/AuthorizationError';
import {FormNames, Methods, PermissionMissingTexts} from '$src/enums';
import {FieldTypes, FormNames, Methods, PermissionMissingTexts} from '$src/enums';
import {getUsersPermissions} from '$src/usersPermissions/selectors';
import Loader from '$components/loader/Loader';
import LoaderWrapper from '$components/loader/LoaderWrapper';
Expand Down Expand Up @@ -63,10 +63,12 @@ import Button from '$components/button/Button';
import EditAreaSearchPreparerModal from '$src/areaSearch/components/EditAreaSearchPreparerModal';
import Authorization from '$components/authorization/Authorization';
import AddButtonSecondary from '$components/form/AddButtonSecondary';
import FormField from '$components/form/FormField';

import type {Attributes, Methods as MethodsType} from '$src/types';
import type {ApiResponse} from '$src/types';
import type {UsersPermissions as UsersPermissionsType} from '$src/usersPermissions/types';
import AreaSearchExportModal from '$src/areaSearch/components/AreaSearchExportModal';

const VisualizationTypes = {
MAP: 'map',
Expand All @@ -93,6 +95,7 @@ type Props = {
isFetchingAreaSearchListAttributes: boolean,
isFetching: boolean,
initialize: Function,
initializeForm: Function,
isFetchingByBBox: boolean,
fetchAreaSearchList: Function,
fetchAreaSearchListByBBox: Function,
Expand All @@ -101,6 +104,8 @@ type Props = {
editAreaSearch: Function,
isEditingAreaSearch: boolean,
lastEditError: any,
change: Function,
selectedSearches: Object,
}

type State = {
Expand All @@ -114,6 +119,7 @@ type State = {
selectedStates: Array<string>,
visualizationType: string,
isEditModalOpen: boolean,
isExportModalOpen: boolean,
editModalTargetAreaSearch: ?number,
}

Expand All @@ -131,6 +137,7 @@ class AreaSearchApplicationListPage extends PureComponent<Props, State> {
selectedStates: DEFAULT_AREA_SEARCH_STATES,
visualizationType: VisualizationTypes.TABLE,
isEditModalOpen: false,
isExportModalOpen: false,
editModalTargetAreaSearch: null,
}

Expand Down Expand Up @@ -198,11 +205,39 @@ class AreaSearchApplicationListPage extends PureComponent<Props, State> {
}

getColumns = () => {
const {areaSearchListAttributes} = this.props;
const {areaSearchListAttributes, selectedSearches} = this.props;
const columns = [];
const intendedUseOptions = getFieldOptions(areaSearchListAttributes, 'intended_use');
const stateOptions = getFieldOptions(areaSearchListAttributes, 'state');

columns.push({
key: 'checkbox',
text: 'Tulosta',
sortable: false,
renderer: (_, item) => <div onMouseDown={(e) => {
e.stopPropagation();
}}>
<FormField
name={`selectedSearches.${item.id}`}
fieldAttributes={{
type: FieldTypes.CHECKBOX,
label: 'Valitse hakemus ' + item.identifier,
read_only: false,
}}
autoBlur
disableDirty
invisibleLabel
overrideValues={{
options: [{value: true, label: ''}],
}}
onBlur={(_, value) => this.updateAllSearchesSelected({
...selectedSearches,
[item.id]: value,
})}
/>
</div>,
});

columns.push({
key: 'identifier',
text: 'Hakemus',
Expand Down Expand Up @@ -293,6 +328,18 @@ class AreaSearchApplicationListPage extends PureComponent<Props, State> {
}));
};

openExportModal = () => {
this.setState(() => ({
isExportModalOpen: true,
}));
};

closeExportModal = () => {
this.setState(() => ({
isExportModalOpen: false,
}));
};

submitAreaSearchEditModal = (data: Object) => {
const {editAreaSearch} = this.props;

Expand Down Expand Up @@ -397,12 +444,14 @@ class AreaSearchApplicationListPage extends PureComponent<Props, State> {
}

updateTableData = () => {
const {areaSearches} = this.props;
const {areaSearches, change} = this.props;

this.setState({
count: getApiResponseCount(areaSearches),
maxPage: getApiResponseMaxPage(areaSearches, LIST_TABLE_PAGE_SIZE),
});
change('selectedSearches', {});
change('allSelected', false);
}

handleSearchChange = (query: Object, resetActivePage?: boolean = true) => {
Expand Down Expand Up @@ -497,7 +546,7 @@ class AreaSearchApplicationListPage extends PureComponent<Props, State> {
}

setSearchFormValues = () => {
const {location: {search}, initialize} = this.props;
const {location: {search}, initializeForm} = this.props;
const searchQuery = getUrlParams(search);
const page = searchQuery.page ? Number(searchQuery.page) : 1;
const states = this.getSearchStates(searchQuery);
Expand All @@ -516,7 +565,7 @@ class AreaSearchApplicationListPage extends PureComponent<Props, State> {
delete initialValues.visualization;
delete initialValues.zoom;

await initialize(FormNames.AREA_SEARCH_SEARCH, initialValues);
await initializeForm(FormNames.AREA_SEARCH_SEARCH, initialValues);
};

this.setState({
Expand All @@ -538,7 +587,23 @@ class AreaSearchApplicationListPage extends PureComponent<Props, State> {
history.push({
pathname: `${getRouteById(Routes.AREA_SEARCH)}/uusi`,
});
}
};

selectAllSearches = (event: SyntheticFocusEvent<HTMLInputElement>, value: boolean) => {
const {change, areaSearches} = this.props;

change('selectedSearches', areaSearches?.results.reduce((acc, result) => {
acc[result.id] = value;
return acc;
}, {}));
};

updateAllSearchesSelected = (selectedSearches: Object) => {
const {change, areaSearches} = this.props;

const isAllSelected = areaSearches?.results.every((search) => selectedSearches[search.id] === true);
change('allSelected', isAllSelected);
};

render() {
const {
Expand All @@ -550,6 +615,7 @@ class AreaSearchApplicationListPage extends PureComponent<Props, State> {
isFetchingByBBox,
isFetchingAreaSearchListAttributes,
location: {search},
selectedSearches = {},
} = this.props;

const {
Expand All @@ -561,6 +627,7 @@ class AreaSearchApplicationListPage extends PureComponent<Props, State> {
selectedStates,
visualizationType,
isEditModalOpen,
isExportModalOpen,
editModalTargetAreaSearch,
} = this.state;
const searchQuery = getUrlParams(search);
Expand Down Expand Up @@ -661,6 +728,27 @@ class AreaSearchApplicationListPage extends PureComponent<Props, State> {
sortable
sortKey={sortKey}
sortOrder={sortOrder}
footer={({columnCount}: {columnCount: number}) => <tr>
<td />
<td colSpan={columnCount - 1}>
<FormField
name={`allSelected`}
fieldAttributes={{
type: FieldTypes.CHECKBOX,
label: '',
read_only: false,
}}
autoBlur
disableDirty
invisibleLabel
overrideValues={{
options: [{value: true, label: 'Valitse kaikki suodatuksen mukaan'}],
}}
onBlur={this.selectAllSearches}
onChange={this.selectAllSearches}
/>
</td>
</tr>}
/>

<Pagination
Expand All @@ -678,17 +766,25 @@ class AreaSearchApplicationListPage extends PureComponent<Props, State> {
/>
}
</TableWrapper>
<Button onClick={this.openExportModal} text="Tulosta" disabled={selectedSearches.length === 0} />
<EditAreaSearchPreparerModal
isOpen={isEditModalOpen}
onClose={this.closeAreaSearchEditModal}
onSubmit={this.submitAreaSearchEditModal}
areaSearchId={editModalTargetAreaSearch}
/>
<AreaSearchExportModal
isOpen={isExportModalOpen}
onClose={this.closeExportModal}
/>
</PageContainer>
);
}
}

const FORM_NAME = FormNames.AREA_SEARCH_EXPORT;
const selector = formValueSelector(FORM_NAME);

export default (flowRight(
withRouter,
withAreaSearchAttributes,
Expand All @@ -702,14 +798,25 @@ export default (flowRight(
areaSearchesByBBox: getAreaSearchListByBBox(state),
isEditingAreaSearch: getIsEditingAreaSearch(state),
lastEditError: getLastAreaSearchEditError(state),
selectedSearches: selector(state, 'selectedSearches'),
};
},
{
receiveTopNavigationSettings,
initialize,
// initialize bound to the row selection form is set by reduxForm
initializeForm: initialize,
fetchAreaSearchList,
fetchAreaSearchListByBBox,
editAreaSearch,
},
),
reduxForm({
form: FORM_NAME,
initialValues: {
mode: null,
selectedSearches: {},
includeInformationChecks: false,
includeAttachments: false,
},
})
)(AreaSearchApplicationListPage): React$ComponentType<OwnProps>);
Loading

0 comments on commit c1331ee

Please sign in to comment.