Spaces:
Running
Running
Commit
•
c8c5d70
1
Parent(s):
06e879d
♿️ No-JS ethics modal (#166)
Browse files- src/lib/components/EthicsModal.svelte +16 -19
- src/lib/components/SettingsModal.svelte +17 -14
- src/lib/components/Switch.svelte +3 -13
- src/lib/components/chat/ChatIntroduction.svelte +5 -7
- src/lib/types/UrlDependency.ts +0 -1
- src/lib/updateSettings.ts +0 -29
- src/routes/+layout.server.ts +0 -1
- src/routes/+layout.svelte +1 -1
- src/routes/settings/+page.server.ts +45 -0
- src/routes/settings/+server.ts +0 -34
src/lib/components/EthicsModal.svelte
CHANGED
@@ -1,11 +1,9 @@
|
|
1 |
<script lang="ts">
|
|
|
|
|
2 |
import { PUBLIC_VERSION } from "$env/static/public";
|
3 |
import Logo from "$lib/components/icons/Logo.svelte";
|
4 |
import Modal from "$lib/components/Modal.svelte";
|
5 |
-
import type { Settings } from "$lib/types/Settings";
|
6 |
-
import { updateSettings } from "$lib/updateSettings";
|
7 |
-
|
8 |
-
export let settings: Omit<Settings, "sessionId" | "createdAt" | "updatedAt">;
|
9 |
</script>
|
10 |
|
11 |
<Modal>
|
@@ -14,13 +12,11 @@
|
|
14 |
>
|
15 |
<h2 class="flex items-center text-2xl font-semibold text-gray-800">
|
16 |
<Logo classNames="text-3xl mr-1.5" />HuggingChat
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
</div>
|
23 |
-
{/if}
|
24 |
</h2>
|
25 |
<p class="px-4 text-lg font-semibold leading-snug text-gray-800 sm:px-12">
|
26 |
This application is for demonstration purposes only.
|
@@ -32,13 +28,14 @@
|
|
32 |
<p class="px-2 text-sm text-gray-500">
|
33 |
Your conversations will be shared with model authors unless you disable it from your settings.
|
34 |
</p>
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
|
|
43 |
</div>
|
44 |
</Modal>
|
|
|
1 |
<script lang="ts">
|
2 |
+
import { enhance } from "$app/forms";
|
3 |
+
import { base } from "$app/paths";
|
4 |
import { PUBLIC_VERSION } from "$env/static/public";
|
5 |
import Logo from "$lib/components/icons/Logo.svelte";
|
6 |
import Modal from "$lib/components/Modal.svelte";
|
|
|
|
|
|
|
|
|
7 |
</script>
|
8 |
|
9 |
<Modal>
|
|
|
12 |
>
|
13 |
<h2 class="flex items-center text-2xl font-semibold text-gray-800">
|
14 |
<Logo classNames="text-3xl mr-1.5" />HuggingChat
|
15 |
+
<div
|
16 |
+
class="ml-3 flex h-6 items-center rounded-lg border border-gray-100 bg-gray-50 px-2 text-base text-gray-400"
|
17 |
+
>
|
18 |
+
v{PUBLIC_VERSION}
|
19 |
+
</div>
|
|
|
|
|
20 |
</h2>
|
21 |
<p class="px-4 text-lg font-semibold leading-snug text-gray-800 sm:px-12">
|
22 |
This application is for demonstration purposes only.
|
|
|
28 |
<p class="px-2 text-sm text-gray-500">
|
29 |
Your conversations will be shared with model authors unless you disable it from your settings.
|
30 |
</p>
|
31 |
+
<form action="{base}/settings" use:enhance method="POST">
|
32 |
+
<input type="hidden" name="ethicsModalAccepted" value={true} />
|
33 |
+
<button
|
34 |
+
type="submit"
|
35 |
+
class="mt-2 rounded-full bg-black px-5 py-2 text-lg font-semibold text-gray-100 transition-colors hover:bg-yellow-500"
|
36 |
+
>
|
37 |
+
Start chatting
|
38 |
+
</button>
|
39 |
+
</form>
|
40 |
</div>
|
41 |
</Modal>
|
src/lib/components/SettingsModal.svelte
CHANGED
@@ -5,7 +5,8 @@
|
|
5 |
import CarbonClose from "~icons/carbon/close";
|
6 |
import Switch from "$lib/components/Switch.svelte";
|
7 |
import type { Settings } from "$lib/types/Settings";
|
8 |
-
import {
|
|
|
9 |
|
10 |
export let settings: Pick<Settings, "shareConversationsWithModelAuthors">;
|
11 |
|
@@ -13,7 +14,14 @@
|
|
13 |
</script>
|
14 |
|
15 |
<Modal>
|
16 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
<div class="flex items-start justify-between text-xl font-semibold text-gray-800">
|
18 |
<h2>Settings</h2>
|
19 |
<button class="group" on:click={() => dispatch("close")}>
|
@@ -21,8 +29,11 @@
|
|
21 |
</button>
|
22 |
</div>
|
23 |
|
24 |
-
<label class="flex cursor-pointer select-none items-center gap-2 text-gray-500"
|
25 |
-
<Switch
|
|
|
|
|
|
|
26 |
Share conversations with model authors
|
27 |
</label>
|
28 |
|
@@ -42,18 +53,10 @@
|
|
42 |
>.
|
43 |
</p>
|
44 |
<button
|
45 |
-
type="
|
46 |
class="mt-2 rounded-full bg-black px-5 py-2 text-lg font-semibold text-gray-100 ring-gray-400 ring-offset-1 transition-colors hover:ring"
|
47 |
-
on:click={() =>
|
48 |
-
updateSettings({
|
49 |
-
shareConversationsWithModelAuthors: settings.shareConversationsWithModelAuthors,
|
50 |
-
}).then((res) => {
|
51 |
-
if (res) {
|
52 |
-
dispatch("close");
|
53 |
-
}
|
54 |
-
})}
|
55 |
>
|
56 |
Apply
|
57 |
</button>
|
58 |
-
</
|
59 |
</Modal>
|
|
|
5 |
import CarbonClose from "~icons/carbon/close";
|
6 |
import Switch from "$lib/components/Switch.svelte";
|
7 |
import type { Settings } from "$lib/types/Settings";
|
8 |
+
import { enhance } from "$app/forms";
|
9 |
+
import { base } from "$app/paths";
|
10 |
|
11 |
export let settings: Pick<Settings, "shareConversationsWithModelAuthors">;
|
12 |
|
|
|
14 |
</script>
|
15 |
|
16 |
<Modal>
|
17 |
+
<form
|
18 |
+
class="flex w-full flex-col gap-5 p-6"
|
19 |
+
use:enhance={() => {
|
20 |
+
dispatch("close");
|
21 |
+
}}
|
22 |
+
method="post"
|
23 |
+
action="{base}/settings"
|
24 |
+
>
|
25 |
<div class="flex items-start justify-between text-xl font-semibold text-gray-800">
|
26 |
<h2>Settings</h2>
|
27 |
<button class="group" on:click={() => dispatch("close")}>
|
|
|
29 |
</button>
|
30 |
</div>
|
31 |
|
32 |
+
<label class="flex cursor-pointer select-none items-center gap-2 text-gray-500">
|
33 |
+
<Switch
|
34 |
+
name="shareConversationsWithModelAuthors"
|
35 |
+
bind:checked={settings.shareConversationsWithModelAuthors}
|
36 |
+
/>
|
37 |
Share conversations with model authors
|
38 |
</label>
|
39 |
|
|
|
53 |
>.
|
54 |
</p>
|
55 |
<button
|
56 |
+
type="submit"
|
57 |
class="mt-2 rounded-full bg-black px-5 py-2 text-lg font-semibold text-gray-100 ring-gray-400 ring-offset-1 transition-colors hover:ring"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
>
|
59 |
Apply
|
60 |
</button>
|
61 |
+
</form>
|
62 |
</Modal>
|
src/lib/components/Switch.svelte
CHANGED
@@ -3,19 +3,9 @@
|
|
3 |
export let name: string;
|
4 |
</script>
|
5 |
|
|
|
6 |
<div
|
7 |
-
class="relative inline-flex h-5 w-9 items-center rounded-full p-1 shadow-inner transition-all
|
8 |
-
? 'bg-black'
|
9 |
-
: 'bg-gray-300 hover:bg-gray-400'}"
|
10 |
>
|
11 |
-
<
|
12 |
-
bind:checked
|
13 |
-
type="checkbox"
|
14 |
-
{name}
|
15 |
-
id={name}
|
16 |
-
class="peer absolute inset-0 cursor-pointer opacity-0"
|
17 |
-
/>
|
18 |
-
<div
|
19 |
-
class="h-3.5 w-3.5 rounded-full bg-white shadow-sm transition-all peer-checked:translate-x-3.5"
|
20 |
-
/>
|
21 |
</div>
|
|
|
3 |
export let name: string;
|
4 |
</script>
|
5 |
|
6 |
+
<input bind:checked type="checkbox" {name} class="peer pointer-events-none absolute opacity-0" />
|
7 |
<div
|
8 |
+
class="relative inline-flex h-5 w-9 items-center rounded-full bg-gray-300 p-1 shadow-inner transition-all peer-checked:bg-black hover:bg-gray-400 peer-checked:[&>div]:translate-x-3.5"
|
|
|
|
|
9 |
>
|
10 |
+
<div class="h-3.5 w-3.5 rounded-full bg-white shadow-sm transition-all" />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
</div>
|
src/lib/components/chat/ChatIntroduction.svelte
CHANGED
@@ -15,13 +15,11 @@
|
|
15 |
<div class="mb-3 flex items-center text-2xl font-semibold">
|
16 |
<Logo classNames="mr-1 text-yellow-400 text-4xl" />
|
17 |
HuggingChat
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
</div>
|
24 |
-
{/if}
|
25 |
</div>
|
26 |
<p class="text-base text-gray-600 dark:text-gray-400">
|
27 |
Making the community's best AI chat models available to everyone.
|
|
|
15 |
<div class="mb-3 flex items-center text-2xl font-semibold">
|
16 |
<Logo classNames="mr-1 text-yellow-400 text-4xl" />
|
17 |
HuggingChat
|
18 |
+
<div
|
19 |
+
class="ml-3 flex h-6 items-center rounded-lg border border-gray-100 bg-gray-50 px-2 text-base text-gray-400 dark:border-gray-700/60 dark:bg-gray-800"
|
20 |
+
>
|
21 |
+
v{PUBLIC_VERSION}
|
22 |
+
</div>
|
|
|
|
|
23 |
</div>
|
24 |
<p class="text-base text-gray-600 dark:text-gray-400">
|
25 |
Making the community's best AI chat models available to everyone.
|
src/lib/types/UrlDependency.ts
CHANGED
@@ -1,5 +1,4 @@
|
|
1 |
/* eslint-disable no-shadow */
|
2 |
export enum UrlDependency {
|
3 |
ConversationList = "conversation:list",
|
4 |
-
Settings = "settings:list",
|
5 |
}
|
|
|
1 |
/* eslint-disable no-shadow */
|
2 |
export enum UrlDependency {
|
3 |
ConversationList = "conversation:list",
|
|
|
4 |
}
|
src/lib/updateSettings.ts
DELETED
@@ -1,29 +0,0 @@
|
|
1 |
-
import { invalidate } from "$app/navigation";
|
2 |
-
import { base } from "$app/paths";
|
3 |
-
import { error } from "$lib/stores/errors";
|
4 |
-
import type { Settings } from "./types/Settings";
|
5 |
-
import { UrlDependency } from "./types/UrlDependency";
|
6 |
-
|
7 |
-
export async function updateSettings(
|
8 |
-
settings: Partial<
|
9 |
-
Omit<Settings, "sessionId" | "ethicsModalAcceptedAt"> & { ethicsModalAccepted?: boolean }
|
10 |
-
>
|
11 |
-
): Promise<boolean> {
|
12 |
-
try {
|
13 |
-
const res = await fetch(`${base}/settings`, {
|
14 |
-
method: "PATCH",
|
15 |
-
headers: { "Content-Type": "application/json" },
|
16 |
-
body: JSON.stringify(settings),
|
17 |
-
});
|
18 |
-
if (!res.ok) {
|
19 |
-
error.set("Error while updating settings, try again.");
|
20 |
-
return false;
|
21 |
-
}
|
22 |
-
await invalidate(UrlDependency.Settings);
|
23 |
-
return true;
|
24 |
-
} catch (err) {
|
25 |
-
console.error(err);
|
26 |
-
error.set(String(err));
|
27 |
-
return false;
|
28 |
-
}
|
29 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/routes/+layout.server.ts
CHANGED
@@ -8,7 +8,6 @@ export const load: LayoutServerLoad = async ({ locals, depends }) => {
|
|
8 |
const { conversations } = collections;
|
9 |
|
10 |
depends(UrlDependency.ConversationList);
|
11 |
-
depends(UrlDependency.Settings);
|
12 |
|
13 |
const settings = await collections.settings.findOne({ sessionId: locals.sessionId });
|
14 |
|
|
|
8 |
const { conversations } = collections;
|
9 |
|
10 |
depends(UrlDependency.ConversationList);
|
|
|
11 |
|
12 |
const settings = await collections.settings.findOne({ sessionId: locals.sessionId });
|
13 |
|
src/routes/+layout.svelte
CHANGED
@@ -135,7 +135,7 @@
|
|
135 |
<SettingsModal on:close={() => (isSettingsOpen = false)} settings={data.settings} />
|
136 |
{/if}
|
137 |
{#if !data.settings.ethicsModalAcceptedAt}
|
138 |
-
<EthicsModal
|
139 |
{/if}
|
140 |
<slot />
|
141 |
</div>
|
|
|
135 |
<SettingsModal on:close={() => (isSettingsOpen = false)} settings={data.settings} />
|
136 |
{/if}
|
137 |
{#if !data.settings.ethicsModalAcceptedAt}
|
138 |
+
<EthicsModal />
|
139 |
{/if}
|
140 |
<slot />
|
141 |
</div>
|
src/routes/settings/+page.server.ts
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { base } from "$app/paths";
|
2 |
+
import { collections } from "$lib/server/database.js";
|
3 |
+
import { redirect } from "@sveltejs/kit";
|
4 |
+
import { z } from "zod";
|
5 |
+
|
6 |
+
export const actions = {
|
7 |
+
default: async function ({ request, locals }) {
|
8 |
+
const formData = await request.formData();
|
9 |
+
|
10 |
+
const existingSettings = await collections.settings.findOne({ sessionId: locals.sessionId });
|
11 |
+
|
12 |
+
const { ethicsModalAccepted, ...settings } = z
|
13 |
+
.object({
|
14 |
+
shareConversationsWithModelAuthors: z
|
15 |
+
.boolean({ coerce: true })
|
16 |
+
.default(existingSettings?.shareConversationsWithModelAuthors ?? true),
|
17 |
+
ethicsModalAccepted: z.boolean({ coerce: true }).optional(),
|
18 |
+
})
|
19 |
+
.parse({
|
20 |
+
shareConversationsWithModelAuthors: formData.get("shareConversationsWithModelAuthors"),
|
21 |
+
ethicsModalAccepted: formData.get("ethicsModalAccepted"),
|
22 |
+
});
|
23 |
+
|
24 |
+
await collections.settings.updateOne(
|
25 |
+
{
|
26 |
+
sessionId: locals.sessionId,
|
27 |
+
},
|
28 |
+
{
|
29 |
+
$set: {
|
30 |
+
...settings,
|
31 |
+
...(ethicsModalAccepted && { ethicsModalAcceptedAt: new Date() }),
|
32 |
+
updatedAt: new Date(),
|
33 |
+
},
|
34 |
+
$setOnInsert: {
|
35 |
+
createdAt: new Date(),
|
36 |
+
},
|
37 |
+
},
|
38 |
+
{
|
39 |
+
upsert: true,
|
40 |
+
}
|
41 |
+
);
|
42 |
+
|
43 |
+
throw redirect(303, request.headers.get("referer") || base || "/");
|
44 |
+
},
|
45 |
+
};
|
src/routes/settings/+server.ts
DELETED
@@ -1,34 +0,0 @@
|
|
1 |
-
import { collections } from "$lib/server/database.js";
|
2 |
-
import { z } from "zod";
|
3 |
-
|
4 |
-
export async function PATCH({ locals, request }) {
|
5 |
-
const json = await request.json();
|
6 |
-
|
7 |
-
const { ethicsModalAccepted, ...settings } = z
|
8 |
-
.object({
|
9 |
-
shareConversationsWithModelAuthors: z.boolean().default(true),
|
10 |
-
ethicsModalAccepted: z.boolean().optional(),
|
11 |
-
})
|
12 |
-
.parse(json);
|
13 |
-
|
14 |
-
await collections.settings.updateOne(
|
15 |
-
{
|
16 |
-
sessionId: locals.sessionId,
|
17 |
-
},
|
18 |
-
{
|
19 |
-
$set: {
|
20 |
-
...settings,
|
21 |
-
...(ethicsModalAccepted && { ethicsModalAcceptedAt: new Date() }),
|
22 |
-
updatedAt: new Date(),
|
23 |
-
},
|
24 |
-
$setOnInsert: {
|
25 |
-
createdAt: new Date(),
|
26 |
-
},
|
27 |
-
},
|
28 |
-
{
|
29 |
-
upsert: true,
|
30 |
-
}
|
31 |
-
);
|
32 |
-
|
33 |
-
return new Response();
|
34 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|