Skip to content

Commit

Permalink
Add front-end routing #10598
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobtylerwalls committed Jun 20, 2024
1 parent 295d183 commit 1d5ac23
Show file tree
Hide file tree
Showing 11 changed files with 146 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,23 @@ import ControlledListManager from '@/plugins/ControlledListManager.vue';
import createVueApp from 'utils/create-vue-application';
import ControlledListManagerTemplate from 'templates/views/components/plugins/controlled-list-manager.htm';

import { createRouter, createWebHistory } from 'vue-router';

const routes = [
{ path: '/plugins/controlled-list-manager', name: 'splash', component: ControlledListManager },
{ path: '/plugins/controlled-list-manager/list/:id', name: 'list', component: ControlledListManager },
{ path: '/plugins/controlled-list-manager/item/:id', name: 'item', component: ControlledListManager },
];

const router = createRouter({
history: createWebHistory(),
routes,
});

ko.components.register('controlled-list-manager', {
viewModel: function() {
createVueApp(ControlledListManager).then((vueApp) => {
vueApp.use(router);
vueApp.mount('#controlled-list-manager-mounting-point');
})
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script setup lang="ts">
import arches from "arches";
import { computed, provide, ref } from "vue";
import { useRouter } from "vue-router";
import ProgressSpinner from "primevue/progressspinner";
import Splitter from "primevue/splitter";
Expand All @@ -9,6 +10,7 @@ import SplitterPanel from "primevue/splitterpanel";
import { LIGHT_GRAY } from "@/theme.ts";
import {
displayedRowKey,
routes,
selectedLanguageKey,
} from "@/components/ControlledListManager/constants.ts";
import { dataIsList } from "@/components/ControlledListManager/utils.ts";
Expand All @@ -19,14 +21,24 @@ import ListHeader from "@/components/ControlledListManager/misc/ListHeader.vue";
import ListTree from "@/components/ControlledListManager/tree/ListTree.vue";
import type { Ref } from "vue";
import type { Selectable } from "@/types/ControlledListManager";
import type {
ControlledListItem,
Selectable,
} from "@/types/ControlledListManager";
import type { Language } from "@/types/arches";
const splash = "splash";
const router = useRouter();
const displayedRow: Ref<Selectable | null> = ref(null);
function setDisplayedRow(val: Selectable | null) {
displayedRow.value = val;
if (val === null) {
router.push({ name: routes.splash });
} else if ((val as ControlledListItem).controlled_list_id) {
router.push({ name: routes.item, params: { id: val.id } });
} else {
router.push({ name: routes.list, params: { id: val.id } });
}
}
provide(displayedRowKey, { displayedRow, setDisplayedRow });
Expand Down Expand Up @@ -85,7 +97,7 @@ const panel = computed(() => {
>
<component
:is="panel"
:key="displayedRow?.id ?? splash"
:key="displayedRow?.id ?? routes.splash"
/>
</SplitterPanel>
</Splitter>
Expand Down
6 changes: 6 additions & 0 deletions arches/app/src/components/ControlledListManager/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ export const ERROR = "error";
export const DANGER = "danger";
export const DEFAULT_ERROR_TOAST_LIFE = 8000;

export const routes = {
splash: "splash",
list: "list",
item: "item",
};

// Django model choices
export const METADATA_CHOICES = {
title: "title",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { useGettext } from "vue3-gettext";
import { useConfirm } from "primevue/useconfirm";
import { useToast } from "primevue/usetoast";
import Button from "primevue/button";
import ConfirmDialog from "primevue/confirmdialog";
import SplitButton from "primevue/splitbutton";
import { BUTTON_GREEN } from "@/theme.ts";
Expand Down Expand Up @@ -203,7 +202,6 @@ await fetchListsAndPopulateTree();
:pt="{ root: { style: { background: BUTTON_GREEN } } }"
@click="createList"
/>
<ConfirmDialog :draggable="false" />
<SplitButton
class="list-button"
:label="$gettext('Delete')"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ const collapseNodesRecursive = (node: TreeNode) => {
};
const updateSelectedAndExpanded = (node: TreeNode) => {
if (isMultiSelecting.value || movingItem.value.key) {
return;
}
let priorListId;
if (displayedRow.value) {
priorListId =
Expand Down Expand Up @@ -190,7 +194,7 @@ const filterCallbackWrapped = computed(() => {
<template>
<ListTreeControls
:key="refetcher"
v-model="tree"
v-model:tree="tree"
v-model:rerender-tree="rerenderTree"
v-model:expanded-keys="expandedKeys"
v-model:selected-keys="selectedKeys"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
<script setup lang="ts">
import { inject, watch } from "vue";
import { useRoute } from "vue-router";
import {
displayedRowKey,
routes,
} from "@/components/ControlledListManager/constants.ts";
import { findNodeInTree } from "@/components/ControlledListManager/utils.ts";
import ActionBanner from "@/components/ControlledListManager/tree/ActionBanner.vue";
import AddDeleteControls from "@/components/ControlledListManager/tree/AddDeleteControls.vue";
import PresentationControls from "@/components/ControlledListManager/tree/PresentationControls.vue";
import type { TreeExpandedKeys, TreeSelectionKeys } from "primevue/tree/Tree";
import type { TreeNode } from "primevue/treenode";
import type { NewControlledList } from "@/types/ControlledListManager";
import type {
DisplayedListItemRefAndSetter,
NewControlledList,
} from "@/types/ControlledListManager";
const controlledListItemsTree = defineModel<TreeNode[]>({ required: true });
const controlledListItemsTree = defineModel<TreeNode[]>("tree", {
required: true,
});
const rerenderTree = defineModel<number>("rerenderTree", { required: true });
const expandedKeys = defineModel<TreeExpandedKeys>("expandedKeys", {
required: true,
Expand All @@ -24,6 +37,69 @@ const newListFormValue = defineModel<string>("newListFormValue", {
required: true,
});
const { setDisplayedRow } = inject(
displayedRowKey,
) as DisplayedListItemRefAndSetter;
const route = useRoute();
// React to route changes.
// Add list tree as dependency so it runs on initial fetch.
watch(
[
() => {
return { ...route };
},
controlledListItemsTree,
],
([newRoute]) => {
switch (newRoute.name) {
case routes.splash:
setDisplayedRow(null);
break;
case routes.list: {
if (!controlledListItemsTree.value.length) {
return;
}
const list = controlledListItemsTree.value.find(
(node) => node.data.id === newRoute.params.id,
);
if (list) {
setDisplayedRow(list.data);
expandedKeys.value = { [list.data.id]: true };
selectedKeys.value = { [list.data.id]: true };
} else {
setDisplayedRow(null);
}
break;
}
case routes.item: {
if (!controlledListItemsTree.value.length) {
return;
}
const { found, path } = findNodeInTree(
controlledListItemsTree.value,
newRoute.params.id,
);
if (found) {
setDisplayedRow(found.data);
const itemsToExpandIds = path.map(
(itemInPath: TreeNode) => itemInPath.key,
);
expandedKeys.value = Object.fromEntries(
[
found.data.controlled_list_id,
...itemsToExpandIds,
].map((x) => [x, true]),
);
selectedKeys.value = { [found.data.id]: true };
}
break;
}
}
},
);
const expandAll = () => {
for (const node of controlledListItemsTree.value) {
expandNode(node);
Expand Down
14 changes: 7 additions & 7 deletions arches/app/src/components/ControlledListManager/tree/MoveRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ const newLabelCounter = ref(1);
const isFirstItem = (item: ControlledListItem) => {
const siblings: TreeNode[] = item.parent_id
? findNodeInTree(tree.value, item.parent_id).data.children
: findNodeInTree(tree.value, item.controlled_list_id).data.items;
? findNodeInTree(tree.value, item.parent_id).found.data.children
: findNodeInTree(tree.value, item.controlled_list_id).found.data.items;
if (!siblings) {
throw new Error();
}
Expand All @@ -73,8 +73,8 @@ const isFirstItem = (item: ControlledListItem) => {
const isLastItem = (item: ControlledListItem) => {
const siblings: TreeNode[] = item.parent_id
? findNodeInTree(tree.value, item.parent_id).data.children
: findNodeInTree(tree.value, item.controlled_list_id).data.items;
? findNodeInTree(tree.value, item.parent_id).found.data.children
: findNodeInTree(tree.value, item.controlled_list_id).found.data.items;
if (!siblings) {
throw new Error();
}
Expand All @@ -85,7 +85,7 @@ const setMovingItem = (node: TreeNode) => {
movingItem.value = findNodeInTree(
[itemAsNode(displayedRow.value, selectedLanguage.value)],
node.key,
);
).found;
};
const addItem = (parent: TreeNode) => {
Expand Down Expand Up @@ -128,11 +128,11 @@ const reorder = async (item: ControlledListItem, up: boolean) => {
const list: ControlledList = findNodeInTree(
tree.value,
item.controlled_list_id,
).data;
).found.data;
let siblings: ControlledListItem[];
if (item.parent_id) {
siblings = findNodeInTree(tree.value, item.parent_id).children.map(
siblings = findNodeInTree(tree.value, item.parent_id).found.children.map(
(child: TreeNode) => child.data,
);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ const setParent = async (parentNode: TreeNode) => {
siblings.push(item);
} else {
item.parent_id = parentNode.key;
list = findNodeInTree(tree.value, item.controlled_list_id).data;
list = findNodeInTree(tree.value, item.controlled_list_id).found.data;
siblings = parentNode.data.children;
siblings.push(item);
}
Expand Down Expand Up @@ -198,7 +198,7 @@ const acceptNewItemShortcutEntry = async () => {
const parent = findNodeInTree(
tree.value,
newItem.parent_id ?? newItem.controlled_list_id,
);
).found;
parent.children = [
...parent.children.filter(
(child: TreeNode) => typeof child.key === "string",
Expand Down
20 changes: 15 additions & 5 deletions arches/app/src/components/ControlledListManager/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,32 @@ export const languageNameFromCode = (code: string) => {
return arches.languages.find((lang: Language) => lang.code === code).name;
};

export const findNodeInTree = (tree: TreeNode[], itemId: string) => {
export const findNodeInTree = (
tree: TreeNode[],
itemId: string,
): {
found: TreeNode | undefined;
path: TreeNode[];
} => {
const path: TreeNode[] = [];

function recurse(items: TreeNode[]): TreeNode | undefined {
for (const item of items) {
if (item.data.id === itemId) {
return item;
}
for (const child of item.items ?? item.children) {
const maybeFound = recurse([child]);
if (maybeFound) {
return maybeFound;
const found = recurse([child]);
if (found) {
path.push(item);
return found;
}
}
}
}

return recurse(tree);
const found = recurse(tree);
return { found, path };
};

export const itemAsNode = (
Expand Down
3 changes: 3 additions & 0 deletions arches/app/src/plugins/ControlledListManager.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script setup lang="ts">
import ConfirmDialog from "primevue/confirmdialog";
import Toast from "primevue/toast";
import ControlledListEditor from "@/components/ControlledListManager/ControlledListEditor.vue";
Expand All @@ -11,7 +12,9 @@ import ControlledListEditor from "@/components/ControlledListManager/ControlledL
<ControlledListEditor />
</div>
</div>
<ConfirmDialog :draggable="false" />
<Toast />
<RouterView />
</template>

<!-- Not scoped: workaround for lack of font-family in <body> -->
Expand Down
4 changes: 2 additions & 2 deletions arches/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -644,9 +644,9 @@
name="concepts",
),
re_path(
r"^plugins/(?P<pluginid>%s)$" % uuid_regex, PluginView.as_view(), name="plugins"
r"^plugins/(?P<pluginid>%s)" % uuid_regex, PluginView.as_view(), name="plugins"
),
re_path(r"^plugins/(?P<slug>[-\w]+)$", PluginView.as_view(), name="plugins"),
re_path(r"^plugins/(?P<slug>[-\w]+)", PluginView.as_view(), name="plugins"),
re_path(
r"^workflow_history/(?P<workflowid>%s|())$" % uuid_regex,
WorkflowHistoryView.as_view(),
Expand Down

0 comments on commit 1d5ac23

Please sign in to comment.