Skip to content

Commit

Permalink
feat: Display deprecated possible fields in entity type dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
beygorghor authored Dec 6, 2024
2 parents 7d32772 + 1003b58 commit 4fd746e
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 29 deletions.
1 change: 1 addition & 0 deletions hat/assets/js/apps/Iaso/domains/app/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@
"iaso.label.deletePlanning": "Delete planning : {planningName}",
"iaso.label.deleteText": "This operation cannot be undone.",
"iaso.label.deleteWarning": "Are you sure you want to delete {name}?",
"iaso.label.deprecated": "deprecated",
"iaso.label.derived": "Deduced from another form",
"iaso.label.destination": "Destination",
"iaso.label.details": "Details",
Expand Down
1 change: 1 addition & 0 deletions hat/assets/js/apps/Iaso/domains/app/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@
"iaso.label.deletePlanning": "Effacer le planning: {planningName}",
"iaso.label.deleteText": "Cette opération est définitive.",
"iaso.label.deleteWarning": "Êtes-vous certain(e) de vouloir supprimer {name}?",
"iaso.label.deprecated": "déprécié",
"iaso.label.derived": "Instances dérivées d'un autre formulaire (Pas de collecte mobile possible)",
"iaso.label.destination": "Destination",
"iaso.label.details": "Détails",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Box } from '@mui/material';
import { Box, Chip } from '@mui/material';
import {
IconButton,
IntlFormatMessage,
Expand All @@ -7,7 +7,13 @@ import {
} from 'bluesquare-components';
import { FormikProps, FormikProvider, useFormik } from 'formik';
import isEqual from 'lodash/isEqual';
import React, { FunctionComponent, ReactNode, useState } from 'react';
import React, {
FunctionComponent,
ReactNode,
useCallback,
useMemo,
useState,
} from 'react';
import * as yup from 'yup';

import ConfirmCancelDialogComponent from '../../../../components/dialogs/ConfirmCancelDialogComponent';
Expand Down Expand Up @@ -129,6 +135,47 @@ export const EntityTypesDialog: FunctionComponent<Props> = ({
formId: values?.reference_form,
enabled: isOpen,
});

const renderTags = useCallback(
(tagValue, getTagProps) =>
tagValue
.sort((a, b) =>
formatLabel(a).localeCompare(formatLabel(b), undefined, {
sensitivity: 'accent',
}),
)
.map((option, index) => {
const field = possibleFields.find(
f => f.name === option.value,
);
return (
<Chip
color={
field?.is_latest
? 'primary'
: 'secondary'
}
label={option.label}
{...getTagProps({ index })}
/>
);
}),
[possibleFields],
);

const possibleFieldsOptions = useMemo(
() =>
possibleFields.map(field => ({
value: field.name,
label: field.is_latest
? formatLabel(field)
: `${formatLabel(field)} (${formatMessage(
MESSAGES.deprecated,
)})`,
})),
[formatMessage, possibleFields],
);

return (
<FormikProvider value={formik}>
{/* @ts-ignore */}
Expand Down Expand Up @@ -212,10 +259,8 @@ export const EntityTypesDialog: FunctionComponent<Props> = ({
}
value={!isFetchingForm ? values.fields_list_view : []}
label={MESSAGES.fieldsListView}
options={possibleFields.map(field => ({
value: field.name,
label: formatLabel(field),
}))}
options={possibleFieldsOptions}
renderTags={renderTags}
helperText={
isNew && !values.reference_form
? formatMessage(MESSAGES.selectReferenceForm)
Expand All @@ -238,10 +283,8 @@ export const EntityTypesDialog: FunctionComponent<Props> = ({
: []
}
label={MESSAGES.fieldsDetailInfoView}
options={possibleFields.map(field => ({
value: field.name,
label: formatLabel(field),
}))}
options={possibleFieldsOptions}
renderTags={renderTags}
helperText={
isNew && !values.reference_form
? formatMessage(MESSAGES.selectReferenceForm)
Expand All @@ -262,10 +305,8 @@ export const EntityTypesDialog: FunctionComponent<Props> = ({
: []
}
label={MESSAGES.fieldsDuplicateSearch}
options={possibleFields.map(field => ({
value: field.name,
label: formatLabel(field),
}))}
renderTags={renderTags}
options={possibleFieldsOptions}
helperText={
isNew && !values.reference_form
? formatMessage(MESSAGES.selectReferenceForm)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { UseQueryResult } from 'react-query';

import { useSnackQuery } from '../../../../../libs/apiHooks';
import { getRequest } from '../../../../../libs/Api';
import { useSnackQuery } from '../../../../../libs/apiHooks';

import { Form, PossibleField } from '../../../../forms/types/forms';
import { usePossibleFields } from '../../../../forms/hooks/useGetPossibleFields';
import { Form, PossibleField } from '../../../../forms/types/forms';

export const useGetForm = (
formId: number | undefined,
Expand Down Expand Up @@ -67,10 +67,14 @@ export const useGetFormForEntityType = ({
const { data: currentForm, isFetching: isFetchingForm } = useGetForm(
formId,
enabled && Boolean(formId),
'possible_fields,name',
'possible_fields_with_latest_version,name,latest_form_version',
);
return {
...usePossibleFields(isFetchingForm, currentForm),
...usePossibleFields(
isFetchingForm,
currentForm,
'possible_fields_with_latest_version',
),
name: currentForm?.name,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ const MESSAGES = defineMessages({
id: 'iaso.label.beneficiaries',
defaultMessage: 'Beneficiaries',
},
deprecated: {
id: 'iaso.label.deprecated',
defaultMessage: 'deprecated',
},
});

export default MESSAGES;
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { cloneDeep } from 'lodash';
import { useMemo } from 'react';
import { UseQueryResult } from 'react-query';
import { cloneDeep } from 'lodash';
import { DropdownOptions } from '../../../types/utils';
import {
useGetForm,
useGetForms,
} from '../../entities/entityTypes/hooks/requests/forms';

import { useSnackQuery } from '../../../libs/apiHooks';
import { getRequest } from '../../../libs/Api';
import { useSnackQuery } from '../../../libs/apiHooks';

import { Form, PossibleField } from '../types/forms';

Expand All @@ -29,18 +29,19 @@ type AllResults = {
export const usePossibleFields = (
isFetchingForm: boolean,
form?: Form,
possible_fields_key = 'possible_fields',
): Result => {
return useMemo(() => {
const possibleFields =
form?.possible_fields?.map(field => ({
form?.[possible_fields_key]?.map(field => ({
...field,
fieldKey: field.name.replace('.', ''),
})) || [];
return {
possibleFields,
isFetchingForm,
};
}, [form?.possible_fields, isFetchingForm]);
}, [form, isFetchingForm, possible_fields_key]);
};

export const useGetPossibleFields = (
Expand Down
1 change: 1 addition & 0 deletions hat/assets/js/apps/Iaso/domains/forms/types/forms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export type PossibleField = {
name: string;
type: FieldType;
fieldKey: string;
is_latest?: boolean;
};
export type ChildrenDescriptor = {
label: string;
Expand Down
29 changes: 22 additions & 7 deletions iaso/api/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@
from datetime import timedelta
from xml.sax.saxutils import escape

from django.db.models import Max, Q, Count
from django.http import StreamingHttpResponse, HttpResponse
from django.db.models import BooleanField, Case, Count, Max, Q, When
from django.http import HttpResponse, StreamingHttpResponse
from django.utils.dateparse import parse_date
from rest_framework import serializers, permissions, status
from rest_framework import permissions, serializers, status
from rest_framework.decorators import action
from rest_framework.generics import get_object_or_404
from rest_framework.request import Request
from django.db.models import Count, BooleanField, Case, When

from hat.api.export_utils import Echo, generate_xlsx, iter_items
from hat.audit.models import log_modification, FORM_API
from hat.audit.models import FORM_API, log_modification
from hat.menupermissions import models as permission
from iaso.models import Form, Project, OrgUnitType, OrgUnit, FormPredefinedFilter
from iaso.models import Form, FormPredefinedFilter, OrgUnit, OrgUnitType, Project
from iaso.utils import timestamp_to_datetime
from .common import ModelViewSet, TimestampField, DynamicFieldsModelSerializer, CONTENT_TYPE_XLSX, CONTENT_TYPE_CSV

from .common import CONTENT_TYPE_CSV, CONTENT_TYPE_XLSX, DynamicFieldsModelSerializer, ModelViewSet, TimestampField
from .enketo import public_url_for_enketo
from .projects import ProjectSerializer

Expand Down Expand Up @@ -107,6 +108,7 @@ class Meta:
"legend_threshold",
"change_request_mode",
"has_mappings",
"possible_fields_with_latest_version",
]
read_only_fields = [
"id",
Expand Down Expand Up @@ -142,6 +144,7 @@ class Meta:
has_attachments = serializers.SerializerMethodField()
reference_form_of_org_unit_types = serializers.SerializerMethodField()
has_mappings = serializers.BooleanField(read_only=True)
possible_fields_with_latest_version = serializers.SerializerMethodField()

@staticmethod
def get_latest_form_version(obj: Form):
Expand All @@ -159,6 +162,18 @@ def get_reference_form_of_org_unit_types(obj: Form):
def get_has_attachments(obj: Form):
return len(obj.attachments.all()) > 0

@staticmethod
def get_possible_fields_with_latest_version(obj: Form):
latest_version = obj.latest_version
if not latest_version:
return obj.possible_fields

# Get the field names from the latest version
latest_version_fields = set(question["name"] for question in latest_version.questions_by_name().values())

# Add a flag to each possible field indicating if it's part of the latest version
return [{**field, "is_latest": field["name"] in latest_version_fields} for field in obj.possible_fields]

def validate(self, data: typing.Mapping):
# validate projects (access check)
if "projects" in data:
Expand Down

0 comments on commit 4fd746e

Please sign in to comment.