diff --git a/src/goals/MergeDuplicates/MergeDupsStep/MergeDragDrop/DropWord.tsx b/src/goals/MergeDuplicates/MergeDupsStep/MergeDragDrop/DropWord.tsx index 2d80007ec7..c6eea5c812 100644 --- a/src/goals/MergeDuplicates/MergeDupsStep/MergeDragDrop/DropWord.tsx +++ b/src/goals/MergeDuplicates/MergeDupsStep/MergeDragDrop/DropWord.tsx @@ -11,7 +11,7 @@ import { type ReactElement } from "react"; import { Droppable } from "react-beautiful-dnd"; import { useTranslation } from "react-i18next"; -import { type Flag, type ProtectReason, ReasonType } from "api/models"; +import { type Flag } from "api/models"; import { FlagButton, IconButtonWithTooltip, @@ -20,6 +20,7 @@ import { import MultilineTooltipTitle from "components/MultilineTooltipTitle"; import { AudioSummary } from "components/WordCard"; import DragSense from "goals/MergeDuplicates/MergeDupsStep/MergeDragDrop/DragSense"; +import { protectReasonsText } from "goals/MergeDuplicates/MergeDupsStep/protectReasonUtils"; import { type MergeTreeWord } from "goals/MergeDuplicates/MergeDupsTreeTypes"; import { flagWord, @@ -164,68 +165,10 @@ export function DropWordCardHeader(
); - const reasonText = (reason: ProtectReason): string => { - // Backend/Helper/LiftHelper.cs > GetProtectedReasons(LiftEntry entry) - switch (reason.type) { - case ReasonType.Annotations: - return t("mergeDups.protectReason.annotations"); - case ReasonType.Etymologies: - return t("mergeDups.protectReason.etymologies"); - case ReasonType.Field: - return t("mergeDups.protectReason.field", { val: reason.value }); - case ReasonType.NoteWithType: - return t("mergeDups.protectReason.noteWithType", { val: reason.value }); - case ReasonType.Notes: - return t("mergeDups.protectReason.notesWord"); - case ReasonType.Relations: - return t("mergeDups.protectReason.relations"); - case ReasonType.Trait: - return reason.value ?? "(unknown trait)"; - case ReasonType.TraitDialectLabels: - return t("mergeDups.protectReason.traitDialectLabels", { - val: reason.value, - }); - case ReasonType.TraitDoNotPublishIn: - return t("mergeDups.protectReason.traitDoNotPublishIn", { - val: reason.value, - }); - case ReasonType.TraitDoNotUseForParsing: - return t("mergeDups.protectReason.traitDoNotUseForParsing", { - val: reason.value, - }); - case ReasonType.TraitEntryType: - return t("mergeDups.protectReason.traitEntryType", { - val: reason.value, - }); - case ReasonType.TraitExcludeAsHeadword: - return t("mergeDups.protectReason.traitExcludeAsHeadword"); - case ReasonType.TraitMinorEntryCondition: - return t("mergeDups.protectReason.traitMinorEntryCondition", { - val: reason.value, - }); - case ReasonType.TraitMorphType: - return t("mergeDups.protectReason.traitMorphType", { - val: reason.value, - }); - case ReasonType.TraitPublishIn: - return t("mergeDups.protectReason.traitPublishIn", { - val: reason.value, - }); - case ReasonType.Variants: - return t("mergeDups.protectReason.variants"); - default: - throw new Error(); - } - }; - const tooltipTexts = [t("mergeDups.helpText.protectedWord")]; const reasons = words[props.wordId]?.protectReasons; if (reasons?.length) { - tooltipTexts.push( - t("mergeDups.helpText.protectedData", { - val: reasons.map(reasonText).join("; "), - }) - ); + tooltipTexts.push(protectReasonsText(t, { word: reasons })); } tooltipTexts.push(t("mergeDups.helpText.protectedWordInfo")); diff --git a/src/goals/MergeDuplicates/MergeDupsStep/SenseCardContent.tsx b/src/goals/MergeDuplicates/MergeDupsStep/SenseCardContent.tsx index 252e431053..ea72dcd0a3 100644 --- a/src/goals/MergeDuplicates/MergeDupsStep/SenseCardContent.tsx +++ b/src/goals/MergeDuplicates/MergeDupsStep/SenseCardContent.tsx @@ -3,17 +3,12 @@ import { CardContent, IconButton } from "@mui/material"; import { type ReactElement } from "react"; import { useTranslation } from "react-i18next"; -import { - GramCatGroup, - type ProtectReason, - ReasonType, - type Sense, - Status, -} from "api/models"; +import { GramCatGroup, type Sense, Status } from "api/models"; import { IconButtonWithTooltip, PartOfSpeechButton } from "components/Buttons"; import MultilineTooltipTitle from "components/MultilineTooltipTitle"; import DomainChipsGrid from "components/WordCard/DomainChipsGrid"; import SenseCardText from "components/WordCard/SenseCardText"; +import { protectReasonsText } from "goals/MergeDuplicates/MergeDupsStep/protectReasonUtils"; import { combineSenses } from "goals/MergeDuplicates/Redux/reducerUtilities"; interface SenseCardContentProps { @@ -41,72 +36,12 @@ export default function SenseCardContent( a.id.localeCompare(b.id) ); - const reasonText = (reason: ProtectReason): string => { - // Backend/Helper/LiftHelper.cs > GetProtectedReasons(LiftSense sense) - switch (reason.type) { - case ReasonType.Annotations: - return t("mergeDups.protectReason.annotations"); - case ReasonType.Examples: - return t("mergeDups.protectReason.examples"); - case ReasonType.Field: - return t("mergeDups.protectReason.field", { val: reason.value }); - case ReasonType.GramInfoTrait: - return t("mergeDups.protectReason.gramInfoTrait", { - val: reason.value, - }); - case ReasonType.Illustrations: - return t("mergeDups.protectReason.illustrations"); - case ReasonType.Notes: - return t("mergeDups.protectReason.notesSense"); - case ReasonType.Relations: - return t("mergeDups.protectReason.relations"); - case ReasonType.Reversals: - return t("mergeDups.protectReason.reversal", { val: reason.value }); - case ReasonType.Subsenses: - return t("mergeDups.protectReason.subsenses"); - case ReasonType.Trait: - return reason.value ?? "(unknown trait)"; - case ReasonType.TraitAnthroCode: - return t("mergeDups.protectReason.traitAnthroCode", { - val: reason.value, - }); - case ReasonType.TraitDomainType: - return t("mergeDups.protectReason.traitDomainType", { - val: reason.value, - }); - case ReasonType.TraitDoNotPublishIn: - return t("mergeDups.protectReason.traitDoNotPublishIn", { - val: reason.value, - }); - case ReasonType.TraitPublishIn: - return t("mergeDups.protectReason.traitPublishIn", { - val: reason.value, - }); - case ReasonType.TraitSenseType: - return t("mergeDups.protectReason.traitSenseType", { - val: reason.value, - }); - case ReasonType.TraitStatus: - return t("mergeDups.protectReason.traitStatus", { val: reason.value }); - case ReasonType.TraitUsageType: - return t("mergeDups.protectReason.traitUsageType", { - val: reason.value, - }); - default: - throw new Error(); - } - }; - const protectedWarning = !props.sidebar && sense.accessibility === Status.Protected; const tooltipTexts = [t("mergeDups.helpText.protectedSense")]; const reasons = sense.protectReasons; if (reasons?.length) { - tooltipTexts.push( - t("mergeDups.helpText.protectedData", { - val: reasons.map(reasonText).join("; "), - }) - ); + tooltipTexts.push(protectReasonsText(t, { sense: reasons })); } tooltipTexts.push(t("mergeDups.helpText.protectedSenseInfo")); diff --git a/src/goals/MergeDuplicates/MergeDupsStep/protectReasonUtils.ts b/src/goals/MergeDuplicates/MergeDupsStep/protectReasonUtils.ts new file mode 100644 index 0000000000..88543aa133 --- /dev/null +++ b/src/goals/MergeDuplicates/MergeDupsStep/protectReasonUtils.ts @@ -0,0 +1,130 @@ +import { type TFunction } from "i18next"; + +import { type ProtectReason, ReasonType } from "api/models"; + +const sep = "; "; + +interface WordSenseReasons { + sense?: ProtectReason[]; + word?: ProtectReason[]; +} + +export function protectReasonsText( + t: TFunction, + reasons: WordSenseReasons +): string { + const wordTexts = reasons.word?.map((r) => wordReasonText(t, r)); + const senseTexts = reasons.sense?.map((r) => senseReasonText(t, r)); + const allTexts = [...(wordTexts ?? []), ...(senseTexts ?? [])]; + return t("mergeDups.helpText.protectedData", { val: allTexts.join(sep) }); +} + +/** Cases match Backend/Helper/LiftHelper.cs > GetProtectedReasons(LiftSense sense) */ +function senseReasonText(t: TFunction, reason: ProtectReason): string { + switch (reason.type) { + case ReasonType.Annotations: + return t("mergeDups.protectReason.annotations"); + case ReasonType.Examples: + return t("mergeDups.protectReason.examples"); + case ReasonType.Field: + return t("mergeDups.protectReason.field", { val: reason.value }); + case ReasonType.GramInfoTrait: + return t("mergeDups.protectReason.gramInfoTrait", { + val: reason.value, + }); + case ReasonType.Illustrations: + return t("mergeDups.protectReason.illustrations"); + case ReasonType.Notes: + return t("mergeDups.protectReason.notesSense"); + case ReasonType.Relations: + return t("mergeDups.protectReason.relations"); + case ReasonType.Reversals: + return t("mergeDups.protectReason.reversal", { val: reason.value }); + case ReasonType.Subsenses: + return t("mergeDups.protectReason.subsenses"); + case ReasonType.Trait: + return reason.value ?? "(unknown trait)"; + case ReasonType.TraitAnthroCode: + return t("mergeDups.protectReason.traitAnthroCode", { + val: reason.value, + }); + case ReasonType.TraitDomainType: + return t("mergeDups.protectReason.traitDomainType", { + val: reason.value, + }); + case ReasonType.TraitDoNotPublishIn: + return t("mergeDups.protectReason.traitDoNotPublishIn", { + val: reason.value, + }); + case ReasonType.TraitPublishIn: + return t("mergeDups.protectReason.traitPublishIn", { + val: reason.value, + }); + case ReasonType.TraitSenseType: + return t("mergeDups.protectReason.traitSenseType", { + val: reason.value, + }); + case ReasonType.TraitStatus: + return t("mergeDups.protectReason.traitStatus", { val: reason.value }); + case ReasonType.TraitUsageType: + return t("mergeDups.protectReason.traitUsageType", { + val: reason.value, + }); + default: + throw new Error(); + } +} + +/** Cases match Backend/Helper/LiftHelper.cs > GetProtectedReasons(LiftEntry entry) */ +function wordReasonText(t: TFunction, reason: ProtectReason): string { + switch (reason.type) { + case ReasonType.Annotations: + return t("mergeDups.protectReason.annotations"); + case ReasonType.Etymologies: + return t("mergeDups.protectReason.etymologies"); + case ReasonType.Field: + return t("mergeDups.protectReason.field", { val: reason.value }); + case ReasonType.NoteWithType: + return t("mergeDups.protectReason.noteWithType", { val: reason.value }); + case ReasonType.Notes: + return t("mergeDups.protectReason.notesWord"); + case ReasonType.Relations: + return t("mergeDups.protectReason.relations"); + case ReasonType.Trait: + return reason.value ?? "(unknown trait)"; + case ReasonType.TraitDialectLabels: + return t("mergeDups.protectReason.traitDialectLabels", { + val: reason.value, + }); + case ReasonType.TraitDoNotPublishIn: + return t("mergeDups.protectReason.traitDoNotPublishIn", { + val: reason.value, + }); + case ReasonType.TraitDoNotUseForParsing: + return t("mergeDups.protectReason.traitDoNotUseForParsing", { + val: reason.value, + }); + case ReasonType.TraitEntryType: + return t("mergeDups.protectReason.traitEntryType", { + val: reason.value, + }); + case ReasonType.TraitExcludeAsHeadword: + return t("mergeDups.protectReason.traitExcludeAsHeadword"); + case ReasonType.TraitMinorEntryCondition: + return t("mergeDups.protectReason.traitMinorEntryCondition", { + val: reason.value, + }); + case ReasonType.TraitMorphType: + return t("mergeDups.protectReason.traitMorphType", { + val: reason.value, + }); + case ReasonType.TraitPublishIn: + return t("mergeDups.protectReason.traitPublishIn", { + val: reason.value, + }); + case ReasonType.Variants: + return t("mergeDups.protectReason.variants"); + default: + throw new Error(); + } +}