Skip to content

Commit

Permalink
fix: multi language switch logic with multi rendered fields, exclamat…
Browse files Browse the repository at this point in the history
…ion mark agency
  • Loading branch information
web-mi committed Jan 28, 2024
1 parent a7ea155 commit 051b681
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 71 deletions.
49 changes: 33 additions & 16 deletions src/components/RichText/RichTextEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
DraftEditorCommand,
convertFromHTML,
Modifier,
SelectionState,
} from 'draft-js';
import { useTranslation } from 'react-i18next';
import { Select } from 'antd';
Expand Down Expand Up @@ -56,21 +57,16 @@ const TEXT_STYLES = [
{ label: 'rte.h6', value: 'header-six' },
];

const TextStyleSelect = ({ setEditorState, editorState }: ToolbarChildrenProps & { editorState: EditorState }) => {
const TextStyleSelect = ({
setEditorState,
editorState,
selectionState,
}: ToolbarChildrenProps & { editorState: EditorState; selectionState: SelectionState }) => {
const { t } = useTranslation();
const [selectionState, setSelectionState] = useState(() => editorState.getSelection());

useEffect(() => {
const selection = editorState.getSelection();
setSelectionState((state) => {
return selection.getHasFocus() ? selection : state;
});
}, [editorState]);

const blockType = useMemo(
() => editorState.getCurrentContent().getBlockForKey(selectionState.getStartKey()).getType(),
[editorState, selectionState],
);
const blockType = useMemo(() => {
return editorState.getCurrentContent().getBlockForKey(selectionState.getStartKey()).getType();
}, [editorState, selectionState]);

const handleToggle = useCallback(
(type: string) => {
Expand Down Expand Up @@ -126,6 +122,7 @@ const RTE = ({
const contentState = ContentState.createFromBlockArray(contentBlocks, entityMap);
return EditorState.createWithContent(contentState);
});
const [selectionState, setSelectionState] = useState<SelectionState>(() => editorState.getSelection());

useEffect(() => {
setEditorState((state) => {
Expand All @@ -137,6 +134,13 @@ const RTE = ({
});
}, [disabled]);

useEffect(() => {
const selection = editorState.getSelection();
setSelectionState((state) => {
return selection.getHasFocus() ? selection : state;
});
}, [editorState]);

const handleChange = useCallback(
(edited: EditorState) => {
setEditorState(edited);
Expand Down Expand Up @@ -197,7 +201,11 @@ const RTE = ({
<>
<div className="RichEditor-controls">
<div className="RichEditor-control-group">
<TextStyleSelect {...externalProps} editorState={editorState} />
<TextStyleSelect
{...externalProps}
editorState={editorState}
selectionState={selectionState}
/>
</div>
<div className="RichEditor-control-group">
<InlineStyleButton
Expand Down Expand Up @@ -239,16 +247,25 @@ const RTE = ({
</BlockStyleButton>
</div>
<div className="RichEditor-control-group">
<LinkControl {...externalProps} editorState={editorState} />
<LinkControl
{...externalProps}
editorState={editorState}
selectionState={selectionState}
/>
</div>
<div className="RichEditor-control-group">
<ImageControl {...externalProps} editorState={editorState} />
<ImageControl
{...externalProps}
editorState={editorState}
selectionState={selectionState}
/>
</div>
</div>
{Object.keys(placeholders || {}).length > 0 && (
<PlaceholderControl
placeholders={placeholders}
editorState={editorState}
selectionState={selectionState}
{...externalProps}
/>
)}
Expand Down
35 changes: 13 additions & 22 deletions src/components/TranslatableFormField/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Form, Select } from 'antd';
import { FieldContext } from 'rc-field-form';
import classNames from 'classnames';
import { cloneElement, useContext, useMemo } from 'react';
import { CheckCircleTwoTone, WarningTwoTone } from '@ant-design/icons';
import { useTranslation } from 'react-i18next';
Expand All @@ -26,17 +25,15 @@ export const TranslatableFormField = ({ name, children }: TranslatableFormFieldP
[tenantData?.settings?.activeLanguages],
);

const errors = formContext
.getFieldsError(languages.map((language) => [...namePath, language]))
.reduce((c, data) => {
const lng = data.name[data.name.length - 1];
return {
...c,
[lng]: !fieldData?.[lng] || data.errors.length > 0,
};
}, {});
const errors = languages
.map((lng) => {
const fieldErrors = formContext.getFieldError([...namePath, lng]);
const fieldValue = formContext.getFieldValue([...namePath, lng]);
return !fieldValue || fieldErrors.length > 0 ? lng : null;
})
.filter(Boolean);

const hasErrors = useMemo(() => Object.values(errors).some((e) => e), [errors]);
const hasErrors = useMemo(() => errors.length > 0, [errors]);

return (
<>
Expand All @@ -54,7 +51,7 @@ export const TranslatableFormField = ({ name, children }: TranslatableFormFieldP
<Select.Option value={language} key={language}>
<div className={styles.containerLabel}>
{t(`language.${language}`)}
{errors[language] ? (
{errors.includes(language) ? (
<WarningTwoTone twoToneColor="#FF9F00" />
) : (
<CheckCircleTwoTone twoToneColor="#4FCC5C" />
Expand All @@ -65,16 +62,10 @@ export const TranslatableFormField = ({ name, children }: TranslatableFormFieldP
</SelectFormField>
)}

{languages.map((language) =>
cloneElement(children, {
name: [...namePath, language],
key: language,
className: classNames({
[styles.activeLanguage]: fieldData?.translate === language || languages.length === 1,
[styles.notActive]: fieldData?.translate !== language && languages.length !== 1,
}),
}),
)}
{cloneElement(children, {
name: [...namePath, fieldData?.translate || languages[0]],
key: fieldData?.translate || languages[0],
})}
</>
);
};
8 changes: 0 additions & 8 deletions src/components/TranslatableFormField/styles.module.scss
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
.activeLanguage {
display: block;
}

.notActive {
display: none;
}

.containerLabel {
display: flex;
flex-grow: 1;
Expand Down
23 changes: 14 additions & 9 deletions src/hooks/useAgencyLegalDataMissing.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
import { useMemo } from 'react';
import { AgencyContact, AgencyData } from '../types/agency';
import { FeatureFlag } from '../enums/FeatureFlag';
import { useFeatureContext } from '../context/FeatureContext';

export const useAgencyLegalDataMissing = (agencyData: AgencyData) => {
const { isEnabled } = useFeatureContext();

return useMemo(() => {
const checkContact = (contact: AgencyContact) => {
const isContactComplete = (contact: AgencyContact) => {
return (
!contact ||
contact &&
['nameAndLegalForm', 'postcode', 'city', 'phoneNumber'].every((field) => {
return !!contact?.[field];
})
);
};
const type = agencyData?.dataProtection?.dataProtectionResponsibleEntity;
const hasMissingAgencyDataProtectionResponsibleContact = !checkContact(
const hasMissingAgencyDataProtectionResponsibleContact = !isContactComplete(
agencyData?.dataProtection?.agencyDataProtectionResponsibleContact,
);

const hasMissingDataProtectionOfficerContact =
type === 'DATA_PROTECTION_OFFICER' &&
!checkContact(agencyData?.dataProtection?.dataProtectionOfficerContact);
!isContactComplete(agencyData?.dataProtection?.dataProtectionOfficerContact);

const hasMissingAlternativeDataProtectionRepresentativeContact =
type === 'ALTERNATIVE_REPRESENTATIVE' &&
!checkContact(agencyData?.dataProtection?.alternativeDataProtectionRepresentativeContact);
!isContactComplete(agencyData?.dataProtection?.alternativeDataProtectionRepresentativeContact);

return !(
hasMissingAgencyDataProtectionResponsibleContact ||
hasMissingDataProtectionOfficerContact ||
hasMissingAlternativeDataProtectionRepresentativeContact
return (
isEnabled(FeatureFlag.CentralDataProtectionTemplate) &&
(hasMissingAgencyDataProtectionResponsibleContact ||
hasMissingDataProtectionOfficerContact ||
hasMissingAlternativeDataProtectionRepresentativeContact)
);
}, [agencyData]);
};
8 changes: 7 additions & 1 deletion src/pages/Agency/EditInitialMeeting/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Button, Table, Typography } from 'antd';
import { useTranslation } from 'react-i18next';
import { PlusOutlined } from '@ant-design/icons';
import { useCallback, useEffect, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { ColumnsType } from 'antd/lib/table';
import { useParams } from 'react-router';
import ErrorOutlinedIcon from '@mui/icons-material/ErrorOutlined';
import EditButtons from '../../../components/EditableTable/EditButtons';
import { ConsultantInterface, AgencyEditData, AgencyEventTypes } from '../../../types/agencyEdit';
import ResizableTitle from '../../../components/Resizable/Resizable';
Expand All @@ -17,12 +18,16 @@ import routePathNames from '../../../appConfig';
import { Resource } from '../../../enums/Resource';
import { Page } from '../../../components/Page';
import { useBookingLocations } from './useBookingLocations';
import { useAgencyData } from '../../../hooks/useAgencyData';
import { useAgencyLegalDataMissing } from '../../../hooks/useAgencyLegalDataMissing';

const { Paragraph } = Typography;

export const AgencyEditInitialMeeting = () => {
const { t } = useTranslation();
const { id: agencyId } = useParams();
const { data: agencyData, isLoading: isLoadingAgency } = useAgencyData({ id: agencyId });
const legalDataMissing = useAgencyLegalDataMissing(agencyData);
const [topics, setTopics] = useState([]);
const [showEditModal, setShowEditModal] = useState(false);
const [showDeleteModal, setShowDeleteModal] = useState(false);
Expand Down Expand Up @@ -202,6 +207,7 @@ export const AgencyEditInitialMeeting = () => {
{
titleKey: 'agency.edit.tab.settings',
to: `${routePathNames.agency}/${agencyId}/general`,
icon: !isLoadingAgency && legalDataMissing ? <ErrorOutlinedIcon color="error" /> : null,
},
{
titleKey: 'agency.edit.tab.initialEnquiry',
Expand Down
7 changes: 2 additions & 5 deletions src/utils/draftjs/imagePlugin/Control/Image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,13 @@ export const ImageControl = ({
setEditorState,
getEditorState,
editorState,
}: ToolbarChildrenProps & { editorState: EditorState }) => {
selectionState,
}: ToolbarChildrenProps & { editorState: EditorState; selectionState: SelectionState }) => {
const [showTooltip, setShowTooltip] = useState(false);
const [selectionState, setSelectionState] = useState(() => editorState.getSelection());
const [disabled, setDisabled] = useState(!editorState.getSelection().isCollapsed());

useEffect(() => {
const selection = editorState.getSelection();
setSelectionState((state) => {
return selection.getHasFocus() ? selection : state;
});
setDisabled((state) => {
return selection.getHasFocus() ? !selection.isCollapsed() : state;
});
Expand Down
7 changes: 2 additions & 5 deletions src/utils/draftjs/linkPlugin/Control/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,16 +93,13 @@ export const LinkControl = ({
setEditorState,
getEditorState,
editorState,
}: ToolbarChildrenProps & { editorState: EditorState }) => {
selectionState,
}: ToolbarChildrenProps & { editorState: EditorState; selectionState: SelectionState }) => {
const [showTooltip, setShowTooltip] = useState(false);
const [selectionState, setSelectionState] = useState(() => editorState.getSelection());
const [disabled, setDisabled] = useState(editorState.getSelection().isCollapsed());

useEffect(() => {
const selection = editorState.getSelection();
setSelectionState((state) => {
return selection.getHasFocus() ? selection : state;
});
setDisabled((state) => {
return selection.getHasFocus() ? selection.isCollapsed() : state;
});
Expand Down
7 changes: 2 additions & 5 deletions src/utils/draftjs/placeholderPlugin/Control/Placeholder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,13 @@ export const PlaceholderControl = ({
setEditorState,
getEditorState,
editorState,
}: ToolbarChildrenProps & { placeholders: any; editorState: EditorState }) => {
selectionState,
}: ToolbarChildrenProps & { placeholders: any; editorState: EditorState; selectionState: SelectionState }) => {
const { t } = useTranslation();
const [selectionState, setSelectionState] = useState(() => editorState.getSelection());
const [disabled, setDisabled] = useState(!editorState.getSelection().isCollapsed());

useEffect(() => {
const selection = editorState.getSelection();
setSelectionState((state) => {
return selection.getHasFocus() ? selection : state;
});
setDisabled((state) => {
return selection.getHasFocus() ? !selection.isCollapsed() : state;
});
Expand Down

0 comments on commit 051b681

Please sign in to comment.