@lobb-js/lobb-ext-auth 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth.d.ts +13 -0
- package/dist/auth.js +44 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +52 -0
- package/dist/lib/components/pages/loginPage/index.svelte +64 -0
- package/dist/lib/components/pages/loginPage/index.svelte.d.ts +14 -0
- package/dist/lib/components/pages/settings/index.svelte +53 -0
- package/dist/lib/components/pages/settings/index.svelte.d.ts +14 -0
- package/dist/lib/components/pages/settings/pages/activityFeed.svelte +21 -0
- package/dist/lib/components/pages/settings/pages/activityFeed.svelte.d.ts +14 -0
- package/dist/lib/components/pages/settings/pages/rolesAndPermissions.svelte +21 -0
- package/dist/lib/components/pages/settings/pages/rolesAndPermissions.svelte.d.ts +14 -0
- package/dist/lib/components/pages/settings/pages/users.svelte +21 -0
- package/dist/lib/components/pages/settings/pages/users.svelte.d.ts +14 -0
- package/dist/lib/components/pages/userSettings/components/account.svelte +106 -0
- package/dist/lib/components/pages/userSettings/components/account.svelte.d.ts +14 -0
- package/dist/lib/components/pages/userSettings/components/profile.svelte +87 -0
- package/dist/lib/components/pages/userSettings/components/profile.svelte.d.ts +14 -0
- package/dist/lib/components/pages/userSettings/index.svelte +48 -0
- package/dist/lib/components/pages/userSettings/index.svelte.d.ts +14 -0
- package/dist/lib/index.d.ts +0 -0
- package/dist/lib/index.js +2 -0
- package/dist/lib/utils.d.ts +12 -0
- package/dist/lib/utils.js +5 -0
- package/dist/onStartup.d.ts +2 -0
- package/dist/onStartup.js +21 -0
- package/dist/tests/login.spec.d.ts +1 -0
- package/dist/tests/login.spec.js +27 -0
- package/dist/tests/package.json +1 -0
- package/dist/tests/playwright.config.cjs +27 -0
- package/dist/tests/playwright.config.d.cts +2 -0
- package/package.json +8 -4
- package/.vscode/settings.json +0 -5
- package/CHANGELOG.md +0 -149
- package/lobb.ts +0 -108
- package/public/public/vite.svg +0 -1
- package/public/vite.svg +0 -1
- package/scripts/postpublish.sh +0 -12
- package/scripts/prepublish.sh +0 -17
- package/studio/app.html +0 -12
- package/studio/routes/+layout.svelte +0 -7
- package/studio/routes/+layout.ts +0 -1
- package/studio/routes/[...path]/+page.svelte +0 -6
- package/svelte.config.js +0 -24
- package/todo.md +0 -37
- package/tsconfig.app.json +0 -27
- package/tsconfig.json +0 -13
- package/tsconfig.node.json +0 -26
- package/vite.config.ts +0 -8
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ExtensionUtils } from "@lobb-js/studio";
|
|
2
|
+
interface LoginPayload {
|
|
3
|
+
email: string;
|
|
4
|
+
password: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class Auth {
|
|
7
|
+
private utils;
|
|
8
|
+
constructor(utils: ExtensionUtils);
|
|
9
|
+
getSession(): any;
|
|
10
|
+
login(payload: LoginPayload): Promise<void>;
|
|
11
|
+
logout(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export {};
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export class Auth {
|
|
2
|
+
utils;
|
|
3
|
+
constructor(utils) {
|
|
4
|
+
this.utils = utils;
|
|
5
|
+
}
|
|
6
|
+
getSession() {
|
|
7
|
+
const lobbSession = localStorage.getItem("lobb_session");
|
|
8
|
+
if (lobbSession) {
|
|
9
|
+
const parsedLobbSession = JSON.parse(lobbSession);
|
|
10
|
+
this.utils.lobb.setHeaders({
|
|
11
|
+
Authorization: `Bearer ${parsedLobbSession.access_token.token}`,
|
|
12
|
+
});
|
|
13
|
+
return parsedLobbSession;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
async login(payload) {
|
|
17
|
+
const response = await this.utils.lobb.request({
|
|
18
|
+
method: "POST",
|
|
19
|
+
route: "/api/collections/auth_sessions",
|
|
20
|
+
payload: {
|
|
21
|
+
data: payload,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
if (response.status >= 400) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const result = await response.json();
|
|
28
|
+
const session = result.data;
|
|
29
|
+
localStorage.setItem("lobb_session", JSON.stringify(session));
|
|
30
|
+
this.utils.ctx.extensions.auth.session = session;
|
|
31
|
+
this.utils.lobb.setHeaders({
|
|
32
|
+
Authorization: `Bearer ${session.access_token.token}`,
|
|
33
|
+
});
|
|
34
|
+
this.utils.location.navigate("/studio");
|
|
35
|
+
}
|
|
36
|
+
async logout() {
|
|
37
|
+
await this.utils.lobb.request({
|
|
38
|
+
method: "DELETE",
|
|
39
|
+
route: "/api/extensions/auth/logout",
|
|
40
|
+
});
|
|
41
|
+
localStorage.removeItem("lobb_session");
|
|
42
|
+
this.utils.location.navigate("/studio/extensions/auth/login_page");
|
|
43
|
+
}
|
|
44
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Auth } from "./auth";
|
|
2
|
+
import { onStartup } from "./onStartup";
|
|
3
|
+
import LoginPage from "./lib/components/pages/loginPage/index.svelte";
|
|
4
|
+
import UserSettings from "./lib/components/pages/userSettings/index.svelte";
|
|
5
|
+
import Settings from "./lib/components/pages/settings/index.svelte";
|
|
6
|
+
// TODO we should export the extension object directly without a function at all. because we dont set configuration in here
|
|
7
|
+
export default function extension(utils) {
|
|
8
|
+
return {
|
|
9
|
+
name: "auth",
|
|
10
|
+
onStartup: onStartup,
|
|
11
|
+
components: {
|
|
12
|
+
"pages.login_page": LoginPage,
|
|
13
|
+
"pages.user_settings": UserSettings,
|
|
14
|
+
"pages.settings": Settings,
|
|
15
|
+
},
|
|
16
|
+
dashboardNavs: {
|
|
17
|
+
middle: [
|
|
18
|
+
{
|
|
19
|
+
label: "Auth",
|
|
20
|
+
icon: utils.components.Icons.Key,
|
|
21
|
+
href: "/studio/extensions/auth/settings/users",
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
bottom: [
|
|
25
|
+
{
|
|
26
|
+
label: "My User",
|
|
27
|
+
icon: utils.components.Icons.User,
|
|
28
|
+
onclick: () => {
|
|
29
|
+
utils.location.navigate("/studio/extensions/auth/user_settings");
|
|
30
|
+
},
|
|
31
|
+
navs: [
|
|
32
|
+
{
|
|
33
|
+
label: "User Settings",
|
|
34
|
+
icon: utils.components.Icons.Settings,
|
|
35
|
+
onclick: () => {
|
|
36
|
+
utils.location.navigate("/studio/extensions/auth/user_settings");
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
label: "Logout",
|
|
41
|
+
icon: utils.components.Icons.LogOut,
|
|
42
|
+
onclick: () => {
|
|
43
|
+
const auth = new Auth(utils);
|
|
44
|
+
auth.logout();
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ExtensionProps } from "@lobb-js/studio";
|
|
3
|
+
import { Auth } from "../../../../auth";
|
|
4
|
+
|
|
5
|
+
const { utils }: ExtensionProps = $props();
|
|
6
|
+
|
|
7
|
+
let formData = {
|
|
8
|
+
email:
|
|
9
|
+
window.location.hostname === "demo.lobb.app"
|
|
10
|
+
? "admin@example.com"
|
|
11
|
+
: "",
|
|
12
|
+
password: window.location.hostname === "demo.lobb.app" ? "admin" : "",
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
async function handleOnSubmit(e: Event) {
|
|
16
|
+
e.preventDefault();
|
|
17
|
+
if (!formData.email && !formData.password) {
|
|
18
|
+
utils.toast.error("Please complete all fields");
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const auth = new Auth(utils);
|
|
23
|
+
await auth.login(formData);
|
|
24
|
+
}
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<div
|
|
28
|
+
class="fixed left-0 top-0 flex h-screen w-screen items-center justify-center bg-muted"
|
|
29
|
+
>
|
|
30
|
+
<div class="flex w-full max-w-[25rem] flex-col gap-6 p-6">
|
|
31
|
+
<div>
|
|
32
|
+
<div class="text-4xl">Welcome back</div>
|
|
33
|
+
<div>Sign in to your account</div>
|
|
34
|
+
</div>
|
|
35
|
+
<form
|
|
36
|
+
class="flex flex-col gap-6 rounded-md border bg-white p-6"
|
|
37
|
+
onsubmit={handleOnSubmit}
|
|
38
|
+
>
|
|
39
|
+
<div class="flex flex-col gap-2">
|
|
40
|
+
<div>
|
|
41
|
+
<div class="mb-1 text-sm font-medium">Email</div>
|
|
42
|
+
<utils.components.Input
|
|
43
|
+
bind:value={formData.email}
|
|
44
|
+
autocomplete="email"
|
|
45
|
+
placeholder="email@example.com"
|
|
46
|
+
/>
|
|
47
|
+
</div>
|
|
48
|
+
<div>
|
|
49
|
+
<div class="mb-1 text-sm font-medium">Password</div>
|
|
50
|
+
<utils.components.Input
|
|
51
|
+
bind:value={formData.password}
|
|
52
|
+
type="password"
|
|
53
|
+
autocomplete="current-password"
|
|
54
|
+
placeholder="••••••••"
|
|
55
|
+
/>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
<utils.components.Button type="submit">
|
|
59
|
+
Sign In
|
|
60
|
+
</utils.components.Button>
|
|
61
|
+
<div class="text-sm underline">Forgot Password?</div>
|
|
62
|
+
</form>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
};
|
|
9
|
+
export type IndexProps = typeof __propDef.props;
|
|
10
|
+
export type IndexEvents = typeof __propDef.events;
|
|
11
|
+
export type IndexSlots = typeof __propDef.slots;
|
|
12
|
+
export default class Index extends SvelteComponentTyped<IndexProps, IndexEvents, IndexSlots> {
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ExtensionProps } from "@lobb-js/studio";
|
|
3
|
+
import Users from "./pages/users.svelte";
|
|
4
|
+
import RolesAndPermissions from "./pages/rolesAndPermissions.svelte";
|
|
5
|
+
import ActivityFeed from "./pages/activityFeed.svelte";
|
|
6
|
+
|
|
7
|
+
const props: ExtensionProps = $props();
|
|
8
|
+
const components = props.utils.components;
|
|
9
|
+
const { Sidebar } = components;
|
|
10
|
+
const { Icons } = components;
|
|
11
|
+
const auth_settings_page = $derived(props.utils.location.url.pathname.split("/")[5]);
|
|
12
|
+
const isSmall = $derived(!props.utils.mediaQueries.sm.current);
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<!-- TODO: add the sidebar in here to add these pages
|
|
16
|
+
- users
|
|
17
|
+
- roles and permissions
|
|
18
|
+
- invitation page
|
|
19
|
+
- activity feed
|
|
20
|
+
-->
|
|
21
|
+
|
|
22
|
+
<Sidebar
|
|
23
|
+
title="Auth settings"
|
|
24
|
+
showSearch={false}
|
|
25
|
+
isSelected={(element: any) => {
|
|
26
|
+
const element_page = element.href?.split("/")[5];
|
|
27
|
+
return element_page === auth_settings_page;
|
|
28
|
+
}}
|
|
29
|
+
data={[
|
|
30
|
+
{
|
|
31
|
+
name: "Users",
|
|
32
|
+
href: "/studio/extensions/auth/settings/users",
|
|
33
|
+
icon: Icons.Users
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: "roles and permissions",
|
|
37
|
+
href: "/studio/extensions/auth/settings/roles_and_permissions",
|
|
38
|
+
icon: Icons.ShieldUser
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "activity feed",
|
|
42
|
+
href: "/studio/extensions/auth/settings/activity_feed",
|
|
43
|
+
icon: Icons.ClipboardList
|
|
44
|
+
},
|
|
45
|
+
]} >
|
|
46
|
+
{#if auth_settings_page === 'users'}
|
|
47
|
+
<Users {...props} />
|
|
48
|
+
{:else if auth_settings_page === 'roles_and_permissions'}
|
|
49
|
+
<RolesAndPermissions {...props} />
|
|
50
|
+
{:else if auth_settings_page === 'activity_feed'}
|
|
51
|
+
<ActivityFeed {...props} />
|
|
52
|
+
{/if}
|
|
53
|
+
</Sidebar>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
};
|
|
9
|
+
export type IndexProps = typeof __propDef.props;
|
|
10
|
+
export type IndexEvents = typeof __propDef.events;
|
|
11
|
+
export type IndexSlots = typeof __propDef.slots;
|
|
12
|
+
export default class Index extends SvelteComponentTyped<IndexProps, IndexEvents, IndexSlots> {
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ExtensionProps } from "@lobb-js/studio";
|
|
3
|
+
|
|
4
|
+
const { utils }: ExtensionProps = $props();
|
|
5
|
+
const components = utils.components;
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<div class="flex flex-col gap-4 p-4 h-full">
|
|
9
|
+
<div>
|
|
10
|
+
<div class="text-xl font-bold">Activity Feed</div>
|
|
11
|
+
<div class="text-sm text-muted-foreground">
|
|
12
|
+
Monitor your users Activity Feed.
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
<components.Separator />
|
|
16
|
+
<div class="flex gap-4 border rounded-md overflow-hidden h-full bg-muted/30">
|
|
17
|
+
<components.DataTable
|
|
18
|
+
collectionName="auth_activity_feed"
|
|
19
|
+
/>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
};
|
|
9
|
+
export type ActivityFeedProps = typeof __propDef.props;
|
|
10
|
+
export type ActivityFeedEvents = typeof __propDef.events;
|
|
11
|
+
export type ActivityFeedSlots = typeof __propDef.slots;
|
|
12
|
+
export default class ActivityFeed extends SvelteComponentTyped<ActivityFeedProps, ActivityFeedEvents, ActivityFeedSlots> {
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ExtensionProps } from "@lobb-js/studio";
|
|
3
|
+
|
|
4
|
+
const { utils }: ExtensionProps = $props();
|
|
5
|
+
const components = utils.components;
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<div class="flex flex-col gap-4 p-4 h-full">
|
|
9
|
+
<div>
|
|
10
|
+
<div class="text-xl font-bold">Roles and Permissions</div>
|
|
11
|
+
<div class="text-sm text-muted-foreground">
|
|
12
|
+
Manage the Roles and Permissions of the system.
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
<components.Separator />
|
|
16
|
+
<div class="flex gap-4 border rounded-md overflow-hidden h-full bg-muted/30">
|
|
17
|
+
<components.DataTable
|
|
18
|
+
collectionName="auth_roles"
|
|
19
|
+
/>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
};
|
|
9
|
+
export type RolesAndPermissionsProps = typeof __propDef.props;
|
|
10
|
+
export type RolesAndPermissionsEvents = typeof __propDef.events;
|
|
11
|
+
export type RolesAndPermissionsSlots = typeof __propDef.slots;
|
|
12
|
+
export default class RolesAndPermissions extends SvelteComponentTyped<RolesAndPermissionsProps, RolesAndPermissionsEvents, RolesAndPermissionsSlots> {
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ExtensionProps } from "@lobb-js/studio";
|
|
3
|
+
|
|
4
|
+
const { utils }: ExtensionProps = $props();
|
|
5
|
+
const components = utils.components;
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<div class="flex flex-col gap-4 p-4 h-full">
|
|
9
|
+
<div>
|
|
10
|
+
<div class="text-xl font-bold">Users</div>
|
|
11
|
+
<div class="text-sm text-muted-foreground">
|
|
12
|
+
Manage the users of the system.
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
<components.Separator />
|
|
16
|
+
<div class="flex gap-4 border rounded-md overflow-hidden h-full bg-muted/30">
|
|
17
|
+
<components.DataTable
|
|
18
|
+
collectionName="auth_users"
|
|
19
|
+
/>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
};
|
|
9
|
+
export type UsersProps = typeof __propDef.props;
|
|
10
|
+
export type UsersEvents = typeof __propDef.events;
|
|
11
|
+
export type UsersSlots = typeof __propDef.slots;
|
|
12
|
+
export default class Users extends SvelteComponentTyped<UsersProps, UsersEvents, UsersSlots> {
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ExtensionProps } from "@lobb-js/studio";
|
|
3
|
+
import { onMount } from "svelte";
|
|
4
|
+
|
|
5
|
+
const { utils }: ExtensionProps = $props();
|
|
6
|
+
|
|
7
|
+
let user = $state({
|
|
8
|
+
old_password: "",
|
|
9
|
+
new_password: "",
|
|
10
|
+
});
|
|
11
|
+
const icons = utils.components.Icons;
|
|
12
|
+
|
|
13
|
+
// @ts-ignore: Im sure the session object exist
|
|
14
|
+
const currentUserId = utils.ctx.extensions.auth.session.user.id;
|
|
15
|
+
let loaded = $state(false);
|
|
16
|
+
onMount(async () => {
|
|
17
|
+
const response = await utils.lobb.findOne("auth_users", currentUserId);
|
|
18
|
+
const result = await response.json();
|
|
19
|
+
user = result.data;
|
|
20
|
+
loaded = true;
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
async function onUpdateCLick() {
|
|
24
|
+
if (!user.new_password) {
|
|
25
|
+
utils.toast.error("Make sure you fill the new password");
|
|
26
|
+
return;
|
|
27
|
+
} else if (!user.old_password) {
|
|
28
|
+
utils.toast.error("Make sure you fill the old password");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const result = await utils.lobb.request({
|
|
33
|
+
method: "POST",
|
|
34
|
+
route: "/api/extensions/auth/change_password",
|
|
35
|
+
payload: {
|
|
36
|
+
old_password: user.old_password,
|
|
37
|
+
new_password: user.new_password,
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
if (result.status >= 400) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
utils.toast.success("Account updated successfully.");
|
|
46
|
+
}
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
{#if loaded}
|
|
50
|
+
<div class="flex max-w-[40rem] flex-1 flex-col gap-4 overflow-y-visible">
|
|
51
|
+
<div>
|
|
52
|
+
<div class="text-lg font-semibold">Account</div>
|
|
53
|
+
<div class="text-sm text-muted-foreground">
|
|
54
|
+
Update your account settings.
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
<utils.components.Separator />
|
|
58
|
+
<!-- TODO: add prefered language here too -->
|
|
59
|
+
<div class="flex flex-col gap-2">
|
|
60
|
+
<div class="text-sm">Change Password</div>
|
|
61
|
+
<div class="flex gap-4">
|
|
62
|
+
<utils.components.Input
|
|
63
|
+
bind:value={user.old_password}
|
|
64
|
+
placeholder="Old password"
|
|
65
|
+
type="password"
|
|
66
|
+
/>
|
|
67
|
+
<utils.components.Input
|
|
68
|
+
bind:value={user.new_password}
|
|
69
|
+
placeholder="New password"
|
|
70
|
+
type="password"
|
|
71
|
+
/>
|
|
72
|
+
</div>
|
|
73
|
+
<div class="text-xs text-muted-foreground">
|
|
74
|
+
This is where you can change your password.
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
<utils.components.Button
|
|
78
|
+
class="self-start"
|
|
79
|
+
onclick={onUpdateCLick}
|
|
80
|
+
Icon={icons.Pencil}
|
|
81
|
+
>
|
|
82
|
+
Update Account
|
|
83
|
+
</utils.components.Button>
|
|
84
|
+
</div>
|
|
85
|
+
{:else}
|
|
86
|
+
<div class="flex max-w-[40rem] flex-1 flex-col gap-8 overflow-y-visible">
|
|
87
|
+
<div class="grid gap-2">
|
|
88
|
+
<utils.components.Skeleton class="h-8 w-full max-w-60" />
|
|
89
|
+
<utils.components.Skeleton class="h-4 w-full max-w-96" />
|
|
90
|
+
</div>
|
|
91
|
+
<utils.components.Separator />
|
|
92
|
+
<div class="flex flex-col gap-2">
|
|
93
|
+
<utils.components.Skeleton class="h-4 w-full max-w-36" />
|
|
94
|
+
<utils.components.Skeleton class="h-8 w-full max-w-60" />
|
|
95
|
+
<utils.components.Skeleton class="h-4 w-full max-w-96" />
|
|
96
|
+
</div>
|
|
97
|
+
<div class="flex flex-col gap-2">
|
|
98
|
+
<utils.components.Skeleton class="h-4 w-full max-w-36" />
|
|
99
|
+
<div class="flex gap-4">
|
|
100
|
+
<utils.components.Skeleton class="h-8 w-full max-w-60" />
|
|
101
|
+
<utils.components.Skeleton class="h-8 w-full max-w-60" />
|
|
102
|
+
</div>
|
|
103
|
+
<utils.components.Skeleton class="h-4 w-full max-w-96" />
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
{/if}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
};
|
|
9
|
+
export type AccountProps = typeof __propDef.props;
|
|
10
|
+
export type AccountEvents = typeof __propDef.events;
|
|
11
|
+
export type AccountSlots = typeof __propDef.slots;
|
|
12
|
+
export default class Account extends SvelteComponentTyped<AccountProps, AccountEvents, AccountSlots> {
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ExtensionProps } from "@lobb-js/studio";
|
|
3
|
+
import { onMount } from "svelte";
|
|
4
|
+
|
|
5
|
+
const { utils }: ExtensionProps = $props();
|
|
6
|
+
|
|
7
|
+
let user = $state({
|
|
8
|
+
name: "",
|
|
9
|
+
});
|
|
10
|
+
const icons = utils.components.Icons;
|
|
11
|
+
|
|
12
|
+
// @ts-ignore: Im sure the session object exist
|
|
13
|
+
const currentUserId = utils.ctx.extensions.auth.session.user.id;
|
|
14
|
+
let loaded = $state(false);
|
|
15
|
+
onMount(async () => {
|
|
16
|
+
const response = await utils.lobb.findOne("auth_users", currentUserId);
|
|
17
|
+
const result = await response.json();
|
|
18
|
+
user = result.data;
|
|
19
|
+
loaded = true;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
async function onUpdateCLick() {
|
|
23
|
+
// TODO: add the logic of updating some of the current user's information
|
|
24
|
+
const updateObject: any = {};
|
|
25
|
+
updateObject["name"] = user.name;
|
|
26
|
+
const response = await utils.lobb.updateOne(
|
|
27
|
+
"auth_users",
|
|
28
|
+
currentUserId,
|
|
29
|
+
updateObject,
|
|
30
|
+
);
|
|
31
|
+
if (response.status >= 400) {
|
|
32
|
+
const result = await response.json();
|
|
33
|
+
utils.toast.error(result.message);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
utils.toast.success("Profile updated successfully.");
|
|
37
|
+
}
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
{#if loaded}
|
|
41
|
+
<div class="flex max-w-[40rem] flex-1 flex-col gap-4 overflow-y-visible">
|
|
42
|
+
<div>
|
|
43
|
+
<div class="text-lg font-semibold">Profile</div>
|
|
44
|
+
<div class="text-sm text-muted-foreground">
|
|
45
|
+
Edit information that others will see.
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
<utils.components.Separator />
|
|
49
|
+
<!-- TODO: you should add name and other stuff like phone number and stuff like that -->
|
|
50
|
+
<div class="flex flex-col gap-2">
|
|
51
|
+
<div class="text-sm">Full Name</div>
|
|
52
|
+
<utils.components.Input
|
|
53
|
+
placeholder="Full Name"
|
|
54
|
+
bind:value={user.name}
|
|
55
|
+
/>
|
|
56
|
+
<div class="text-xs text-muted-foreground">
|
|
57
|
+
This is your public display name. It can be your real name or a
|
|
58
|
+
pseudonym.
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
<utils.components.Button
|
|
62
|
+
class="self-start"
|
|
63
|
+
onclick={onUpdateCLick}
|
|
64
|
+
Icon={icons.Pencil}
|
|
65
|
+
>
|
|
66
|
+
Update Profile
|
|
67
|
+
</utils.components.Button>
|
|
68
|
+
</div>
|
|
69
|
+
{:else}
|
|
70
|
+
<div class="flex max-w-[40rem] flex-1 flex-col gap-8 overflow-y-visible">
|
|
71
|
+
<div class="grid gap-2">
|
|
72
|
+
<utils.components.Skeleton class="h-8 w-full max-w-60" />
|
|
73
|
+
<utils.components.Skeleton class="h-4 w-full max-w-96" />
|
|
74
|
+
</div>
|
|
75
|
+
<utils.components.Separator />
|
|
76
|
+
<div class="flex flex-col gap-2">
|
|
77
|
+
<utils.components.Skeleton class="h-4 w-full max-w-36" />
|
|
78
|
+
<utils.components.Skeleton class="h-8 w-full max-w-60" />
|
|
79
|
+
<utils.components.Skeleton class="h-4 w-full max-w-96" />
|
|
80
|
+
</div>
|
|
81
|
+
<div class="flex flex-col gap-2">
|
|
82
|
+
<utils.components.Skeleton class="h-4 w-full max-w-36" />
|
|
83
|
+
<utils.components.Skeleton class="h-8 w-full max-w-60" />
|
|
84
|
+
<utils.components.Skeleton class="h-4 w-full max-w-96" />
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
{/if}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
};
|
|
9
|
+
export type ProfileProps = typeof __propDef.props;
|
|
10
|
+
export type ProfileEvents = typeof __propDef.events;
|
|
11
|
+
export type ProfileSlots = typeof __propDef.slots;
|
|
12
|
+
export default class Profile extends SvelteComponentTyped<ProfileProps, ProfileEvents, ProfileSlots> {
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ExtensionProps } from "@lobb-js/studio";
|
|
3
|
+
import Profile from "./components/profile.svelte";
|
|
4
|
+
import Account from "./components/account.svelte";
|
|
5
|
+
|
|
6
|
+
const props: ExtensionProps = $props();
|
|
7
|
+
const components = props.utils.components;
|
|
8
|
+
const isSmall = $derived(!props.utils.mediaQueries.sm.current);
|
|
9
|
+
|
|
10
|
+
let selectedView: "profile" | "account" = $state("profile");
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<div class="flex flex-col gap-4 p-4">
|
|
14
|
+
<div>
|
|
15
|
+
<div class="text-xl font-bold">User Settings</div>
|
|
16
|
+
<div class="text-sm text-muted-foreground">
|
|
17
|
+
Manage your user settings.
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
<components.Separator />
|
|
21
|
+
<div class="flex gap-4 {isSmall ? "flex-col" : ""}">
|
|
22
|
+
<div class="flex w-64 {isSmall ? "" : "flex-col"}">
|
|
23
|
+
<components.Button
|
|
24
|
+
onclick={() => (selectedView = "profile")}
|
|
25
|
+
variant="ghost"
|
|
26
|
+
class="flex justify-start text-muted-foreground hover:underline"
|
|
27
|
+
>
|
|
28
|
+
Profile
|
|
29
|
+
</components.Button>
|
|
30
|
+
<components.Button
|
|
31
|
+
onclick={() => (selectedView = "account")}
|
|
32
|
+
variant="ghost"
|
|
33
|
+
class="flex justify-start text-muted-foreground hover:underline"
|
|
34
|
+
>
|
|
35
|
+
Account
|
|
36
|
+
</components.Button>
|
|
37
|
+
</div>
|
|
38
|
+
{#if selectedView === "profile"}
|
|
39
|
+
<Profile {...props} />
|
|
40
|
+
{:else if selectedView === "account"}
|
|
41
|
+
<Account {...props} />
|
|
42
|
+
{:else}
|
|
43
|
+
<div class="font-bold text-red-500">
|
|
44
|
+
The "{selectedView}" view doesnt exist
|
|
45
|
+
</div>
|
|
46
|
+
{/if}
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: Record<string, never>;
|
|
4
|
+
events: {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
};
|
|
7
|
+
slots: {};
|
|
8
|
+
};
|
|
9
|
+
export type IndexProps = typeof __propDef.props;
|
|
10
|
+
export type IndexEvents = typeof __propDef.events;
|
|
11
|
+
export type IndexSlots = typeof __propDef.slots;
|
|
12
|
+
export default class Index extends SvelteComponentTyped<IndexProps, IndexEvents, IndexSlots> {
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
File without changes
|