Users.svelte 6.82 KB
Newer Older
Timothy J. Baek's avatar
Timothy J. Baek committed
1
<script lang="ts">
2
	import { getBackendConfig, getModelFilterConfig, updateModelFilterConfig } from '$lib/apis';
Timothy J. Baek's avatar
Timothy J. Baek committed
3
4
	import { getSignUpEnabledStatus, toggleSignUpEnabledStatus } from '$lib/apis/auths';
	import { getUserPermissions, updateUserPermissions } from '$lib/apis/users';
5

6
	import { onMount, getContext } from 'svelte';
7
8
9
	import { models, config } from '$lib/stores';
	import Switch from '$lib/components/common/Switch.svelte';
	import { setDefaultModels } from '$lib/apis/configs';
10
11

	const i18n = getContext('i18n');
Timothy J. Baek's avatar
Timothy J. Baek committed
12
13
14

	export let saveHandler: Function;

15
16
	let defaultModelId = '';

Timothy J. Baek's avatar
Timothy J. Baek committed
17
	let whitelistEnabled = false;
18
	let whitelistModels = [''];
Timothy J. Baek's avatar
Timothy J. Baek committed
19
20
21
22
23
24
25
26
	let permissions = {
		chat: {
			deletion: true
		}
	};

	onMount(async () => {
		permissions = await getUserPermissions(localStorage.token);
27
28
29
30
31
32

		const res = await getModelFilterConfig(localStorage.token);
		if (res) {
			whitelistEnabled = res.enabled;
			whitelistModels = res.models.length > 0 ? res.models : [''];
		}
33
34

		defaultModelId = $config.default_models ? $config?.default_models.split(',')[0] : '';
Timothy J. Baek's avatar
Timothy J. Baek committed
35
36
37
38
39
40
41
	});
</script>

<form
	class="flex flex-col h-full justify-between space-y-3 text-sm"
	on:submit|preventDefault={async () => {
		// console.log('submit');
42

43
44
		await setDefaultModels(localStorage.token, defaultModelId);
		await updateUserPermissions(localStorage.token, permissions);
45
		await updateModelFilterConfig(localStorage.token, whitelistEnabled, whitelistModels);
Timothy J. Baek's avatar
Timothy J. Baek committed
46
		saveHandler();
47
48

		await config.set(await getBackendConfig());
Timothy J. Baek's avatar
Timothy J. Baek committed
49
50
	}}
>
Timothy J. Baek's avatar
Timothy J. Baek committed
51
	<div class=" space-y-3 overflow-y-scroll max-h-full">
Timothy J. Baek's avatar
Timothy J. Baek committed
52
		<div>
53
			<div class=" mb-2 text-sm font-medium">{$i18n.t('User Permissions')}</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
54
55

			<div class="  flex w-full justify-between">
