add button to to delete an individual chat.

This commit is contained in:
Emil Elgaard 2023-03-26 16:49:15 -04:00
parent 4ee5d0e5f6
commit 8075585778
4 changed files with 99 additions and 53 deletions

8
package-lock.json generated
View File

@ -7,6 +7,9 @@
"": { "": {
"name": "chatgpt-web", "name": "chatgpt-web",
"version": "0.0.0", "version": "0.0.0",
"dependencies": {
"lodash": "^4.17.21"
},
"devDependencies": { "devDependencies": {
"@fullhuman/postcss-purgecss": "^5.0.0", "@fullhuman/postcss-purgecss": "^5.0.0",
"@microsoft/fetch-event-source": "^2.0.1", "@microsoft/fetch-event-source": "^2.0.1",
@ -3074,6 +3077,11 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash.merge": { "node_modules/lodash.merge": {
"version": "4.6.2", "version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",

View File

@ -39,5 +39,8 @@
"tslib": "^2.5.0", "tslib": "^2.5.0",
"typescript": "^5.0.2", "typescript": "^5.0.2",
"vite": "^4.1.0" "vite": "^4.1.0"
},
"dependencies": {
"lodash": "^4.17.21"
} }
} }

View File

@ -13,7 +13,7 @@
flex-grow: 1; flex-grow: 1;
min-height: 100vh; min-height: 100vh;
section.section{ section.section {
flex-grow: 1; flex-grow: 1;
} }
} }
@ -32,7 +32,7 @@ a.is-disabled {
filter: grayscale(100%); filter: grayscale(100%);
} }
.user-message { .user-message {
max-width: 90%; max-width: 90%;
margin-right: 0; margin-right: 0;
margin-left: auto; margin-left: auto;
@ -110,6 +110,26 @@ $modal-background-background-color-dark: rgba($dark, 0.86) !default; // remove t
top: 1rem; top: 1rem;
} }
.menu-list {
a:hover {
.delete-btn {
display: block;
}
}
}
.delete-btn {
display: none;
position: absolute;
width: 20px;
height: 20px;
top: 50%;
right: 0;
transform: translateY(-50%);
margin-right: 5px;
}
/* Loading chat messages */ /* Loading chat messages */
.is-loading { .is-loading {
opacity: 0.5; opacity: 0.5;

View File

@ -1,70 +1,85 @@
<script lang="ts"> <script lang="ts">
import { params, replace } from 'svelte-spa-router' import {params, replace} from 'svelte-spa-router'
import { apiKeyStorage, chatsStorage, clearChats } from './Storage.svelte' import {apiKeyStorage, chatsStorage, clearChats, deleteChat} from './Storage.svelte'
import { exportAsMarkdown } from './Export.svelte' import {exportAsMarkdown} from './Export.svelte'
import _ from 'lodash'
$: sortedChats = $chatsStorage.sort((a, b) => b.id - a.id)
$: sortedChats = $chatsStorage.sort((a, b) => b.id - a.id) $: activeChatId = $params && $params.chatId ? parseInt($params.chatId) : undefined
function delChat(chatId) {
if (activeChatId === chatId) {
// switch to another chat if deleting the active one
const newChatId = _.maxBy($chatsStorage.filter(chat => chat.id !== chatId), 'id').id
replace(`/chat/:${newChatId}`).then(() => deleteChat(chatId))
} else {
deleteChat(chatId)
}
}
$: activeChatId = $params && $params.chatId ? parseInt($params.chatId) : undefined
</script> </script>
<aside class="menu"> <aside class="menu">
<p class="menu-label">Chats</p> <p class="menu-label">Chats</p>
<ul class="menu-list"> <ul class="menu-list">
{#if sortedChats.length === 0} {#if sortedChats.length === 0}
<li><a href={'#'} class="is-disabled">No chats yet...</a></li> <li><a href={'#'} class="is-disabled">No chats yet...</a></li>
{:else} {:else}
<li>
<ul>
{#each sortedChats as chat}
<li> <li>
<a href={`#/chat/${chat.id}`} class:is-disabled={!$apiKeyStorage} class:is-active={activeChatId === chat.id} <ul>
>{chat.name || `Chat ${chat.id}`}</a {#each sortedChats as chat}
> <li>
<a style="position: relative" href={`#/chat/${chat.id}`} class:is-disabled={!$apiKeyStorage} class:is-active={activeChatId === chat.id}
>{chat.name || `Chat ${chat.id}`}
<svg on:click={() => delChat(chat.id)} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="delete-btn">
<path stroke-linecap="round" stroke-linejoin="round" d="M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
</a
>
</li>
{/each}
</ul>
</li> </li>
{/each} {/if}
</ul> </ul>
</li> <p class="menu-label">Actions</p>
{/if} <ul class="menu-list">
</ul> <li>
<p class="menu-label">Actions</p> <a href={'#/'} class="panel-block" class:is-disabled={!$apiKeyStorage} class:is-active={!activeChatId}
<ul class="menu-list"> ><span class="greyscale mr-2">🔑</span> API key</a
<li> >
<a href={'#/'} class="panel-block" class:is-disabled={!$apiKeyStorage} class:is-active={!activeChatId} </li>
><span class="greyscale mr-2">🔑</span> API key</a <li>
> <a href={'#/chat/new'} class="panel-block" class:is-disabled={!$apiKeyStorage}
</li> ><span class="greyscale mr-2"></span> New chat</a
<li> >
<a href={'#/chat/new'} class="panel-block" class:is-disabled={!$apiKeyStorage} </li>
><span class="greyscale mr-2"></span> New chat</a <li>
> <a class="panel-block"
</li> href="{'#/'}"
<li> class:is-disabled={!$apiKeyStorage}
<a class="panel-block" on:click|preventDefault={() => {
href="{'#/'}"
class:is-disabled={!$apiKeyStorage}
on:click|preventDefault={() => {
const confirmDelete = window.confirm('Are you sure you want to delete all your chats?') const confirmDelete = window.confirm('Are you sure you want to delete all your chats?')
if (confirmDelete) { if (confirmDelete) {
replace('#/').then(() => clearChats()) replace('#/').then(() => clearChats())
} }
}}><span class="greyscale mr-2">🗑️</span> Clear chats</a }}><span class="greyscale mr-2">🗑️</span> Clear chats</a
> >
</li> </li>
{#if activeChatId} {#if activeChatId}
<li> <li>
<a <a
href={'#/'} href={'#/'}
class="panel-block" class="panel-block"
class:is-disabled={!apiKeyStorage} class:is-disabled={!apiKeyStorage}
on:click|preventDefault={() => { on:click|preventDefault={() => {
if (activeChatId) { if (activeChatId) {
exportAsMarkdown(activeChatId) exportAsMarkdown(activeChatId)
} }
}}><span class="greyscale mr-2">📥</span> Export chat</a }}><span class="greyscale mr-2">📥</span> Export chat</a
> >
</li> </li>
{/if} {/if}
</ul> </ul>
</aside> </aside>