fix api api communications

This commit is contained in:
2024-05-17 14:03:34 +02:00
parent 069d9317a3
commit 4db7a35271
12 changed files with 195 additions and 145 deletions

View File

@@ -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)

View File

@@ -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"})

View File

@@ -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)

View File

@@ -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>

View File

@@ -45,7 +45,7 @@
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: auth_token
Authorization: 'Bearer' + auth_token
},
body: JSON.stringify(payload)
}).then((response) => {

View File

@@ -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>

View File

@@ -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>

View File

@@ -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 });
});

View File

@@ -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();

View 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 };

View File

@@ -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');
}

View File

@@ -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,