diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 5c5e288..f7e7642 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -8,7 +8,9 @@
"name": "frontend",
"version": "0.0.1",
"dependencies": {
+ "@dagrejs/dagre": "github:dagrejs/dagre",
"@xyflow/svelte": "^0.0.41",
+ "oidc-client-ts": "^3.0.1",
"svelte-eslint-parser": "^0.33.1"
},
"devDependencies": {
@@ -572,6 +574,22 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@dagrejs/dagre": {
+ "version": "1.1.3-pre",
+ "resolved": "git+ssh://git@github.com/dagrejs/dagre.git#e6d4c7f6f95834fc794d82e6c803ead3aa3816d2",
+ "license": "MIT",
+ "dependencies": {
+ "@dagrejs/graphlib": "2.2.2"
+ }
+ },
+ "node_modules/@dagrejs/graphlib": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/@dagrejs/graphlib/-/graphlib-2.2.2.tgz",
+ "integrity": "sha512-CbyGpCDKsiTg/wuk79S7Muoj8mghDGAESWGxcSyhHX5jD35vYMBZochYVFzlHxynpE9unpu6O+4ZuhrLxASsOg==",
+ "engines": {
+ "node": ">17.0.0"
+ }
+ },
"node_modules/@esbuild/aix-ppc64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
@@ -3205,6 +3223,14 @@
"node": ">=6"
}
},
+ "node_modules/jwt-decode": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
+ "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -3480,6 +3506,17 @@
"node": ">= 6"
}
},
+ "node_modules/oidc-client-ts": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/oidc-client-ts/-/oidc-client-ts-3.0.1.tgz",
+ "integrity": "sha512-xX8unZNtmtw3sOz4FPSqDhkLFnxCDsdo2qhFEH2opgWnF/iXMFoYdBQzkwCxAZVgt3FT3DnuBY3k80EZHT0RYg==",
+ "dependencies": {
+ "jwt-decode": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 68495df..0f24fc8 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -30,7 +30,9 @@
},
"type": "module",
"dependencies": {
+ "@dagrejs/dagre": "github:dagrejs/dagre",
"@xyflow/svelte": "^0.0.41",
+ "oidc-client-ts": "^3.0.1",
"svelte-eslint-parser": "^0.33.1"
}
}
diff --git a/frontend/src/app.html b/frontend/src/app.html
index 929e4b5..b8fadaf 100644
--- a/frontend/src/app.html
+++ b/frontend/src/app.html
@@ -1,51 +1,79 @@
-
+
+
+
+
+
+ %sveltekit.head%
+
-
-
-
-
- %sveltekit.head%
-
-
-
- %sveltekit.body%
-
-
- Theme
-
+
+
+ %sveltekit.body%
-
-
-
-
-
\ No newline at end of file
+
+
+
diff --git a/frontend/src/lib/auth.ts b/frontend/src/lib/auth.ts
new file mode 100644
index 0000000..8688ac5
--- /dev/null
+++ b/frontend/src/lib/auth.ts
@@ -0,0 +1,70 @@
+import { UserManager, WebStorageStateStore, User } from 'oidc-client-ts';
+import { isAuthenticated, user } from './stores';
+import {
+ PUBLIC_ZITADEL_CLIENT_ID,
+ PUBLIC_ISSUER,
+ PUBLIC_LOGIN_REDIRECT_URI,
+ PUBLIC_LOGOUT_REDIRECT_URI
+} from '$env/static/public';
+import { goto } from '$app/navigation';
+import { browser } from '$app/environment';
+
+
+
+let userManager: UserManager;
+if (browser) {
+ const config = {
+ authority: PUBLIC_ISSUER, // At Zitadel Project Console > [Your project] > [Your application] > URLs - Issuer
+ client_id: PUBLIC_ZITADEL_CLIENT_ID, // At Zitadel Project Console > [Your project] > [Your application] > Configuration - Client ID
+ redirect_uri: PUBLIC_LOGIN_REDIRECT_URI+ '/callback', // At Zitadel Project Console > [Your project] > [Your application] > URLs - Login Redirect URI
+ response_type: 'code',
+ scope: 'openid profile email',
+ post_logout_redirect_uri: PUBLIC_LOGOUT_REDIRECT_URI,
+ userStore: new WebStorageStateStore({ store: window.localStorage }),
+ automaticSilentRenew: true,
+ silent_redirect_uri: PUBLIC_LOGIN_REDIRECT_URI + '/silent-refresh'
+ };
+
+ userManager = new UserManager(config);
+
+ userManager.events.addUserLoaded((loadedUser: User) => {
+ console.log('userManager.events.addUserLoaded');
+ user.set(loadedUser);
+ isAuthenticated.set(true);
+ });
+
+ userManager.events.addUserUnloaded(() => {
+ console.log('userManager.events.addUserUnloaded');
+ user.set(null);
+ isAuthenticated.set(false);
+ });
+}
+
+async function login(): Promise
{
+ console.log('UserManager.login()');
+ if (browser) {
+ await userManager.signinRedirect();
+ }
+}
+
+async function logout(): Promise {
+ if (browser) {
+ await userManager.signoutRedirect();
+ }
+}
+
+async function handleCallback(): Promise {
+ if (browser) {
+ await userManager.signinRedirectCallback();
+ goto('/');
+ }
+}
+
+async function handleSilentCallback(): Promise {
+ if (browser) {
+ await userManager.signinSilentCallback();
+ goto('/');
+ }
+}
+
+export { login, logout, handleCallback, handleSilentCallback };
diff --git a/frontend/src/lib/family_tree/PersonNode.svelte b/frontend/src/lib/family_tree/PersonNode.svelte
index baa078a..aff1246 100644
--- a/frontend/src/lib/family_tree/PersonNode.svelte
+++ b/frontend/src/lib/family_tree/PersonNode.svelte
@@ -2,12 +2,11 @@
import { Handle, Position } from '@xyflow/svelte';
export let person = {
- ID : "",
- Lastname : "Nem",
- Firstname : "Ismert",
- Middlename : "",
- ProfilePicture : "https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg",
-
+ ID: '',
+ Lastname: 'Nem',
+ Firstname: 'Ismert',
+ Middlename: '',
+ ProfilePicture: 'https://www.flaticon.com/free-icons/user'
};
@@ -15,10 +14,14 @@
-
+
-
{person.Lastname} {person.Firstname} {person.Middlename}
+
+ {person.Lastname}
+ {person.Firstname}
+ {person.Middlename}
+
({}));
+
+const nodeWidth = 172;
+const nodeHeight = 36;
+
+function getLayoutedElements(nodes: Node[], edges: Edge[], direction = 'TB') {
+ const isHorizontal = direction === 'LR';
+ dagreGraph.setGraph({ rankdir: direction });
+
+ nodes.forEach((node) => {
+ dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });
+ });
+
+ edges.forEach((edge) => {
+ dagreGraph.setEdge(edge.source, edge.target);
+ });
+
+ dagre.layout(dagreGraph);
+
+ nodes.forEach((node) => {
+ const nodeWithPosition = dagreGraph.node(node.id);
+ node.targetPosition = isHorizontal ? Position.Left : Position.Top;
+ node.sourcePosition = isHorizontal ? Position.Right : Position.Bottom;
+
+ // We are shifting the dagre node position (anchor=center center) to the top left
+ // so it matches the React Flow node anchor point (top left).
+ node.position = {
+ x: nodeWithPosition.x - nodeWidth / 2,
+ y: nodeWithPosition.y - nodeHeight / 2
+ };
+ });
+
+ return { nodes, edges };
+}
+
+export { getLayoutedElements };
diff --git a/frontend/src/lib/family_tree/getFamilyTree.ts b/frontend/src/lib/family_tree/getFamilyTree.ts
new file mode 100644
index 0000000..2727bc4
--- /dev/null
+++ b/frontend/src/lib/family_tree/getFamilyTree.ts
@@ -0,0 +1,27 @@
+import { PUBLIC_API_URL } from '$env/static/public';
+import { user } from '$lib/stores';
+
+let auth_token: string;
+
+user.subscribe((value) => {
+ if (value) {
+ auth_token = value.access_token;
+ }
+});
+
+async function fetch_family_tree() {
+ const response = await fetch(
+ { PUBLIC_API_URL } + '/familyTree?id=8a8b9b05bdc24550a5cc73e0b55e8d7d',
+ {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: auth_token
+ }
+ }
+ );
+ const data = await response.json();
+ return data;
+}
+
+export { fetch_family_tree };
diff --git a/frontend/src/lib/stores.ts b/frontend/src/lib/stores.ts
new file mode 100644
index 0000000..08cee58
--- /dev/null
+++ b/frontend/src/lib/stores.ts
@@ -0,0 +1,5 @@
+import { writable } from 'svelte/store';
+import type { User } from 'oidc-client-ts';
+
+export const isAuthenticated = writable(false);
+export const user = writable(null);
diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte
index c698ada..2cf8c5e 100644
--- a/frontend/src/routes/+page.svelte
+++ b/frontend/src/routes/+page.svelte
@@ -1,47 +1,78 @@
-
-
-
+
+
diff --git a/frontend/src/routes/callback/+page.svelte b/frontend/src/routes/callback/+page.svelte
new file mode 100644
index 0000000..234dfe6
--- /dev/null
+++ b/frontend/src/routes/callback/+page.svelte
@@ -0,0 +1,11 @@
+
+
+
+
Logging in...
diff --git a/frontend/src/routes/siltent-refresh/+page.svelte b/frontend/src/routes/siltent-refresh/+page.svelte
new file mode 100644
index 0000000..9914605
--- /dev/null
+++ b/frontend/src/routes/siltent-refresh/+page.svelte
@@ -0,0 +1,10 @@
+
+
+
Refreshing...
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
new file mode 100644
index 0000000..2200a64
--- /dev/null
+++ b/frontend/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "extends": "./.svelte-kit/tsconfig.json",
+ "compilerOptions": {
+ "allowJs": true,
+ "checkJs": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "sourceMap": true,
+ "strict": true
+ },
+ "include": ["src/**/*", "src/node_modules", ".svelte-kit/ambient.d.ts"] // see last element
+}