From f7e09f19f63000bf0dced1d9dc434c3b747cd8f9 Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Wed, 5 Feb 2025 09:11:47 -0500 Subject: [PATCH] Deduplicate routes #198 (#201) --- arches_lingo/serializers.py | 136 ++------- arches_lingo/src/arches_lingo/api.ts | 258 ++++-------------- .../components/generic/LabelEditor.vue | 41 ++- .../components/generic/NoteEditor.vue | 42 ++- .../components/scheme/report/SchemeLabel.vue | 13 +- .../scheme/report/SchemeLicense.vue | 41 +-- .../scheme/report/SchemeNamespace.vue | 13 +- .../components/scheme/report/SchemeNote.vue | 13 +- .../scheme/report/SchemeStandard.vue | 38 ++- .../src/arches_lingo/pages/SchemeList.vue | 4 +- arches_lingo/src/arches_lingo/types.ts | 39 ++- arches_lingo/templates/arches_urls.htm | 19 +- arches_lingo/urls.py | 121 ++------ arches_lingo/views/api/generic.py | 33 +++ arches_lingo/views/api/pythonic_models.py | 146 ---------- 15 files changed, 273 insertions(+), 684 deletions(-) create mode 100644 arches_lingo/views/api/generic.py delete mode 100644 arches_lingo/views/api/pythonic_models.py diff --git a/arches_lingo/serializers.py b/arches_lingo/serializers.py index 6b0f7488..be938d25 100644 --- a/arches_lingo/serializers.py +++ b/arches_lingo/serializers.py @@ -4,47 +4,24 @@ from arches.app.models.models import ResourceInstance, TileModel from arches.app.models.serializers import ArchesModelSerializer, ArchesTileSerializer from arches.app.models.tile import Tile -from arches_references.models import ListItem - -class SchemeStatementSerializer(ArchesTileSerializer): - class Meta: - model = TileModel - graph_slug = "scheme" - root_node = "statement" - fields = "__all__" +from arches_references.models import ListItem -class SchemeSerializer(ArchesModelSerializer): +# Generic serializers for Lingo. +class LingoResourceSerializer(ArchesModelSerializer): class Meta: model = ResourceInstance - graph_slug = "scheme" + graph_slug = None # generic nodegroups = "__all__" fields = "__all__" - -class SchemeNamespaceSerializer(ArchesModelSerializer): - class Meta: - model = ResourceInstance - graph_slug = "scheme" - nodegroups = ["namespace"] - fields = "__all__" - - -class SchemeCreationSerializer(ArchesModelSerializer): - class Meta: - model = ResourceInstance - graph_slug = "scheme" - nodegroups = ["creation"] - fields = "__all__" - - -class SchemeRightsSerializer(ArchesModelSerializer): - class Meta: - model = ResourceInstance - graph_slug = "scheme" - nodegroups = ["rights", "right_statement"] - fields = "__all__" + def create(self, validated_data): + """Repair parenttile until fixed in core.""" + created = super().create(validated_data) + if created.right_statement: + self.repair_right_statement(created) + return created def update(self, instance, validated_data): """Repair parenttile until fixed in core.""" @@ -69,33 +46,21 @@ def repair_right_statement(self, instance): return instance -class SchemeLabelSerializer(ArchesModelSerializer): - class Meta: - model = ResourceInstance - graph_slug = "scheme" - nodegroups = ["appellative_status"] - fields = "__all__" - - -class SchemeLabelTileSerializer(ArchesTileSerializer): +class LingoTileSerializer(ArchesTileSerializer): class Meta: model = TileModel - graph_slug = "scheme" - root_node = "appellative_status" + graph_slug = None # generic + root_node = None # generic fields = "__all__" - def validate(self, data): - data = super().validate(data) + def validate_appellative_status(self, data): try: - PREF_LABEL_LIST_ITEM = ListItem.objects.get( - list_item_values__value="prefLabel", - ) + PREF_LABEL = ListItem.objects.get(list_item_values__value="prefLabel") except ListItem.MultipleObjectsReturned: - raise RuntimeError( - _( - "Ask your system administrator to deduplicate the prefLabel list items." - ) + msg = _( + "Ask your system administrator to deduplicate the prefLabel list items." ) + raise ValidationError(msg) if data: # TODO: reduce nested-fallback awkwardness by returning a dataclass from @@ -118,68 +83,11 @@ def validate(self, data): ) if ( data.get("tileid", None) not in (None, label.tileid) - and new_label_type.get("uri", "") == PREF_LABEL_LIST_ITEM.uri - and label_type.get("uri", "") == PREF_LABEL_LIST_ITEM.uri + and new_label_type.get("uri", "") == PREF_LABEL.uri + and label_type.get("uri", "") == PREF_LABEL.uri and label_language.get("uri", "") == new_label_language.get("uri", "") ): - raise ValidationError( - _("Only one preferred label per language is permitted.") - ) + msg = _("Only one preferred label per language is permitted.") + raise ValidationError(msg) return data - - -class SchemeNoteSerializer(ArchesModelSerializer): - class Meta: - model = ResourceInstance - graph_slug = "scheme" - nodegroups = ["statement"] - fields = "__all__" - - -class SchemeNoteTileSerializer(ArchesTileSerializer): - class Meta: - model = TileModel - graph_slug = "scheme" - root_node = "statement" - fields = "__all__" - - -class TextualWorkRdmSystemSerializer(ArchesModelSerializer): - class Meta: - model = ResourceInstance - graph_slug = "textual_work" - nodegroups = "__all__" - fields = "__all__" - - -class ConceptStatementSerializer(ArchesTileSerializer): - class Meta: - model = TileModel - graph_slug = "concept" - root_node = "statement" - fields = "__all__" - - -class ConceptSerializer(ArchesModelSerializer): - class Meta: - model = ResourceInstance - graph_slug = "concept" - nodegroups = "__all__" - fields = "__all__" - - -class PersonRdmSystemSerializer(ArchesModelSerializer): - class Meta: - model = ResourceInstance - graph_slug = "person" - nodegroups = "__all__" - fields = "__all__" - - -class GroupRdmSystemSerializer(ArchesModelSerializer): - class Meta: - model = ResourceInstance - graph_slug = "group" - nodegroups = "__all__" - fields = "__all__" diff --git a/arches_lingo/src/arches_lingo/api.ts b/arches_lingo/src/arches_lingo/api.ts index e1cd1056..7b1d0224 100644 --- a/arches_lingo/src/arches_lingo/api.ts +++ b/arches_lingo/src/arches_lingo/api.ts @@ -1,12 +1,7 @@ import arches from "arches"; import Cookies from "js-cookie"; -import type { - AppellativeStatus, - SchemeInstance, - SchemeStatement, - SchemeRights, - SchemeRightStatement, -} from "@/arches_lingo/types"; + +import type { SchemeInstance, SchemeTile } from "@/arches_lingo/types"; function getToken() { const token = Cookies.get("csrftoken"); @@ -44,166 +39,97 @@ export const fetchUser = async () => { return parsed; }; -export const fetchSchemeNamespace = async (schemeId: string) => { - const response = await fetch(arches.urls.api_uri_namespace(schemeId)); - const parsed = await response.json(); - if (!response.ok) throw new Error(parsed.message || response.statusText); - return parsed; -}; - -export const fetchTextualWorkRdmSystemList = async () => { - const response = await fetch(arches.urls.api_textualwork_list); - const parsed = await response.json(); - if (!response.ok) throw new Error(parsed.message || response.statusText); - return parsed; -}; - -export const fetchGroupRdmSystemList = async () => { - const response = await fetch(arches.urls.api_group_list); - const parsed = await response.json(); - if (!response.ok) throw new Error(parsed.message || response.statusText); - return parsed; -}; - -export const fetchPersonRdmSystemList = async () => { - const response = await fetch(arches.urls.api_person_list); - const parsed = await response.json(); - if (!response.ok) throw new Error(parsed.message || response.statusText); - return parsed; -}; - -export const fetchSchemeCreation = async (schemeId: string) => { - const response = await fetch(arches.urls.api_scheme_creation(schemeId)); - const parsed = await response.json(); - if (!response.ok) throw new Error(parsed.message || response.statusText); - return parsed; -}; - -export const fetchSchemeLabel = async (schemeId: string) => { - const response = await fetch(arches.urls.api_scheme_label(schemeId)); +export const fetchLingoResources = async (graphSlug: string) => { + const response = await fetch(arches.urls.api_lingo_resources(graphSlug)); const parsed = await response.json(); if (!response.ok) throw new Error(parsed.message || response.statusText); return parsed; }; -export const createSchemeLabel = async ( +export const fetchLingoResource = async ( + graphSlug: string, schemeId: string, - appellative_status: AppellativeStatus, ) => { - const response = await fetch(arches.urls.api_scheme_label_list_create, { - method: "POST", - headers: { - "X-CSRFTOKEN": getToken(), - "Content-Type": "application/json", - }, - body: JSON.stringify({ - resourceinstance: schemeId, - ...appellative_status, - }), - }); + const response = await fetch( + arches.urls.api_lingo_resource(graphSlug, schemeId), + ); const parsed = await response.json(); if (!response.ok) throw new Error(parsed.message || response.statusText); return parsed; }; -export const createSchemeNote = async ( +export const fetchLingoResourcePartial = async ( + graphSlug: string, schemeId: string, - statement: SchemeStatement, + nodegroupAlias: string, ) => { - const response = await fetch(arches.urls.api_scheme_note_create, { - method: "POST", - headers: { - "X-CSRFTOKEN": getToken(), - "Content-Type": "application/json", - }, - body: JSON.stringify({ - resourceinstance: schemeId, - ...statement, - }), - }); + const response = await fetch( + arches.urls.api_lingo_resource_partial( + graphSlug, + schemeId, + nodegroupAlias, + ), + ); const parsed = await response.json(); if (!response.ok) throw new Error(parsed.message || response.statusText); return parsed; }; -export const deleteSchemeLabelTile = async ( +export const updateLingoResource = async ( + graphSlug: string, schemeId: string, - tileId: string, -) => { - const response = await fetch( - arches.urls.api_scheme_label_tile(schemeId, tileId), - { - method: "DELETE", - headers: { "X-CSRFTOKEN": getToken() }, - }, - ); - - if (!response.ok) { - const parsed = await response.json(); - throw new Error(parsed.message || response.statusText); - } else { - return true; - } -}; - -export const updateSchemeLabel = async ( - schemeId: string, - tileId: string, - appellative_status: AppellativeStatus, + schemeInstance: SchemeInstance, ) => { const response = await fetch( - arches.urls.api_scheme_label_tile(schemeId, tileId), + arches.urls.api_lingo_resource(graphSlug, schemeId), { method: "PATCH", headers: { "X-CSRFTOKEN": getToken(), "Content-Type": "application/json", }, - body: JSON.stringify(appellative_status), + body: JSON.stringify(schemeInstance), }, ); const parsed = await response.json(); - if (!response.ok) - throw new Error( - parsed.non_field_errors || parsed.message || response.statusText, - ); - return parsed; -}; - -export const fetchSchemeNotes = async (schemeId: string) => { - const response = await fetch(arches.urls.api_scheme_note(schemeId)); - const parsed = await response.json(); if (!response.ok) throw new Error(parsed.message || response.statusText); return parsed; }; -export const updateSchemeNote = async ( - schemeId: string, - tileId: string, - schemeStatement: SchemeStatement, +export const upsertLingoTile = async ( + graphSlug: string, + nodegroupAlias: string, + tileData: SchemeTile, // TODO: generalize type + tileId: string | undefined, ) => { - const response = await fetch( - arches.urls.api_scheme_note_tile(schemeId, tileId), - { - method: "PATCH", - headers: { - "X-CSRFTOKEN": getToken(), - "Content-Type": "application/json", - }, - body: JSON.stringify(schemeStatement), + const url = tileId + ? arches.urls.api_lingo_tile + : arches.urls.api_lingo_tiles; + const response = await fetch(url(graphSlug, nodegroupAlias, tileId), { + method: tileId ? "PATCH" : "POST", + headers: { + "X-CSRFTOKEN": getToken(), + "Content-Type": "application/json", }, - ); + body: JSON.stringify(tileData), + }); + const parsed = await response.json(); - if (!response.ok) throw new Error(parsed.message || response.statusText); + if (!response.ok) + throw new Error( + // TODO: show all errors + parsed.non_field_errors || parsed.message || response.statusText, + ); return parsed; }; -export const deleteSchemeNoteTile = async ( +export const deleteLingoTile = async ( schemeId: string, + nodegroupAlias: string, tileId: string, ) => { const response = await fetch( - arches.urls.api_scheme_note_tile(schemeId, tileId), + arches.urls.api_lingo_tile(schemeId, nodegroupAlias, tileId), { method: "DELETE", headers: { "X-CSRFTOKEN": getToken() }, @@ -219,7 +145,7 @@ export const deleteSchemeNoteTile = async ( }; export const createScheme = async (newScheme: SchemeInstance) => { - const response = await fetch(arches.urls.api_schemes, { + const response = await fetch(arches.urls.api_lingo_resources("scheme"), { method: "POST", headers: { "X-CSRFTOKEN": getToken(), @@ -232,85 +158,6 @@ export const createScheme = async (newScheme: SchemeInstance) => { return parsed; }; -export const fetchSchemeRights = async (schemeId: string) => { - const response = await fetch(arches.urls.api_scheme_rights(schemeId)); - const parsed = await response.json(); - if (!response.ok) throw new Error(parsed.message || response.statusText); - return parsed; -}; - -export const updateSchemeCreation = async ( - schemeId: string, - schemeInstance: SchemeInstance, -) => { - const response = await fetch(arches.urls.api_scheme_creation(schemeId), { - method: "PATCH", - headers: { - "X-CSRFTOKEN": getToken(), - "Content-Type": "application/json", - }, - body: JSON.stringify(schemeInstance), - }); - const parsed = await response.json(); - if (!response.ok) throw new Error(parsed.message || response.statusText); - return parsed; -}; - -export const updateSchemeNamespace = async ( - schemeId: string, - schemeNamespace: SchemeInstance, -) => { - const response = await fetch(arches.urls.api_uri_namespace(schemeId), { - method: "PATCH", - headers: { - "X-CSRFTOKEN": getToken(), - "Content-Type": "application/json", - }, - body: JSON.stringify(schemeNamespace), - }); - const parsed = await response.json(); - if (!response.ok) throw new Error(parsed.message || response.statusText); - return parsed; -}; - -export const createSchemeFromRights = async ( - schemeRightsValue: SchemeInstance, -) => { - const response = await fetch(arches.urls.api_scheme_rights_list_create, { - method: "POST", - headers: { - "X-CSRFTOKEN": getToken(), - "Content-Type": "application/json", - }, - body: JSON.stringify({ schemeRightsValue }), - }); - const parsed = await response.json(); - if (!response.ok) throw new Error(parsed.message || response.statusText); - return parsed; -}; - -export const updateSchemeRights = async ( - schemeId: string, - schemeRightsValue: SchemeRights, - schemeRightStatementValue: SchemeRightStatement, -) => { - const response = await fetch(arches.urls.api_scheme_rights(schemeId), { - method: "PATCH", - headers: { - "X-CSRFTOKEN": getToken(), - "Content-Type": "application/json", - }, - body: JSON.stringify({ - resourceinstanceid: schemeId, - rights: schemeRightsValue, - right_statement: schemeRightStatementValue, - }), - }); - const parsed = await response.json(); - if (!response.ok) throw new Error(parsed.message || response.statusText); - return parsed; -}; - export const fetchSearchResults = async ( searchTerm: string, items: number, @@ -336,13 +183,6 @@ export const fetchConcepts = async () => { 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; -}; - export const fetchControlledListOptions = async (controlledListId: string) => { const response = await fetch(arches.urls.controlled_list(controlledListId)); const parsed = await response.json(); diff --git a/arches_lingo/src/arches_lingo/components/generic/LabelEditor.vue b/arches_lingo/src/arches_lingo/components/generic/LabelEditor.vue index b0ce784f..2d45d281 100644 --- a/arches_lingo/src/arches_lingo/components/generic/LabelEditor.vue +++ b/arches_lingo/src/arches_lingo/components/generic/LabelEditor.vue @@ -10,11 +10,8 @@ import { fetchLists } from "@/arches_references/api.ts"; import { createScheme, - createSchemeLabel, - fetchGroupRdmSystemList, - fetchPersonRdmSystemList, - fetchTextualWorkRdmSystemList, - updateSchemeLabel, + fetchLingoResources, + upsertLingoTile, } from "@/arches_lingo/api.ts"; import DateDatatype from "@/arches_lingo/components/generic/DateDatatype.vue"; @@ -137,30 +134,30 @@ function onUpdateResourceInstance( async function save() { try { + let newTileId; if (route.params.id === NEW) { const newSchemeInstance: SchemeInstance = { appellative_status: [toRaw(formValue.value)], }; const updated = await createScheme(newSchemeInstance); + newTileId = updated.appellative_status[0].tileid; await router.push({ name: "scheme", params: { id: updated.resourceinstanceid }, }); - } else if (!formValue.value.tileid) { - const schemeLabel: AppellativeStatus = await createSchemeLabel( - route.params.id as string, - formValue.value, - ); - valueRef.value = schemeLabel; - emit("update", schemeLabel.tileid); } else { - await updateSchemeLabel( - route.params.id as string, + const updated = await upsertLingoTile( + "scheme", + "appellative_status", + { + resourceinstance: route.params.id as string, + ...formValue.value, + }, formValue.value.tileid, - formValue.value, ); + newTileId = updated.tileid; } - emit("update"); + emit("update", newTileId); } catch (error) { toast.add({ severity: ERROR, @@ -233,15 +230,17 @@ async function getResourceInstanceOptions( } async function initializeSelectOptions() { getControlledLists(); - groupAndPersonOptions.value = await getResourceInstanceOptions( - fetchGroupRdmSystemList, + groupAndPersonOptions.value = await getResourceInstanceOptions(() => + fetchLingoResources("group"), ); groupAndPersonOptions.value = [ ...(groupAndPersonOptions.value || []), - ...(await getResourceInstanceOptions(fetchPersonRdmSystemList)), + ...(await getResourceInstanceOptions(() => + fetchLingoResources("person"), + )), ]; - textualWorkOptions.value = await getResourceInstanceOptions( - fetchTextualWorkRdmSystemList, + textualWorkOptions.value = await getResourceInstanceOptions(() => + fetchLingoResources("textual_work"), ); } diff --git a/arches_lingo/src/arches_lingo/components/generic/NoteEditor.vue b/arches_lingo/src/arches_lingo/components/generic/NoteEditor.vue index 87b3a934..e1838872 100644 --- a/arches_lingo/src/arches_lingo/components/generic/NoteEditor.vue +++ b/arches_lingo/src/arches_lingo/components/generic/NoteEditor.vue @@ -17,11 +17,8 @@ import { useToast } from "primevue/usetoast"; import { createScheme, - createSchemeNote, - fetchGroupRdmSystemList, - fetchPersonRdmSystemList, - fetchTextualWorkRdmSystemList, - updateSchemeNote, + fetchLingoResources, + upsertLingoTile, } from "@/arches_lingo/api.ts"; import { fetchLists } from "@/arches_references/api.ts"; import DateDatatype from "@/arches_lingo/components/generic/DateDatatype.vue"; @@ -174,31 +171,30 @@ async function getControlledLists() { async function save() { try { + let newTileId; if (route.params.id === NEW) { const newSchemeInstance: SchemeInstance = { statement: [toRaw(formValue.value)], }; const updated = await createScheme(newSchemeInstance); + newTileId = updated.statement[0].tileid; await router.push({ name: "scheme", params: { id: updated.resourceinstanceid }, }); - } else if (!formValue.value.tileid) { - const schemeStatement: SchemeStatement = await createSchemeNote( - route.params.id as string, - { ...formValue.value }, - ); - valueRef.value = schemeStatement; - emit("update", schemeStatement.tileid); - return; } else { - await updateSchemeNote( - route.params.id as string, + const updated = await upsertLingoTile( + "scheme", + "statement", + { + resourceinstance: route.params.id as string, + ...formValue.value, + }, formValue.value.tileid, - { ...formValue.value }, ); + newTileId = updated.tileid; } - emit("update"); + emit("update", newTileId); } catch (error) { toast.add({ severity: ERROR, @@ -226,15 +222,17 @@ async function getResourceInstanceOptions( async function initializeSelectOptions() { getControlledLists(); - groupAndPersonOptions.value = await getResourceInstanceOptions( - fetchGroupRdmSystemList, + groupAndPersonOptions.value = await getResourceInstanceOptions(() => + fetchLingoResources("group"), ); groupAndPersonOptions.value = [ ...(groupAndPersonOptions.value || []), - ...(await getResourceInstanceOptions(fetchPersonRdmSystemList)), + ...(await getResourceInstanceOptions(() => + fetchLingoResources("person"), + )), ]; - textualWorkOptions.value = await getResourceInstanceOptions( - fetchTextualWorkRdmSystemList, + textualWorkOptions.value = await getResourceInstanceOptions(() => + fetchLingoResources("textual_work"), ); } diff --git a/arches_lingo/src/arches_lingo/components/scheme/report/SchemeLabel.vue b/arches_lingo/src/arches_lingo/components/scheme/report/SchemeLabel.vue index b80d1c6d..b8a7787e 100644 --- a/arches_lingo/src/arches_lingo/components/scheme/report/SchemeLabel.vue +++ b/arches_lingo/src/arches_lingo/components/scheme/report/SchemeLabel.vue @@ -12,7 +12,10 @@ import { VIEW, UPDATED, } from "@/arches_lingo/constants.ts"; -import { deleteSchemeLabelTile, fetchSchemeLabel } from "@/arches_lingo/api.ts"; +import { + deleteLingoTile, + fetchLingoResourcePartial, +} from "@/arches_lingo/api.ts"; import LabelEditor from "@/arches_lingo/components/generic/LabelEditor.vue"; import MetaStringViewer from "@/arches_lingo/components/generic/MetaStringViewer.vue"; import ResourceInstanceRelationships from "@/arches_lingo/components/generic/ResourceInstanceRelationships.vue"; @@ -70,7 +73,11 @@ async function getSectionValue() { return; } try { - const result = await fetchSchemeLabel(route.params.id as string); + const result = await fetchLingoResourcePartial( + "scheme", + route.params.id as string, + "appellative_status", + ); schemeInstance.value = { appellative_status: result.appellative_status, }; @@ -89,7 +96,7 @@ async function getSectionValue() { async function deleteSectionValue(tileId: string) { let result = false; try { - result = await deleteSchemeLabelTile(route.params.id as string, tileId); + result = await deleteLingoTile("scheme", "appellative_status", tileId); } catch (error) { toast.add({ severity: ERROR, diff --git a/arches_lingo/src/arches_lingo/components/scheme/report/SchemeLicense.vue b/arches_lingo/src/arches_lingo/components/scheme/report/SchemeLicense.vue index 24ad3e92..8517e650 100644 --- a/arches_lingo/src/arches_lingo/components/scheme/report/SchemeLicense.vue +++ b/arches_lingo/src/arches_lingo/components/scheme/report/SchemeLicense.vue @@ -6,11 +6,10 @@ import { useToast } from "primevue/usetoast"; import Button from "primevue/button"; import SchemeReportSection from "@/arches_lingo/components/scheme/report/SchemeSection.vue"; import { - fetchSchemeRights, - createSchemeFromRights, - updateSchemeRights, - fetchPersonRdmSystemList, - fetchGroupRdmSystemList, + createScheme, + fetchLingoResource, + fetchLingoResources, + updateLingoResource, } from "@/arches_lingo/api.ts"; import { fetchLists } from "@/arches_references/api.ts"; @@ -21,7 +20,6 @@ import type { DataComponentMode, ResourceInstanceReference, ResourceInstanceResult, - SchemeInstance, SchemeRights, SchemeRightStatement, } from "@/arches_lingo/types"; @@ -71,8 +69,8 @@ const languageOptions = ref(); const noteOptions = ref(); const metatypesOptions = ref(); const parentExists = ref(false); -const schemeRights = ref(); -const schemeRightStatement = ref(); +const schemeRights = ref({}); +const schemeRightStatement = ref({}); const referenceNodeConfig = [ { @@ -98,8 +96,8 @@ const referenceNodeConfig = [ ]; async function getActorOptions() { - const options_person = await fetchPersonRdmSystemList(); - const options_group = await fetchGroupRdmSystemList(); + const options_person = await fetchLingoResources("person"); + const options_group = await fetchLingoResources("group"); const options = options_person.concat(options_group); actorRdmOptions.value = options.map((option: ResourceInstanceResult) => { @@ -198,24 +196,26 @@ function onUpdateString(node: keyof SchemeRightStatement, val: string) { } async function saveRights() { + const schemeInstance = { + rights: schemeRights.value, + right_statement: schemeRightStatement.value, + }; try { + let updated; if (route.params.id === NEW) { - const newSchemeInstance: SchemeInstance = { - rights: toRaw(schemeRights.value), - right_statement: toRaw(schemeRightStatement.value), - }; - const updated = await createSchemeFromRights(newSchemeInstance); + updated = await createScheme(schemeInstance); await router.push({ name: "scheme", params: { id: updated.resourceinstanceid }, }); } else { - await updateSchemeRights( + updated = await updateLingoResource( + "scheme", route.params.id as string, - schemeRights.value as SchemeRights, - schemeRightStatement.value as SchemeRightStatement, + schemeInstance, ); } + // TODO: could use updated server response here. emit(UPDATED); } catch (error) { toast.add({ @@ -230,7 +230,10 @@ async function getSectionValue() { if (route.params.id === NEW) { return; } - const schemeInstance = await fetchSchemeRights(route.params.id as string); + const schemeInstance = await fetchLingoResource( + "scheme", + route.params.id as string, + ); schemeRights.value = schemeInstance?.rights ?? {}; if (schemeInstance?.rights) { parentExists.value = true; diff --git a/arches_lingo/src/arches_lingo/components/scheme/report/SchemeNamespace.vue b/arches_lingo/src/arches_lingo/components/scheme/report/SchemeNamespace.vue index 36f96dbe..b8102619 100644 --- a/arches_lingo/src/arches_lingo/components/scheme/report/SchemeNamespace.vue +++ b/arches_lingo/src/arches_lingo/components/scheme/report/SchemeNamespace.vue @@ -7,8 +7,8 @@ import SchemeReportSection from "@/arches_lingo/components/scheme/report/SchemeS import NonLocalizedString from "@/arches_lingo/components/generic/NonLocalizedString.vue"; import { createScheme, - fetchSchemeNamespace, - updateSchemeNamespace, + fetchLingoResourcePartial, + updateLingoResource, } from "@/arches_lingo/api.ts"; import { EDIT, @@ -55,7 +55,8 @@ async function save() { params: { id: updated.resourceinstanceid }, }); } else { - updated = await updateSchemeNamespace( + updated = await updateLingoResource( + "scheme", route.params.id as string, schemeInstance.value, ); @@ -76,7 +77,11 @@ async function getSectionValue() { return; } try { - const response = await fetchSchemeNamespace(route.params.id as string); + const response = await fetchLingoResourcePartial( + "scheme", + route.params.id as string, + "namespace", + ); schemeInstance.value = response; if (schemeInstance.value.namespace) { exists.value = true; diff --git a/arches_lingo/src/arches_lingo/components/scheme/report/SchemeNote.vue b/arches_lingo/src/arches_lingo/components/scheme/report/SchemeNote.vue index fcff21bd..043bae12 100644 --- a/arches_lingo/src/arches_lingo/components/scheme/report/SchemeNote.vue +++ b/arches_lingo/src/arches_lingo/components/scheme/report/SchemeNote.vue @@ -5,7 +5,10 @@ import { useRoute } from "vue-router"; import { useToast } from "primevue/usetoast"; import MetaStringViewer from "@/arches_lingo/components/generic/MetaStringViewer.vue"; import SchemeReportSection from "@/arches_lingo/components/scheme/report/SchemeSection.vue"; -import { deleteSchemeNoteTile, fetchSchemeNotes } from "@/arches_lingo/api.ts"; +import { + deleteLingoTile, + fetchLingoResourcePartial, +} from "@/arches_lingo/api.ts"; import { ERROR, NEW, @@ -70,7 +73,11 @@ async function getSectionValue() { return; } try { - const result = await fetchSchemeNotes(route.params.id as string); + const result = await fetchLingoResourcePartial( + "scheme", + route.params.id as string, + "statement", + ); schemeInstance.value = { statement: result.statement, }; @@ -89,7 +96,7 @@ async function getSectionValue() { async function deleteSectionValue(tileId: string) { let result = false; try { - result = await deleteSchemeNoteTile(route.params.id as string, tileId); + result = await deleteLingoTile("scheme", "statement", tileId); } catch (error) { toast.add({ severity: ERROR, diff --git a/arches_lingo/src/arches_lingo/components/scheme/report/SchemeStandard.vue b/arches_lingo/src/arches_lingo/components/scheme/report/SchemeStandard.vue index a8e090f7..cf19a645 100644 --- a/arches_lingo/src/arches_lingo/components/scheme/report/SchemeStandard.vue +++ b/arches_lingo/src/arches_lingo/components/scheme/report/SchemeStandard.vue @@ -2,21 +2,18 @@ import { inject, onMounted, ref, type Ref } from "vue"; import { useRoute, useRouter } from "vue-router"; import { useGettext } from "vue3-gettext"; + import Button from "primevue/button"; -import type { - DataComponentMode, - ResourceInstanceReference, - ResourceInstanceResult, - SchemeInstance, -} from "@/arches_lingo/types"; +import { useToast } from "primevue/usetoast"; + +import ResourceInstanceRelationships from "@/arches_lingo/components/generic/ResourceInstanceRelationships.vue"; import SchemeReportSection from "@/arches_lingo/components/scheme/report/SchemeSection.vue"; import { createScheme, - fetchSchemeCreation, - fetchTextualWorkRdmSystemList, - updateSchemeCreation, + fetchLingoResourcePartial, + fetchLingoResources, + updateLingoResource, } from "@/arches_lingo/api.ts"; -import ResourceInstanceRelationships from "@/arches_lingo/components/generic/ResourceInstanceRelationships.vue"; import { selectedLanguageKey, VIEW, @@ -26,8 +23,14 @@ import { UPDATED, ERROR, } from "@/arches_lingo/constants.ts"; + import type { Language } from "@/arches_vue_utils/types.ts"; -import { useToast } from "primevue/usetoast"; +import type { + DataComponentMode, + ResourceInstanceReference, + ResourceInstanceResult, + SchemeInstance, +} from "@/arches_lingo/types"; const toast = useToast(); const schemeInstance = ref({}); @@ -50,7 +53,7 @@ onMounted(async () => { }); async function getOptions(): Promise { - const options = await fetchTextualWorkRdmSystemList(); + const options = await fetchLingoResources("textual_work"); const results = options.map((option: ResourceInstanceResult) => { const result: ResourceInstanceReference = { display_value: option.descriptors[selectedLanguage.value.code].name, @@ -73,7 +76,8 @@ async function save() { params: { id: updated.resourceinstanceid }, }); } else { - updated = await updateSchemeCreation( + updated = await updateLingoResource( + "scheme", route.params.id as string, schemeInstance.value, ); @@ -114,7 +118,11 @@ async function setSchemeInstance( options: ResourceInstanceReference[] | undefined, ) { try { - const scheme = await fetchSchemeCreation(route.params.id as string); + const scheme = await fetchLingoResourcePartial( + "scheme", + route.params.id as string, + "creation", + ); const hydratedResults = options?.map((option) => { const savedSource = scheme.creation?.creation_sources.find( @@ -188,6 +196,6 @@ function onCreationUpdate(val: string[]) { + /> diff --git a/arches_lingo/src/arches_lingo/pages/SchemeList.vue b/arches_lingo/src/arches_lingo/pages/SchemeList.vue index 571eab28..814ae581 100644 --- a/arches_lingo/src/arches_lingo/pages/SchemeList.vue +++ b/arches_lingo/src/arches_lingo/pages/SchemeList.vue @@ -9,7 +9,7 @@ import { } from "@/arches_references/constants.ts"; import SchemeCard from "@/arches_lingo/components/scheme/SchemeCard.vue"; -import { fetchSchemes } from "@/arches_lingo/api.ts"; +import { fetchLingoResources } from "@/arches_lingo/api.ts"; import { NEW } from "@/arches_lingo/constants.ts"; import type { SchemeResource } from "@/arches_lingo/types"; @@ -21,7 +21,7 @@ const schemes = ref([]); onMounted(async () => { try { - schemes.value = await fetchSchemes(); + schemes.value = await fetchLingoResources("scheme"); } catch (error) { toast.add({ severity: ERROR, diff --git a/arches_lingo/src/arches_lingo/types.ts b/arches_lingo/src/arches_lingo/types.ts index a44edaac..342c5117 100644 --- a/arches_lingo/src/arches_lingo/types.ts +++ b/arches_lingo/src/arches_lingo/types.ts @@ -115,7 +115,8 @@ export interface MetaStringText { } export interface AppellativeStatus { - tileid: string; + resourceinstance?: string; + tileid?: string; appellative_status_ascribed_name_content: string; appellative_status_ascribed_name_language?: ControlledListItem[]; appellative_status_ascribed_relation?: ControlledListItem[]; @@ -129,7 +130,8 @@ export interface AppellativeStatus { } export interface SchemeStatement { - tileid: string; + resourceinstance?: string; + tileid?: string; statement_content_n1: string; statement_language_n1?: ControlledListItem[]; statement_type_n1?: ControlledListItem[]; @@ -142,13 +144,13 @@ export interface SchemeStatement { } export interface SchemeRights { - tileid: string; + tileid?: string; right_holder?: ResourceInstanceReference[]; right_type?: ControlledListItem[]; } export interface SchemeRightStatement { - tileid: string; + tileid?: string; right_statement_content?: string; right_statement_label?: string; right_statement_language?: ControlledListItem[]; @@ -156,14 +158,29 @@ export interface SchemeRightStatement { right_statement_type_metatype?: ControlledListItem[]; } +export interface SchemeNamespace { + resourceinstance?: string; + tileid?: string; + namespace_name: string; + namespace_type: ControlledListItem[]; +} + +export interface SchemeCreation { + resourceinstance?: string; + tileid?: string; + creation_sources: ResourceInstanceReference[]; +} + +export type SchemeTile = + | AppellativeStatus + | SchemeStatement + | SchemeNamespace + | SchemeCreation + | SchemeRights; + export interface SchemeInstance { - namespace?: { - namespace_name: string; - namespace_type: ControlledListItem[]; - }; - creation?: { - creation_sources: ResourceInstanceReference[]; - }; + namespace?: SchemeNamespace; + creation?: SchemeCreation; appellative_status?: AppellativeStatus[]; statement?: SchemeStatement[]; rights?: SchemeRights; diff --git a/arches_lingo/templates/arches_urls.htm b/arches_lingo/templates/arches_urls.htm index d8d0fc1c..da4c6d1c 100644 --- a/arches_lingo/templates/arches_urls.htm +++ b/arches_lingo/templates/arches_urls.htm @@ -9,19 +9,10 @@
{% endblock arches_urls %} diff --git a/arches_lingo/urls.py b/arches_lingo/urls.py index 351346c5..ab354963 100644 --- a/arches_lingo/urls.py +++ b/arches_lingo/urls.py @@ -5,28 +5,11 @@ from arches_lingo.views.root import LingoRootView from arches_lingo.views.api.concepts import ConceptTreeView, ValueSearchView -from arches_lingo.views.api.pythonic_models import ( - ConceptDetailView, - ConceptListCreateView, - ConceptStatementDetailView, - ConceptStatementListCreateView, - GroupRdmSystemSerializerView, - PersonRdmSystemSerializerView, - SchemeCreationView, - SchemeRightsListCreateView, - SchemeRightsView, - SchemeDetailView, - SchemeLabelTileView, - SchemeLabelView, - SchemeLabelCreateView, - SchemeListCreateView, - SchemeNamespaceView, - SchemeNoteTileView, - SchemeNoteView, - SchemeNoteCreateView, - SchemeStatementDetailView, - SchemeStatementListCreateView, - TextualWorkRdmSystemSerializerView, +from arches_lingo.views.api.generic import ( + LingoResourceDetailView, + LingoResourceListCreateView, + LingoTileDetailView, + LingoTileListCreateView, ) urlpatterns = [ @@ -40,94 +23,30 @@ path("concept/", LingoRootView.as_view(), name="concept"), path("api/concept-tree", ConceptTreeView.as_view(), name="api-concepts"), path("api/search", ValueSearchView.as_view(), name="api-search"), - path("api/concepts", ConceptListCreateView.as_view(), name="concepts-list-create"), - path("api/concept/", ConceptDetailView.as_view(), name="concept-detail"), path( - "api/concept/statements", - ConceptStatementListCreateView.as_view(), - name="concept-statements-list-create", + "api/lingo/", + LingoResourceListCreateView.as_view(), + name="api-lingo-resources", ), path( - "api/concept/statement/", - ConceptStatementDetailView.as_view(), - name="concept-statement-detail", + "api/lingo//", + LingoResourceDetailView.as_view(), + name="api-lingo-resource", ), - path("api/schemes", SchemeListCreateView.as_view(), name="schemes-list-create"), - path("api/scheme/", SchemeDetailView.as_view(), name="scheme-detail"), path( - "api/scheme//namespace", - SchemeNamespaceView.as_view(), - name="api-uri-components", + "api/lingo///", + LingoResourceDetailView.as_view(), + name="api-lingo-resource-partial", ), path( - "api/scheme//creation", - SchemeCreationView.as_view(), - name="api-scheme-creation", + "api/lingo//", + LingoTileListCreateView.as_view(), + name="api-lingo-tiles", ), path( - "api/scheme//label", - SchemeLabelView.as_view(), - name="api-scheme-label", - ), - path( - "api/scheme//label/", - SchemeLabelTileView.as_view(), - name="api-scheme-label-tile", - ), - path( - "api/scheme/labels", - SchemeLabelCreateView.as_view(), - name="api-scheme-label-list-create", - ), - path( - "api/scheme//note", - SchemeNoteView.as_view(), - name="api-scheme-note", - ), - path( - "api/scheme//note/", - SchemeNoteTileView.as_view(), - name="api-scheme-note-tile", - ), - path( - "api/scheme/note", - SchemeNoteCreateView.as_view(), - name="api-scheme-note-create", - ), - path( - "api/scheme/scheme-rights", - SchemeRightsListCreateView.as_view(), - name="api-scheme-rights-list-create", - ), - path( - "api/scheme//scheme-rights", - SchemeRightsView.as_view(), - name="api-scheme-rights", - ), - path( - "api/textual-work", - TextualWorkRdmSystemSerializerView.as_view(), - name="api-textualwork-list", - ), - path( - "api/group-rdm-system", - GroupRdmSystemSerializerView.as_view(), - name="api-group-list", - ), - path( - "api/person-rdm-system", - PersonRdmSystemSerializerView.as_view(), - name="api-person-list", - ), - path( - "api/scheme/statements", - SchemeStatementListCreateView.as_view(), - name="scheme-statements-list-create", - ), - path( - "api/scheme/statement/", - SchemeStatementDetailView.as_view(), - name="scheme-statement-detail", + "api/lingo///", + LingoTileDetailView.as_view(), + name="api-lingo-tile", ), path("", include("arches_references.urls")), ] diff --git a/arches_lingo/views/api/generic.py b/arches_lingo/views/api/generic.py new file mode 100644 index 00000000..c2bc6038 --- /dev/null +++ b/arches_lingo/views/api/generic.py @@ -0,0 +1,33 @@ +from rest_framework.generics import ( + ListCreateAPIView, + RetrieveUpdateDestroyAPIView, +) + +from arches.app.permissions.rest_framework import RDMAdministrator +from arches.app.views.api.mixins import ArchesModelAPIMixin + +from arches_lingo.serializers import ( + LingoResourceSerializer, + LingoTileSerializer, +) + + +class LingoResourceListCreateView(ArchesModelAPIMixin, ListCreateAPIView): + permission_classes = [RDMAdministrator] + serializer_class = LingoResourceSerializer + pagination_class = None + + +class LingoResourceDetailView(ArchesModelAPIMixin, RetrieveUpdateDestroyAPIView): + permission_classes = [RDMAdministrator] + serializer_class = LingoResourceSerializer + + +class LingoTileListCreateView(ArchesModelAPIMixin, ListCreateAPIView): + permission_classes = [RDMAdministrator] + serializer_class = LingoTileSerializer + + +class LingoTileDetailView(ArchesModelAPIMixin, RetrieveUpdateDestroyAPIView): + permission_classes = [RDMAdministrator] + serializer_class = LingoTileSerializer diff --git a/arches_lingo/views/api/pythonic_models.py b/arches_lingo/views/api/pythonic_models.py deleted file mode 100644 index 5e9732c1..00000000 --- a/arches_lingo/views/api/pythonic_models.py +++ /dev/null @@ -1,146 +0,0 @@ -from rest_framework.generics import ( - ListCreateAPIView, - ListAPIView, - RetrieveUpdateDestroyAPIView, -) - -from arches.app.permissions.rest_framework import RDMAdministrator -from arches.app.views.api.mixins import ArchesModelAPIMixin - -from arches_lingo.serializers import ( - ConceptSerializer, - ConceptStatementSerializer, - GroupRdmSystemSerializer, - PersonRdmSystemSerializer, - SchemeCreationSerializer, - SchemeLabelSerializer, - SchemeLabelTileSerializer, - SchemeNamespaceSerializer, - SchemeNoteSerializer, - SchemeNoteTileSerializer, - SchemeSerializer, - SchemeStatementSerializer, - SchemeRightsSerializer, - TextualWorkRdmSystemSerializer, -) - - -class SchemeListCreateView(ArchesModelAPIMixin, ListCreateAPIView): - permission_classes = [RDMAdministrator] - serializer_class = SchemeSerializer - pagination_class = None - - -class SchemeDetailView(ArchesModelAPIMixin, RetrieveUpdateDestroyAPIView): - permission_classes = [RDMAdministrator] - serializer_class = SchemeSerializer - - -class SchemeStatementListCreateView(ArchesModelAPIMixin, ListCreateAPIView): - permission_classes = [RDMAdministrator] - serializer_class = SchemeStatementSerializer - - -class SchemeStatementDetailView(ArchesModelAPIMixin, RetrieveUpdateDestroyAPIView): - permission_classes = [RDMAdministrator] - serializer_class = SchemeStatementSerializer - - -class ConceptListCreateView(ArchesModelAPIMixin, ListCreateAPIView): - permission_classes = [RDMAdministrator] - serializer_class = ConceptSerializer - - -class SchemeNamespaceView(ArchesModelAPIMixin, RetrieveUpdateDestroyAPIView): - permission_classes = [RDMAdministrator] - serializer_class = SchemeNamespaceSerializer - - -class SchemeCreationView(ArchesModelAPIMixin, RetrieveUpdateDestroyAPIView): - permission_classes = [RDMAdministrator] - serializer_class = SchemeCreationSerializer - - -class SchemeRightsListCreateView(ArchesModelAPIMixin, ListCreateAPIView): - permission_classes = [RDMAdministrator] - serializer_class = SchemeRightsSerializer - - -class SchemeRightsView(ArchesModelAPIMixin, RetrieveUpdateDestroyAPIView): - permission_classes = [RDMAdministrator] - serializer_class = SchemeRightsSerializer - - -class SchemeLabelView(ArchesModelAPIMixin, RetrieveUpdateDestroyAPIView): - permission_classes = [RDMAdministrator] - serializer_class = SchemeLabelSerializer - - -class SchemeLabelTileView(ArchesModelAPIMixin, RetrieveUpdateDestroyAPIView): - permission_classes = [RDMAdministrator] - serializer_class = SchemeLabelTileSerializer - - -class SchemeLabelCreateView(ArchesModelAPIMixin, ListCreateAPIView): - permission_classes = [RDMAdministrator] - serializer_class = SchemeLabelTileSerializer - - -class SchemeNoteView(ArchesModelAPIMixin, RetrieveUpdateDestroyAPIView): - permission_classes = [RDMAdministrator] - serializer_class = SchemeNoteSerializer - - -class SchemeNoteTileView(ArchesModelAPIMixin, RetrieveUpdateDestroyAPIView): - permission_classes = [RDMAdministrator] - serializer_class = SchemeNoteTileSerializer - - -class SchemeNoteCreateView(ArchesModelAPIMixin, ListCreateAPIView): - permission_classes = [RDMAdministrator] - serializer_class = SchemeNoteTileSerializer - - -class TextualWorkRdmSystemSerializerView(ArchesModelAPIMixin, ListAPIView): - permission_classes = [RDMAdministrator] - serializer_class = TextualWorkRdmSystemSerializer - pagination_class = None - - -class GroupRdmSystemSerializerView(ArchesModelAPIMixin, ListAPIView): - permission_classes = [RDMAdministrator] - serializer_class = GroupRdmSystemSerializer - pagination_class = None - - -class PersonRdmSystemSerializerView(ArchesModelAPIMixin, ListAPIView): - permission_classes = [RDMAdministrator] - serializer_class = PersonRdmSystemSerializer - pagination_class = None - - -class GroupRdmSystemSerializerView(ArchesModelAPIMixin, ListAPIView): - permission_classes = [RDMAdministrator] - serializer_class = GroupRdmSystemSerializer - pagination_class = None - - -class PersonRdmSystemSerializerView(ArchesModelAPIMixin, ListAPIView): - permission_classes = [RDMAdministrator] - serializer_class = PersonRdmSystemSerializer - pagination_class = None - - -class ConceptDetailView(ArchesModelAPIMixin, RetrieveUpdateDestroyAPIView): - permission_classes = [RDMAdministrator] - serializer_class = ConceptSerializer - - -class ConceptStatementListCreateView(ArchesModelAPIMixin, ListCreateAPIView): - permission_classes = [RDMAdministrator] - serializer_class = ConceptStatementSerializer - - -class ConceptStatementDetailView(ArchesModelAPIMixin, RetrieveUpdateDestroyAPIView): - permission_classes = [RDMAdministrator] - serializer_class = ConceptStatementSerializer