Update provenance when inputs change (#3064)
This commit is contained in:
@@ -126,3 +126,38 @@ export function isModelAccepted(
|
||||
modeledMethod.provenance !== "ai-generated"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the new provenance for a modeled method based on the current provenance.
|
||||
* @param modeledMethod The modeled method if there is one.
|
||||
* @returns The new provenance.
|
||||
*/
|
||||
export function calculateNewProvenance(
|
||||
modeledMethod: ModeledMethod | undefined,
|
||||
) {
|
||||
if (!modeledMethod || !modeledMethodSupportsProvenance(modeledMethod)) {
|
||||
// If nothing has been modeled or the modeled method does not support
|
||||
// provenance, we assume that the user has entered it manually.
|
||||
return "manual";
|
||||
}
|
||||
|
||||
switch (modeledMethod.provenance) {
|
||||
case "df-generated":
|
||||
// If the method has been generated and there has been a change, we assume
|
||||
// that the user has manually edited it.
|
||||
return "df-manual";
|
||||
case "df-manual":
|
||||
// If the method has had manual edits, we want the provenance to stay the same.
|
||||
return "df-manual";
|
||||
case "ai-generated":
|
||||
// If the method has been generated and there has been a change, we assume
|
||||
// that the user has manually edited it.
|
||||
return "ai-manual";
|
||||
case "ai-manual":
|
||||
// If the method has had manual edits, we want the provenance to stay the same.
|
||||
return "ai-manual";
|
||||
default:
|
||||
// The method has been modeled manually.
|
||||
return "manual";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import * as React from "react";
|
||||
import { ChangeEvent, useCallback, useMemo } from "react";
|
||||
import {
|
||||
ModeledMethod,
|
||||
calculateNewProvenance,
|
||||
isModelAccepted,
|
||||
modeledMethodSupportsInput,
|
||||
} from "../../model-editor/modeled-method";
|
||||
@@ -53,6 +54,7 @@ export const ModelInputDropdown = ({
|
||||
|
||||
onChange({
|
||||
...modeledMethod,
|
||||
provenance: calculateNewProvenance(modeledMethod),
|
||||
input: target.value,
|
||||
});
|
||||
},
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
ModeledMethodKind,
|
||||
modeledMethodSupportsKind,
|
||||
isModelAccepted,
|
||||
calculateNewProvenance,
|
||||
} from "../../model-editor/modeled-method";
|
||||
import { getModelsAsDataLanguage } from "../../model-editor/languages";
|
||||
import { QueryLanguage } from "../../common/query-language";
|
||||
@@ -52,6 +53,7 @@ export const ModelKindDropdown = ({
|
||||
|
||||
onChange({
|
||||
...modeledMethod,
|
||||
provenance: calculateNewProvenance(modeledMethod),
|
||||
kind,
|
||||
});
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@ import * as React from "react";
|
||||
import { ChangeEvent, useCallback, useMemo } from "react";
|
||||
import {
|
||||
ModeledMethod,
|
||||
calculateNewProvenance,
|
||||
isModelAccepted,
|
||||
modeledMethodSupportsOutput,
|
||||
} from "../../model-editor/modeled-method";
|
||||
@@ -54,6 +55,7 @@ export const ModelOutputDropdown = ({
|
||||
|
||||
onChange({
|
||||
...modeledMethod,
|
||||
provenance: calculateNewProvenance(modeledMethod),
|
||||
output: target.value,
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import * as React from "react";
|
||||
import { ChangeEvent, useCallback } from "react";
|
||||
import {
|
||||
calculateNewProvenance,
|
||||
isModelAccepted,
|
||||
ModeledMethod,
|
||||
modeledMethodSupportsProvenance,
|
||||
ModeledMethodType,
|
||||
Provenance,
|
||||
} from "../../model-editor/modeled-method";
|
||||
import { Method } from "../../model-editor/method";
|
||||
import { createEmptyModeledMethod } from "../../model-editor/modeled-method-empty";
|
||||
@@ -43,15 +42,6 @@ export const ModelTypeDropdown = ({
|
||||
(e: ChangeEvent<HTMLSelectElement>) => {
|
||||
const modelsAsDataLanguage = getModelsAsDataLanguage(language);
|
||||
|
||||
let newProvenance: Provenance = "manual";
|
||||
if (modeledMethod && modeledMethodSupportsProvenance(modeledMethod)) {
|
||||
if (modeledMethod.provenance === "df-generated") {
|
||||
newProvenance = "df-manual";
|
||||
} else if (modeledMethod.provenance === "ai-generated") {
|
||||
newProvenance = "ai-manual";
|
||||
}
|
||||
}
|
||||
|
||||
const emptyModeledMethod = createEmptyModeledMethod(
|
||||
e.target.value as ModeledMethodType,
|
||||
method,
|
||||
@@ -67,7 +57,7 @@ export const ModelTypeDropdown = ({
|
||||
updatedModeledMethod.output = "ReturnValue";
|
||||
}
|
||||
if ("provenance" in updatedModeledMethod) {
|
||||
updatedModeledMethod.provenance = newProvenance;
|
||||
updatedModeledMethod.provenance = calculateNewProvenance(modeledMethod);
|
||||
}
|
||||
if ("kind" in updatedModeledMethod) {
|
||||
updatedModeledMethod.kind = "value";
|
||||
|
||||
@@ -27,7 +27,7 @@ describe(MethodRow.name, () => {
|
||||
input: "Argument[0]",
|
||||
output: "ReturnValue",
|
||||
kind: "taint",
|
||||
provenance: "df-generated",
|
||||
provenance: "manual",
|
||||
};
|
||||
const onChange = jest.fn();
|
||||
|
||||
@@ -111,6 +111,32 @@ describe(MethodRow.name, () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("changes the provenance when the kind is changed", async () => {
|
||||
const modeledMethodWithGeneratedProvenance: ModeledMethod = {
|
||||
...modeledMethod,
|
||||
provenance: "df-generated",
|
||||
};
|
||||
render({ modeledMethods: [modeledMethodWithGeneratedProvenance] });
|
||||
|
||||
onChange.mockReset();
|
||||
|
||||
expect(screen.getByRole("combobox", { name: "Kind" })).toHaveValue("taint");
|
||||
|
||||
await userEvent.selectOptions(
|
||||
screen.getByRole("combobox", { name: "Kind" }),
|
||||
"value",
|
||||
);
|
||||
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
expect(onChange).toHaveBeenCalledWith(method.signature, [
|
||||
{
|
||||
...modeledMethod,
|
||||
kind: "value",
|
||||
provenance: "df-manual",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("has the correct input options", () => {
|
||||
render();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user