Skip to content

Commit

Permalink
[editor] Support Deleting Prompt
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Holinshead committed Dec 29, 2023
1 parent 924a65f commit b680f62
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 15 deletions.
7 changes: 7 additions & 0 deletions python/src/aiconfig/editor/client/src/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ export default function Editor() {
[]
);

const deletePrompt = useCallback(async (promptName: string) => {
// return await ufetch.post(ROUTE_TABLE.DELETE_PROMPT, {
// prompt_name: promptName,
// });
}, []);

const runPrompt = useCallback(async (promptName: string) => {
return await ufetch.post(ROUTE_TABLE.RUN_PROMPT, {
prompt_name: promptName,
Expand Down Expand Up @@ -79,6 +85,7 @@ export default function Editor() {
const callbacks: AIConfigCallbacks = useMemo(
() => ({
addPrompt,
deletePrompt,
getModels,
runPrompt,
save,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import PromptContainer from "./prompt/PromptContainer";
import { Container, Group, Button, createStyles, Stack } from "@mantine/core";
import {
Container,
Group,
Button,
createStyles,
Stack,
Flex,
} from "@mantine/core";
import { showNotification } from "@mantine/notifications";
import { AIConfig, ModelMetadata, Prompt, PromptInput } from "aiconfig";
import { useCallback, useMemo, useReducer, useRef, useState } from "react";
Expand All @@ -11,8 +18,12 @@ import {
clientPromptToAIConfigPrompt,
} from "../shared/types";
import AddPromptButton from "./prompt/AddPromptButton";
import { getDefaultNewPromptName } from "../utils/aiconfigStateUtils";
import {
getDefaultNewPromptName,
getPrompt,
} from "../utils/aiconfigStateUtils";
import { debounce, uniqueId } from "lodash";
import PromptMenuButton from "./prompt/PromptMenuButton";

type Props = {
aiconfig: AIConfig;
Expand All @@ -25,6 +36,7 @@ export type AIConfigCallbacks = {
prompt: Prompt,
index: number
) => Promise<{ aiconfig: AIConfig }>;
deletePrompt: (promptName: string) => Promise<void>;
getModels: (search: string) => Promise<string[]>;
runPrompt: (promptName: string) => Promise<void>;
save: (aiconfig: AIConfig) => Promise<void>;
Expand Down Expand Up @@ -272,6 +284,29 @@ export default function EditorContainer({
[callbacks.addPrompt, dispatch]
);

const onDeletePrompt = useCallback(
async (promptId: string) => {
const action: AIConfigReducerAction = {
type: "DELETE_PROMPT",
id: promptId,
};

dispatch(action);

try {
const prompt = getPrompt(stateRef.current, promptId)!;
await callbacks.deletePrompt(prompt.name);
} catch (err: any) {
showNotification({
title: "Error deleting prompt",
message: err.message,
color: "red",
});
}
},
[callbacks.deletePrompt, dispatch]
);

const onRunPrompt = useCallback(
async (promptIndex: number) => {
const promptName = aiconfigState.prompts[promptIndex].name;
Expand Down Expand Up @@ -306,18 +341,24 @@ export default function EditorContainer({
{aiconfigState.prompts.map((prompt: ClientPrompt, i: number) => {
return (
<Stack key={prompt._ui.id}>
<PromptContainer
index={i}
prompt={prompt}
getModels={callbacks.getModels}
onChangePromptInput={onChangePromptInput}
onChangePromptName={onChangePromptName}
onRunPrompt={onRunPrompt}
onUpdateModel={onUpdatePromptModel}
onUpdateModelSettings={onUpdatePromptModelSettings}
onUpdateParameters={onUpdatePromptParameters}
defaultConfigModelName={aiconfigState.metadata.default_model}
/>
<Flex mt="md">
<PromptMenuButton
promptId={prompt._ui.id}
onDeletePrompt={() => onDeletePrompt(prompt._ui.id)}
/>
<PromptContainer
index={i}
prompt={prompt}
getModels={callbacks.getModels}
onChangePromptInput={onChangePromptInput}
onChangePromptName={onChangePromptName}
onRunPrompt={onRunPrompt}
onUpdateModel={onUpdatePromptModel}
onUpdateModelSettings={onUpdatePromptModelSettings}
onUpdateParameters={onUpdatePromptParameters}
defaultConfigModelName={aiconfigState.metadata.default_model}
/>
</Flex>
<div className={classes.addPromptRow}>
<AddPromptButton
getModels={callbacks.getModels}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export type AIConfigReducerAction =

export type MutateAIConfigAction =
| AddPromptAction
| DeletePromptAction
| UpdatePromptInputAction
| UpdatePromptNameAction
| UpdatePromptModelAction
Expand All @@ -26,6 +27,12 @@ export type AddPromptAction = {
prompt: ClientPrompt;
};

export type DeletePromptAction = {
type: "DELETE_PROMPT";
id: string;
};

// TODO: Update index to prompt id for all existing-prompt actions
export type UpdatePromptInputAction = {
type: "UPDATE_PROMPT_INPUT";
index: number;
Expand Down Expand Up @@ -132,6 +139,12 @@ export default function aiconfigReducer(
case "ADD_PROMPT_AT_INDEX": {
return reduceInsertPromptAtIndex(state, action.index, action.prompt);
}
case "DELETE_PROMPT": {
return {
...state,
prompts: state.prompts.filter((prompt) => prompt._ui.id !== action.id),
};
}
case "UPDATE_PROMPT_INPUT": {
return reduceReplaceInput(state, action.index, () => action.input);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export default memo(function PromptContainer({
const { classes } = useStyles();

return (
<Flex justify="space-between" mt="md">
<Flex justify="space-between">
<Card withBorder className={classes.promptInputCard}>
<Flex direction="column">
<Flex justify="space-between" mb="0.5em">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Button, Menu, createStyles } from "@mantine/core";
import { IconDotsVertical, IconTrash } from "@tabler/icons-react";
import { memo } from "react";

const useStyles = createStyles((theme) => ({
cellAction: {
marginLeft: -8,
[theme.fn.smallerThan("sm")]: {
float: "left",
marginTop: -2,
marginLeft: 0,
zIndex: 99,
"&:hover": {
backgroundColor:
theme.colorScheme === "dark"
? "rgba(0, 0, 0, 0)"
: "rgba(255, 255, 255, 0)",
},
},
},
}));

export default memo(function PromptMenuButton({
promptId,
onDeletePrompt,
}: {
promptId: string;
onDeletePrompt: (id: string) => void;
}) {
const { classes } = useStyles();

return (
<Menu position="bottom-end">
<Menu.Target>
<Button
size="xs"
variant="subtle"
color="dark"
className={classes.cellAction}
style={{}}
>
<IconDotsVertical size={14} />
</Button>
</Menu.Target>

<Menu.Dropdown>
<Menu.Item
icon={<IconTrash size={16} />}
color="red"
onClick={() => onDeletePrompt(promptId)}
>
Delete Prompt
</Menu.Item>
</Menu.Dropdown>
</Menu>
);
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { AIConfig } from "aiconfig";
import { ClientAIConfig, ClientPrompt } from "../shared/types";

export function getDefaultNewPromptName(aiconfig: AIConfig): string {
const existingNames = aiconfig.prompts.map((prompt) => prompt.name);
Expand All @@ -8,3 +9,10 @@ export function getDefaultNewPromptName(aiconfig: AIConfig): string {
}
return `prompt_${i}`;
}

export function getPrompt(
aiconfig: ClientAIConfig,
id: string
): ClientPrompt | undefined {
return aiconfig.prompts.find((prompt) => prompt._ui.id === id);
}
1 change: 1 addition & 0 deletions python/src/aiconfig/editor/client/src/utils/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const API_ENDPOINT = `${HOST_ENDPOINT}/api`;

export const ROUTE_TABLE = {
ADD_PROMPT: urlJoin(API_ENDPOINT, "/add_prompt"),
DELETE_PROMPT: urlJoin(API_ENDPOINT, "/delete_prompt"),
SAVE: urlJoin(API_ENDPOINT, "/save"),
LOAD: urlJoin(API_ENDPOINT, "/load"),
LIST_MODELS: urlJoin(API_ENDPOINT, "/list_models"),
Expand Down

0 comments on commit b680f62

Please sign in to comment.