mirror of
https://github.com/vcscsvcscs/GenerationsHeritage.git
synced 2025-08-12 22:09:07 +02:00
fix api api communications
This commit is contained in:
@@ -26,7 +26,7 @@ func ViewFamiliyTree(driver neo4j.DriverWithContext) gin.HandlerFunc {
|
||||
}
|
||||
|
||||
query := `
|
||||
MATCH (n:Person {ID: $person_id})-[p:Parent*1..]->(family:Person)
|
||||
MATCH (n:Person {id: $person_id})-[p:Parent*1..]->(family:Person)
|
||||
OPTIONAL MATCH (family)-[c:Child]->(children:Person)
|
||||
WITH family, p, children, c, n
|
||||
OPTIONAL MATCH (children)<-[p2:Parent]-(OtherParents:Person)
|
||||
|
@@ -19,13 +19,17 @@ func ViewPerson(driver neo4j.DriverWithContext) gin.HandlerFunc {
|
||||
defer session.Close(ctx)
|
||||
|
||||
id := c.Query("id")
|
||||
if id == "" {
|
||||
id = c.GetString("id")
|
||||
}
|
||||
|
||||
if id == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "id is required"})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
result, err := session.Run(ctx, "MATCH (n:Person) WHERE n.ID = $person_id RETURN n;", map[string]any{"person_id": id})
|
||||
result, err := session.Run(ctx, "MATCH (n:Person) WHERE n.id = $person_id RETURN n;", map[string]any{"person_id": id})
|
||||
if err != nil {
|
||||
log.Printf("ip: %s error: %s", c.ClientIP(), err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"})
|
||||
|
@@ -2,10 +2,8 @@ package memgraph
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
@@ -21,8 +19,6 @@ func (p *Person) CreatePerson(driver neo4j.DriverWithContext) (*neo4j.Record, er
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p.ID = strings.ReplaceAll(uuid.New().String(), "-", "")
|
||||
|
||||
query := fmt.Sprintf("CREATE (n:Person {%s}) RETURN n;", p.ToString())
|
||||
|
||||
result, err := session.Run(ctx, query, nil)
|
||||
|
@@ -90,129 +90,126 @@
|
||||
You can add a family member to your family tree by filling out the form below. You can update
|
||||
the information later.
|
||||
</p>
|
||||
<form on:submit={handleSubmit} method="dialog" class="grid grid-cols-2 gap-4">
|
||||
<label for="id" class="input input-bordered flex items-center gap-2">
|
||||
ID:
|
||||
<input type="text" id="id" class="grow input-md" bind:value={id} required />
|
||||
</label>
|
||||
<label for="relationship" class="input input-bordered flex items-center gap-2">
|
||||
Relationship type:
|
||||
<select id="relationship" bind:value={relationship} required>
|
||||
<option value="" disabled selected>Choose one ...</option>
|
||||
<option value="Parent">Parent</option>
|
||||
<option value="Child">Child</option>
|
||||
<option value="Spouse">Spouse</option>
|
||||
<option value="Sibling">Sibling</option>
|
||||
</select>
|
||||
</label>
|
||||
<form on:submit={handleSubmit} method="dialog" class="flex flex-col gap-4">
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<label for="relationship" class="input input-bordered flex items-center gap-2">
|
||||
Relationship type:
|
||||
<select id="relationship" bind:value={relationship} required>
|
||||
<option value="" disabled selected>Choose one ...</option>
|
||||
<option value="Parent">Parent</option>
|
||||
<option value="Child">Child</option>
|
||||
<option value="Spouse">Spouse</option>
|
||||
<option value="Sibling">Sibling</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label for="firstName" class="input input-bordered flex items-center gap-2">
|
||||
First Name:
|
||||
<input
|
||||
type="text"
|
||||
id="firstName"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.first_name}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
<label for="firstName" class="input input-bordered flex items-center gap-2">
|
||||
First Name:
|
||||
<input
|
||||
type="text"
|
||||
id="firstName"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.first_name}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label for="middleName" class="input input-bordered flex items-center gap-2">
|
||||
Middle Name:
|
||||
<input
|
||||
type="text"
|
||||
id="middleName"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.middle_name}
|
||||
/>
|
||||
</label>
|
||||
<label for="middleName" class="input input-bordered flex items-center gap-2">
|
||||
Middle Name:
|
||||
<input
|
||||
type="text"
|
||||
id="middleName"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.middle_name}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label for="lastName" class="input input-bordered flex items-center gap-2">
|
||||
Last Name:
|
||||
<input
|
||||
type="text"
|
||||
id="lastName"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.last_name}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
<label for="lastName" class="input input-bordered flex items-center gap-2">
|
||||
Last Name:
|
||||
<input
|
||||
type="text"
|
||||
id="lastName"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.last_name}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label for="born" class="input input-bordered flex items-center gap-2">
|
||||
Born:
|
||||
<input
|
||||
type="date"
|
||||
id="born"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.born}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
<label for="born" class="input input-bordered flex items-center gap-2">
|
||||
Born:
|
||||
<input
|
||||
type="date"
|
||||
id="born"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.born}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label for="birthplace" class="input input-bordered flex items-center gap-2">
|
||||
Birthplace:
|
||||
<input
|
||||
type="text"
|
||||
id="birthplace"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.birthplace}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
<label for="birthplace" class="input input-bordered flex items-center gap-2">
|
||||
Birthplace:
|
||||
<input
|
||||
type="text"
|
||||
id="birthplace"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.birthplace}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label for="mothersFirstName" class="input input-bordered flex items-center gap-2">
|
||||
Mother's First Name:
|
||||
<input
|
||||
type="text"
|
||||
id="mothersFirstName"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.mothers_first_name}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
<label for="mothersFirstName" class="input input-bordered flex items-center gap-2">
|
||||
Mother's First Name:
|
||||
<input
|
||||
type="text"
|
||||
id="mothersFirstName"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.mothers_first_name}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label for="mothersLastName" class="input input-bordered flex items-center gap-2">
|
||||
Mother's Last Name:
|
||||
<input
|
||||
type="text"
|
||||
id="mothersLastName"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.mothers_last_name}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
<label for="mothersLastName" class="input input-bordered flex items-center gap-2">
|
||||
Mother's Last Name:
|
||||
<input
|
||||
type="text"
|
||||
id="mothersLastName"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.mothers_last_name}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label for="death" class="input input-bordered flex items-center gap-2">
|
||||
Death:
|
||||
<input type="date" id="death" class="grow input-md" bind:value={payload.person.death} />
|
||||
</label>
|
||||
<label for="death" class="input input-bordered flex items-center gap-2">
|
||||
Death:
|
||||
<input type="date" id="death" class="grow input-md" bind:value={payload.person.death} />
|
||||
</label>
|
||||
|
||||
<label for="deathplace" class="input input-bordered flex items-center gap-2">
|
||||
Place of death:
|
||||
<input
|
||||
type="text"
|
||||
id="deathplace"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.deathplace}
|
||||
/>
|
||||
</label>
|
||||
<label for="deathplace" class="input input-bordered flex items-center gap-2">
|
||||
Place of death:
|
||||
<input
|
||||
type="text"
|
||||
id="deathplace"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.deathplace}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label for="residence" class="input input-bordered flex items-center gap-2">
|
||||
Residence:
|
||||
<input
|
||||
type="text"
|
||||
id="residence"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.residence}
|
||||
/>
|
||||
</label>
|
||||
<label for="residence" class="input input-bordered flex items-center gap-2">
|
||||
Residence:
|
||||
<input
|
||||
type="text"
|
||||
id="residence"
|
||||
class="grow input-md"
|
||||
bind:value={payload.person.residence}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label for="titles" class="input input-bordered flex items-center gap-2">
|
||||
Titles:
|
||||
<input type="text" id="titles" class="grow input-md" bind:value={payload.person.titles} />
|
||||
</label>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Add</button>
|
||||
<label for="titles" class="input input-bordered flex items-center gap-2">
|
||||
Titles:
|
||||
<input type="text" id="titles" class="grow input-md" bind:value={payload.person.titles} />
|
||||
</label>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-40 place-self-end">Add</button>
|
||||
</form>
|
||||
</div>
|
||||
</dialog>
|
||||
|
@@ -45,7 +45,7 @@
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: auth_token
|
||||
Authorization: 'Bearer' + auth_token
|
||||
},
|
||||
body: JSON.stringify(payload)
|
||||
}).then((response) => {
|
||||
|
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
export let onClick: () => void;
|
||||
export let deleteNode: () => void;
|
||||
export let addRelationship: () => void;
|
||||
@@ -8,21 +10,37 @@
|
||||
export let left: number | undefined;
|
||||
export let right: number | undefined;
|
||||
export let bottom: number | undefined;
|
||||
|
||||
let contextMenu: HTMLDivElement;
|
||||
onMount(() => {
|
||||
if (top) {
|
||||
contextMenu.style.top = `${top}px`;
|
||||
}
|
||||
if (left) {
|
||||
contextMenu.style.left = `${left}px`;
|
||||
}
|
||||
if (right) {
|
||||
contextMenu.style.right = `${right}px`;
|
||||
}
|
||||
if (bottom) {
|
||||
contextMenu.style.bottom = `${bottom}px`;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
style="top: {top}px; left: {left}px; right: {right}px; bottom: {bottom}px;"
|
||||
bind:this={contextMenu}
|
||||
class="context-menu bg-primary-100 rounded-lg shadow-lg"
|
||||
on:click={onClick}
|
||||
>
|
||||
<p style="margin: 0.5em;">
|
||||
<small>node: {id}</small>
|
||||
</p>
|
||||
<button on:click={addRelationship}>Add Relationship</button>
|
||||
<button on:click={addFamilymember}>Add familymember</button>
|
||||
<button on:click={deleteNode}>Delete</button>
|
||||
<button on:click={addRelationship} class="btn">Add Relationship</button>
|
||||
<button on:click={addFamilymember} class="btn">Add familymember</button>
|
||||
<button on:click={deleteNode} class="btn">Delete</button>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
@@ -37,7 +37,7 @@
|
||||
</div>
|
||||
<h2 class="card-title text-base-content">
|
||||
{data.first_name}
|
||||
{data.middle_name}
|
||||
{data.middle_name ? data.middle_name : ''}
|
||||
{data.last_name}
|
||||
</h2>
|
||||
</div>
|
||||
|
@@ -10,7 +10,6 @@ function getLayoutedElements(nodes: Node[], edges: Edge[], direction = 'TB') {
|
||||
dagreGraph.setDefaultEdgeLabel(() => ({}));
|
||||
const isHorizontal = direction === 'LR';
|
||||
dagreGraph.setGraph({ rankdir: direction });
|
||||
|
||||
nodes.forEach((node) => {
|
||||
dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });
|
||||
});
|
||||
|
@@ -10,13 +10,11 @@ user.subscribe((value) => {
|
||||
});
|
||||
|
||||
async function fetch_family_tree() {
|
||||
console.log(PUBLIC_API_URL);
|
||||
|
||||
const response = await fetch(PUBLIC_API_URL + '/familyTree', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: 'Bearer '+auth_token
|
||||
Authorization: 'Bearer ' + auth_token
|
||||
}
|
||||
});
|
||||
const data = await response.json();
|
||||
|
24
frontend/src/lib/family_tree/getProfile.ts
Normal file
24
frontend/src/lib/family_tree/getProfile.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
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_profile(id: string = '') {
|
||||
const response = await fetch(PUBLIC_API_URL + '/person' + (id != '' ? '?id=' + id : ''), {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: 'Bearer ' + auth_token
|
||||
}
|
||||
});
|
||||
const data = await response.json();
|
||||
return data;
|
||||
}
|
||||
|
||||
export { fetch_profile };
|
@@ -3,19 +3,29 @@ import { getLayoutedElements } from '$lib/family_tree/dagreLayout';
|
||||
import { AddToNodesData, AddToEdgesData } from '$lib/family_tree/dataAdapter';
|
||||
import type { Node, Edge } from '@xyflow/svelte';
|
||||
import { useEdges, useNodes } from '@xyflow/svelte';
|
||||
import { fetch_profile } from './getProfile';
|
||||
|
||||
export function setFamilyTreeNodes(): {
|
||||
export async function setFamilyTreeNodes(): Promise<{
|
||||
nodes: Node[];
|
||||
edges: Edge[];
|
||||
} {
|
||||
}> {
|
||||
console.log('fetching nodes');
|
||||
let layoutedElements: {
|
||||
nodes: Node[];
|
||||
edges: Edge[];
|
||||
} = { nodes: [], edges: [] };
|
||||
fetch_family_tree().then((data: []) => {
|
||||
let nodes_data: Node[] = [];
|
||||
let nodes_data: Node[] = [];
|
||||
let edges_data: Edge[] = [];
|
||||
await fetch_profile().then((data) => {
|
||||
nodes_data.push({
|
||||
id: data.ElementId,
|
||||
type: 'custom',
|
||||
data: data.Props,
|
||||
position: { x: 0, y: 0 }
|
||||
});
|
||||
});
|
||||
|
||||
await fetch_family_tree().then((data: []) => {
|
||||
if (data.length == 0) {
|
||||
return layoutedElements;
|
||||
}
|
||||
@@ -30,7 +40,6 @@ export function setFamilyTreeNodes(): {
|
||||
AddToNodesData(data, 6, pushNodeToData);
|
||||
AddToNodesData(data, 8, pushNodeToData);
|
||||
|
||||
let edges_data: Edge[] = [];
|
||||
function pushEdgeToData(edge: Edge) {
|
||||
edges_data.push(edge);
|
||||
}
|
||||
@@ -39,10 +48,14 @@ export function setFamilyTreeNodes(): {
|
||||
AddToEdgesData(data, 3, pushEdgeToData);
|
||||
AddToEdgesData(data, 5, pushEdgeToData);
|
||||
AddToEdgesData(data, 7, pushEdgeToData);
|
||||
|
||||
layoutedElements = getLayoutedElements(nodes_data, edges_data, 'TB');
|
||||
console.log('nodes fetched and set');
|
||||
});
|
||||
|
||||
return layoutedElements;
|
||||
console.log('Fetched nodes and edges data.');
|
||||
|
||||
// Remove duplicate nodes
|
||||
nodes_data = nodes_data.filter(
|
||||
(node, index, self) => index === self.findIndex((n) => n.id === node.id)
|
||||
);
|
||||
|
||||
return getLayoutedElements(nodes_data, edges_data, 'TB');
|
||||
}
|
||||
|
@@ -27,13 +27,14 @@
|
||||
login();
|
||||
} else {
|
||||
console.log('user is authenticated');
|
||||
let layout = setFamilyTreeNodes();
|
||||
if (layout.nodes.length === 0) {
|
||||
CreateProfilePanel = true;
|
||||
} else {
|
||||
nodes.set(layout.nodes);
|
||||
edges.set(layout.edges);
|
||||
}
|
||||
setFamilyTreeNodes().then((layout) => {
|
||||
if (layout.nodes.length < 1) {
|
||||
CreateProfilePanel = true;
|
||||
} else {
|
||||
nodes.set(layout.nodes);
|
||||
edges.set(layout.edges);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -63,7 +64,7 @@
|
||||
event.preventDefault();
|
||||
|
||||
menu = {
|
||||
id: node.data.ID,
|
||||
id: node.data.id,
|
||||
top: event.clientY < height - 200 ? event.clientY : undefined,
|
||||
left: event.clientX < width - 200 ? event.clientX : undefined,
|
||||
right: event.clientX >= width - 200 ? width - event.clientX : undefined,
|
||||
|
Reference in New Issue
Block a user