Skip to content

Commit

Permalink
kie-issues#208: Renaming any "NamedElement" on the DMN Editor should …
Browse files Browse the repository at this point in the history
…update all references to the old name
  • Loading branch information
danielzhe committed Nov 22, 2024
1 parent 36aae9a commit de7015e
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 20 deletions.
93 changes: 83 additions & 10 deletions packages/dmn-editor/src/dataTypes/DataTypeName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@
*/

import * as React from "react";
import { useCallback, useMemo } from "react";
import { DMN15__tItemDefinition } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types";
import { useCallback, useMemo, useState } from "react";
import {
DMN15__tDefinitions,
DMN15__tItemDefinition,
} from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types";
import { Normalized } from "@kie-tools/dmn-marshaller/dist/normalization/normalize";
import { Flex } from "@patternfly/react-core/dist/js/layouts/Flex";
import { EditableNodeLabel, useEditableNodeLabel } from "../diagram/nodes/EditableNodeLabel";
Expand All @@ -33,6 +36,11 @@ import { useExternalModels } from "../includedModels/DmnEditorDependenciesContex
import { State } from "../store/Store";
import { DmnBuiltInDataType } from "@kie-tools/boxed-expression-component/dist/api";
import { DmnLatestModel } from "@kie-tools/dmn-marshaller";
import {
isIdentifierReferencedInSomeExpression,
RefactorConfirmationDialog,
} from "../refactor/RefactorConfirmationDialog";
import { DataTypeIndex } from "./DataTypes";

