Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IA-3628: Change requests: filter use default datasource by default, add advanced filters #1860

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
fedba84
Merge branch 'main' into IA-3628-Change-requests-filter-use-default-d…
hakifran Dec 3, 2024
bbdee68
default data source on groups: WIP
hakifran Dec 3, 2024
e877fbe
Merge branch 'main' into IA-3628-Change-requests-filter-use-default-d…
hakifran Dec 4, 2024
dfca861
add source versions dropdown
hakifran Dec 5, 2024
27924ba
WIP: update default_version on handle handleDataSourceChange
hakifran Dec 5, 2024
bdfa7f2
Merge branch 'main' into IA-3628-Change-requests-filter-use-default-d…
hakifran Dec 9, 2024
c8c4982
onChange data source versions
hakifran Dec 9, 2024
bdf7e2a
update groupOptions when the version is changed
hakifran Dec 9, 2024
f154b88
filter groups on datasource and versions
hakifran Dec 10, 2024
6c72b43
display the right group's name
hakifran Dec 10, 2024
0100ac3
filter orgUnit changes request by default on default_version
hakifran Dec 10, 2024
78e2452
transfer source_version_id from frontend to backend
hakifran Dec 10, 2024
1e08b40
improving the source version filter
hakifran Dec 10, 2024
a8f2a37
fix a frontend bug n selectedVersionId
hakifran Dec 10, 2024
5e51efc
refactor the code
hakifran Dec 11, 2024
46eac01
use style instead of classes
hakifran Dec 11, 2024
da4f083
useCallBack on handleDataSourceVersionChange
hakifran Dec 11, 2024
1139aaf
Update iaso/api/groups.py
hakifran Dec 12, 2024
fd7e331
Update iaso/api/org_unit_change_requests/filters.py
hakifran Dec 12, 2024
0616977
Update iaso/api/org_unit_change_requests/filters.py
hakifran Dec 12, 2024
52ef6e9
Fix code formatting
hakifran Dec 12, 2024
cce736d
Not use project before its definition
hakifran Dec 12, 2024
9f50992
get selectedVersionId from index.tsx
hakifran Dec 13, 2024
d506a2a
refactor the code
hakifran Dec 13, 2024
9e1f1e9
fix cypress test
hakifran Dec 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions hat/assets/js/apps/Iaso/constants/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ export const baseRouteConfigs: Record<string, RouteConfig> = {
'userRoles',
'withLocation',
'projectIds',
'source_version_id',
'paymentStatus',
...paginationPathParams,
'paymentIds',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import React, { FunctionComponent, useCallback, useMemo } from 'react';
import { Box, Grid } from '@mui/material';
import React, {
FunctionComponent,
useCallback,
useEffect,
useMemo,
useState,
} from 'react';
import { Box, Grid, Typography } from '@mui/material';
import { useSafeIntl } from 'bluesquare-components';
import { FilterButton } from '../../../../components/FilterButton';
import { useFilterState } from '../../../../hooks/useFilterState';
Expand All @@ -8,8 +14,6 @@ import { baseUrls } from '../../../../constants/urls';
import MESSAGES from '../messages';
import { OrgUnitTreeviewModal } from '../../components/TreeView/OrgUnitTreeviewModal';
import { useGetOrgUnit } from '../../components/TreeView/requests';
// IA-3641 uncomment when UI has been refactored to limlit size of API call
// import { useGetGroupDropdown } from '../../hooks/requests/useGetGroups';
import { useGetOrgUnitTypesDropdownOptions } from '../../orgUnitTypes/hooks/useGetOrgUnitTypesDropdownOptions';
import { DropdownOptions } from '../../../../types/utils';
import DatesRange from '../../../../components/filters/DatesRange';
Expand All @@ -21,23 +25,44 @@ import { useGetProfilesDropdown } from '../../../instances/hooks/useGetProfilesD
import { useGetUserRolesDropDown } from '../../../userRoles/hooks/requests/useGetUserRoles';
import { useGetProjectsDropdownOptions } from '../../../projects/hooks/requests';
import { usePaymentStatusOptions } from '../hooks/api/useGetPaymentStatusOptions';
import { useGetGroupDropdown } from '../../hooks/requests/useGetGroups';
import { useGetDataSources } from '../../hooks/requests/useGetDataSources';
import { useDefaultSourceVersion } from '../../../dataSources/utils';
import { useGetVersionLabel } from '../../hooks/useGetVersionLabel';

const baseUrl = baseUrls.orgUnitsChangeRequest;
type Props = { params: ApproveOrgUnitParams };
type Props = {
params: ApproveOrgUnitParams;
selectedVersionId: string;
setSelectedVersionId: (id: string) => void;
dataSource: string;
setDataSource: (id: string) => void;
};

const styles = {
advancedSettings: {
color: theme => theme.palette.primary.main,
alignSelf: 'center',
textAlign: 'right',
flex: '1',
cursor: 'pointer',
},
};

export const ReviewOrgUnitChangesFilter: FunctionComponent<Props> = ({
params,
selectedVersionId,
setSelectedVersionId,
dataSource,
setDataSource,
}) => {
const { formatMessage } = useSafeIntl();
const defaultSourceVersion = useDefaultSourceVersion();

const { filters, handleSearch, handleChange, filtersUpdated } =
useFilterState({ baseUrl, params });
const { data: dataSources, isFetching: isFetchingDataSources } =
useGetDataSources(true);
const { data: initialOrgUnit } = useGetOrgUnit(params.parent_id);
// IA-3641 hard coding values fro groups dropdown until refactor
// const { data: groupOptions, isLoading: isLoadingGroups } =
// useGetGroupDropdown({});
const groupOptions = [];
const isLoadingGroups = false;
// IA-3641 -----END
const { data: orgUnitTypeOptions, isLoading: isLoadingTypes } =
useGetOrgUnitTypesDropdownOptions();
const { data: forms, isFetching: isLoadingForms } = useGetForms();
Expand All @@ -49,6 +74,7 @@ export const ReviewOrgUnitChangesFilter: FunctionComponent<Props> = ({
useGetProjectsDropdownOptions();
const { data: paymentStatuses, isFetching: isFetchingPaymentStatuses } =
usePaymentStatusOptions();

const formOptions = useMemo(
() =>
forms?.map(form => ({
Expand All @@ -57,6 +83,43 @@ export const ReviewOrgUnitChangesFilter: FunctionComponent<Props> = ({
})) || [],
[forms],
);
const initialDataSource = useMemo(
() =>
dataSources?.find(
source =>
source.value === defaultSourceVersion.source.id.toString(),
)?.value || '',
[dataSources, defaultSourceVersion.source.id],
);

Comment on lines +86 to +93
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is where the deep linking is broken. You need to check the params for a source version and use it as initial source

const [showAdvancedSettings, setShowAdvancedSettings] = useState(false);
const { formatMessage } = useSafeIntl();

const {
data: groupOptions,
isLoading: isLoadingGroups,
refetch: refetchGroups,
} = useGetGroupDropdown(
selectedVersionId ? { defaultVersion: selectedVersionId } : {},
);

useEffect(() => {
if (selectedVersionId) {
refetchGroups();
}
}, [selectedVersionId, refetchGroups]);

Comment on lines +106 to +110
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason you don't pass selectedVersionId to useGetGroupsDropdown and put it in the query key instead of this useEffect ?

useEffect(() => {
const updatedDataSource = dataSources?.find(
source =>
source.value === defaultSourceVersion.source.id.toString(),
)?.value;

if (updatedDataSource) {
setDataSource(updatedDataSource as unknown as string);
}
}, [dataSources, defaultSourceVersion.source.id, setDataSource]);

const statusOptions: DropdownOptions<string>[] = useMemo(
() => [
{
Expand All @@ -82,6 +145,52 @@ export const ReviewOrgUnitChangesFilter: FunctionComponent<Props> = ({
[handleChange],
);

const handleDataSourceVersionChange = useCallback(
(key, newValue) => {
if (key === 'source') {
setDataSource(newValue);
const selectedSource = dataSources?.filter(
source => source.value === newValue,
)[0];
setSelectedVersionId(
selectedSource?.original?.default_version.id.toString(),
);
handleChange(
'source_version_id',
selectedSource?.original?.default_version.id,
);
} else {
setSelectedVersionId(newValue.toString());
handleChange('source_version_id', newValue);
}
Comment on lines +158 to +164
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need additional code here to reset the treeview when changing source/version

filters.groups = [];
},
[
dataSources,
filters,
handleChange,
setDataSource,
setSelectedVersionId,
],
);

const getVersionLabel = useGetVersionLabel(dataSources);

const versionsDropDown = useMemo(() => {
if (!dataSources || !dataSource) return [];
return (
dataSources
.filter(
src => (src.value as unknown as string) === dataSource,
)[0]
?.original?.versions.sort((a, b) => a.number - b.number)
.map(version => ({
label: getVersionLabel(version.id),
value: version.id.toString(),
})) ?? []
);
}, [dataSource, dataSources, getVersionLabel]);

return (
<Grid container spacing={2}>
<Grid item xs={12} md={4} lg={3}>
Expand Down Expand Up @@ -117,15 +226,70 @@ export const ReviewOrgUnitChangesFilter: FunctionComponent<Props> = ({
options={groupOptions}
loading={isLoadingGroups}
labelString={formatMessage(MESSAGES.group)}
disabled
helperText={formatMessage(MESSAGES.featureDisabled)}
/>
<Box mt={2}>
{!showAdvancedSettings && (
<Typography
data-test="advanced-settings"
variant="overline"
sx={styles.advancedSettings}
onClick={() => setShowAdvancedSettings(true)}
>
{formatMessage(MESSAGES.showAdvancedSettings)}
</Typography>
)}
{showAdvancedSettings && (
<>
<InputComponent
type="select"
disabled={isFetchingDataSources}
keyValue="source"
onChange={handleDataSourceVersionChange}
value={isFetchingDataSources ? '' : dataSource}
label={MESSAGES.source}
options={dataSources}
loading={isFetchingDataSources}
/>
<InputComponent
Comment on lines +243 to +252
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you move this one outside of the advanced settings, so it's the same as in Org Units?

type="select"
disabled={isFetchingDataSources}
keyValue="version"
onChange={handleDataSourceVersionChange}
value={selectedVersionId || ''}
label={MESSAGES.sourceVersion}
options={versionsDropDown}
clearable={false}
loading={isFetchingDataSources}
/>

<Box ml={1}>
<Typography
data-test="advanced-settings"
variant="overline"
onClick={() =>
setShowAdvancedSettings(false)
}
>
{formatMessage(
MESSAGES.hideAdvancedSettings,
)}
</Typography>
</Box>
</>
)}
</Box>
</Grid>
<Grid item xs={12} md={4} lg={3}>
<Box id="ou-tree-input">
<OrgUnitTreeviewModal
toggleOnLabelClick={false}
titleMessage={MESSAGES.parent}
source={
dataSource
? dataSource.toString()
: initialDataSource.toString()
}
version={selectedVersionId}
onConfirm={orgUnit => {
handleChange('parent_id', orgUnit?.id);
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const useGetApprovalProposals = (
projects: params.projectIds,
payment_status: params.paymentStatus,
payment_ids: params.paymentIds,
source_version_id: params.source_version_id,
potential_payment_ids: params.potentialPaymentIds,
};

Expand Down
21 changes: 19 additions & 2 deletions hat/assets/js/apps/Iaso/domains/orgUnits/reviewChanges/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Box } from '@mui/material';
import { makeStyles } from '@mui/styles';
import { commonStyles, getTableUrl, useSafeIntl } from 'bluesquare-components';
import React, { FunctionComponent, useMemo } from 'react';
import React, { FunctionComponent, useMemo, useState } from 'react';
import DownloadButtonsComponent from '../../../components/DownloadButtonsComponent';
import TopBar from '../../../components/nav/TopBarComponent';
import { ReviewOrgUnitChangesFilter } from './Filter/ReviewOrgUnitChangesFilter';
Expand All @@ -11,6 +11,7 @@ import MESSAGES from './messages';
import { ApproveOrgUnitParams } from './types';
import { useParamsObject } from '../../../routing/hooks/useParamsObject';
import { baseUrls } from '../../../constants/urls';
import { useDefaultSourceVersion } from '../../dataSources/utils';
/*
# Org Unit Change Request

Expand Down Expand Up @@ -79,6 +80,7 @@ export const ReviewOrgUnitChanges: FunctionComponent = () => {
users: params.userIds,
user_roles: params.userRoles,
with_location: params.withLocation,
source_version_id: params.source_version_id,
}),
[
params.created_at_after,
Expand All @@ -87,6 +89,7 @@ export const ReviewOrgUnitChanges: FunctionComponent = () => {
params.groups,
params.org_unit_type_id,
params.parent_id,
params.source_version_id,
params.status,
params.userIds,
params.userRoles,
Expand All @@ -95,12 +98,26 @@ export const ReviewOrgUnitChanges: FunctionComponent = () => {
);

const csv_url = getTableUrl(endPointUrl, csv_params);
const defaultSourceVersion = useDefaultSourceVersion();
const [selectedVersionId, setSelectedVersionId] = useState<string>(
defaultSourceVersion.version.id.toString(),
);
const [dataSource, setDataSource] = useState<string>(
defaultSourceVersion.source.id.toString(),
);

params.source_version_id = selectedVersionId;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We try to avoid mutating params directly and use a redirection instead (unless it breaks the whole thing)

Comment on lines +101 to +109
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you could move all this code to the Filters, since you only pass it as props. You could use a redirection from within the filters instead of mutating the params here

return (
<div>
<TopBar title={formatMessage(MESSAGES.reviewChangeProposals)} />
<Box className={classes.containerFullHeightNoTabPadded}>
<ReviewOrgUnitChangesFilter params={params} />
<ReviewOrgUnitChangesFilter
params={params}
selectedVersionId={selectedVersionId}
setSelectedVersionId={setSelectedVersionId}
dataSource={dataSource}
setDataSource={setDataSource}
/>
<Box mb={2} display="flex" justifyContent="flex-end">
<DownloadButtonsComponent csvUrl={csv_url} />
</Box>
Expand Down
16 changes: 16 additions & 0 deletions hat/assets/js/apps/Iaso/domains/orgUnits/reviewChanges/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,22 @@ const MESSAGES = defineMessages({
id: 'iaso.label.featureDisabled',
defaultMessage: 'Feature temporarily disabled',
},
showAdvancedSettings: {
id: 'iaso.form.label.showAdvancedSettings',
defaultMessage: 'Show advanced settings',
},
hideAdvancedSettings: {
id: 'iaso.form.label.hideAdvancedSettings',
defaultMessage: 'Hide advanced settings',
},
source: {
defaultMessage: 'Source',
id: 'iaso.orgUnits.source',
},
sourceVersion: {
id: 'iaso.form.label.sourceVersion',
defaultMessage: 'Source version',
},
});

export default MESSAGES;
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export type ApproveOrgUnitParams = UrlParams & {
paymentStatus?: 'pending' | 'sent' | 'rejected' | 'paid';
paymentIds?: string; // comma separated ids
potentialPaymentIds?: string; // comma separated ids
source_version_id?: string;
};

export type OrgUnitChangeRequestDetailParams = UrlParams & {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ describe('Organisations changes', () => {
'have.attr',
'href',
// `/api/orgunits/changes/export_to_csv/?&groups=2,3&status=new`,
`/api/orgunits/changes/export_to_csv/?&status=new`,
`/api/orgunits/changes/export_to_csv/?&status=new&source_version_id=3`,
);
});
});
Expand Down
7 changes: 5 additions & 2 deletions iaso/api/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,15 @@ def dropdown(self, request, *args):
if user and user.is_authenticated:
account = user.iaso_profile.account
# Filter on version ids (linked to the account)""
versions = SourceVersion.objects.filter(data_source__projects__account=account)
default_version = self.request.query_params.get("defaultVersion", account.default_version.id)
versions = SourceVersion.objects.filter(data_source__projects__account=account, pk=default_version)

else:
# this check if project need auth
project = Project.objects.get_for_user_and_app_id(user, app_id)
versions = SourceVersion.objects.filter(data_source__projects=project)
default_version = self.request.query_params.get("defaultVersion", project.account.default_version.id)
versions = SourceVersion.objects.filter(data_source__projects=project, pk=default_version)

groups = Group.objects.filter(source_version__in=versions).distinct()

queryset = self.filter_queryset(groups)
Expand Down
Loading
Loading