Skip to content

Commit

Permalink
Extract protect-reason text functions
Browse files Browse the repository at this point in the history
  • Loading branch information
imnasnainaec committed Dec 13, 2024
1 parent cfdf244 commit c5e9cc6
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 137 deletions.
63 changes: 3 additions & 60 deletions src/goals/MergeDuplicates/MergeDupsStep/MergeDragDrop/DropWord.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -164,68 +165,10 @@ export function DropWordCardHeader(
<div />
);

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, reasons, []));
}
tooltipTexts.push(t("mergeDups.helpText.protectedWordInfo"));

Expand Down
27 changes: 18 additions & 9 deletions src/goals/MergeDuplicates/MergeDupsStep/MergeDragDrop/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import { DragDropContext, Droppable, DropResult } from "react-beautiful-dnd";
import { useTranslation } from "react-i18next";
import { v4 } from "uuid";

import { type ProtectReason } from "api/models";
import { appBarHeight } from "components/AppBar/AppBarTypes";
import { CancelConfirmDialog } from "components/Dialogs";
import DropWord from "goals/MergeDuplicates/MergeDupsStep/MergeDragDrop/DropWord";
import SidebarDrop from "goals/MergeDuplicates/MergeDupsStep/MergeDragDrop/SidebarDrop";
import { protectReasonsText } from "goals/MergeDuplicates/MergeDupsStep/protectReasonUtils";
import { MergeTreeReference } from "goals/MergeDuplicates/MergeDupsTreeTypes";
import {
combineSense,
Expand All @@ -27,6 +29,9 @@ export default function MergeDragDrop(): ReactElement {
const overrideProtection = useAppSelector(
(state: StoreState) => state.mergeDuplicateGoal.overrideProtection
);
const senses = useAppSelector(
(state: StoreState) => state.mergeDuplicateGoal.data.senses
);
const sidebarOpen = useAppSelector(
(state: StoreState) =>
state.mergeDuplicateGoal.tree.sidebar.mergeSenses.length > 1
Expand Down Expand Up @@ -71,20 +76,24 @@ export default function MergeDragDrop(): ReactElement {
const src: MergeTreeReference = JSON.parse(res.draggableId);
const srcWordId = res.source.droppableId;
const srcWord = words[srcWordId];
if (
srcWord?.protected &&
!overrideProtection &&
Object.keys(srcWord.sensesGuids).length === 1
) {
const senseReasons = senses[src.mergeSenseId].sense.protectReasons ?? [];
let wordReasons: ProtectReason[] = [];
if (srcWord?.protected && Object.keys(srcWord.sensesGuids).length === 1) {
// Case 0: The final sense of a protected word cannot be moved.
return;
} else if (res.destination?.droppableId === trashId) {
if (overrideProtection) {
wordReasons = srcWord.protectReasons ?? [];
} else {
return;
}
}
const reasonsText = protectReasonsText(t, wordReasons, senseReasons);
if (res.destination?.droppableId === trashId) {
// Case 1: The sense was dropped on the trash icon.
if (src.isSenseProtected) {
// Case 1a: Cannot delete a protected sense.
if (overrideProtection) {
// ... unless protection override is active and user confirms.
startOverrideProtectedData("TODO: extract data", src);
startOverrideProtectedData(reasonsText, src);
}
return;
}
Expand All @@ -98,7 +107,7 @@ export default function MergeDragDrop(): ReactElement {
// Case 2a: Cannot merge a protected sense into another sense.
if (overrideProtection) {
// ... unless protection override is active and user confirms.
startOverrideProtectedData("TODO: extract data", src, combineRef);
startOverrideProtectedData(reasonsText, src, combineRef);
} else if (srcWordId !== res.combine.droppableId) {
// Otherwise, if target sense is in different word, move instead of combine.
dispatch(
Expand Down
71 changes: 3 additions & 68 deletions src/goals/MergeDuplicates/MergeDupsStep/SenseCardContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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, [], reasons));
}
tooltipTexts.push(t("mergeDups.helpText.protectedSenseInfo"));

Expand Down
133 changes: 133 additions & 0 deletions src/goals/MergeDuplicates/MergeDupsStep/protectReasonUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { TFunction } from "i18next";

import { ProtectReason, ReasonType } from "api/models";

const sep = "; ";

export function protectReasonsText(
t: TFunction<"translation", undefined>,
wordReasons: ProtectReason[],
senseReasons: ProtectReason[]
): string {
const wordTexts = wordReasons.map((r) => wordReasonText(t, r));
const senseTexts = senseReasons.map((r) => senseReasonText(t, r));
return t("mergeDups.helpText.protectedData", {
val: [...wordTexts, ...senseTexts].join(sep),
});
}

/** Cases match Backend/Helper/LiftHelper.cs > GetProtectedReasons(LiftSense sense) */
function senseReasonText(
t: TFunction<"translation", undefined>,
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<"translation", undefined>,
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();
}
}
Loading

0 comments on commit c5e9cc6

Please sign in to comment.