Skip to content

Commit

Permalink
Add saved prompt deletion with confirmation
Browse files Browse the repository at this point in the history
  • Loading branch information
DrJKL committed Aug 28, 2023
1 parent 3ae0e63 commit 4799f0f
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 12 deletions.
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
- [x] Save current prompt to local storage
- [x] Save named prompts to local storage
- [ ] Save history to local storage
- [ ] Allow deleting history items
- [x] Allow deleting history items

## Autocomplete

Expand Down
29 changes: 25 additions & 4 deletions src/common/saving/localstorage.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { RenderingOptions } from './../rendering/RenderType';
import { BehaviorSubject, Observable, ReplaySubject, Subject } from 'rxjs';
import { scan, takeUntil } from 'rxjs/operators';
import {
BehaviorSubject,
Observable,
ReplaySubject,
Subject,
merge,
} from 'rxjs';
import { scan, shareReplay, takeUntil } from 'rxjs/operators';

import {
RenderingOptionsSchema,
Expand All @@ -9,6 +15,7 @@ import {
SavedPromptsSchema,
} from './types';
import { getDefaultPrompts } from '../../examples/prompts';
import { isArray, isEqual } from 'lodash';

/** Keys */
const ACTIVE_PROMPT_NAME = 'pc.active_prompt.name' as const;
Expand Down Expand Up @@ -64,6 +71,13 @@ function savePromptsLocal(newPrompts: SavedPrompts) {
localStorage.setItem(SAVED_PROMPTS, JSON.stringify(newPrompts));
}

export function deletePromptLocal(promptToDelete: SavedPrompt) {
const currentPrompts = getSavedPromptsLocal();
const filtered = currentPrompts.filter((p) => !isEqual(p, promptToDelete));
savePromptsLocal(filtered);
forceUpdatePromptsSubject.next(filtered);
}

export function getSavedPromptsLocal(): SavedPrompts {
const currentValue = localStorage.getItem(SAVED_PROMPTS);
const parsedMaybe = SavedPromptsSchema.safeParse(
Expand All @@ -83,13 +97,19 @@ export function getSavedPromptsLocal(): SavedPrompts {
const activePromptSubject = new BehaviorSubject(getActivePromptLocal());
const activePromptNameSubject = new BehaviorSubject(getActivePromptNameLocal());
const activePromptTagsSubject = new BehaviorSubject(getActivePromptTagsLocal());
const forceUpdatePromptsSubject = new Subject<SavedPrompts>();
const savedPromptInputSubject = new Subject<SavedPrompt>();

const savedPromptsComposed = savedPromptInputSubject.pipe(
const savedPromptsComposed = merge(
savedPromptInputSubject,
forceUpdatePromptsSubject,
).pipe(
scan(
(existingPrompts, newPrompt) => [...existingPrompts, newPrompt],
(existingPrompts, newPrompt) =>
isArray(newPrompt) ? newPrompt : [...existingPrompts, newPrompt],
getSavedPromptsLocal(),
),
shareReplay(1),
);

/* Exports */
Expand All @@ -111,6 +131,7 @@ export const savedPrompts$: Observable<SavedPrompts> = savedPromptsComposed;
export function savePrompt(prompt: SavedPrompt) {
savedPromptInputSubject.next(prompt);
}

/* Persistence */
activePrompt$
.pipe(takeUntil(cleanupLocalStorageSubscriptions$))
Expand Down
23 changes: 22 additions & 1 deletion src/components/SavedPrompt.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Chip, Collapse, Tooltip, IconButton } from '@mui/material';
import { SavedPrompt } from '../common/saving/types';
import { useRef, useState } from 'react';
import { NorthWest } from '@mui/icons-material';
import { DeleteForever, NorthWest } from '@mui/icons-material';
import { useConfirm } from 'material-ui-confirm';
import { deletePromptLocal } from '../common/saving/localstorage';

export interface SavedPromptDisplayProps {
prompt: SavedPrompt;
Expand All @@ -15,6 +17,7 @@ export function SavedPromptDisplay({
const { name, contents, tags } = prompt;

const [open, setOpen] = useState(false);
const confirm = useConfirm();

const promptText = useRef<HTMLPreElement | null>(null);

Expand All @@ -27,6 +30,18 @@ export function SavedPromptDisplay({
window.getSelection()?.selectAllChildren(promptTextNode);
}

async function handleDelete() {
try {
await confirm({
description: `Are you sure you want to delete ${name}?`,
});

deletePromptLocal(prompt);
} catch (err: unknown) {
console.error(`Canceled deletion of ${name}\n${err}`);
}
}

return (
<div className="py-1">
<h3 className="flex justify-between pb-2">
Expand Down Expand Up @@ -58,6 +73,12 @@ export function SavedPromptDisplay({
<NorthWest />
</IconButton>
</Tooltip>

<Tooltip title="Delete this Saved Prompt">
<IconButton aria-label="" onClick={handleDelete}>
<DeleteForever />
</IconButton>
</Tooltip>
</div>
</Collapse>
<hr />
Expand Down
15 changes: 9 additions & 6 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.tsx';
import './index.css';
import { Button, ThemeProvider, createTheme } from '@mui/material';
import { red } from '@mui/material/colors';
import { BrowserRouter } from 'react-router-dom';
import { ConfirmProvider } from 'material-ui-confirm';
import React from 'react';
import ReactDOM from 'react-dom/client';
import { ErrorBoundary, FallbackProps } from 'react-error-boundary';
import { BrowserRouter } from 'react-router-dom';
import App from './App.tsx';
import { saveActivePrompt } from './common/saving/localstorage.ts';
import './index.css';

const theme = createTheme({
palette: {
Expand Down Expand Up @@ -51,7 +52,9 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
<ThemeProvider theme={theme}>
<BrowserRouter>
<ErrorBoundary fallbackRender={fallbackRender}>
<App />
<ConfirmProvider>
<App />
</ConfirmProvider>
</ErrorBoundary>
</BrowserRouter>
</ThemeProvider>
Expand Down

0 comments on commit 4799f0f

Please sign in to comment.