From 75c74e7e360d6eb7dfdb04e17fec053844a9e33c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 15:03:45 +0000 Subject: [PATCH 001/328] Bump rubocop-ast from 1.28.1 to 1.29.0 in /back Bumps [rubocop-ast](https://github.com/rubocop/rubocop-ast) from 1.28.1 to 1.29.0. - [Release notes](https://github.com/rubocop/rubocop-ast/releases) - [Changelog](https://github.com/rubocop/rubocop-ast/blob/master/CHANGELOG.md) - [Commits](https://github.com/rubocop/rubocop-ast/compare/v1.28.1...v1.29.0) --- updated-dependencies: - dependency-name: rubocop-ast dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- back/Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/Gemfile.lock b/back/Gemfile.lock index 953feae700f1..9931a2d2f57e 100644 --- a/back/Gemfile.lock +++ b/back/Gemfile.lock @@ -942,7 +942,7 @@ GEM rubocop-ast (>= 1.28.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.28.1) + rubocop-ast (1.29.0) parser (>= 3.2.1.0) rubocop-performance (1.18.0) rubocop (>= 1.7.0, < 2.0) From 8d236f3119ed0d9cbbaa3b55569619b9b8a21b91 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jul 2023 14:10:01 +0000 Subject: [PATCH 002/328] Bump bunny from 2.20.3 to 2.22.0 in /back Bumps [bunny](https://github.com/ruby-amqp/bunny) from 2.20.3 to 2.22.0. - [Release notes](https://github.com/ruby-amqp/bunny/releases) - [Changelog](https://github.com/ruby-amqp/bunny/blob/main/ChangeLog.md) - [Commits](https://github.com/ruby-amqp/bunny/compare/2.20.3...2.22.0) --- updated-dependencies: - dependency-name: bunny dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- back/Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/Gemfile.lock b/back/Gemfile.lock index 0a9d8254685a..50f3c2921083 100644 --- a/back/Gemfile.lock +++ b/back/Gemfile.lock @@ -498,7 +498,7 @@ GEM bundler-audit (0.9.1) bundler (>= 1.2.0, < 3) thor (~> 1.0) - bunny (2.20.3) + bunny (2.22.0) amq-protocol (~> 2.3, >= 2.3.1) sorted_set (~> 1, >= 1.0.2) byebug (11.1.3) From 6c4f07c7007db047d080f09a1554ee10320fa44d Mon Sep 17 00:00:00 2001 From: Iva Date: Mon, 2 Oct 2023 12:52:33 +0300 Subject: [PATCH 003/328] Update launch modal --- .../project/analysis/LaunchModal/index.tsx | 25 +++++----- .../project/analysis/LaunchModal/messages.ts | 49 +++++++++++++++++++ .../analysis/LaunchModal/translations.ts | 43 ---------------- 3 files changed, 62 insertions(+), 55 deletions(-) create mode 100644 front/app/containers/Admin/projects/project/analysis/LaunchModal/messages.ts delete mode 100644 front/app/containers/Admin/projects/project/analysis/LaunchModal/translations.ts diff --git a/front/app/containers/Admin/projects/project/analysis/LaunchModal/index.tsx b/front/app/containers/Admin/projects/project/analysis/LaunchModal/index.tsx index 77f9262d8ae9..509b7ce67006 100644 --- a/front/app/containers/Admin/projects/project/analysis/LaunchModal/index.tsx +++ b/front/app/containers/Admin/projects/project/analysis/LaunchModal/index.tsx @@ -9,7 +9,7 @@ import { } from '@citizenlab/cl2-component-library'; import { useIntl } from 'utils/cl-intl'; -import translations from './translations'; +import messages from './messages'; type LaunchModalProps = { onClose: () => void; @@ -21,24 +21,25 @@ const LaunchModal = ({ onClose }: LaunchModalProps) => { - {formatMessage(translations.title)} + {formatMessage(messages.title)} - {formatMessage(translations.subtitle)} + {formatMessage(messages.subtitle)} - {formatMessage(translations.limitation1Title)}{' '} - {formatMessage(translations.limitation1Text)} + {formatMessage(messages.limitation1Title)}{' '} + {formatMessage(messages.limitation1Text)} - {formatMessage(translations.limitation2Title)}{' '} - {formatMessage(translations.limitation2Text)} + {formatMessage(messages.limitation2Title)}{' '} + {formatMessage(messages.limitation2Text)} - {formatMessage(translations.description1)} - {formatMessage(translations.description2)} + + {formatMessage(messages.limitation3Title)}{' '} + {formatMessage(messages.limitation3Text)} + + {formatMessage(messages.description)} - + ); }; diff --git a/front/app/containers/Admin/projects/project/analysis/LaunchModal/messages.ts b/front/app/containers/Admin/projects/project/analysis/LaunchModal/messages.ts new file mode 100644 index 000000000000..b60304fd5ec0 --- /dev/null +++ b/front/app/containers/Admin/projects/project/analysis/LaunchModal/messages.ts @@ -0,0 +1,49 @@ +import { defineMessages } from 'react-intl'; + +export default defineMessages({ + title: { + id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.title', + defaultMessage: 'How to work with AI', + }, + subtitle: { + id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.subtitle', + defaultMessage: + 'We recommend using AI-generated summaries as a starting point for understanding large datasets, but not as the final word.', + }, + limitation1Title: { + id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.limitation1Title', + defaultMessage: 'Hallucinations:', + }, + limitation1Text: { + id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.limitation1Text', + defaultMessage: + 'While rare, the AI might occasionally generate information that was not explicitly present in the original dataset.', + }, + limitation2Title: { + id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.limitation2Title', + defaultMessage: 'Exaggeration:', + }, + limitation2Text: { + id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.limitation2Text', + defaultMessage: + 'The AI might emphasize certain themes or ideas more than others, potentially skewing the overall interpretation.', + }, + limitation3Title: { + id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.limitation3Title', + defaultMessage: 'Data Volume and Accuracy:', + }, + limitation3Text: { + id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.limitation3Text', + defaultMessage: + 'Our system is optimized for handling 20-200 well-defined inputs for the most accurate results. As the volume of data increases beyond this range, the summary may become more high-level and generalized. This does not mean the AI becomes "less accurate", but rather that it will focus on broader trends and patterns. For more nuanced insights, we recommend using the (auto)-tagging feature to segment larger datasets into smaller, more manageable subsets.', + }, + description: { + id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.description', + defaultMessage: + 'Our platform enables you to explore the core themes, summarize the data, and examine various perspectives. If you are looking for specific answers or insights, consider using the "Ask a Question" feature to dive deeper beyond the summary.', + }, + agreeButton: { + id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.agreeButton', + defaultMessage: 'I understand', + }, +}); diff --git a/front/app/containers/Admin/projects/project/analysis/LaunchModal/translations.ts b/front/app/containers/Admin/projects/project/analysis/LaunchModal/translations.ts deleted file mode 100644 index 448d1e5474f1..000000000000 --- a/front/app/containers/Admin/projects/project/analysis/LaunchModal/translations.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { defineMessages } from 'react-intl'; - -export default defineMessages({ - title: { - id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.title', - defaultMessage: 'How to work with AI', - }, - subtitle: { - id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.subtitle', - defaultMessage: - 'We heavily recommend not to take AI generated summaries at face value and look at the data.', - }, - limitation1Title: { - id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.limitation1Title', - defaultMessage: 'Hallucinations:', - }, - limitation1Text: { - id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.limitation1Text', - defaultMessage: 'the AI might make up non existing ideas', - }, - limitation2Title: { - id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.limitation2Title', - defaultMessage: 'Exaggeration:', - }, - limitation2Text: { - id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.limitation2Text', - defaultMessage: 'the AI might give excessive importance to one idea', - }, - description1: { - id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.description1', - defaultMessage: - 'The more data you use, the less accurate AI becomes. Based on our experience, everything between 20-200 inputs delivers great results if the input is well defined. If you’re exceeding this limit, the best approach is to use the (auto)-tagging feature to create smaller datasets for a better analysis.', - }, - description2: { - id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.description2', - defaultMessage: - 'Our system helps you to uncover the underlying talking points, summarise it and look for different angles. Looking for specific answers? Use ‘Ask a question’ to go beyond the summary.', - }, - agreeButton: { - id: 'app.containers.AdminPage.projects.project.analysis.LaunchModal.agreeButton', - defaultMessage: 'I understand', - }, -}); From c8066c18fcd1ae2321042bb1fa2044301f31f500 Mon Sep 17 00:00:00 2001 From: CircleCI Date: Mon, 2 Oct 2023 09:54:46 +0000 Subject: [PATCH 004/328] Translations updated by CI (extract-intl) --- front/app/translations/admin/en.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/front/app/translations/admin/en.json b/front/app/translations/admin/en.json index e290030c2c4b..51b3c91a9ff5 100644 --- a/front/app/translations/admin/en.json +++ b/front/app/translations/admin/en.json @@ -1902,6 +1902,16 @@ "app.containers.AdminPage.projects.all.existingProjects": "Existing projects", "app.containers.AdminPage.projects.all.newProjectFolder": "Create a project folder", "app.containers.AdminPage.projects.all.projectsAndFolders": "Projects and folders", + "app.containers.AdminPage.projects.project.analysis.LaunchModal.agreeButton": "I understand", + "app.containers.AdminPage.projects.project.analysis.LaunchModal.description": "Our platform enables you to explore the core themes, summarize the data, and examine various perspectives. If you are looking for specific answers or insights, consider using the \"Ask a Question\" feature to dive deeper beyond the summary.", + "app.containers.AdminPage.projects.project.analysis.LaunchModal.limitation1Text": "While rare, the AI might occasionally generate information that was not explicitly present in the original dataset.", + "app.containers.AdminPage.projects.project.analysis.LaunchModal.limitation1Title": "Hallucinations:", + "app.containers.AdminPage.projects.project.analysis.LaunchModal.limitation2Text": "The AI might emphasize certain themes or ideas more than others, potentially skewing the overall interpretation.", + "app.containers.AdminPage.projects.project.analysis.LaunchModal.limitation2Title": "Exaggeration:", + "app.containers.AdminPage.projects.project.analysis.LaunchModal.limitation3Text": "Our system is optimized for handling 20-200 well-defined inputs for the most accurate results. As the volume of data increases beyond this range, the summary may become more high-level and generalized. This does not mean the AI becomes \"less accurate\", but rather that it will focus on broader trends and patterns. For more nuanced insights, we recommend using the (auto)-tagging feature to segment larger datasets into smaller, more manageable subsets.", + "app.containers.AdminPage.projects.project.analysis.LaunchModal.limitation3Title": "Data Volume and Accuracy:", + "app.containers.AdminPage.projects.project.analysis.LaunchModal.subtitle": "We recommend using AI-generated summaries as a starting point for understanding large datasets, but not as the final word.", + "app.containers.AdminPage.projects.project.analysis.LaunchModal.title": "How to work with AI", "app.containers.AdminPage.widgets.copied": "Copied to clipboard", "app.containers.AdminPage.widgets.copyToClipboard": "Copy this code", "app.containers.AdminPage.widgets.exportHtmlCodeButton": "Copy the HTML code", From 4cf1349c739ff5e8a45a2120d0522cafd7057ba6 Mon Sep 17 00:00:00 2001 From: Iva Date: Mon, 2 Oct 2023 12:59:57 +0300 Subject: [PATCH 005/328] Tags --- .../projects/project/analysis/Tags/AddTag.tsx | 4 +- .../analysis/Tags/AutoTaggingModal/Step1.tsx | 50 +++++++++---------- .../Step2FewShotClassification.tsx | 10 ++-- .../Step2LabelClassification.tsx | 10 ++-- .../project/analysis/Tags/RenameTagModal.tsx | 12 ++--- .../project/analysis/Tags/TagActions.tsx | 10 ++-- .../project/analysis/Tags/TagAssistance.tsx | 16 +++--- .../projects/project/analysis/Tags/index.tsx | 10 ++-- .../Tags/{translations.ts => messages.ts} | 30 +++++------ .../projects/project/analysis/Tasks/index.tsx | 42 ++++++++-------- .../Tasks/{translations.ts => messages.ts} | 4 +- 11 files changed, 99 insertions(+), 99 deletions(-) rename front/app/containers/Admin/projects/project/analysis/Tags/{translations.ts => messages.ts} (90%) rename front/app/containers/Admin/projects/project/analysis/Tasks/{translations.ts => messages.ts} (97%) diff --git a/front/app/containers/Admin/projects/project/analysis/Tags/AddTag.tsx b/front/app/containers/Admin/projects/project/analysis/Tags/AddTag.tsx index 7a1d86c501e4..776d7675968f 100644 --- a/front/app/containers/Admin/projects/project/analysis/Tags/AddTag.tsx +++ b/front/app/containers/Admin/projects/project/analysis/Tags/AddTag.tsx @@ -7,7 +7,7 @@ import Error from 'components/UI/Error'; import { Box, Button, Input } from '@citizenlab/cl2-component-library'; import { useIntl } from 'utils/cl-intl'; -import translations from './translations'; +import messages from './messages'; import { trackEventByName } from 'utils/analytics'; import tracks from '../tracks'; @@ -48,7 +48,7 @@ const AddTag = ({ onCreateTag }: { onCreateTag?: (tagId: string) => void }) => { type="text" value={name} onChange={onChangeName} - placeholder={formatMessage(translations.addTag)} + placeholder={formatMessage(messages.addTag)} size="small" /> diff --git a/front/app/containers/Admin/projects/project/analysis/Tags/AutoTaggingModal/Step2LabelClassification.tsx b/front/app/containers/Admin/projects/project/analysis/Tags/AutoTaggingModal/Step2LabelClassification.tsx index d13cf1bfb1bf..8c02113b1095 100644 --- a/front/app/containers/Admin/projects/project/analysis/Tags/AutoTaggingModal/Step2LabelClassification.tsx +++ b/front/app/containers/Admin/projects/project/analysis/Tags/AutoTaggingModal/Step2LabelClassification.tsx @@ -13,7 +13,7 @@ import Tag from '../Tag'; import AddTag from '../AddTag'; import { useIntl } from 'utils/cl-intl'; -import translations from '../translations'; +import messages from '../messages'; type Props = { onLaunch: (tagsIds: string[]) => void; @@ -36,9 +36,9 @@ const Step2LabelClassification = ({ onLaunch }: Props) => { return ( - {formatMessage(translations.byLabelTitle)} - {formatMessage(translations.byLabelSubtitle1)} - {formatMessage(translations.byLabelSubtitle2)} + {formatMessage(messages.byLabelTitle)} + {formatMessage(messages.byLabelSubtitle1)} + {formatMessage(messages.byLabelSubtitle2)} {customTags?.map((tag) => ( @@ -66,7 +66,7 @@ const Step2LabelClassification = ({ onLaunch }: Props) => { disabled={selectedTagIds.length === 0} onClick={() => onLaunch(selectedTagIds)} > - {formatMessage(translations.launch)} + {formatMessage(messages.launch)} diff --git a/front/app/containers/Admin/projects/project/analysis/Tags/RenameTagModal.tsx b/front/app/containers/Admin/projects/project/analysis/Tags/RenameTagModal.tsx index af60f46bec3c..23fb650f97de 100644 --- a/front/app/containers/Admin/projects/project/analysis/Tags/RenameTagModal.tsx +++ b/front/app/containers/Admin/projects/project/analysis/Tags/RenameTagModal.tsx @@ -2,7 +2,7 @@ import React from 'react'; // styles // intl -import translations from './translations'; +import messages from './messages'; import { useIntl } from 'utils/cl-intl'; // components @@ -37,7 +37,7 @@ const RenameTag = ({ const { mutate: updateTag, isLoading } = useUpdateAnalysisTag(); const schema = object({ - name: string().required(formatMessage(translations.emptyNameError)), + name: string().required(formatMessage(messages.emptyNameError)), }); const methods = useForm({ @@ -62,14 +62,14 @@ const RenameTag = ({ return ( - {formatMessage(translations.renameTagModalTitle)} + {formatMessage(messages.renameTagModalTitle)} diff --git a/front/app/containers/Admin/projects/project/analysis/Tags/TagActions.tsx b/front/app/containers/Admin/projects/project/analysis/Tags/TagActions.tsx index 03a62207a189..e60a3188d6e8 100644 --- a/front/app/containers/Admin/projects/project/analysis/Tags/TagActions.tsx +++ b/front/app/containers/Admin/projects/project/analysis/Tags/TagActions.tsx @@ -13,7 +13,7 @@ import { import useDeleteAnalysisTag from 'api/analysis_tags/useDeleteAnalysisTag'; import { useIntl } from 'utils/cl-intl'; import { useParams } from 'react-router-dom'; -import translations from './translations'; +import messages from './messages'; import RenameTagModal from './RenameTagModal'; import Modal from 'components/UI/Modal'; import { ITagData } from 'api/analysis_tags/types'; @@ -51,7 +51,7 @@ const TagActions = ({ tag }: { tag: ITagData }) => { }; const handleTagDelete = () => { - if (window.confirm(formatMessage(translations.deleteTagConfirmation))) { + if (window.confirm(formatMessage(messages.deleteTagConfirmation))) { deleteTag( { analysisId, @@ -129,7 +129,7 @@ const TagActions = ({ tag }: { tag: ITagData }) => { ) : ( )} - {formatMessage(translations.addInputToTag)} + {formatMessage(messages.addInputToTag)} @@ -141,7 +141,7 @@ const TagActions = ({ tag }: { tag: ITagData }) => { > - {formatMessage(translations.renameTag)} + {formatMessage(messages.renameTag)} { ) : ( )} - {formatMessage(translations.deleteTag)} + {formatMessage(messages.deleteTag)} diff --git a/front/app/containers/Admin/projects/project/analysis/Tags/TagAssistance.tsx b/front/app/containers/Admin/projects/project/analysis/Tags/TagAssistance.tsx index 598fa186fe15..927c2b94aba6 100644 --- a/front/app/containers/Admin/projects/project/analysis/Tags/TagAssistance.tsx +++ b/front/app/containers/Admin/projects/project/analysis/Tags/TagAssistance.tsx @@ -10,7 +10,7 @@ import { Text, } from '@citizenlab/cl2-component-library'; import CloseIconButton from 'components/UI/CloseIconButton'; -import translations from './translations'; +import messages from './messages'; import { FormattedMessage } from 'utils/cl-intl'; type Props = { @@ -22,7 +22,7 @@ const Step1 = ({ onSetStep }) => { return ( - <FormattedMessage {...translations.autoAssignQuestion} /> + <FormattedMessage {...messages.autoAssignQuestion} /> @@ -30,13 +30,13 @@ const Step1 = ({ onSetStep }) => { buttonStyle="primary-outlined" onClick={() => onSetStep('step2-auto')} > - + @@ -53,7 +53,7 @@ const Step2Auto = () => { {chunks} ), }} - {...translations.autoAssignStep2AutoText1} + {...messages.autoAssignStep2AutoText1} /> @@ -63,7 +63,7 @@ const Step2Auto = () => { {chunks} ), }} - {...translations.autoAssignStep2AutoText2} + {...messages.autoAssignStep2AutoText2} /> @@ -74,7 +74,7 @@ const Step2Manual = () => { return ( - + ); @@ -136,7 +136,7 @@ const FirstTagAssistance = ({ tagId, onHide }: Props) => { setDontShowAgainCheckbox(!dontShowAgainCheckbox) } /> - + diff --git a/front/app/containers/Admin/projects/project/analysis/Tags/index.tsx b/front/app/containers/Admin/projects/project/analysis/Tags/index.tsx index e99a0f4f575f..f7b58e70db68 100644 --- a/front/app/containers/Admin/projects/project/analysis/Tags/index.tsx +++ b/front/app/containers/Admin/projects/project/analysis/Tags/index.tsx @@ -31,7 +31,7 @@ import inputsKeys from 'api/analysis_inputs/keys'; import TagActions from './TagActions'; import { trackEventByName } from 'utils/analytics'; import tracks from '../tracks'; -import translations from './translations'; +import messages from './messages'; import { useIntl } from 'utils/cl-intl'; const BlickingIcon = styled(Icon)` @@ -194,7 +194,7 @@ const Tags = () => { size="s" buttonStyle="admin-dark" > - {formatMessage(translations.autoTag)} + {formatMessage(messages.autoTag)} {emptyState && ( { onClick={() => removeSearchParams(['tag_ids'])} className={!selectedTags ? 'selected' : ''} > - {formatMessage(translations.allInputs)} + {formatMessage(messages.allInputs)} { selectedTags && selectedTags[0] === null ? 'selected' : '' } > - {formatMessage(translations.inputsWithoutTags)} + {formatMessage(messages.inputsWithoutTags)} { {!isLoadingTags && emptyState && ( - {formatMessage(translations.noTags)} + {formatMessage(messages.noTags)} )} diff --git a/front/app/containers/Admin/projects/project/analysis/Tags/translations.ts b/front/app/containers/Admin/projects/project/analysis/Tags/messages.ts similarity index 90% rename from front/app/containers/Admin/projects/project/analysis/Tags/translations.ts rename to front/app/containers/Admin/projects/project/analysis/Tags/messages.ts index 6768bb4764b6..b33fd0d502ab 100644 --- a/front/app/containers/Admin/projects/project/analysis/Tags/translations.ts +++ b/front/app/containers/Admin/projects/project/analysis/Tags/messages.ts @@ -95,54 +95,54 @@ export default defineMessages({ id: 'app.containers.AdminPage.projects.project.analysis.Tags.howToTag', defaultMessage: 'How do you want to tag?', }, - topicDetection: { - id: 'app.containers.AdminPage.projects.project.analysis.Tags.topicDetection', - defaultMessage: 'Topic detection', + tagDetection: { + id: 'app.containers.AdminPage.projects.project.analysis.Tags.tagDetection', + defaultMessage: 'Tag detection', }, fullyAutomatedTitle: { id: 'app.containers.AdminPage.projects.project.analysis.Tags.fullyAutomatedTitle', - defaultMessage: 'Topics: Fully automated', + defaultMessage: 'Tags: Fully automated', }, fullyAutomatedTooltip: { id: 'app.containers.AdminPage.projects.project.analysis.Tags.fullyAutomatedTooltip', defaultMessage: - 'Works well when your projects covers a broad range of topics. Good place to start.', + 'Works well when your projects covers a broad range of tags. Good place to start.', }, fullyAutomatedDescription: { id: 'app.containers.AdminPage.projects.project.analysis.Tags.fullyAutomatedDescription', defaultMessage: - 'The computer automatically detects topics and assigns them to your inputs.', + 'The computer automatically detects tags and assigns them to your inputs.', }, classificationByLabelTitle: { id: 'app.containers.AdminPage.projects.project.analysis.Tags.classificationByLabelTitle', - defaultMessage: 'Topics: By label', + defaultMessage: 'Tags: By label', }, classificationByLabelTooltip: { id: 'app.containers.AdminPage.projects.project.analysis.Tags.classificationByLabelTooltip', defaultMessage: - 'Works well when you know what topics you are looking for, or when your project has a narrow scope in terms of topics.', + 'This works well when you have a pre-defined set of tags or when your project has a limited scope in terms of tags.', }, classificationByLabelDescription: { id: 'app.containers.AdminPage.projects.project.analysis.Tags.classificationByLabelDescription', - defaultMessage: 'You create the topics, the computer assigns the inputs', + defaultMessage: 'You create the tags, the computer assigns the inputs', }, classificationByExampleTitle: { id: 'app.containers.AdminPage.projects.project.analysis.Tags.classificationByExampleTitle', - defaultMessage: 'Topics: By example', + defaultMessage: 'Tags: By example', }, classificationByExampleTooltip: { id: 'app.containers.AdminPage.projects.project.analysis.Tags.classificationByExampleTooltip', defaultMessage: - 'Works well when you need to tag some really specific things. Use this in case "Topics: By label" does not give you good results', + 'Similar to "Tags: by label" but with increased accuracy as you’re training the system with good examples.', }, classificationByExampleDescription: { id: 'app.containers.AdminPage.projects.project.analysis.Tags.classificationByExampleDescription', defaultMessage: - 'You create the topics and manually assign a few inputs as an example, the computer assigns the rest', + 'You create the tags and manually assign a few inputs as an example, the computer assigns the rest', }, platformTagsTitle: { id: 'app.containers.AdminPage.projects.project.analysis.Tags.platformTags', - defaultMessage: 'Topics: Platform tags', + defaultMessage: 'Tags: Platform tags', }, platformTagsDescription: { id: 'app.containers.AdminPage.projects.project.analysis.Tags.platformTagsDescription', @@ -180,7 +180,7 @@ export default defineMessages({ }, fewShotTitle: { id: 'app.containers.AdminPage.projects.project.analysis.Tags.fewShotTitle', - defaultMessage: 'Topics: By example', + defaultMessage: 'Tags: By example', }, fewShotSubtitle: { id: 'app.containers.AdminPage.projects.project.analysis.Tags.fewShotSubtitle', @@ -194,7 +194,7 @@ export default defineMessages({ }, byLabelTitle: { id: 'app.containers.AdminPage.projects.project.analysis.Tags.byLabelTitle', - defaultMessage: 'Topics: By label', + defaultMessage: 'Tags: By label', }, byLabelSubtitle1: { id: 'app.containers.AdminPage.projects.project.analysis.Tags.byLabelSubtitle1', diff --git a/front/app/containers/Admin/projects/project/analysis/Tasks/index.tsx b/front/app/containers/Admin/projects/project/analysis/Tasks/index.tsx index 62f4df7f7d57..4648f298b3e2 100644 --- a/front/app/containers/Admin/projects/project/analysis/Tasks/index.tsx +++ b/front/app/containers/Admin/projects/project/analysis/Tasks/index.tsx @@ -19,7 +19,7 @@ import useLocale from 'hooks/useLocale'; import { isNilOrError } from 'utils/helperUtils'; import { useIntl } from 'utils/cl-intl'; -import translations from './translations'; +import messages from './messages'; import { AutoTaggingMethod, IBackgroundTaskData, @@ -59,29 +59,29 @@ const Tasks = () => { IBackgroundTaskData['attributes']['type'], string > = { - auto_tagging_task: formatMessage(translations.autotaggingTask), - summarization_task: formatMessage(translations.summarizationTask), + auto_tagging_task: formatMessage(messages.autotaggingTask), + summarization_task: formatMessage(messages.summarizationTask), }; const taggingMethodTranslationMap: Record = { - custom: formatMessage(translations.custom), - language: formatMessage(translations.language), - platform_topic: formatMessage(translations.platformTopic), - nlp_topic: formatMessage(translations.nlpTopic), - sentiment: formatMessage(translations.sentiment), - controversial: formatMessage(translations.controversial), - label_classification: formatMessage(translations.labelClassification), - few_shot_classification: formatMessage(translations.fewShotClassification), + custom: formatMessage(messages.custom), + language: formatMessage(messages.language), + platform_topic: formatMessage(messages.platformTopic), + nlp_topic: formatMessage(messages.nlpTopic), + sentiment: formatMessage(messages.sentiment), + controversial: formatMessage(messages.controversial), + label_classification: formatMessage(messages.labelClassification), + few_shot_classification: formatMessage(messages.fewShotClassification), }; const stateTranslationMap: Record< IBackgroundTaskData['attributes']['state'], string > = { - queued: formatMessage(translations.queued), - in_progress: formatMessage(translations.inProgress), - succeeded: formatMessage(translations.succeeded), - failed: formatMessage(translations.failed), + queued: formatMessage(messages.queued), + in_progress: formatMessage(messages.inProgress), + succeeded: formatMessage(messages.succeeded), + failed: formatMessage(messages.failed), }; return ( @@ -91,7 +91,7 @@ const Tasks = () => { buttonStyle="text" width="24px" height="24px" - aria-label={formatMessage(translations.backgroundJobs)} + aria-label={formatMessage(messages.backgroundJobs)} onClick={() => setIsDropdownOpened(!isDropdownOpened)} > @@ -99,7 +99,7 @@ const Tasks = () => { ) : ( setIsDropdownOpened(!isDropdownOpened)} @@ -117,7 +117,7 @@ const Tasks = () => { content={ {tasks?.data.length === 0 && ( - {formatMessage(translations.noJobs)} + {formatMessage(messages.noJobs)} )} {tasks?.data.map((task) => { return ( @@ -187,20 +187,20 @@ const Tasks = () => { {stateTranslationMap[task.attributes.state]} - {formatMessage(translations.triggeredAt)} + {formatMessage(messages.triggeredAt)} {timeAgo(Date.parse(task.attributes.created_at), locale)} - {formatMessage(translations.startedAt)} + {formatMessage(messages.startedAt)} {task.attributes.started_at && timeAgo(Date.parse(task.attributes.started_at), locale)} - {formatMessage(translations.endedAt)} + {formatMessage(messages.endedAt)} {task.attributes.ended_at && timeAgo(Date.parse(task.attributes.ended_at), locale)} diff --git a/front/app/containers/Admin/projects/project/analysis/Tasks/translations.ts b/front/app/containers/Admin/projects/project/analysis/Tasks/messages.ts similarity index 97% rename from front/app/containers/Admin/projects/project/analysis/Tasks/translations.ts rename to front/app/containers/Admin/projects/project/analysis/Tasks/messages.ts index e56297a57965..2a4e380520c7 100644 --- a/front/app/containers/Admin/projects/project/analysis/Tasks/translations.ts +++ b/front/app/containers/Admin/projects/project/analysis/Tasks/messages.ts @@ -23,11 +23,11 @@ export default defineMessages({ }, platformTopic: { id: 'app.containers.AdminPage.projects.project.analysis.Tasks.platformTopic', - defaultMessage: 'Platform topic', + defaultMessage: 'Platform tag', }, nlpTopic: { id: 'app.containers.AdminPage.projects.project.analysis.Tasks.nlpTopic', - defaultMessage: 'NLP topic', + defaultMessage: 'NLP tag', }, sentiment: { id: 'app.containers.AdminPage.projects.project.analysis.Tasks.sentiment', From 64c8165239d3744e396e4d63a9a5408233e9415d Mon Sep 17 00:00:00 2001 From: Iva Date: Mon, 2 Oct 2023 13:01:14 +0300 Subject: [PATCH 006/328] Demographics --- .../project/analysis/Demographics/AuthorsByAge.tsx | 6 +++--- .../project/analysis/Demographics/AuthorsByDomicile.tsx | 8 ++++---- .../projects/project/analysis/Demographics/index.tsx | 4 ++-- .../Demographics/{translations.ts => messages.ts} | 0 4 files changed, 9 insertions(+), 9 deletions(-) rename front/app/containers/Admin/projects/project/analysis/Demographics/{translations.ts => messages.ts} (100%) diff --git a/front/app/containers/Admin/projects/project/analysis/Demographics/AuthorsByAge.tsx b/front/app/containers/Admin/projects/project/analysis/Demographics/AuthorsByAge.tsx index 3a638779b33c..055f126dfa4f 100644 --- a/front/app/containers/Admin/projects/project/analysis/Demographics/AuthorsByAge.tsx +++ b/front/app/containers/Admin/projects/project/analysis/Demographics/AuthorsByAge.tsx @@ -22,7 +22,7 @@ import { import { updateSearchParams } from 'utils/cl-router/updateSearchParams'; import useAuthorsByAge from 'api/analysis_stats/useAuthorsByAge'; import { FormattedMessage, useIntl } from 'utils/cl-intl'; -import translations from './translations'; +import messages from './messages'; // Custom tooltip is rendered when the user hovers over a bar const CustomTooltip = ({ payload }: { payload?: any }) => { @@ -88,7 +88,7 @@ const AuthorsByAge = ({ customFieldId }: Props) => { let filtered; if (fromAge === null) { - name = formatMessage(translations.unknown); + name = formatMessage(messages.unknown); shortName = '?'; total = totalAuthorsByAge?.data.attributes.unknown_age_count; filtered = filteredAuthorsByAge?.data.attributes.unknown_age_count; @@ -162,7 +162,7 @@ const AuthorsByAge = ({ customFieldId }: Props) => { return ( - <FormattedMessage {...translations.authorsByAge} /> + <FormattedMessage {...messages.authorsByAge} /> diff --git a/front/app/containers/Admin/projects/project/analysis/Demographics/AuthorsByDomicile.tsx b/front/app/containers/Admin/projects/project/analysis/Demographics/AuthorsByDomicile.tsx index f162ea0b9934..95add864dbc6 100644 --- a/front/app/containers/Admin/projects/project/analysis/Demographics/AuthorsByDomicile.tsx +++ b/front/app/containers/Admin/projects/project/analysis/Demographics/AuthorsByDomicile.tsx @@ -25,7 +25,7 @@ import useUserCustomFieldsOptions from 'api/user_custom_fields_options/useUserCu import { xor } from 'lodash-es'; import { updateSearchParams } from 'utils/cl-router/updateSearchParams'; import { FormattedMessage, useIntl } from 'utils/cl-intl'; -import translations from './translations'; +import messages from './messages'; // Custom tooltip is rendered when the user hovers over a bar const CustomTooltip = ({ payload }: { payload?: any }) => { @@ -93,7 +93,7 @@ const AuthorsByDomicile = ({ customFieldId }: Props) => { let optionKey; if (optionId === '_blank') { - name = formatMessage(translations.unknown); + name = formatMessage(messages.unknown); shortName = '?'; filtered = filteredAuthorsByDomicile?.data.attributes.series.users[optionId]; @@ -145,7 +145,7 @@ const AuthorsByDomicile = ({ customFieldId }: Props) => { if (chartData.length > 27) { return ( - + ); } @@ -153,7 +153,7 @@ const AuthorsByDomicile = ({ customFieldId }: Props) => { return ( - <FormattedMessage {...translations.authorsByDomicile} /> + <FormattedMessage {...messages.authorsByDomicile} /> diff --git a/front/app/containers/Admin/projects/project/analysis/Demographics/index.tsx b/front/app/containers/Admin/projects/project/analysis/Demographics/index.tsx index cf90fa0441f5..0f98183743aa 100644 --- a/front/app/containers/Admin/projects/project/analysis/Demographics/index.tsx +++ b/front/app/containers/Admin/projects/project/analysis/Demographics/index.tsx @@ -12,7 +12,7 @@ import AuthorsByAge from './AuthorsByAge'; import useUserCustomFields from 'api/user_custom_fields/useUserCustomFields'; import { IUserCustomFieldData } from 'api/user_custom_fields/types'; import { isEmpty } from 'lodash-es'; -import translations from './translations'; +import messages from './messages'; import { FormattedMessage } from 'utils/cl-intl'; const SUPPORTED_CODES: IUserCustomFieldData['attributes']['code'][] = [ @@ -73,7 +73,7 @@ const Demographics = ({ - <FormattedMessage {...translations.demographicsTitle} /> + <FormattedMessage {...messages.demographicsTitle} /> } diff --git a/front/app/containers/Admin/projects/project/analysis/Demographics/translations.ts b/front/app/containers/Admin/projects/project/analysis/Demographics/messages.ts similarity index 100% rename from front/app/containers/Admin/projects/project/analysis/Demographics/translations.ts rename to front/app/containers/Admin/projects/project/analysis/Demographics/messages.ts From 0884516d66a71bf81c5845787a5f8e13aa7a72ba Mon Sep 17 00:00:00 2001 From: Iva Date: Mon, 2 Oct 2023 13:04:29 +0300 Subject: [PATCH 007/328] Inputs --- .../FilterItems/AuthorFieldFilterItem.tsx | 4 ++-- .../FilterItems/InputFieldFilterItem.tsx | 4 ++-- .../project/analysis/FilterItems/index.tsx | 24 +++++++++---------- .../{translations.ts => messages.ts} | 0 .../analysis/InputPreview/LongFieldValue.tsx | 16 ++++++------- .../project/analysis/InputPreview/index.tsx | 4 ++-- .../{translations.ts => messages.ts} | 0 .../analysis/InputsList/InputListItem.tsx | 4 ++-- .../project/analysis/InputsList/index.tsx | 4 ++-- .../{translations.ts => messages.ts} | 0 .../analysis/{translations.ts => messages.ts} | 0 11 files changed, 30 insertions(+), 30 deletions(-) rename front/app/containers/Admin/projects/project/analysis/FilterItems/{translations.ts => messages.ts} (100%) rename front/app/containers/Admin/projects/project/analysis/InputPreview/{translations.ts => messages.ts} (100%) rename front/app/containers/Admin/projects/project/analysis/InputsList/{translations.ts => messages.ts} (100%) rename front/app/containers/Admin/projects/project/analysis/{translations.ts => messages.ts} (100%) diff --git a/front/app/containers/Admin/projects/project/analysis/FilterItems/AuthorFieldFilterItem.tsx b/front/app/containers/Admin/projects/project/analysis/FilterItems/AuthorFieldFilterItem.tsx index 453d7abe770e..2439ea883a5c 100644 --- a/front/app/containers/Admin/projects/project/analysis/FilterItems/AuthorFieldFilterItem.tsx +++ b/front/app/containers/Admin/projects/project/analysis/FilterItems/AuthorFieldFilterItem.tsx @@ -11,7 +11,7 @@ import T from 'components/T'; import ShortUserFieldValue from '../components/ShortUserFieldValue'; import ElipsisFilterValue from './EllipsisFilterValue'; import { useIntl } from 'utils/cl-intl'; -import translations from './translations'; +import messages from './messages'; type Props = { customFieldId: string; @@ -81,7 +81,7 @@ const AuthorFieldFilterItem = ({ onClick={() => { removeSearchParams([filterKey]); }} - a11y_buttonActionMessage={formatMessage(translations.removeFilter)} + a11y_buttonActionMessage={formatMessage(messages.removeFilter)} /> )} diff --git a/front/app/containers/Admin/projects/project/analysis/FilterItems/InputFieldFilterItem.tsx b/front/app/containers/Admin/projects/project/analysis/FilterItems/InputFieldFilterItem.tsx index 8c40c1c7e8d1..dbcba305b5c7 100644 --- a/front/app/containers/Admin/projects/project/analysis/FilterItems/InputFieldFilterItem.tsx +++ b/front/app/containers/Admin/projects/project/analysis/FilterItems/InputFieldFilterItem.tsx @@ -11,7 +11,7 @@ import { useParams } from 'react-router-dom'; import { removeSearchParams } from 'utils/cl-router/removeSearchParams'; import ShortFieldValue from '../components/ShortInputFieldValue'; import EllipsisFilterValue from './EllipsisFilterValue'; -import translations from './translations'; +import messages from './messages'; import { useIntl } from 'utils/cl-intl'; type Props = { @@ -90,7 +90,7 @@ const InputFieldFilterItem = ({ onClick={() => { removeSearchParams([filterKey]); }} - a11y_buttonActionMessage={formatMessage(translations.removeFilter)} + a11y_buttonActionMessage={formatMessage(messages.removeFilter)} /> )} diff --git a/front/app/containers/Admin/projects/project/analysis/FilterItems/index.tsx b/front/app/containers/Admin/projects/project/analysis/FilterItems/index.tsx index c9e42c11455d..3ac74ddc3030 100644 --- a/front/app/containers/Admin/projects/project/analysis/FilterItems/index.tsx +++ b/front/app/containers/Admin/projects/project/analysis/FilterItems/index.tsx @@ -13,7 +13,7 @@ import EllipsisFilterValue from './EllipsisFilterValue'; import { useParams } from 'react-router-dom'; import useAnalysisTags from 'api/analysis_tags/useAnalysisTags'; import Tag from '../Tags/Tag'; -import translations from './translations'; +import messages from './messages'; import { MessageDescriptor, useIntl } from 'utils/cl-intl'; const clauseToPredicate = (clause?: string): '>' | '<' | '=' => { @@ -36,39 +36,39 @@ const translationKeys: Record< { translationKey: MessageDescriptor; predicate: '>' | '<' | '=' } > = { search: { - translationKey: translations.search, + translationKey: messages.search, predicate: '=', }, published_at_from: { - translationKey: translations.start, + translationKey: messages.start, predicate: '>', }, published_at_to: { - translationKey: translations.end, + translationKey: messages.end, predicate: '<', }, reactions_from: { - translationKey: translations.reactions, + translationKey: messages.reactions, predicate: '>', }, reactions_to: { - translationKey: translations.reactions, + translationKey: messages.reactions, predicate: '<', }, votes_from: { - translationKey: translations.votes, + translationKey: messages.votes, predicate: '>', }, votes_to: { - translationKey: translations.votes, + translationKey: messages.votes, predicate: '<', }, comments_from: { - translationKey: translations.comments, + translationKey: messages.comments, predicate: '>', }, comments_to: { - translationKey: translations.comments, + translationKey: messages.comments, predicate: '<', }, }; @@ -114,7 +114,7 @@ const FilterItems = ({ filters, isEditable }: FilterItemsProps) => { return ( ); @@ -160,7 +160,7 @@ const FilterItems = ({ filters, isEditable }: FilterItemsProps) => { removeSearchParams([key]); }} a11y_buttonActionMessage={formatMessage( - translations.removeFilter + messages.removeFilter )} /> )} diff --git a/front/app/containers/Admin/projects/project/analysis/FilterItems/translations.ts b/front/app/containers/Admin/projects/project/analysis/FilterItems/messages.ts similarity index 100% rename from front/app/containers/Admin/projects/project/analysis/FilterItems/translations.ts rename to front/app/containers/Admin/projects/project/analysis/FilterItems/messages.ts diff --git a/front/app/containers/Admin/projects/project/analysis/InputPreview/LongFieldValue.tsx b/front/app/containers/Admin/projects/project/analysis/InputPreview/LongFieldValue.tsx index 41befa751250..948cf9b186b1 100644 --- a/front/app/containers/Admin/projects/project/analysis/InputPreview/LongFieldValue.tsx +++ b/front/app/containers/Admin/projects/project/analysis/InputPreview/LongFieldValue.tsx @@ -22,7 +22,7 @@ import { trackEventByName } from 'utils/analytics'; import tracks from '../tracks'; import { useIntl } from 'utils/cl-intl'; -import translations from '../translations'; +import messages from '../messages'; type Props = { customFieldId: string; @@ -78,8 +78,8 @@ const FilterToggleButton = ({ customFieldId, value }) => { content={ {isFilterSet - ? formatMessage(translations.removeFilter) - : formatMessage(translations.filter)} + ? formatMessage(messages.removeFilter) + : formatMessage(messages.filter)} } /> @@ -153,7 +153,7 @@ const FieldValue = ({ projectId, phaseId, customFieldId, input }: Props) => { {input.attributes.custom_field_values[ customField.data.attributes.key - ] || formatMessage(translations.noAnswer)} + ] || formatMessage(messages.noAnswer)} ); @@ -172,7 +172,7 @@ const FieldValue = ({ projectId, phaseId, customFieldId, input }: Props) => { {input.attributes.custom_field_values[ customField.data.attributes.key - ] || formatMessage(translations.noAnswer)} + ] || formatMessage(messages.noAnswer)} { {input.attributes.custom_field_values[ customField.data.attributes.key - ] || formatMessage(translations.noAnswer)} + ] || formatMessage(messages.noAnswer)} ); @@ -265,7 +265,7 @@ const FieldValue = ({ projectId, phaseId, customFieldId, input }: Props) => { {rawValue === true || rawValue === false ? ( {}} /> ) : ( - formatMessage(translations.noAnswer) + formatMessage(messages.noAnswer) )} @@ -281,7 +281,7 @@ const FieldValue = ({ projectId, phaseId, customFieldId, input }: Props) => { {rawValue ? ( ) : ( - formatMessage(translations.noAnswer) + formatMessage(messages.noAnswer) )} diff --git a/front/app/containers/Admin/projects/project/analysis/InputPreview/index.tsx b/front/app/containers/Admin/projects/project/analysis/InputPreview/index.tsx index eeab37ae27fe..ee40f9cd5c51 100644 --- a/front/app/containers/Admin/projects/project/analysis/InputPreview/index.tsx +++ b/front/app/containers/Admin/projects/project/analysis/InputPreview/index.tsx @@ -14,7 +14,7 @@ import useAnalysisUserById from 'api/analysis_users/useAnalysisUserById'; import { getFullName } from 'utils/textUtils'; import { useSelectedInputContext } from '../SelectedInputContext'; import { useIntl } from 'utils/cl-intl'; -import translations from './translations'; +import messages from './messages'; const InputListItem = () => { const { formatMessage } = useIntl(); @@ -47,7 +47,7 @@ const InputListItem = () => { size="s" padding="4px 8px" > - {formatMessage(translations.manageIdea)} + {formatMessage(messages.manageIdea)} )} diff --git a/front/app/containers/Admin/projects/project/analysis/InputPreview/translations.ts b/front/app/containers/Admin/projects/project/analysis/InputPreview/messages.ts similarity index 100% rename from front/app/containers/Admin/projects/project/analysis/InputPreview/translations.ts rename to front/app/containers/Admin/projects/project/analysis/InputPreview/messages.ts diff --git a/front/app/containers/Admin/projects/project/analysis/InputsList/InputListItem.tsx b/front/app/containers/Admin/projects/project/analysis/InputsList/InputListItem.tsx index 33ecc37692dc..190d4fbcab28 100644 --- a/front/app/containers/Admin/projects/project/analysis/InputsList/InputListItem.tsx +++ b/front/app/containers/Admin/projects/project/analysis/InputsList/InputListItem.tsx @@ -16,7 +16,7 @@ import useAnalysis from 'api/analyses/useAnalysis'; import InputShortFieldValue from './FieldValue'; import { trackEventByName } from 'utils/analytics'; import tracks from '../tracks'; -import translations from './translations'; +import messages from './messages'; interface Props { input: IInputsData; @@ -66,7 +66,7 @@ const InputListItem = memo(({ input, onSelect, selected }: Props) => { ))} {!title_multiloc || (isEmpty(title_multiloc) && !author && ( - {formatMessage(translations.anonymous)} + {formatMessage(messages.anonymous)} ))} {title_multiloc && ( diff --git a/front/app/containers/Admin/projects/project/analysis/InputsList/index.tsx b/front/app/containers/Admin/projects/project/analysis/InputsList/index.tsx index dd2792b4c31c..4d5b60c696d6 100644 --- a/front/app/containers/Admin/projects/project/analysis/InputsList/index.tsx +++ b/front/app/containers/Admin/projects/project/analysis/InputsList/index.tsx @@ -13,7 +13,7 @@ import useAnalysisFilterParams from '../hooks/useAnalysisFilterParams'; import useKeyPress from 'hooks/useKeyPress'; import { useSelectedInputContext } from '../SelectedInputContext'; import InputListItem from './InputListItem'; -import translations from './translations'; +import messages from './messages'; import { useIntl } from 'utils/cl-intl'; import { useVirtualizer } from '@tanstack/react-virtual'; import Demographics from '../Demographics'; @@ -151,7 +151,7 @@ const InputsList = () => { {emptyList ? ( - {formatMessage(translations.noInputs)} + {formatMessage(messages.noInputs)} ) : ( diff --git a/front/app/containers/Admin/projects/project/analysis/InputsList/translations.ts b/front/app/containers/Admin/projects/project/analysis/InputsList/messages.ts similarity index 100% rename from front/app/containers/Admin/projects/project/analysis/InputsList/translations.ts rename to front/app/containers/Admin/projects/project/analysis/InputsList/messages.ts diff --git a/front/app/containers/Admin/projects/project/analysis/translations.ts b/front/app/containers/Admin/projects/project/analysis/messages.ts similarity index 100% rename from front/app/containers/Admin/projects/project/analysis/translations.ts rename to front/app/containers/Admin/projects/project/analysis/messages.ts From cc330666c98429714731ced98ae73e4c8a2231ac Mon Sep 17 00:00:00 2001 From: Iva Date: Mon, 2 Oct 2023 13:07:24 +0300 Subject: [PATCH 008/328] Insights and top bar --- .../project/analysis/Insights/Question.tsx | 22 ++++++++----------- .../analysis/Insights/QuestionButton.tsx | 14 ++++++------ .../analysis/Insights/QuestionInput.tsx | 4 ++-- .../project/analysis/Insights/Rate.tsx | 6 ++--- .../analysis/Insights/SummarizeButton.tsx | 14 ++++++------ .../project/analysis/Insights/Summary.tsx | 20 ++++++++--------- .../project/analysis/Insights/index.tsx | 8 +++---- .../Insights/{translations.ts => messages.ts} | 0 .../analysis/TopBar/Filters/AuthorFilters.tsx | 16 +++++++------- .../TopBar/Filters/EngagementFilter.tsx | 6 ++--- .../project/analysis/TopBar/Filters/index.tsx | 14 ++++++------ .../project/analysis/TopBar/index.tsx | 10 ++++----- .../TopBar/{translations.ts => messages.ts} | 0 13 files changed, 63 insertions(+), 71 deletions(-) rename front/app/containers/Admin/projects/project/analysis/Insights/{translations.ts => messages.ts} (100%) rename front/app/containers/Admin/projects/project/analysis/TopBar/{translations.ts => messages.ts} (100%) diff --git a/front/app/containers/Admin/projects/project/analysis/Insights/Question.tsx b/front/app/containers/Admin/projects/project/analysis/Insights/Question.tsx index 5e96ddf437a7..3282afee30ba 100644 --- a/front/app/containers/Admin/projects/project/analysis/Insights/Question.tsx +++ b/front/app/containers/Admin/projects/project/analysis/Insights/Question.tsx @@ -28,7 +28,7 @@ import Rate from './Rate'; import tracks from 'containers/Admin/projects/project/analysis/tracks'; import { trackEventByName } from 'utils/analytics'; -import translations from './translations'; +import messages from './messages'; import { deleteTrailingIncompleteIDs, refRegex, removeRefs } from './util'; import useToggleInsightBookmark from 'api/analysis_insights/useBookmarkAnalysisInsight'; @@ -69,9 +69,7 @@ const Question = ({ insight }: Props) => { backgroundTask?.data.attributes.state === 'queued'; const handleQuestionDelete = (id: string) => { - if ( - window.confirm(formatMessage(translations.deleteQuestionConfirmation)) - ) { + if (window.confirm(formatMessage(messages.deleteQuestionConfirmation))) { deleteQuestion( { analysisId, @@ -173,7 +171,7 @@ const Question = ({ insight }: Props) => { > {hasFilters && ( <> - {formatMessage(translations.questionFor)} + {formatMessage(messages.questionFor)} { )} {!hasFilters && ( - - {formatMessage(translations.questionForAllInputs)} - + {formatMessage(messages.questionForAllInputs)} )} @@ -204,10 +200,10 @@ const Question = ({ insight }: Props) => { {question.data.attributes.accuracy && ( @@ -221,7 +217,7 @@ const Question = ({ insight }: Props) => { mt="16px" > @@ -230,7 +226,7 @@ const Question = ({ insight }: Props) => { onClick={() => handleQuestionDelete(insight.id)} iconColor={colors.teal400} iconColorOnHover={colors.teal700} - a11y_buttonActionMessage={formatMessage(translations.deleteSummary)} + a11y_buttonActionMessage={formatMessage(messages.deleteSummary)} /> { } iconColor={colors.teal400} iconColorOnHover={colors.teal700} - a11y_buttonActionMessage={formatMessage(translations.deleteSummary)} + a11y_buttonActionMessage={formatMessage(messages.deleteSummary)} onClick={() => toggleBookmark({ analysisId, id: insight.id })} /> diff --git a/front/app/containers/Admin/projects/project/analysis/Insights/QuestionButton.tsx b/front/app/containers/Admin/projects/project/analysis/Insights/QuestionButton.tsx index 96ced5ac2c94..00117ac45ac7 100644 --- a/front/app/containers/Admin/projects/project/analysis/Insights/QuestionButton.tsx +++ b/front/app/containers/Admin/projects/project/analysis/Insights/QuestionButton.tsx @@ -11,7 +11,7 @@ import useAddAnalysisQuestionPreCheck from 'api/analysis_question_pre_check/useA import { IQuestionPreCheck } from 'api/analysis_question_pre_check/types'; import { useIntl, FormattedMessage } from 'utils/cl-intl'; -import translations from './translations'; +import messages from './messages'; const QuestionButton = ({ onClick }: { onClick: () => void }) => { const { formatMessage } = useIntl(); @@ -48,31 +48,31 @@ const QuestionButton = ({ onClick }: { onClick: () => void }) => { disabled={!questionPossible} whiteSpace="wrap" > - {formatMessage(translations.askQuestion)} + {formatMessage(messages.askQuestion)}
{questionPossible && questionAccuracy && ( <> )} {!questionPossible && ( <> - + )} diff --git a/front/app/containers/Admin/projects/project/analysis/Insights/QuestionInput.tsx b/front/app/containers/Admin/projects/project/analysis/Insights/QuestionInput.tsx index 0e8ee2389a81..7e6ae7e2078e 100644 --- a/front/app/containers/Admin/projects/project/analysis/Insights/QuestionInput.tsx +++ b/front/app/containers/Admin/projects/project/analysis/Insights/QuestionInput.tsx @@ -14,7 +14,7 @@ import tracks from 'containers/Admin/projects/project/analysis/tracks'; import { trackEventByName } from 'utils/analytics'; import { useIntl } from 'utils/cl-intl'; -import translations from './translations'; +import messages from './messages'; const QuestionInput = ({ onClose }: { onClose: () => void }) => { const [question, setQuestion] = useState(''); @@ -66,7 +66,7 @@ const QuestionInput = ({ onClose }: { onClose: () => void }) => { disabled={!question} type="submit" > - {formatMessage(translations.ask)} + {formatMessage(messages.ask)} diff --git a/front/app/containers/Admin/projects/project/analysis/Insights/Rate.tsx b/front/app/containers/Admin/projects/project/analysis/Insights/Rate.tsx index 345fb8c00160..7b707f062011 100644 --- a/front/app/containers/Admin/projects/project/analysis/Insights/Rate.tsx +++ b/front/app/containers/Admin/projects/project/analysis/Insights/Rate.tsx @@ -8,7 +8,7 @@ import { } from '@citizenlab/cl2-component-library'; import { useIntl } from 'utils/cl-intl'; -import translations from './translations'; +import messages from './messages'; import useRateAnalysisInsight from 'api/analysis_insights/useRateAnalysisInsight'; import { useParams } from 'react-router-dom'; @@ -52,11 +52,11 @@ const Rate = ({ insightId }: { insightId: string }) => { gap="8px" > - {formatMessage(translations.thankYou)} + {formatMessage(messages.thankYou)} ) : ( - {formatMessage(translations.rate)} + {formatMessage(messages.rate)} { const { formatMessage } = useIntl(); @@ -70,31 +70,31 @@ const SummarizeButton = () => { processing={isLoadingPreCheck || isLoadingSummary} whiteSpace="wrap" > - {formatMessage(translations.summarize)} + {formatMessage(messages.summarize)}
{summaryPossible && summaryAccuracy && ( <> )} {!summaryPossible && ( <> - + )} diff --git a/front/app/containers/Admin/projects/project/analysis/Insights/Summary.tsx b/front/app/containers/Admin/projects/project/analysis/Insights/Summary.tsx index a73a4f21f60a..be91c3aadf7c 100644 --- a/front/app/containers/Admin/projects/project/analysis/Insights/Summary.tsx +++ b/front/app/containers/Admin/projects/project/analysis/Insights/Summary.tsx @@ -18,7 +18,7 @@ import { } from '@citizenlab/cl2-component-library'; import { useIntl, FormattedMessage } from 'utils/cl-intl'; -import translations from './translations'; +import messages from './messages'; import styled from 'styled-components'; import { useSelectedInputContext } from '../SelectedInputContext'; import useAnalysisSummary from 'api/analysis_summaries/useAnalysisSummary'; @@ -70,7 +70,7 @@ const Summary = ({ insight }: Props) => { backgroundTask?.data.attributes.state === 'queued'; const handleSummaryDelete = (id: string) => { - if (window.confirm(formatMessage(translations.deleteSummaryConfirmation))) { + if (window.confirm(formatMessage(messages.deleteSummaryConfirmation))) { deleteSummary( { analysisId, @@ -171,7 +171,7 @@ const Summary = ({ insight }: Props) => { > {hasFilters && ( <> - {formatMessage(translations.summaryFor)} + {formatMessage(messages.summaryFor)} { {!hasFilters && ( <> - - {formatMessage(translations.summaryForAllInputs)} - + {formatMessage(messages.summaryForAllInputs)} )} @@ -204,10 +202,10 @@ const Summary = ({ insight }: Props) => { {summary.data.attributes.accuracy && ( @@ -222,7 +220,7 @@ const Summary = ({ insight }: Props) => { mt="16px" > { onClick={() => handleSummaryDelete(insight.id)} iconColor={colors.teal400} iconColorOnHover={colors.teal700} - a11y_buttonActionMessage={formatMessage(translations.deleteSummary)} + a11y_buttonActionMessage={formatMessage(messages.deleteSummary)} /> { } iconColor={colors.teal400} iconColorOnHover={colors.teal700} - a11y_buttonActionMessage={formatMessage(translations.deleteSummary)} + a11y_buttonActionMessage={formatMessage(messages.deleteSummary)} onClick={() => toggleBookmark({ analysisId, id: insight.id })} /> diff --git a/front/app/containers/Admin/projects/project/analysis/Insights/index.tsx b/front/app/containers/Admin/projects/project/analysis/Insights/index.tsx index e089b41bfb5f..d97f6f0aee03 100644 --- a/front/app/containers/Admin/projects/project/analysis/Insights/index.tsx +++ b/front/app/containers/Admin/projects/project/analysis/Insights/index.tsx @@ -13,7 +13,7 @@ import QuestionInput from './QuestionInput'; import Question from './Question'; import useAnalysisFilterParams from '../hooks/useAnalysisFilterParams'; import useInfiniteAnalysisInputs from 'api/analysis_inputs/useInfiniteAnalysisInputs'; -import translations from './translations'; +import messages from './messages'; import { useIntl } from 'utils/cl-intl'; const Insights = () => { @@ -45,7 +45,7 @@ const Insights = () => {
- {formatMessage(translations.appliesTo)} ({inputsCount}) + {formatMessage(messages.appliesTo)} ({inputsCount}) @@ -66,10 +66,10 @@ const Insights = () => { {!isLoading && insights?.data?.length === 0 && ( <> - {formatMessage(translations.emptyList)} + {formatMessage(messages.emptyList)} - {formatMessage(translations.emptyListDescription)} + {formatMessage(messages.emptyListDescription)} )} diff --git a/front/app/containers/Admin/projects/project/analysis/Insights/translations.ts b/front/app/containers/Admin/projects/project/analysis/Insights/messages.ts similarity index 100% rename from front/app/containers/Admin/projects/project/analysis/Insights/translations.ts rename to front/app/containers/Admin/projects/project/analysis/Insights/messages.ts diff --git a/front/app/containers/Admin/projects/project/analysis/TopBar/Filters/AuthorFilters.tsx b/front/app/containers/Admin/projects/project/analysis/TopBar/Filters/AuthorFilters.tsx index dc1808dc1dc9..c686821d3936 100644 --- a/front/app/containers/Admin/projects/project/analysis/TopBar/Filters/AuthorFilters.tsx +++ b/front/app/containers/Admin/projects/project/analysis/TopBar/Filters/AuthorFilters.tsx @@ -12,7 +12,7 @@ import useLocalize from 'hooks/useLocalize'; import { updateSearchParams } from 'utils/cl-router/updateSearchParams'; import { useSearchParams } from 'react-router-dom'; import { useIntl } from 'utils/cl-intl'; -import translations from '../translations'; +import messages from '../messages'; import { handleArraySearchParam } from '../../util'; import { trackEventByName } from 'utils/analytics'; import tracks from '../../tracks'; @@ -78,7 +78,7 @@ const AuthorFilters = () => { return ( - {formatMessage(translations.gender)} + {formatMessage(messages.gender)} {genderOptions?.data.map((option) => ( @@ -121,7 +121,7 @@ const AuthorFilters = () => { ))} - {formatMessage(translations.domicile)} + {formatMessage(messages.domicile)} {domicileOptions?.data.map((option) => ( @@ -165,12 +165,12 @@ const AuthorFilters = () => { {birthyearField && ( - + { updateSearchParams({ diff --git a/front/app/containers/Admin/projects/project/analysis/TopBar/Filters/EngagementFilter.tsx b/front/app/containers/Admin/projects/project/analysis/TopBar/Filters/EngagementFilter.tsx index a906b42ea65c..27b30bbeb5a0 100644 --- a/front/app/containers/Admin/projects/project/analysis/TopBar/Filters/EngagementFilter.tsx +++ b/front/app/containers/Admin/projects/project/analysis/TopBar/Filters/EngagementFilter.tsx @@ -7,7 +7,7 @@ import { removeSearchParams } from 'utils/cl-router/removeSearchParams'; import { useSearchParams } from 'react-router-dom'; import { useIntl } from 'utils/cl-intl'; -import translations from '../translations'; +import messages from '../messages'; import { trackEventByName } from 'utils/analytics'; import tracks from '../../tracks'; @@ -38,11 +38,11 @@ const EngagementFilter = ({ + + + + + + +
+ +
+
+
+ + + +
+ +
+
+
+ + + +
+ +
+
+
+ + + +
+ +
+
+
+ + + +
+ +
+
+
+ + + +
+ +
+
+
+ + + +
+ +
+
+
diff --git a/cl2-component-library/src/components/Input/Input.test.tsx b/cl2-component-library/src/components/Input/Input.test.tsx new file mode 100644 index 000000000000..4c768d4a9baa --- /dev/null +++ b/cl2-component-library/src/components/Input/Input.test.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { render, screen } from '../../utils/testUtils/rtl'; +import Input from '.'; + +describe('', () => { + it('renders', () => { + render(); + expect(screen.getByDisplayValue('Test Input')).toBeInTheDocument(); + }); +}); diff --git a/cl2-component-library/src/components/Input/InputMultiloc.tsx b/cl2-component-library/src/components/Input/InputMultiloc.tsx new file mode 100644 index 000000000000..56db615d834f --- /dev/null +++ b/cl2-component-library/src/components/Input/InputMultiloc.tsx @@ -0,0 +1,118 @@ +import React, { PureComponent } from 'react'; + +// components +import Input, { InputProps } from '.'; +import IconTooltip from '../IconTooltip'; +import Label from '../Label'; + +// utils +import { isNilOrError } from '../../utils/helperUtils'; + +// style +import styled from 'styled-components'; + +// typings +import { Locale, Multiloc } from '../../utils/typings'; + +const Container = styled.div``; + +const InputWrapper = styled.div` + &:not(.last) { + margin-bottom: 10px; + } +`; + +const LanguageExtension = styled.span` + font-weight: 500; +`; + +export interface Props + extends Omit { + valueMultiloc: Multiloc | null | undefined; + locales: Locale[]; + errorMultiloc?: Multiloc | null; + onChange?: (arg: Multiloc, locale: Locale) => void; +} + +class InputMultiloc extends PureComponent { + handleOnChange = (value: string, locale: Locale | undefined) => { + if (locale && this.props.onChange) { + this.props.onChange( + { + ...this.props.valueMultiloc, + [locale]: value, + }, + locale + ); + } + }; + + render() { + const { + id, + valueMultiloc, + label, + labelTooltipText, + onBlur, + type, + placeholder, + errorMultiloc, + maxCharCount, + disabled, + ariaLabel, + className, + locales, + } = this.props; + + if (!isNilOrError(locales)) { + return ( + + {locales.map((locale, index) => { + const value = valueMultiloc?.[locale] || null; + const error = errorMultiloc?.[locale] || null; + const inputId = id && `${id}-${locale}`; + + return ( + + {label && ( + + )} + + + + ); + })} + + ); + } + + return null; + } +} + +export default InputMultiloc; diff --git a/cl2-component-library/src/components/Input/InputMultilocWithLocaleSwitcher.test.tsx b/cl2-component-library/src/components/Input/InputMultilocWithLocaleSwitcher.test.tsx new file mode 100644 index 000000000000..2271269c9e38 --- /dev/null +++ b/cl2-component-library/src/components/Input/InputMultilocWithLocaleSwitcher.test.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { render, screen } from '../../utils/testUtils/rtl'; +import InputMultilocWithLocaleSwitcher from './InputMultilocWithLocaleSwitcher'; + +const locales = ['en', 'fr-BE']; + +const valueMultiloc = { + "en": "English value", + "fr-BE": "French value" +} + +describe('', () => { + it('renders', () => { + render( + + ); + expect(screen.getByDisplayValue('English value')).toBeInTheDocument(); + }); + it('renders correct initial locale when set', () => { + render( + + ); + expect(screen.getByDisplayValue('French value')).toBeInTheDocument(); + }); +}); diff --git a/cl2-component-library/src/components/Input/InputMultilocWithLocaleSwitcher.tsx b/cl2-component-library/src/components/Input/InputMultilocWithLocaleSwitcher.tsx new file mode 100644 index 000000000000..47bc857a4c23 --- /dev/null +++ b/cl2-component-library/src/components/Input/InputMultilocWithLocaleSwitcher.tsx @@ -0,0 +1,145 @@ +import React, { memo, useState, useCallback, useEffect } from 'react'; +import { isNilOrError } from '../../utils/helperUtils'; + +// components +import Input, { InputProps } from '.'; +import IconTooltip from '../IconTooltip'; +import LocaleSwitcher from '../LocaleSwitcher'; +import Label from '../Label'; + +// style +import styled from 'styled-components'; + +// typings +import { Locale, Multiloc } from '../../utils/typings'; +import Box from '../Box'; + +const LabelContainer = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; +`; + +const StyledLabel = styled(Label)` + flex: 1; + padding-bottom: 0px; +`; + +const Spacer = styled.div` + flex: 1; +`; + +const StyledLocaleSwitcher = styled(LocaleSwitcher)` + width: auto; +`; + +export interface Props extends Omit { + valueMultiloc: Multiloc | null | undefined; + locales: Locale[]; + onChange?: (value: Multiloc, locale?: Locale) => void; + onSelectedLocaleChange?: (locale: Locale) => void; + errorMultiloc?: Multiloc | null; + initiallySelectedLocale?: Locale; +} + +const InputMultilocWithLocaleSwitcher = memo((props) => { + const { + valueMultiloc, + locales, + onChange, + onSelectedLocaleChange, + label, + labelTooltipText, + errorMultiloc, + initiallySelectedLocale, + ...inputProps + } = props; + const { id, className } = props; + const [selectedLocale, setSelectedLocale] = useState( + initiallySelectedLocale ? initiallySelectedLocale : locales[0] + ); + const [error, setError] = useState(null); + + useEffect(() => { + if (errorMultiloc) { + const localesWithError = Object.keys(errorMultiloc).filter((locale) => { + const errorForLocale = errorMultiloc?.[locale]; + return ( + errorForLocale && + typeof errorForLocale === 'string' && + errorForLocale.length > 0 + ); + }); + + if (localesWithError.length > 0) { + const firstLocaleWithError = localesWithError[0]; + const firstError = errorMultiloc[firstLocaleWithError] as string; + setError(firstError); + setSelectedLocale(firstLocaleWithError); + } + } else { + setError(null); + } + }, [errorMultiloc]); + + const handleValueOnChange = useCallback( + (value: string) => { + if (onChange && !isNilOrError(selectedLocale)) { + onChange( + { + ...valueMultiloc, + [selectedLocale]: value, + }, + selectedLocale + ); + } + }, + [valueMultiloc, selectedLocale, onChange] + ); + + const handleOnSelectedLocaleChange = useCallback( + (newSelectedLocale: Locale) => { + setSelectedLocale(newSelectedLocale); + onSelectedLocaleChange?.(newSelectedLocale); + }, + [onSelectedLocaleChange] + ); + + if (selectedLocale) { + return ( + + + + {label ? ( + + {label} + {labelTooltipText && } + + ) : ( + + )} + + + + + + ); + } + + return null; +}); + +export default InputMultilocWithLocaleSwitcher; diff --git a/cl2-component-library/src/components/Input/index.tsx b/cl2-component-library/src/components/Input/index.tsx new file mode 100644 index 000000000000..48ed3ab5afc7 --- /dev/null +++ b/cl2-component-library/src/components/Input/index.tsx @@ -0,0 +1,227 @@ +import React, { PureComponent, FormEvent } from 'react'; +import { isNil, isEmpty, size as lodashSize, isBoolean } from 'lodash'; + +// components +import Error from '../Error'; +import Label from '../Label'; +import IconTooltip from '../IconTooltip'; + +// style +import styled from 'styled-components'; +import { + colors, + fontSizes, + defaultInputStyle, + defaultStyles, + isRtl, +} from '../../utils/styleUtils'; +import { ScreenReaderOnly } from '../../utils/a11y'; + +// typings +import { Locale, InputSize } from '../../utils/typings'; + +interface ContainerProps { + size: InputSize; +} + +const Container = styled.div` + width: 100%; + position: relative; + + input { + width: 100%; + + &.hasMaxCharCount { + padding-right: 62px; + } + ${isRtl` + &.hasMaxCharCount { + padding-right: ${defaultStyles.inputPadding}; + padding-left: 62px; + }`} + ${defaultInputStyle}; + } +`; + +const CharCount = styled.div<{ inputSize?: InputSize }>` + color: ${colors.textSecondary}; + font-size: ${fontSizes.s}px; + font-weight: 400; + text-align: right; + position: absolute; + bottom: ${({ inputSize }) => (inputSize === 'small' ? '10px' : '14px')}; + right: 10px; + + ${isRtl` + left: 10px; + right: auto; + `} + + &.error { + color: red; + } +`; + +export interface InputProps { + ariaLabel?: string; + id?: string; + label?: string | JSX.Element | null; + labelTooltipText?: string | JSX.Element | null; + value?: string | null; + locale?: Locale; + type: 'text' | 'email' | 'password' | 'number' | 'date'; + placeholder?: string | null; + error?: string | null; + onChange?: (arg: string, locale: Locale | undefined) => void; + onFocus?: (arg: FormEvent) => void; + onBlur?: (arg: FormEvent) => void; + setRef?: (arg: HTMLInputElement) => void | undefined; + autoFocus?: boolean; + min?: string; + max?: string; + name?: string; + maxCharCount?: number; + disabled?: boolean; + spellCheck?: boolean; + readOnly?: boolean; + required?: boolean; + autocomplete?: + | 'email' + | 'given-name' + | 'family-name' + | 'current-password' + | 'new-password' + | 'off' + | 'on'; // https://www.w3.org/TR/WCAG21/#input-purposes + a11yCharactersLeftMessage?: string; + className?: string; + size?: InputSize; + 'data-testid'?: string; +} + +class Input extends PureComponent { + handleOnChange = (event: FormEvent) => { + const { maxCharCount, onChange, locale } = this.props; + + if ( + !maxCharCount || + lodashSize(event.currentTarget.value) <= maxCharCount + ) { + if (onChange) { + onChange(event.currentTarget.value, locale); + } + } + }; + + handleOnBlur = (event: FormEvent) => { + const { onBlur } = this.props; + + if (onBlur) { + onBlur(event); + } + }; + + handleRef = (element: HTMLInputElement) => { + this.props.setRef && this.props.setRef(element); + }; + + render() { + const { + label, + labelTooltipText, + ariaLabel, + a11yCharactersLeftMessage, + className, + } = this.props; + const { + id, + type, + name, + maxCharCount, + min, + max, + autoFocus, + onFocus, + disabled, + spellCheck, + readOnly, + required, + autocomplete, + size = 'medium', + 'data-testid': dataTestId, + } = this.props; + const hasError = !isNil(this.props.error) && !isEmpty(this.props.error); + const optionalProps = isBoolean(spellCheck) ? { spellCheck } : null; + const value = !isNil(this.props.value) ? this.props.value : ''; + const placeholder = this.props.placeholder || ''; + const error = this.props.error || null; + const currentCharCount = maxCharCount && lodashSize(value); + const tooManyChars = !!( + maxCharCount && + currentCharCount && + currentCharCount > maxCharCount + ); + + return ( + + {label && ( + + )} + + + + {maxCharCount && ( + <> + {a11yCharactersLeftMessage && ( + + {a11yCharactersLeftMessage} + + )} + + {currentCharCount}/{maxCharCount} + + + )} + + + + ); + } +} + +export default Input; diff --git a/cl2-component-library/src/components/Label/Label.test.tsx b/cl2-component-library/src/components/Label/Label.test.tsx new file mode 100644 index 000000000000..ce9ed343a1be --- /dev/null +++ b/cl2-component-library/src/components/Label/Label.test.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { render, screen } from '../../utils/testUtils/rtl'; +import Label from '.'; + +describe('