mirror of
https://github.com/vcscsvcscs/GenerationsHeritage.git
synced 2025-08-11 21:39:06 +02:00
lint things, add sidebar
This commit is contained in:
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@@ -11,7 +11,7 @@
|
||||
"mode": "debug",
|
||||
"program": "${workspaceFolder}/apps/db-adapter/main.go",
|
||||
"env": {
|
||||
"HTTP_PORT": ":8080",
|
||||
"HTTP_PORT": ":5237",
|
||||
"MEMGRAPH_URI": "bolt://127.0.0.1:7687",
|
||||
"MEMGRAPH_USER": "memgraph",
|
||||
"MEMGRAPH_PASSWORD": "memgraph"
|
||||
|
@@ -158,5 +158,6 @@
|
||||
"welcome": "Welcome to Generations Heritage",
|
||||
"yes": "Yes",
|
||||
"zip_code": "Zip Code",
|
||||
"add_life_event": "Add life-event"
|
||||
"add_life_event": "Add life-event",
|
||||
"deleted_profiles": "Deleted profiles"
|
||||
}
|
||||
|
@@ -156,5 +156,7 @@
|
||||
"welcome": "Üdvözöljük a Generációk Öröksége oldalán",
|
||||
"yes": "Igen",
|
||||
"zip_code": "Irányítószám",
|
||||
"add_life_event": "Életesemény hozzadása"
|
||||
"add_life_event": "Életesemény hozzadása",
|
||||
"deleted_profiles": "Törölt profilok",
|
||||
"managed_profiles": "Adminisztrált profilok"
|
||||
}
|
||||
|
@@ -69,4 +69,4 @@
|
||||
"openapi-fetch": "^0.13.5",
|
||||
"pikaday": "^1.8.2"
|
||||
}
|
||||
}
|
||||
}
|
@@ -27,7 +27,7 @@ const authHandle: Handle = async ({ event, resolve }) => {
|
||||
if (session !== null) {
|
||||
setSessionTokenCookie(event, token, session.expiresAt);
|
||||
} else {
|
||||
console.log('Session token is invalid');
|
||||
console.error('Session token is invalid');
|
||||
deleteSessionTokenCookie(event);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,8 @@
|
||||
add_administrator
|
||||
} from '$lib/paraglide/messages';
|
||||
|
||||
export let id: string;
|
||||
export let XUserId: string;
|
||||
export let top: number | undefined;
|
||||
export let left: number | undefined;
|
||||
export let right: number | undefined;
|
||||
@@ -18,6 +20,7 @@
|
||||
export let addAdmin: (() => void) | undefined;
|
||||
|
||||
let contextMenu: HTMLDivElement;
|
||||
let isAdmin: boolean = false;
|
||||
onMount(() => {
|
||||
if (top) {
|
||||
contextMenu.style.top = `${top}px`;
|
||||
@@ -31,6 +34,16 @@
|
||||
if (bottom) {
|
||||
contextMenu.style.bottom = `${bottom}px`;
|
||||
}
|
||||
fetch(`/api/admin/${id}/${XUserId}`
|
||||
).then((response) => {
|
||||
if(response.status === 200){
|
||||
isAdmin = true;
|
||||
}else {
|
||||
isAdmin = false
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error('Error fetching admin status:', error);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -51,7 +64,9 @@
|
||||
</button>
|
||||
<button onclick={addRelationship} class="btn">{add_relationship()}</button>
|
||||
<button onclick={addAdmin} class="btn">{add_administrator()}</button>
|
||||
<button onclick={deleteNode} class="btn">{remove()}</button>
|
||||
{#if (Number(XUserId) !== Number(id)) && isAdmin}
|
||||
<button onclick={deleteNode} class="btn">{remove()}</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
@@ -78,7 +78,7 @@ export class FamilyTree extends dagre.graphlib.Graph {
|
||||
}
|
||||
newEdge.type = 'smoothstep';
|
||||
|
||||
newEdges.push(newEdge), newEdge;
|
||||
newEdges.push(newEdge);
|
||||
});
|
||||
|
||||
const layoutedNodes = nodes.map((node) => {
|
||||
|
@@ -10,6 +10,8 @@ export type NodeMenu = {
|
||||
addRelationship: () => void;
|
||||
addRecipe: (() => void) | undefined;
|
||||
addAdmin: (() => void) | undefined;
|
||||
id: string;
|
||||
XUserId: string;
|
||||
top: number | undefined;
|
||||
left: number | undefined;
|
||||
right: number | undefined;
|
||||
|
@@ -44,8 +44,8 @@
|
||||
} = $props();
|
||||
|
||||
let birth_date: HTMLInputElement;
|
||||
let relationship_from_time: HTMLInputElement;
|
||||
let relationship_until: HTMLInputElement;
|
||||
let relationship_from_time: HTMLInputElement = $state({} as HTMLInputElement);
|
||||
let relationship_until: HTMLInputElement = $state({} as HTMLInputElement);
|
||||
|
||||
let draftRelationship: (components['schemas']['FamilyRelationship'] & { type: string }) | null =
|
||||
$state({} as components['schemas']['FamilyRelationship'] & { type: string });
|
||||
@@ -266,22 +266,22 @@
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<label class="label" for="from_time">{from_time()}</label>
|
||||
<label class="label" for="relationship_from_time">{from_time()}</label>
|
||||
<input
|
||||
type="text"
|
||||
name="from_time"
|
||||
id="from_time"
|
||||
name="relationship_from_time"
|
||||
id="relationship_from_time"
|
||||
class="input input-bordered validator pika-single"
|
||||
placeholder={optional_field()}
|
||||
bind:this={relationship_from_time}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<label class="label" for="until">{until()}</label>
|
||||
<label class="label" for="relationship_until">{until()}</label>
|
||||
<input
|
||||
type="text"
|
||||
name="until"
|
||||
id="until"
|
||||
name="relationship_until"
|
||||
id="relationship_until"
|
||||
class="input input-bordered validator pika-single"
|
||||
placeholder={optional_field()}
|
||||
bind:this={relationship_until}
|
||||
|
34
apps/app/src/lib/sidebar/hamburgerIcon.svelte
Normal file
34
apps/app/src/lib/sidebar/hamburgerIcon.svelte
Normal file
@@ -0,0 +1,34 @@
|
||||
<script>
|
||||
export let show = false;
|
||||
</script>
|
||||
|
||||
{#if show}
|
||||
<label for="my-drawer" class="btn btn-circle drawer-button swap swap-rotate">
|
||||
<!-- this hidden checkbox controls the state -->
|
||||
<input id="my-drawer" type="checkbox" class="drawer-toggle" />
|
||||
|
||||
<!-- hamburger icon -->
|
||||
<svg
|
||||
class="swap-off fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 512 512"
|
||||
>
|
||||
<path d="M64,384H448V341.33H64Zm0-106.67H448V234.67H64ZM64,128v42.67H448V128Z" />
|
||||
</svg>
|
||||
|
||||
<!-- close icon -->
|
||||
<svg
|
||||
class="swap-on fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 512 512"
|
||||
>
|
||||
<polygon
|
||||
points="400 145.49 366.51 112 256 222.51 145.49 112 112 145.49 222.51 256 112 366.51 145.49 400 256 289.49 366.51 400 400 366.51 289.49 256 400 145.49"
|
||||
/>
|
||||
</svg>
|
||||
</label>
|
||||
{/if}
|
12
apps/app/src/lib/sidebar/sideBar.svelte
Normal file
12
apps/app/src/lib/sidebar/sideBar.svelte
Normal file
@@ -0,0 +1,12 @@
|
||||
<script>
|
||||
import { deleted_profiles, managed_profiles } from '$lib/paraglide/messages';
|
||||
</script>
|
||||
|
||||
<div class="drawer-side">
|
||||
<label for="my-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
|
||||
<ul class="menu bg-base-200 text-base-content min-h-full w-80 p-4">
|
||||
<!-- Sidebar content here -->
|
||||
<li><button class="btn btn-soft btn-primary">{managed_profiles}</button></li>
|
||||
<li><button class="btn btn-soft btn-primary">{deleted_profiles()}</button></li>
|
||||
</ul>
|
||||
</div>
|
@@ -1,4 +1,5 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import type { Mock } from 'vitest';
|
||||
import { switchToLanguage } from './switchToLanguage';
|
||||
import { i18n } from '$lib/i18n';
|
||||
import { goto } from '$app/navigation';
|
||||
@@ -28,8 +29,8 @@ describe('switchToLanguage', () => {
|
||||
const canonicalPath = '/canonical-path';
|
||||
const localisedPath = '/en/canonical-path';
|
||||
|
||||
i18n.route.mockReturnValue(canonicalPath);
|
||||
i18n.resolveRoute.mockReturnValue(localisedPath);
|
||||
(i18n.route as Mock).mockReturnValue(canonicalPath);
|
||||
(i18n.resolveRoute as Mock).mockReturnValue(localisedPath);
|
||||
|
||||
switchToLanguage(newLanguage);
|
||||
|
||||
|
@@ -6,10 +6,14 @@
|
||||
import ThemeButton from '$lib/ThemeSelect.svelte';
|
||||
import Logout from '$lib/Logout.svelte';
|
||||
import { page } from '$app/state';
|
||||
import HamburgerIcon from '$lib/sidebar/hamburgerIcon.svelte';
|
||||
</script>
|
||||
|
||||
<ParaglideJS {i18n}>
|
||||
{@render children()}
|
||||
<div class="absolute top-2 left-2 flex flex-row items-center gap-2">
|
||||
<HamburgerIcon show={!page.url.pathname.includes('login')} />
|
||||
</div>
|
||||
<div class="absolute top-2 right-2 flex flex-row items-center gap-2">
|
||||
<ThemeButton />
|
||||
<Logout show={!page.url.pathname.includes('login')} />
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { parseFamilyTree } from '$lib/graph/fetch_family_tree';
|
||||
import { parseFamilyTree } from '$lib/graph/parse_family_tree';
|
||||
import type { components } from '$lib/api/api.gen';
|
||||
import type { RequestEvent } from './$types';
|
||||
import { browser } from '$app/environment';
|
||||
@@ -24,7 +24,6 @@ export async function load(event: RequestEvent) {
|
||||
}
|
||||
|
||||
const data = (await response.json()) as components['schemas']['FamilyTree'];
|
||||
|
||||
const layout = parseFamilyTree(data) as Layout & { id: string };
|
||||
layout.id = event.locals.session.userId;
|
||||
|
||||
|
@@ -10,9 +10,8 @@
|
||||
ConnectionLineType
|
||||
} from '@xyflow/svelte';
|
||||
import '@xyflow/svelte/dist/style.css';
|
||||
import type { Node, Edge, NodeTypes, NodeEventWithPointer } from '@xyflow/svelte';
|
||||
import type { Node, Edge, NodeEventWithPointer } from '@xyflow/svelte';
|
||||
|
||||
import PersonNode from '$lib/graph/PersonNode.svelte';
|
||||
import PersonModal from '$lib/profile/Modal.svelte';
|
||||
import PersonMenu from '$lib/graph/PersonMenu.svelte';
|
||||
import CreatePerson from '$lib/profile/create/Modal.svelte';
|
||||
@@ -21,11 +20,12 @@
|
||||
import type { NodeMenu } from '$lib/graph/model';
|
||||
|
||||
import { handleNodeClick } from '$lib/graph/node_click';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
import { FamilyTree } from '$lib/graph/layout';
|
||||
import { tailwindClassToPixels } from '$lib/tailwindSizeToPx';
|
||||
import type { Layout } from '$lib/graph/model';
|
||||
import SideBar from '$lib/sidebar/sideBar.svelte';
|
||||
|
||||
let { data }: { data: Layout & { id: string } } = $props();
|
||||
|
||||
let selectedPerson: components['schemas']['PersonProperties'] & { id: number | null } = $state({
|
||||
@@ -62,6 +62,7 @@
|
||||
}
|
||||
|
||||
openPersonMenu = {
|
||||
XUserId: data.id,
|
||||
onClick: () => {
|
||||
openPersonMenu = undefined;
|
||||
},
|
||||
@@ -108,6 +109,7 @@
|
||||
relationshipStart = Number(node.id);
|
||||
openPersonMenu = undefined;
|
||||
},
|
||||
id: node.id,
|
||||
top: event.clientY < clientHeight - 200 ? event.clientY : undefined,
|
||||
left: event.clientX < clientWidth - 200 ? event.clientX : undefined,
|
||||
right: event.clientX >= clientWidth - 200 ? clientWidth - event.clientX : undefined,
|
||||
@@ -178,46 +180,48 @@
|
||||
<svelte:head>
|
||||
<title>{title({ page: family_tree() })}</title>
|
||||
</svelte:head>
|
||||
|
||||
<div style="height:100vh;" class="!bg-base-200 flex flex-col">
|
||||
<SvelteFlowProvider>
|
||||
<SvelteFlow
|
||||
bind:nodes
|
||||
bind:edges
|
||||
onnodeclick={handleNodeClickFunc}
|
||||
onnodecontextmenu={handleContextMenu}
|
||||
onpaneclick={handlePaneClick}
|
||||
class="!bg-base-200"
|
||||
{nodeTypes}
|
||||
fitView
|
||||
onlyRenderVisibleElements
|
||||
connectionLineType={ConnectionLineType.SmoothStep}
|
||||
>
|
||||
<MiniMap class="!bg-base-300" />
|
||||
<Controls class="!bg-base-300" />
|
||||
{#if openPersonPanel}
|
||||
<PersonModal
|
||||
person={selectedPerson}
|
||||
closeModal={() => {
|
||||
openPersonPanel = false;
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
{#if createPerson}
|
||||
<CreatePerson
|
||||
onOnlyPersonCreation={() => {
|
||||
createPerson = false;
|
||||
}}
|
||||
{onCreation}
|
||||
closeModal={() => {
|
||||
createPerson = false;
|
||||
}}
|
||||
relationshipStartID={relationshipStart}
|
||||
></CreatePerson>
|
||||
{/if}
|
||||
{#if openPersonMenu !== undefined}
|
||||
<PersonMenu {...openPersonMenu!} />
|
||||
{/if}
|
||||
</SvelteFlow>
|
||||
</SvelteFlowProvider>
|
||||
<div class="drawer">
|
||||
<div style="height:100vh;" class="!bg-base-200 drawer-content flex flex-col">
|
||||
<SvelteFlowProvider>
|
||||
<SvelteFlow
|
||||
bind:nodes
|
||||
bind:edges
|
||||
onnodeclick={handleNodeClickFunc}
|
||||
onnodecontextmenu={handleContextMenu}
|
||||
onpaneclick={handlePaneClick}
|
||||
class="!bg-base-200"
|
||||
{nodeTypes}
|
||||
fitView
|
||||
onlyRenderVisibleElements
|
||||
connectionLineType={ConnectionLineType.SmoothStep}
|
||||
>
|
||||
<MiniMap class="!bg-base-300" />
|
||||
<Controls class="!bg-base-300" />
|
||||
{#if openPersonPanel}
|
||||
<PersonModal
|
||||
person={selectedPerson}
|
||||
closeModal={() => {
|
||||
openPersonPanel = false;
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
{#if createPerson}
|
||||
<CreatePerson
|
||||
onOnlyPersonCreation={() => {
|
||||
createPerson = false;
|
||||
}}
|
||||
{onCreation}
|
||||
closeModal={() => {
|
||||
createPerson = false;
|
||||
}}
|
||||
relationshipStartID={relationshipStart}
|
||||
></CreatePerson>
|
||||
{/if}
|
||||
{#if openPersonMenu !== undefined}
|
||||
<PersonMenu {...openPersonMenu!} />
|
||||
{/if}
|
||||
</SvelteFlow>
|
||||
</SvelteFlowProvider>
|
||||
</div>
|
||||
<SideBar />
|
||||
</div>
|
||||
|
@@ -35,7 +35,7 @@ export async function GET(event: RequestEvent): Promise<Response> {
|
||||
message: 'Family tree is empty'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var graphToReturn: components['schemas']['FamilyTree'] = {
|
||||
people: [],
|
||||
relationships: response.data.relationships
|
||||
|
@@ -20,7 +20,7 @@ export async function POST(event: RequestEvent): Promise<Response> {
|
||||
}
|
||||
});
|
||||
|
||||
if (response.response.ok) {
|
||||
if (response.response.ok && response.response.status === 200) {
|
||||
return new Response(JSON.stringify(response.data), {
|
||||
status: response.response.status
|
||||
});
|
||||
|
@@ -53,6 +53,7 @@ func (srv *server) GetFamilyTreeWithSpousesById(
|
||||
err = FlattenFamilyTree(res, &results)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"msg": err.Error()})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user