56
				<div class=" self-center text-xs font-medium">{$i18n.t('Allow Chat Deletion')}</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

				<button
					class="p-1 px-3 text-xs flex rounded transition"
					on:click={() => {
						permissions.chat.deletion = !permissions.chat.deletion;
					}}
					type="button"
				>
					{#if permissions.chat.deletion}
						<svg
							xmlns="http://www.w3.org/2000/svg"
							viewBox="0 0 16 16"
							fill="currentColor"
							class="w-4 h-4"
						>
							<path
								d="M11.5 1A3.5 3.5 0 0 0 8 4.5V7H2.5A1.5 1.5 0 0 0 1 8.5v5A1.5 1.5 0 0 0 2.5 15h7a1.5 1.5 0 0 0 1.5-1.5v-5A1.5 1.5 0 0 0 9.5 7V4.5a2 2 0 1 1 4 0v1.75a.75.75 0 0 0 1.5 0V4.5A3.5 3.5 0 0 0 11.5 1Z"
							/>
						</svg>
76
						<span class="ml-2 self-center">{$i18n.t('Allow')}</span>
Timothy J. Baek's avatar
Timothy J. Baek committed
77
78
79
80
81
82
83
84
85
86
87
88
89
90
					{:else}
						<svg
							xmlns="http://www.w3.org/2000/svg"
							viewBox="0 0 16 16"
							fill="currentColor"
							class="w-4 h-4"
						>
							<path
								fill-rule="evenodd"
								d="M8 1a3.5 3.5 0 0 0-3.5 3.5V7A1.5 1.5 0 0 0 3 8.5v5A1.5 1.5 0 0 0 4.5 15h7a1.5 1.5 0 0 0 1.5-1.5v-5A1.5 1.5 0 0 0 11.5 7V4.5A3.5 3.5 0 0 0 8 1Zm2 6V4.5a2 2 0 1 0-4 0V7h4Z"
								clip-rule="evenodd"
							/>
						</svg>

91
						<span class="ml-2 self-center">{$i18n.t("Don't Allow")}</span>
Timothy J. Baek's avatar
Timothy J. Baek committed
92
93
94
95
					{/if}
				</button>
			</div>
		</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
96

Timothy J. Baek's avatar
Timothy J. Baek committed
97
		<hr class=" dark:border-gray-850 my-2" />
Timothy J. Baek's avatar
Timothy J. Baek committed
98

99
		<div class="mt-2 space-y-3">
Timothy J. Baek's avatar
Timothy J. Baek committed
100
101
102
			<div>
				<div class="mb-2">
					<div class="flex justify-between items-center text-xs">
Jannik Streidl's avatar
Jannik Streidl committed
103
						<div class=" text-sm font-medium">{$i18n.t('Manage Models')}</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
104
105
					</div>
				</div>
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
				<div class=" space-y-1 mb-3">
					<div class="mb-2">
						<div class="flex justify-between items-center text-xs">
							<div class=" text-xs font-medium">{$i18n.t('Default Model')}</div>
						</div>
					</div>

					<div class="flex-1 mr-2">
						<select
							class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
							bind:value={defaultModelId}
							placeholder="Select a model"
						>
							<option value="" disabled selected>{$i18n.t('Select a model')}</option>
							{#each $models.filter((model) => model.id) as model}
								<option value={model.id} class="bg-gray-100 dark:bg-gray-700">{model.name}</option>
							{/each}
						</select>
					</div>
				</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
126

127
128
				<div class=" space-y-1">
					<div class="mb-2">
Timothy J. Baek's avatar
Timothy J. Baek committed
129
						<div class="flex justify-between items-center text-xs">
Jannik Streidl's avatar
Jannik Streidl committed
130
							<div class=" text-xs font-medium">{$i18n.t('Model Whitelisting')}</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
131

132
							<Switch bind:state={whitelistEnabled} />
Timothy J. Baek's avatar
Timothy J. Baek committed
133
134
135
136
137
						</div>
					</div>

					{#if whitelistEnabled}
						<div>
138
139
140
141
142
143
144
145
146
							<div class=" space-y-1.5">
								{#each whitelistModels as modelId, modelIdx}
									<div class="flex w-full">
										<div class="flex-1 mr-2">
											<select
												class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
												bind:value={modelId}
												placeholder="Select a model"
											>
147
												<option value="" disabled selected>{$i18n.t('Select a model')}</option>
148
149
150
151
152
153
154
												{#each $models.filter((model) => model.id) as model}
													<option value={model.id} class="bg-gray-100 dark:bg-gray-700"
														>{model.name}</option
													>
												{/each}
											</select>
										</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
155

156
157
158
159
160
161
162
163
164
										{#if modelIdx === 0}
											<button
												class="px-2.5 bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-900 dark:text-white rounded-lg transition"
												type="button"
												on:click={() => {
													if (whitelistModels.at(-1) !== '') {
														whitelistModels = [...whitelistModels, ''];
													}
												}}
Timothy J. Baek's avatar
Timothy J. Baek committed
165
											>
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
												<svg
													xmlns="http://www.w3.org/2000/svg"
													viewBox="0 0 16 16"
													fill="currentColor"
													class="w-4 h-4"
												>
													<path
														d="M8.75 3.75a.75.75 0 0 0-1.5 0v3.5h-3.5a.75.75 0 0 0 0 1.5h3.5v3.5a.75.75 0 0 0 1.5 0v-3.5h3.5a.75.75 0 0 0 0-1.5h-3.5v-3.5Z"
													/>
												</svg>
											</button>
										{:else}
											<button
												class="px-2.5 bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-900 dark:text-white rounded-lg transition"
												type="button"
												on:click={() => {
													whitelistModels.splice(modelIdx, 1);
													whitelistModels = whitelistModels;
												}}
											>
												<svg
													xmlns="http://www.w3.org/2000/svg"
													viewBox="0 0 16 16"
													fill="currentColor"
													class="w-4 h-4"
												>
													<path d="M3.75 7.25a.75.75 0 0 0 0 1.5h8.5a.75.75 0 0 0 0-1.5h-8.5Z" />
												</svg>
											</button>
										{/if}
									</div>
								{/each}
							</div>

							<div class="flex justify-end items-center text-xs mt-1.5 text-right">
								<div class=" text-xs font-medium">
202
203
									{whitelistModels.length}
									{$i18n.t('Model(s) Whitelisted')}
Timothy J. Baek's avatar
Timothy J. Baek committed
204
205
206
207
208
209
210
								</div>
							</div>
						</div>
					{/if}
				</div>
			</div>
		</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
211
212
213
214
	</div>

	<div class="flex justify-end pt-3 text-sm font-medium">
		<button
Timothy J. Baek's avatar
Timothy J. Baek committed
215
			class=" px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
Timothy J. Baek's avatar
Timothy J. Baek committed
216
217
			type="submit"
		>
Jannik Streidl's avatar
Jannik Streidl committed
218
			{$i18n.t('Save')}
Timothy J. Baek's avatar
Timothy J. Baek committed
219
220
221
		</button>
	</div>
</form>