export function DataTypeName({
isReadOnly,
Expand Down Expand Up @@ -75,7 +83,7 @@ export function DataTypeName({
(s) => s.computed(s).getDirectlyIncludedExternalModelsByNamespace(externalModelsByNamespace).dmns
);

const externalModelsByNamespaceMap = useMemo(() => {
const externalDmnModelsByNamespaceMap = useMemo(() => {
const externalModels = new Map<string, Normalized<DmnLatestModel>>();

for (const [key, externalDmn] of externalDmnsByNamespace) {
Expand All @@ -84,29 +92,94 @@ export function DataTypeName({
return externalModels;
}, [externalDmnsByNamespace]);

const _shouldCommitOnBlur = shouldCommitOnBlur ?? true; // Defaults to true

const [isRefactorModalOpen, setIsRefactorModalOpen] = useState(false);
const [newName, setNewName] = useState("");
const identifierId = useMemo(() => itemDefinition["@_id"], [itemDefinition]);
const oldName = useMemo(() => itemDefinition["@_name"], [itemDefinition]);

const applyRename = useCallback(
(args: {
definitions: Normalized<DMN15__tDefinitions>;
newName: string;
shouldRenameReferencedExpressions: boolean;
allDataTypesById: DataTypeIndex;
}) => {
renameItemDefinition({
...args,
itemDefinitionId: itemDefinition["@_id"]!,
externalDmnModelsByNamespaceMap,
});
},
[externalDmnModelsByNamespaceMap, itemDefinition]
);

const onRenamed = useCallback<OnInlineFeelNameRenamed>(
(newName) => {
if (isReadOnly) {
if (isReadOnly || newName === oldName) {
return;
}

dmnEditorStoreApi.setState((state) => {
renameItemDefinition({
if (
isIdentifierReferencedInSomeExpression({
identifierUuid: identifierId,
dmnDefinitions: state.dmn.model.definitions,
externalDmnModelsByNamespaceMap,
})
) {
setNewName(newName);
setIsRefactorModalOpen(true);
} else {
applyRename({
definitions: state.dmn.model.definitions,
newName,
shouldRenameReferencedExpressions: false,
allDataTypesById: state.computed(state).getDataTypes(externalModelsByNamespace).allDataTypesById,
});
}
});
},
[
applyRename,
dmnEditorStoreApi,
externalDmnModelsByNamespaceMap,
externalModelsByNamespace,
identifierId,
isReadOnly,
oldName,
]
);

const confirmRename = useCallback(
(shouldRenameReferencedExpressions: boolean) => {
setIsRefactorModalOpen(false);
dmnEditorStoreApi.setState((state) => {
applyRename({
definitions: state.dmn.model.definitions,
newName,
itemDefinitionId: itemDefinition["@_id"]!,
shouldRenameReferencedExpressions,
allDataTypesById: state.computed(state).getDataTypes(externalModelsByNamespace).allDataTypesById,
externalModelsByNamespaceMap,
});
});
},
[dmnEditorStoreApi, externalModelsByNamespace, externalModelsByNamespaceMap, isReadOnly, itemDefinition]
[applyRename, dmnEditorStoreApi, externalModelsByNamespace, newName]
);

const _shouldCommitOnBlur = shouldCommitOnBlur ?? true; // Defaults to true

return (
<>
<RefactorConfirmationDialog
onConfirmExpressionRefactor={() => {
confirmRename(true);
}}
onConfirmRenameOnly={() => {
confirmRename(false);
}}
isRefactorModalOpen={isRefactorModalOpen}
fromName={oldName}
toName={newName}
/>
{editMode === "hover" && (
<InlineFeelNameInput
isPlain={true}
Expand Down
18 changes: 11 additions & 7 deletions packages/dmn-editor/src/mutations/renameItemDefinition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ export function renameItemDefinition({
newName,
allDataTypesById,
itemDefinitionId,
externalModelsByNamespaceMap,
externalDmnModelsByNamespaceMap,
shouldRenameReferencedExpressions,
}: {
definitions: Normalized<DMN15__tDefinitions>;
newName: string;
itemDefinitionId: string;
allDataTypesById: DataTypeIndex;
externalModelsByNamespaceMap: Map<string, Normalized<DmnLatestModel>>;
externalDmnModelsByNamespaceMap: Map<string, Normalized<DmnLatestModel>>;
shouldRenameReferencedExpressions: boolean;
}) {
const dataType = allDataTypesById.get(itemDefinitionId);
if (!dataType) {
Expand Down Expand Up @@ -90,12 +92,14 @@ export function renameItemDefinition({

// Not top-level.. meaning that we need to update FEEL expressions referencing it
else {
const identifiersRefactor = new IdentifiersRefactor({
writeableDmnDefinitions: definitions,
_readonly_externalDmnModelsByNamespaceMap: externalModelsByNamespaceMap,
});
if (shouldRenameReferencedExpressions) {
const identifiersRefactor = new IdentifiersRefactor({
writeableDmnDefinitions: definitions,
_readonly_externalDmnModelsByNamespaceMap: externalDmnModelsByNamespaceMap,
});

identifiersRefactor.rename({ identifierUuid: itemDefinitionId, newName: trimmedNewName });
identifiersRefactor.rename({ identifierUuid: itemDefinitionId, newName: trimmedNewName });
}
}

itemDefinition["@_name"] = trimmedNewName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ export class IdentifiersRefactor {
public getExpressionsThatUseTheIdentifier(identifierId: string) {
const identifierContext = this.repository.identifiers.get(identifierId);
if (!identifierContext) {
return [];
return (
this.repository.dataTypeIndexedByUuid.get(identifierId)?.source.expressionsThatUseTheIdentifier.values() ?? []
);
}

return identifierContext.identifier.expressionsThatUseTheIdentifier.values();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ describe("Refactor renamed identifiers", () => {
newName: "MON",
});

// id="_4a4d01be-fe97-49a2-8c4c-3a49ff27968d" name="Tax"
// Rename the "Tax" property of "Monthly" data type to "The Tax"
identifiersRefactor.rename({
identifierUuid: "_4a4d01be-fe97-49a2-8c4c-3a49ff27968d",
Expand Down Expand Up @@ -193,7 +192,6 @@ describe("Refactor renamed identifiers", () => {
).toEqual("x > 2");
});

// test("rename decision service element - should update referenced expressions", async () => {});
test("rename included model - should update referenced expressions", async () => {
const identifiersRefactor = new IdentifiersRefactor({
writeableDmnDefinitions: getDefinitions(includeMathModelDmn()),
Expand Down

0 comments on commit de7015e

Please sign in to comment.