Skip to content

Commit

Permalink
41 implement a tree view to displays the root mandr and its children (#…
Browse files Browse the repository at this point in the history
…43)

* FileTree component and test

* connect dashboard tree to the API

* update makefile to easily launch api

* fix typos found by auguste

* Apply suggestions from code review

Co-authored-by: Auguste Baum <[email protected]>

---------

Co-authored-by: Auguste Baum <[email protected]>
  • Loading branch information
rouk1 and augustebaum authored Jul 17, 2024
1 parent 438dbe0 commit f7701e3
Show file tree
Hide file tree
Showing 23 changed files with 482 additions and 42 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ check-wip:
python -m pytest tests

serve-api:
python -m uvicorn mandr.dashboard.webapp:app --reload --reload-dir src --host 0.0.0.0 --timeout-graceful-shutdown 0
MANDR_ROOT=.datamander MANDR_PATH=probabl-ai python -m uvicorn mandr.dashboard.webapp:app --reload --reload-dir ./src --host 0.0.0.0 --timeout-graceful-shutdown 0

build-frontend:
# build the SPA
Expand Down
4 changes: 2 additions & 2 deletions frontend/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ require('@rushstack/eslint-patch/modern-module-resolution')

module.exports = {
root: true,
'extends': [
'plugin:vue/vue3-essential',
extends: [
'eslint:recommended',
'plugin:vue/vue3-essential',
'@vue/eslint-config-typescript',
'@vue/eslint-config-prettier/skip-formatting'
],
Expand Down
2 changes: 1 addition & 1 deletion frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"@vue/tsconfig": "^0.5.1",
"autoprefixer": "^10.4.19",
"eslint": "^8.57.0",
"eslint-plugin-vue": "^9.23.0",
"eslint-plugin-vue": "^9.27.0",
"jsdom": "^24.1.0",
"npm-run-all2": "^6.2.0",
"postcss-html": "^1.7.0",
Expand Down
16 changes: 11 additions & 5 deletions frontend/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
<script setup lang="ts">
import { RouterView } from "vue-router";
import LoadingBars from "./components/LoadingBars.vue";
</script>

<template>
<header>
<nav></nav>
</header>

<RouterView />
<RouterView v-slot="{ Component }">
<template v-if="Component">
<Suspense>
<component :is="Component" />
<template #fallback>
<LoadingBars />
</template>
</Suspense>
</template>
</RouterView>
</template>
27 changes: 20 additions & 7 deletions frontend/src/components/FileTree.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
<script setup lang="ts"></script>
<script lang="ts">
export interface FileTreeNode {
label: string;
children?: FileTreeNode[];
indentationLevel?: number;
}
</script>

<script setup lang="ts">
import FileTreeItem from "./FileTreeItem.vue";
defineProps<{ nodes: FileTreeNode[] }>();
</script>

<template>
<div class="file-tree">
<div class="tree-item">1</div>
<div class="tree-item">2</div>
<div class="tree-item">3</div>
<div class="tree-item">4</div>
</div>
<FileTreeItem
v-for="(node, index) in nodes"
:key="index"
:label="node.label"
:children="node.children"
:indentation-level="0"
/>
</template>

<style>
Expand Down
58 changes: 58 additions & 0 deletions frontend/src/components/FileTreeItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<script setup lang="ts">
import { computed } from "vue";
import { type FileTreeNode } from "./FileTree.vue";
import FolderIcon from "./icons/FolderIcon.vue";
import ManderIcon from "./icons/ManderIcon.vue";
const props = defineProps<FileTreeNode>();
const hasChildren = computed(() => props.children?.length);
</script>

<template>
<div class="file-tree-item" :style="`--indentation-level: ${indentationLevel};`">
<div class="label">
<div class="icon">
<FolderIcon v-if="hasChildren" />
<ManderIcon v-else />
</div>
<div class="text">{{ props.label }}</div>
</div>
<div class="children" v-if="hasChildren">
<FileTreeItem
v-for="(child, index) in props.children"
:key="index"
:label="child.label"
:children="child.children"
:indentation-level="(indentationLevel ?? 0) + 1"
/>
</div>
</div>
</template>
<style>
.file-tree-item {
margin-left: calc(8px * var(--indentation-level));
.label {
display: flex;
flex-direction: row;
align-items: center;
padding: 3px;
border-radius: 4px;
cursor: pointer;
transition: var(--transition);
&:hover {
background-color: #ddd;
}
& .icon {
display: flex;
width: 24px;
height: 24px;
align-items: center;
}
}
}
</style>
94 changes: 94 additions & 0 deletions frontend/src/components/LoadingBars.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="45" height="45" viewBox="0 0 135 140" fill="#ddd">
<rect y="10" width="15" height="120" rx="6">
<animate
attributeName="height"
begin="0.5s"
dur="1s"
values="120;110;100;90;80;70;60;50;40;140;120"
calcMode="linear"
repeatCount="indefinite"
/>
<animate
attributeName="y"
begin="0.5s"
dur="1s"
values="10;15;20;25;30;35;40;45;50;0;10"
calcMode="linear"
repeatCount="indefinite"
/>
</rect>
<rect x="30" y="10" width="15" height="120" rx="6">
<animate
attributeName="height"
begin="0.25s"
dur="1s"
values="120;110;100;90;80;70;60;50;40;140;120"
calcMode="linear"
repeatCount="indefinite"
/>
<animate
attributeName="y"
begin="0.25s"
dur="1s"
values="10;15;20;25;30;35;40;45;50;0;10"
calcMode="linear"
repeatCount="indefinite"
/>
</rect>
<rect x="60" width="15" height="140" rx="6">
<animate
attributeName="height"
begin="0s"
dur="1s"
values="120;110;100;90;80;70;60;50;40;140;120"
calcMode="linear"
repeatCount="indefinite"
/>
<animate
attributeName="y"
begin="0s"
dur="1s"
values="10;15;20;25;30;35;40;45;50;0;10"
calcMode="linear"
repeatCount="indefinite"
/>
</rect>
<rect x="90" y="10" width="15" height="120" rx="6">
<animate
attributeName="height"
begin="0.25s"
dur="1s"
values="120;110;100;90;80;70;60;50;40;140;120"
calcMode="linear"
repeatCount="indefinite"
/>
<animate
attributeName="y"
begin="0.25s"
dur="1s"
values="10;15;20;25;30;35;40;45;50;0;10"
calcMode="linear"
repeatCount="indefinite"
/>
</rect>
<rect x="120" y="10" width="15" height="120" rx="6">
<animate
attributeName="height"
begin="0.5s"
dur="1s"
values="120;110;100;90;80;70;60;50;40;140;120"
calcMode="linear"
repeatCount="indefinite"
/>
<animate
attributeName="y"
begin="0.5s"
dur="1s"
values="10;15;20;25;30;35;40;45;50;0;10"
calcMode="linear"
repeatCount="indefinite"
/>
</rect>
</svg>
</template>
11 changes: 0 additions & 11 deletions frontend/src/components/__tests__/FileTree.spec.ts

This file was deleted.

11 changes: 11 additions & 0 deletions frontend/src/components/icons/FolderIcon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<template>
<svg width="20" height="17" viewBox="0 0 20 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M1 2V15C1 15.5523 1.44772 16 2 16H18C18.5523 16 19 15.5523 19 15V5C19 4.44772 18.5523 4 18 4H10.5352C10.2008 4 9.8886 3.8329 9.7031 3.5547L8.2969 1.4453C8.1114 1.1671 7.79917 1 7.46482 1H2C1.44772 1 1 1.44772 1 2Z"
stroke="#7E7E7E"
stroke-width="1.3"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</template>
8 changes: 8 additions & 0 deletions frontend/src/components/icons/ManderIcon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<template>
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M6.4 1C6.12386 1 5.9 1.22386 5.9 1.5C5.9 1.77614 6.12386 2 6.4 2V1ZM6.6 2C6.87614 2 7.1 1.77614 7.1 1.5C7.1 1.22386 6.87614 1 6.6 1V2ZM17 13L17.416 13.2774C17.5183 13.1239 17.5278 12.9266 17.4408 12.7641C17.3538 12.6015 17.1844 12.5 17 12.5V13ZM1 13V12.5C0.815602 12.5 0.646172 12.6015 0.559163 12.7641C0.472153 12.9266 0.481689 13.1239 0.583975 13.2774L1 13ZM7 16.5C6.72386 16.5 6.5 16.7239 6.5 17C6.5 17.2761 6.72386 17.5 7 17.5V16.5ZM11 17.5C11.2761 17.5 11.5 17.2761 11.5 17C11.5 16.7239 11.2761 16.5 11 16.5V17.5ZM11.8333 3.83333L12.0569 4.28054C12.1537 4.23216 12.2321 4.1537 12.2805 4.05694L11.8333 3.83333ZM13.25 1L13.6972 0.776389C13.6125 0.606999 13.4394 0.5 13.25 0.5C13.0606 0.5 12.8875 0.606999 12.8028 0.776389L13.25 1ZM14.6667 3.83333L14.2195 4.05694C14.2679 4.1537 14.3463 4.23216 14.4431 4.28054L14.6667 3.83333ZM17.5 5.25L17.7236 5.69721C17.893 5.61252 18 5.43939 18 5.25C18 5.06061 17.893 4.88748 17.7236 4.80279L17.5 5.25ZM14.6667 6.66667L14.4431 6.21946C14.3463 6.26784 14.2679 6.3463 14.2195 6.44306L14.6667 6.66667ZM13.25 9.5L12.8028 9.72361C12.8875 9.893 13.0606 10 13.25 10C13.4394 10 13.6125 9.893 13.6972 9.72361L13.25 9.5ZM11.8333 6.66667L12.2805 6.44306C12.2321 6.3463 12.1537 6.26784 12.0569 6.21946L11.8333 6.66667ZM9 5.25L8.77639 4.80279C8.607 4.88748 8.5 5.06061 8.5 5.25C8.5 5.43939 8.607 5.61252 8.77639 5.69721L9 5.25ZM2.63393 5.96482L3.08115 6.18844L3.08115 6.18843L2.63393 5.96482ZM2.9983 5.23608L3.44552 5.01248C3.36082 4.84308 3.18769 4.73608 2.9983 4.73608C2.80892 4.73608 2.63579 4.84308 2.55109 5.01248L2.9983 5.23608ZM3.36267 5.96482L2.91546 6.18843L2.91546 6.18844L3.36267 5.96482ZM4.03349 6.63564L3.80988 7.08285L3.80989 7.08286L4.03349 6.63564ZM4.76223 7.00001L4.98586 7.44722C5.15524 7.36252 5.26224 7.18939 5.26223 7C5.26223 6.81062 5.15523 6.63749 4.98584 6.5528L4.76223 7.00001ZM4.03349 7.36441L4.25705 7.81165L4.25712 7.81162L4.03349 7.36441ZM3.36267 8.03521L3.80988 8.25883L3.80989 8.25882L3.36267 8.03521ZM2.9983 8.76391L2.5511 8.98753C2.63579 9.15691 2.80892 9.26391 2.9983 9.26391C3.18769 9.26391 3.36082 9.15691 3.44551 8.98753L2.9983 8.76391ZM2.63393 8.03521L2.18672 8.25882L2.18673 8.25883L2.63393 8.03521ZM1.96311 7.36441L1.73949 7.81162L1.73956 7.81165L1.96311 7.36441ZM1.23438 7.00001L1.01077 6.5528C0.841379 6.63749 0.734378 6.81062 0.734375 7C0.734372 7.18939 0.841367 7.36252 1.01075 7.44722L1.23438 7.00001ZM1.96311 6.63564L2.18672 7.08286L2.18673 7.08285L1.96311 6.63564ZM3.2219 4.78886L3.66912 5.01247L4.11634 4.11805L3.66913 3.89444L3.2219 4.78886ZM3.22192 3.67083L2.7747 3.44722L2.32748 4.34164L2.77469 4.56525L3.22192 3.67083ZM6.5 1.5V2.5C7.05228 2.5 7.5 2.05228 7.5 1.5H6.5ZM6.5 1.5H5.5C5.5 2.05228 5.94772 2.5 6.5 2.5V1.5ZM6.5 1.5V0.5C5.94772 0.5 5.5 0.947718 5.5 1.5H6.5ZM6.5 1.5H7.5C7.5 0.947718 7.05228 0.5 6.5 0.5V1.5ZM9 16.5C12.0879 16.5 14.1772 15.7268 15.5072 14.9287C16.1703 14.5309 16.6398 14.1298 16.9473 13.8223C17.101 13.6686 17.2142 13.5383 17.291 13.4435C17.3293 13.3961 17.3586 13.3576 17.3793 13.3294C17.3896 13.3153 17.3978 13.3038 17.4039 13.295C17.407 13.2907 17.4095 13.287 17.4115 13.284C17.4125 13.2826 17.4134 13.2813 17.4141 13.2802C17.4145 13.2796 17.4149 13.2791 17.4152 13.2786C17.4153 13.2784 17.4155 13.2781 17.4156 13.2779C17.4158 13.2776 17.416 13.2774 17 13C16.584 12.7226 16.5842 12.7224 16.5843 12.7221C16.5844 12.7221 16.5845 12.7218 16.5846 12.7217C16.5848 12.7214 16.585 12.7211 16.5851 12.7209C16.5854 12.7206 16.5855 12.7203 16.5856 12.7203C16.5856 12.7202 16.5852 12.7209 16.5843 12.7222C16.5824 12.7248 16.5786 12.7301 16.5729 12.738C16.5613 12.7538 16.5418 12.7797 16.5137 12.8143C16.4576 12.8836 16.3677 12.9877 16.2402 13.1152C15.9852 13.3702 15.5797 13.7191 14.9928 14.0713C13.8228 14.7732 11.9121 15.5 9 15.5V16.5ZM17 12.5H1V13.5H17V12.5ZM1 13C0.583975 13.2774 0.58417 13.2776 0.584374 13.2779C0.584452 13.2781 0.584663 13.2784 0.58482 13.2786C0.585133 13.2791 0.585478 13.2796 0.585855 13.2802C0.586608 13.2813 0.587489 13.2826 0.588498 13.284C0.590515 13.287 0.593046 13.2907 0.596098 13.295C0.6022 13.3038 0.610388 13.3153 0.620723 13.3294C0.641393 13.3576 0.670661 13.3961 0.709034 13.4435C0.785774 13.5383 0.898982 13.6686 1.0527 13.8223C1.36024 14.1298 1.82967 14.5309 2.49275 14.9287C3.82279 15.7268 5.91214 16.5 9 16.5V15.5C6.08786 15.5 4.17721 14.7732 3.00725 14.0713C2.42033 13.7191 2.01476 13.3702 1.7598 13.1152C1.63227 12.9877 1.54235 12.8836 1.48628 12.8143C1.45825 12.7797 1.43869 12.7538 1.42713 12.738C1.42135 12.7301 1.41757 12.7248 1.41574 12.7222C1.41483 12.7209 1.4144 12.7202 1.41445 12.7203C1.41447 12.7203 1.41462 12.7206 1.41488 12.7209C1.41501 12.7211 1.41517 12.7214 1.41536 12.7217C1.41546 12.7218 1.41562 12.7221 1.41567 12.7221C1.41584 12.7224 1.41603 12.7226 1 13ZM7 17.5H11V16.5H7V17.5ZM12.2805 4.05694L13.6972 1.22361L12.8028 0.776389L11.3861 3.60972L12.2805 4.05694ZM12.8028 1.22361L14.2195 4.05694L15.1139 3.60972L13.6972 0.776389L12.8028 1.22361ZM14.4431 4.28054L17.2764 5.69721L17.7236 4.80279L14.8903 3.38612L14.4431 4.28054ZM17.2764 4.80279L14.4431 6.21946L14.8903 7.11388L17.7236 5.69721L17.2764 4.80279ZM14.2195 6.44306L12.8028 9.27639L13.6972 9.72361L15.1139 6.89028L14.2195 6.44306ZM13.6972 9.27639L12.2805 6.44306L11.3861 6.89028L12.8028 9.72361L13.6972 9.27639ZM12.0569 6.21946L9.22361 4.80279L8.77639 5.69721L11.6097 7.11388L12.0569 6.21946ZM9.22361 5.69721L12.0569 4.28054L11.6097 3.38612L8.77639 4.80279L9.22361 5.69721ZM3.08115 6.18843L3.44552 5.45969L2.55109 5.01248L2.18672 5.74122L3.08115 6.18843ZM2.55109 5.45969L2.91546 6.18843L3.80989 5.74122L3.44552 5.01248L2.55109 5.45969ZM2.91546 6.18844C3.109 6.57548 3.42283 6.88932 3.80988 7.08285L4.25711 6.18843C4.06358 6.09166 3.90665 5.93474 3.80989 5.74121L2.91546 6.18844ZM3.80989 7.08286L4.53863 7.44723L4.98584 6.5528L4.2571 6.18843L3.80989 7.08286ZM4.53861 6.55281L3.80987 6.91721L4.25712 7.81162L4.98586 7.44722L4.53861 6.55281ZM3.80994 6.91717C3.42283 7.11067 3.10898 7.42456 2.91546 7.81161L3.80989 8.25882C3.90667 8.06526 4.06358 7.90835 4.25705 7.81165L3.80994 6.91717ZM2.91547 7.8116L2.5511 8.5403L3.44551 8.98753L3.80988 8.25883L2.91547 7.8116ZM3.44551 8.5403L3.08114 7.8116L2.18673 8.25883L2.5511 8.98753L3.44551 8.5403ZM3.08115 7.81161C2.88763 7.42456 2.57378 7.11067 2.18667 6.91717L1.73956 7.81165C1.93303 7.90835 2.08994 8.06526 2.18672 8.25882L3.08115 7.81161ZM2.18674 6.91721L1.458 6.55281L1.01075 7.44722L1.73949 7.81162L2.18674 6.91721ZM1.45798 7.44723L2.18672 7.08286L1.73951 6.18843L1.01077 6.5528L1.45798 7.44723ZM2.18673 7.08285C2.57378 6.88932 2.88761 6.57548 3.08115 6.18844L2.18672 5.74121C2.08996 5.93474 1.93303 6.09166 1.7395 6.18843L2.18673 7.08285ZM3.66913 3.89444L3.22192 3.67083L2.77469 4.56525L3.2219 4.78886L3.66913 3.89444ZM6.4 2H6.6V1H6.4V2Z"
fill="#7E7E7E"
/>
</svg>
</template>
File renamed without changes.
21 changes: 21 additions & 0 deletions frontend/src/services/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const BASE_URL = "http://localhost:8000/api";

function getErrorMessage(error: unknown) {
if (error instanceof Error) return error.message;
return String(error);
}

function reportError(message: string) {
console.error(message);
}

export async function getAllManderPaths(): Promise<string[]> {
try {
const r = await fetch(`${BASE_URL}/mandrs`);
const paths = await r.json();
return paths;
} catch (error) {
reportError(getErrorMessage(error));
return [];
}
}
3 changes: 3 additions & 0 deletions frontend/src/services/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function sleep(delay: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, delay));
}
38 changes: 33 additions & 5 deletions frontend/src/views/DashboardView.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,38 @@
<script setup lang="ts">
import FileTree from "../components/FileTree.vue";
import { computed } from "vue";
import FileTree, { type FileTreeNode } from "@/components/FileTree.vue";
import { getAllManderPaths } from "@/services/api";
const manderPaths = await getAllManderPaths();
const pathsAsFileTreeNodes = computed(() => {
const tree: FileTreeNode[] = [];
for (let p of manderPaths) {
const slugs = p.split("/");
const rootSlug = slugs[0];
let currentNode = tree.find((n) => n.label == rootSlug);
if (!currentNode) {
currentNode = { label: rootSlug };
tree.push(currentNode);
}
// Force the compiler to understand that currentNode can't be undefined at this point
let n = currentNode!;
for (let s of slugs.slice(1)) {
n.children = n.children || [];
let childNode = n.children.find((n) => n.label == s);
if (!childNode) {
childNode = { label: s };
n.children.push(childNode);
}
n = childNode;
}
}
return tree;
});
</script>

<template>
<main>
<h1>Hey</h1>
<FileTree />
</main>
<div class="dashboard">
<FileTree :nodes="pathsAsFileTreeNodes"></FileTree>
</div>
</template>
Loading

0 comments on commit f7701e3

Please sign in to comment.