Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rough out scheme list #122

Merged
merged 10 commits into from
Dec 9, 2024
7 changes: 7 additions & 0 deletions arches_lingo/src/arches_lingo/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,10 @@ export const fetchConcepts = async () => {
if (!response.ok) throw new Error(parsed.message || response.statusText);
return parsed;
};

export const fetchSchemes = async () => {
const response = await fetch(arches.urls.api_schemes);
const parsed = await response.json();
if (!response.ok) throw new Error(parsed.message || response.statusText);
return parsed;
};
61 changes: 61 additions & 0 deletions arches_lingo/src/arches_lingo/components/scheme/SchemeCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<script setup lang="ts">
import { inject } from "vue";
import { systemLanguageKey } from "@/arches_lingo/constants.ts";
import { routeNames } from "@/arches_lingo/routes.ts";

import type { Language } from "@/arches_vue_utils/types";
import type { SchemeResource, ResourceDescriptor } from "@/arches_lingo/types";

const systemLanguage = inject(systemLanguageKey) as Language;

const { scheme } = defineProps<{ scheme: SchemeResource }>();
const schemeURL = {
name: routeNames.scheme,
params: { id: scheme.resourceinstanceid },
};

const descriptors = scheme.descriptors;
let schemeDescriptor: ResourceDescriptor = {
name: "",
description: "",
};
if (descriptors) {
const descriptor =
descriptors[systemLanguage.code] ?? Object.values(descriptors)[0];
schemeDescriptor.name = descriptor.name ?? "";
schemeDescriptor.description = descriptor.description ?? "";
}
</script>

<template>
<RouterLink
:to="schemeURL"
class="scheme-card"
>
<p>{{ schemeDescriptor.name }}</p>
<p>{{ schemeDescriptor.description }}</p>
</RouterLink>
</template>

<style scoped>
p {
text-align: center;
}
.scheme-card {
text-decoration: none;
color: var(--p-text-color);
width: 15rem;
height: 15rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 0.5rem;
border: 1px solid var(--p-menubar-border-color);
background-color: var(--p-primary-400);
}
.scheme-card:hover {
background-color: var(--p-button-primary-hover-background);
cursor: pointer;
}
</style>
65 changes: 64 additions & 1 deletion arches_lingo/src/arches_lingo/pages/SchemeList.vue
Original file line number Diff line number Diff line change
@@ -1 +1,64 @@
<template>Schemes list placeholder</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { useGettext } from "vue3-gettext";

import { useToast } from "primevue/usetoast";
import {
DEFAULT_ERROR_TOAST_LIFE,
ERROR,
} from "@/arches_references/constants.ts";

import SchemeCard from "@/arches_lingo/components/scheme/SchemeCard.vue";
import { fetchSchemes } from "@/arches_lingo/api.ts";

import type { SchemeResource } from "@/arches_lingo/types";

const toast = useToast();
const { $gettext } = useGettext();

const schemes = ref<SchemeResource[]>([]);

onMounted(async () => {
try {
schemes.value = await fetchSchemes();
} catch (error) {
toast.add({
severity: ERROR,
life: DEFAULT_ERROR_TOAST_LIFE,
summary: $gettext("Unable to fetch schemes"),
detail: error instanceof Error ? error.message : undefined,
});
}
schemes.value.unshift({
resourceinstanceid: "placeholder-id",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an interesting pattern. An equally valid pattern would be to manually create a list item for this entry. However I like this just fine 👍

descriptors: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clicking this populates the front-end route with /placeholder-id, and then refreshing issues a request for that route which fails because placeholder-id is not a uuid. We should harden for this somehow, but maybe without necessarily creating dummy data on the backend that we have to filter out everywhere else (which is what I like about what you're doing here!)

Copy link
Member Author

@johnatawnclementawn johnatawnclementawn Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't exactly sure what to do, which is why I ended up punting with placeholder-id... My thought was that a PR for adding the scheme-editor and it's corresponding route would be coming hot on the heels of this, and we could just swap placeholder-id for the new scheme route.

As you point out, it's probably not desirable to have a dummy uuid in lieu of string placeholder-id because we'd need to handle that on the back-end.

Alternatively, I could mint the new scheme resourceid here - but I see that as less desirable since it would create a new uuid each time /schemes is visited, even if creating a new scheme is not the intention of the user.

All that to say, I'm not exactly sure what to do about this

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, got it. If we're about to swap in a new route for the scheme editor then all is good 👍

en: {
name: "Create a new scheme",
description: "This is a placeholder to create a new scheme",
},
},
});
});
</script>

<template>
<div>
<ul class="scheme-cards">
<li
v-for="scheme in schemes"
:key="scheme.resourceinstanceid"
>
<SchemeCard :scheme="scheme" />
</li>
</ul>
</div>
</template>

<style scoped>
.scheme-cards {
display: flex;
flex-wrap: wrap;
list-style-type: none;
padding: 0;
}
</style>
15 changes: 15 additions & 0 deletions arches_lingo/src/arches_lingo/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,21 @@ export interface SchemeNamespace {

export type DataComponentMode = "edit" | "view";

export interface SchemeResource {
resourceinstanceid: string;
descriptors: {
[key: string]: {
name: string;
description: string;
};
};
}

export interface ResourceDescriptor {
name: string;
description: string;
}

export interface NodeAndParentInstruction {
node: TreeNode;
shouldHideSiblings: boolean;
Expand Down
1 change: 1 addition & 0 deletions arches_lingo/templates/arches_urls.htm
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
api_concepts="{% url 'api-concepts' %}"
api_search="{% url 'api-search' %}"
api_uri_namespace='(pluginid)=>{return "{% url "api-uri-components" "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" %}".replace("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", pluginid)}'
api_schemes="{% url 'schemes-list-create' %}"
></div>
{% endblock arches_urls %}
1 change: 1 addition & 0 deletions arches_lingo/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
path("login", LingoRootView.as_view(), name="login"),
path("advanced-search", LingoRootView.as_view(), name="advanced-search"),
path("schemes", LingoRootView.as_view(), name="schemes"),
path("scheme/<uuid:id>", LingoRootView.as_view(), name="scheme"),
path("concept/<uuid:id>", LingoRootView.as_view(), name="concept"),
path("api/concept-tree", ConceptTreeView.as_view(), name="api-concepts"),
path("api/search", ValueSearchView.as_view(), name="api-search"),
Expand Down
1 change: 1 addition & 0 deletions arches_lingo/views/api/pythonic_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
class SchemeListCreateView(ArchesModelAPIMixin, ListCreateAPIView):
permission_classes = [RDMAdministrator]
serializer_class = SchemeSerializer
pagination_class = None


class SchemeDetailView(ArchesModelAPIMixin, RetrieveUpdateDestroyAPIView):
Expand Down
Loading