Skip to content

Commit

Permalink
Merge branch 'master' of bitbucket.org:quoin/primero into r2-1941_2.2…
Browse files Browse the repository at this point in the history
….0.2-to-master
  • Loading branch information
jtoliver-quoin committed Dec 13, 2021
2 parents 0599df8 + 3fd1904 commit f403013
Show file tree
Hide file tree
Showing 171 changed files with 4,610 additions and 310 deletions.
7 changes: 7 additions & 0 deletions app/controllers/api/v2/incidents_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,11 @@ def authorize_create!
can_create = current_user.can?(:create, Incident) || current_user.can?(:incident_from_case, Child)
raise Errors::ForbiddenOperation unless can_create
end

alias select_updated_fields_super select_updated_fields
def select_updated_fields
changes = @record.saved_changes_to_record.keys +
@record.associations_as_data_keys.select { |association| association.in?(record_params.keys) }
@updated_field_names = changes & @permitted_field_names
end
end
4 changes: 3 additions & 1 deletion app/javascript/components/form/records.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ export const FieldRecord = Record({
i18nName: false,
i18nDescription: false,
renderChildren: true,
max_length: null
max_length: null,
display_conditions_record: [],
display_conditions_subform: []
});

export const FormSectionRecord = Record({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ const Component = ({ mode, lookup }) => {
const body = {
data: {
name,
values: buildValues(lookupValues, i18n.locale, disabled)
values: buildValues(lookupValues, i18n.locale, disabled, items)
}
};

Expand Down
4 changes: 2 additions & 2 deletions app/javascript/components/pages/admin/lookups-form/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ export const reorderValues = (items, startIndex, endIndex) => {
return result;
};

export const buildValues = (values, defaultLocale, disabledValues) => {
export const buildValues = (values, defaultLocale, disabledValues, orderItems) => {
const locales = Object.keys(values);
const displayTextKeys = Object.keys(values[defaultLocale]);
const displayTextKeys = orderItems || Object.keys(values[defaultLocale]);

return displayTextKeys.map(key => {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ describe("<LookupsForm> - utils", () => {
}
];

expect(utils.buildValues(values, "en", disabled)).to.deep.equal(expected);
expect(utils.buildValues(values, "en", disabled, null)).to.deep.equal(expected);
});
it("DEPRECATED should return values with _delete key if there are removed values", () => {
const values = {
Expand All @@ -187,7 +187,39 @@ describe("<LookupsForm> - utils", () => {
}
];

expect(utils.buildValues(values, "en", removed)).to.not.equal(expected);
expect(utils.buildValues(values, "en", removed, [])).to.not.equal(expected);
});
it("should return values for a lookup with ordered item", () => {
const values = {
en: { test: "Test", new_option_1: "Test 1" },
es: { test: "Prueba", new_option_1: "Prueba 1" }
};

const disabled = {
test: true,
test_1: false
};

const expected = [
{
id: "test_1_1234abc",
disabled: true,
display_text: {
en: "Test 1",
es: "Prueba 1"
}
},
{
id: "test",
disabled: false,
display_text: {
en: "Test",
es: "Prueba"
}
}
];

expect(utils.buildValues(values, "en", disabled, ["new_option_1", "test"])).to.deep.equal(expected);
});
});
});
7 changes: 6 additions & 1 deletion app/javascript/components/record-form-alerts/component.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import InternalAlert from "../internal-alert";
import { useMemoizedSelector } from "../../libs";
import { getRecordFormAlerts } from "../records";
import { getSubformsDisplayName, getValidationErrors } from "../record-form";
import { getDuplicatedFields } from "../record-form/selectors";

import { getMessageData } from "./utils";
import { NAME } from "./constants";
Expand All @@ -16,6 +17,7 @@ const Component = ({ form, recordType, attachmentForms }) => {
const recordAlerts = useMemoizedSelector(state => getRecordFormAlerts(state, recordType, form.unique_id));
const validationErrors = useMemoizedSelector(state => getValidationErrors(state, form.unique_id));
const subformDisplayNames = useMemoizedSelector(state => getSubformsDisplayName(state, i18n.locale));
const duplicatedFields = useMemoizedSelector(state => getDuplicatedFields(state, recordType, form.unique_id));

const errors =
validationErrors?.size &&
Expand All @@ -37,7 +39,10 @@ const Component = ({ form, recordType, attachmentForms }) => {

const items = recordAlerts.map(alert =>
fromJS({
message: i18n.t(`messages.alerts_for.${alert.get("alert_for")}`, getMessageData({ alert, form, i18n }))
message: i18n.t(
`messages.alerts_for.${alert.get("alert_for")}`,
getMessageData({ alert, form, duplicatedFields, i18n })
)
})
);

Expand Down
8 changes: 7 additions & 1 deletion app/javascript/components/record-form-alerts/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { format, parseISO } from "date-fns";

import { ALERTS_FOR, DATE_FORMAT } from "../../config";

export const getMessageData = ({ alert, form, i18n }) => {
export const getMessageData = ({ alert, form, duplicatedFields, i18n }) => {
const alertFor = alert.get("alert_for");

switch (alertFor) {
Expand All @@ -14,6 +14,12 @@ export const getMessageData = ({ alert, form, i18n }) => {
};
case ALERTS_FOR.approval:
return { form_section_name: form.getIn(["name", i18n.locale]) };
case ALERTS_FOR.duplicate_field:
return {
field_name: duplicatedFields
.find(field => field.name === alert.get("type"))
?.getIn(["display_name", i18n.locale])
};
default:
return {};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ import useIncidentFromCase from "../../../records/use-incident-form-case";
import SaveAndRedirectDialog from "../../../save-and-redirect-dialog";
import { fetchReferralUsers } from "../../../record-actions/transitions/action-creators";
import { SERVICES_SUBFORM } from "../../../record-actions/add-service/constants";
import { getLoadingState, getErrors, getSelectedForm } from "../../selectors";
import { getLoadingState, getErrors, getSelectedForm, getReadOnlyFields } from "../../selectors";
import { clearDataProtectionInitialValues, clearValidationErrors, setPreviousRecord } from "../../action-creators";
import Nav from "../../nav";
import { RecordForm, RecordFormToolbar } from "../../form";
import css from "../../styles.css";
import { compactBlank, compactValues, getRedirectPath } from "../../utils";
import { compactBlank, compactReadOnlyFields, compactValues, getRedirectPath } from "../../utils";
import externalForms from "../external-forms";

const Component = ({
Expand Down Expand Up @@ -65,7 +65,6 @@ const Component = ({
const selectedModule = {
recordType,
primeroModule: record ? record.get("module_id") : params.module,
checkPermittedForms: true,
renderCustomForms: canViewSummaryForm
};

Expand All @@ -89,6 +88,9 @@ const Component = ({
const isProcessingSomeAttachment = useMemoizedSelector(state =>
getIsProcessingSomeAttachment(state, params.recordType)
);
const readOnlyFields = useMemoizedSelector(state =>
getReadOnlyFields(state, { recordType: selectedModule.recordType, primeroModule: selectedModule.primeroModule })
);

const handleFormSubmit = e => {
if (submitForm) {
Expand All @@ -108,9 +110,11 @@ const Component = ({
const saveMethod = containerMode.isEdit ? "update" : "save";
const { incidentPath, ...formValues } = values;

const writableValues = compactReadOnlyFields(formValues, readOnlyFields);

const body = {
data: {
...(containerMode.isEdit ? compactValues(formValues, initialValues) : compactBlank(formValues)),
...(containerMode.isEdit ? compactValues(writableValues, initialValues) : compactBlank(writableValues)),
...(!containerMode.isEdit ? { module_id: selectedModule.primeroModule } : {}),
...(fetchFromCaseId ? { incident_case_id: fetchFromCaseId } : {})
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Fragment } from "react";
import isEmpty from "lodash/isEmpty";

import { SUBFORM_SECTION } from "../constants";
import RecordFormAlerts from "../../record-form-alerts";
Expand All @@ -7,6 +8,56 @@ import RecordFormTitle from "../form/record-form-title";
import { RECORD_FORM_PERMISSION } from "../form/constants";
import FormSectionField from "../form/form-section-field";
import SubformField from "../form/subforms";
import { parseExpression } from "../../../libs/expressions";
import { getViolationFieldForGuidance, isViolationSubform } from "../form/utils";

const renderFormFields = (
forms,
form,
mode,
recordType,
record,
primeroModule,
isReadWriteForm,
guidanceFieldForViolation,
values
) => {
return form.fields.map(field => {
const fieldProps = {
field,
form,
mode,
recordType,
recordID: record?.get("id"),
recordModuleID: primeroModule
};

if (!field?.visible) {
return null;
}

if (guidanceFieldForViolation === field.name) {
return null;
}

if (
!isEmpty(field.display_conditions_record) &&
!parseExpression(field.display_conditions_record).evaluate(values)
) {
return null;
}

return (
<div key={field.name}>
{SUBFORM_SECTION === field.type ? (
<SubformField {...{ ...fieldProps, formSection: field.subform_section_id, isReadWriteForm, forms }} />
) : (
<FormSectionField name={field.name} {...{ ...fieldProps, formSection: form, isReadWriteForm }} />
)}
</div>
);
});
};

const renderFormSections = (
externalForms,
Expand All @@ -33,40 +84,39 @@ const renderFormSections = (
if (selectedForm === form.unique_id) {
const isReadWriteForm = userPermittedFormsIds?.get(selectedForm) === RECORD_FORM_PERMISSION.readWrite;

const isViolation = isViolationSubform(recordType, selectedForm);
const fieldForGuidance = isViolation ? getViolationFieldForGuidance(form.fields) : {};

const titleProps = isViolation
? {
displayText: i18n.t("incident.violation.title"),
subTitle: displayNameHelper(form.name, i18n.locale),
subTitleGuidance: fieldForGuidance.guiding_questions
}
: { displayText: displayNameHelper(form.name, i18n.locale) };

return (
<Fragment key={form.unique_id}>
<RecordFormTitle
mobileDisplay={mobileDisplay}
handleToggleNav={handleToggleNav}
displayText={displayNameHelper(form.name, i18n.locale)}
mode={mode}
i18n={i18n}
{...titleProps}
/>

<RecordFormAlerts recordType={recordType} form={form} attachmentForms={attachmentForms} />

{form.fields.map(field => {
const fieldProps = {
field,
form,
mode,
recordType,
recordID: record?.get("id"),
recordModuleID: primeroModule
};

if (!field?.visible) {
return null;
}

return (
<div key={field.name}>
{SUBFORM_SECTION === field.type ? (
<SubformField {...{ ...fieldProps, formSection: field.subform_section_id, isReadWriteForm }} />
) : (
<FormSectionField name={field.name} {...{ ...fieldProps, formSection: form, isReadWriteForm }} />
)}
</div>
);
})}
{renderFormFields(
fs,
form,
mode,
recordType,
record,
primeroModule,
isReadWriteForm,
fieldForGuidance?.name,
values
)}
</Fragment>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { fromJS } from "immutable";

import { setupMountedComponent } from "../../../test";
import { FormSectionRecord, FieldRecord } from "../records";
import TextField from "../form/field-types/text-field";
import { TEXT_FIELD } from "../constants";

import renderFormSections from "./render-form-sections";

describe("renderFormSections()", () => {
it("does not render the fields that do not meet the conditions", () => {
const externalForms = () => {};
const selectedForm = "form1";
const userPermittedFormsIds = fromJS({ selectedForm: "rw" });
const mobileDisplay = false;
const handleToggleNav = () => {};
const i18n = () => {};
const recordType = "recordType1";
const attachmentForms = [];
const mode = { isEdit: true };
const record = fromJS({});
const primeroModule = "primeroModule1";

const formSectionsRender = renderFormSections(
externalForms,
selectedForm,
userPermittedFormsIds,
mobileDisplay,
handleToggleNav,
i18n,
recordType,
attachmentForms,
mode,
record,
primeroModule
);

const formSection = () =>
formSectionsRender(
[
FormSectionRecord({
unique_id: "form1",
visible: true,
fields: [
FieldRecord({
name: "field1",
type: TEXT_FIELD,
visible: true,
display_conditions_record: { eq: { sex: "male" } }
}),
FieldRecord({
name: "field2",
type: TEXT_FIELD,
visible: true,
display_conditions_record: { le: { age: 18 } }
}),
FieldRecord({ name: "field3", type: TEXT_FIELD, visible: true })
]
})
],
() => {},
() => {},
{ sex: "male", age: 19 },
false
);

const renderedFormSections = () => <>{formSection()}</>;

const { component } = setupMountedComponent(renderedFormSections, {}, {}, [], { initialValues: {} });

expect(component.find(TextField)).to.have.lengthOf(2);
});
});
Loading

0 comments on commit f403013

Please sign in to comment.