ManageModal.svelte 5.56 KB
Newer Older
1
2
3
4
5
6
7
8
<script lang="ts">
	import { toast } from 'svelte-sonner';
	import dayjs from 'dayjs';
	import { getContext, createEventDispatcher } from 'svelte';

	const dispatch = createEventDispatcher();

	import Modal from '$lib/components/common/Modal.svelte';
Timothy J. Baek's avatar
Timothy J. Baek committed
9
	import AddMemoryModal from './AddMemoryModal.svelte';
Timothy J. Baek's avatar
Timothy J. Baek committed
10
	import { deleteMemoriesByUserId, deleteMemoryById, getMemories } from '$lib/apis/memories';
Timothy J. Baek's avatar
Timothy J. Baek committed
11
12
	import Tooltip from '$lib/components/common/Tooltip.svelte';
	import { error } from '@sveltejs/kit';
13
14
15
16
17
18
19

	const i18n = getContext('i18n');

	export let show = false;

	let memories = [];

Timothy J. Baek's avatar
Timothy J. Baek committed
20
21
	let showAddMemoryModal = false;

22
23
	$: if (show) {
		(async () => {
Timothy J. Baek's avatar
Timothy J. Baek committed
24
			memories = await getMemories(localStorage.token);
25
26
27
28
		})();
	}
</script>

Timothy J. Baek's avatar
Timothy J. Baek committed
29
<Modal size="xl" bind:show>
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
	<div>
		<div class=" flex justify-between dark:text-gray-300 px-5 pt-4 pb-1">
			<div class=" text-lg font-medium self-center">{$i18n.t('Memory')}</div>
			<button
				class="self-center"
				on:click={() => {
					show = false;
				}}
			>
				<svg
					xmlns="http://www.w3.org/2000/svg"
					viewBox="0 0 20 20"
					fill="currentColor"
					class="w-5 h-5"
				>
					<path
						d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
					/>
				</svg>
			</button>
		</div>

Timothy J. Baek's avatar
Timothy J. Baek committed
52
53
54
55
56
		<div class="flex flex-col w-full px-5 pb-5 dark:text-gray-200">
			<div
				class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6 h-[28rem] max-h-screen outline outline-1 rounded-xl outline-gray-100 dark:outline-gray-800 mb-4 mt-1"
			>
				{#if memories.length > 0}
57
58
59
60
61
62
63
64
65
66
67
68
69
					<div class="text-left text-sm w-full mb-4 max-h-[22rem] overflow-y-scroll">
						<div class="relative overflow-x-auto">
							<table class="w-full text-sm text-left text-gray-600 dark:text-gray-400 table-auto">
								<thead
									class="text-xs text-gray-700 uppercase bg-transparent dark:text-gray-200 border-b-2 dark:border-gray-800"
								>
									<tr>
										<th scope="col" class="px-3 py-2"> {$i18n.t('Name')} </th>
										<th scope="col" class="px-3 py-2 hidden md:flex"> {$i18n.t('Created At')} </th>
										<th scope="col" class="px-3 py-2 text-right" />
									</tr>
								</thead>
								<tbody>
Timothy J. Baek's avatar
Timothy J. Baek committed
70
									{#each memories as memory}
Timothy J. Baek's avatar
Timothy J. Baek committed
71
										<tr class="border-b dark:border-gray-800 items-center">
Timothy J. Baek's avatar
Timothy J. Baek committed
72
73
74
75
76
											<td class="px-3 py-1">
												<div class="line-clamp-1">
													{memory.content}
												</div>
											</td>
Timothy J. Baek's avatar
Timothy J. Baek committed
77
											<td class=" px-3 py-1 hidden md:flex h-[2.5rem]">
Timothy J. Baek's avatar
Timothy J. Baek committed
78
												<div class="my-auto whitespace-nowrap">
Timothy J. Baek's avatar
Timothy J. Baek committed
79
80
													{dayjs(memory.created_at * 1000).format($i18n.t('MMMM DD, YYYY'))}
												</div>
81
											</td>
Timothy J. Baek's avatar
Timothy J. Baek committed
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
											<td class="px-3 py-1">
												<div class="flex justify-end w-full">
													<Tooltip content="Delete">
														<button
															class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
															on:click={async () => {
																const res = await deleteMemoryById(
																	localStorage.token,
																	memory.id
																).catch((error) => {
																	toast.error(error);
																	return null;
																});

																if (res) {
																	toast.success('Memory deleted successfully');
																	memories = await getMemories(localStorage.token);
																}
															}}
														>
															<svg
																xmlns="http://www.w3.org/2000/svg"
																fill="none"
																viewBox="0 0 24 24"
																stroke-width="1.5"
																stroke="currentColor"
																class="w-4 h-4"
															>
																<path
																	stroke-linecap="round"
																	stroke-linejoin="round"
																	d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0"
																/>
															</svg>
														</button>
													</Tooltip>
												</div>
119
120
121
122
123
124
125
126
											</td>
										</tr>
									{/each}
								</tbody>
							</table>
						</div>
					</div>
				{:else}
Timothy J. Baek's avatar
Timothy J. Baek committed
127
128
					<div class="text-center flex h-full text-sm w-full">
						<div class=" my-auto pb-10 px-4 w-full text-gray-500">
Timothy J. Baek's avatar
Timothy J. Baek committed
129
							{$i18n.t('Memories accessible by LLMs will be shown here.')}
Timothy J. Baek's avatar
Timothy J. Baek committed
130
						</div>
131
132
133
					</div>
				{/if}
			</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
134
135
136
137
138
139
140
			<div class="flex text-sm font-medium gap-1.5">
				<button
					class=" px-3.5 py-1.5 font-medium hover:bg-black/5 dark:hover:bg-white/5 outline outline-1 outline-gray-300 dark:outline-gray-800 rounded-3xl"
					on:click={() => {
						showAddMemoryModal = true;
					}}>Add memory</button
				>
Timothy J. Baek's avatar
Timothy J. Baek committed
141
				<button
Timothy J. Baek's avatar
Timothy J. Baek committed
142
					class=" px-3.5 py-1.5 font-medium text-red-500 hover:bg-black/5 dark:hover:bg-white/5 outline outline-1 outline-red-300 dark:outline-red-800 rounded-3xl"
Timothy J. Baek's avatar
Timothy J. Baek committed
143
144
145
146
147
148
149
150
151
152
153
154
					on:click={async () => {
						const res = await deleteMemoriesByUserId(localStorage.token).catch((error) => {
							toast.error(error);
							return null;
						});

						if (res) {
							toast.success('Memory cleared successfully');
							memories = [];
						}
					}}>Clear memory</button
				>
Timothy J. Baek's avatar
Timothy J. Baek committed
155
			</div>
156
157
158
		</div>
	</div>
</Modal>
Timothy J. Baek's avatar
Timothy J. Baek committed
159

Timothy J. Baek's avatar
Timothy J. Baek committed
160
161
162
163
164
165
<AddMemoryModal
	bind:show={showAddMemoryModal}
	on:save={async () => {
		memories = await getMemories(localStorage.token);
	}}
/>