From d8355e79a68d5d495e155936d08130450a89fc78 Mon Sep 17 00:00:00 2001 From: Aaron Gundel Date: Fri, 14 Feb 2025 13:01:19 -0700 Subject: [PATCH 1/9] Working Resource Instance Select --- .../ResourceInstanceSelectWidget.vue | 51 ++-- .../ResourceInstanceSelectWidgetEditor.vue | 247 ++++++++++++++++++ .../ResourceInstanceSelectWidgetViewer.vue | 7 +- .../src/arches_component_lab/widgets/api.ts | 36 +++ .../src/arches_component_lab/widgets/types.ts | 23 ++ .../templates/arches_urls.htm | 13 + arches_component_lab/urls.py | 14 +- .../views/api/relatable_resources.py | 54 ++++ arches_component_lab/views/api/widgets.py | 18 ++ 9 files changed, 441 insertions(+), 22 deletions(-) create mode 100644 arches_component_lab/templates/arches_urls.htm create mode 100644 arches_component_lab/views/api/relatable_resources.py create mode 100644 arches_component_lab/views/api/widgets.py diff --git a/arches_component_lab/src/arches_component_lab/widgets/ResourceInstanceSelectWidget/ResourceInstanceSelectWidget.vue b/arches_component_lab/src/arches_component_lab/widgets/ResourceInstanceSelectWidget/ResourceInstanceSelectWidget.vue index 9e01c8b..d1c8e99 100644 --- a/arches_component_lab/src/arches_component_lab/widgets/ResourceInstanceSelectWidget/ResourceInstanceSelectWidget.vue +++ b/arches_component_lab/src/arches_component_lab/widgets/ResourceInstanceSelectWidget/ResourceInstanceSelectWidget.vue @@ -1,28 +1,38 @@ diff --git a/arches_component_lab/src/arches_component_lab/widgets/ResourceInstanceSelectWidget/components/ResourceInstanceSelectWidgetEditor.vue b/arches_component_lab/src/arches_component_lab/widgets/ResourceInstanceSelectWidget/components/ResourceInstanceSelectWidgetEditor.vue index e69de29..d5232f7 100644 --- a/arches_component_lab/src/arches_component_lab/widgets/ResourceInstanceSelectWidget/components/ResourceInstanceSelectWidgetEditor.vue +++ b/arches_component_lab/src/arches_component_lab/widgets/ResourceInstanceSelectWidget/components/ResourceInstanceSelectWidgetEditor.vue @@ -0,0 +1,247 @@ + + + \ No newline at end of file diff --git a/arches_component_lab/src/arches_component_lab/widgets/ResourceInstanceSelectWidget/components/ResourceInstanceSelectWidgetViewer.vue b/arches_component_lab/src/arches_component_lab/widgets/ResourceInstanceSelectWidget/components/ResourceInstanceSelectWidgetViewer.vue index 5ba6c97..c3fe9bc 100644 --- a/arches_component_lab/src/arches_component_lab/widgets/ResourceInstanceSelectWidget/components/ResourceInstanceSelectWidgetViewer.vue +++ b/arches_component_lab/src/arches_component_lab/widgets/ResourceInstanceSelectWidget/components/ResourceInstanceSelectWidgetViewer.vue @@ -1,15 +1,16 @@ diff --git a/arches_component_lab/src/arches_component_lab/widgets/api.ts b/arches_component_lab/src/arches_component_lab/widgets/api.ts index fbafb8c..e0646fc 100644 --- a/arches_component_lab/src/arches_component_lab/widgets/api.ts +++ b/arches_component_lab/src/arches_component_lab/widgets/api.ts @@ -16,3 +16,39 @@ export const fetchLists = async ( throw new Error((error as Error).message || response.statusText); } }; + +export const fetchRelatableResources = async ( + graphSlug: string, + nodeAlias: string, + page: number, +) => { + const response = await fetch( + `${arches.urls.api_relatable_resources( + graphSlug, + nodeAlias, + )}?page=${page}`, + ); + + const parsed = await response.json(); + if (!response.ok) throw new Error(parsed.message || response.statusText); + return parsed; +}; + +export const fetchWidgetConfiguration = async ( + graphSlug: string, + nodeAlias: string, +) => { + const response = await fetch( + arches.urls.api_widget_configuration(graphSlug, nodeAlias), + ); + + try { + const parsed = await response.json(); + if (response.ok) { + return parsed; + } + throw new Error(parsed.message); + } catch (error) { + throw new Error((error as Error).message || response.statusText); + } +}; diff --git a/arches_component_lab/src/arches_component_lab/widgets/types.ts b/arches_component_lab/src/arches_component_lab/widgets/types.ts index cf2b846..7009183 100644 --- a/arches_component_lab/src/arches_component_lab/widgets/types.ts +++ b/arches_component_lab/src/arches_component_lab/widgets/types.ts @@ -1,3 +1,26 @@ import { EDIT, VIEW } from "@/arches_component_lab/widgets/constants"; export type WidgetMode = typeof EDIT | typeof VIEW; + +export interface GraphInfo { + graphid: string; + name: string; +} + +export interface NewResourceInstance { + displayValue: string; + graphId: string; +} + +export interface ResourceInstanceReference { + resourceId: string; + ontologyProperty: string; + resourceXresourceId?: string; + inverseOntologyProperty: string; + display_value?: string; +} + +export interface ResourceInstanceResult { + resourceinstanceid: string; + display_value: string; +} diff --git a/arches_component_lab/templates/arches_urls.htm b/arches_component_lab/templates/arches_urls.htm new file mode 100644 index 0000000..9519855 --- /dev/null +++ b/arches_component_lab/templates/arches_urls.htm @@ -0,0 +1,13 @@ +{% extends "arches_urls.htm" %} + +{% load static %} +{% load l10n %} +{% load i18n %} + +{% block arches_urls %} +{{ block.super }} +
+{% endblock arches_urls %} diff --git a/arches_component_lab/urls.py b/arches_component_lab/urls.py index 4f9c69b..f479155 100644 --- a/arches_component_lab/urls.py +++ b/arches_component_lab/urls.py @@ -3,8 +3,20 @@ from django.conf.urls.i18n import i18n_patterns from django.urls import include, path +from arches_component_lab.views.api.relatable_resources import RelatableResourcesView +from arches_component_lab.views.api.widgets import WidgetConfigurationView + urlpatterns = [ - # project-level urls + path( + "arches-component-lab/api/widget-configuration///relatable-resources", + RelatableResourcesView.as_view(), + name="api-node-relatable-resources", + ), + path( + "arches-component-lab/api/widget-configuration//", + WidgetConfigurationView.as_view(), + name="api-widget-configuration", + ), ] # Ensure Arches core urls are superseded by project-level urls diff --git a/arches_component_lab/views/api/relatable_resources.py b/arches_component_lab/views/api/relatable_resources.py new file mode 100644 index 0000000..daa7283 --- /dev/null +++ b/arches_component_lab/views/api/relatable_resources.py @@ -0,0 +1,54 @@ +from django.core.paginator import Paginator +from django.utils.decorators import method_decorator +from django.views import View +from django.utils.translation import get_language +from arches.app.models.models import Node, ResourceInstance, GraphModel +from arches.app.utils.response import JSONResponse +from arches.app.utils.betterJSONSerializer import JSONDeserializer + +from arches.app.utils.decorators import user_can_read_resource + + +class RelatableResourcesView(View): + def get(self, request, graph, node_alias): + node = Node.objects.get( + name=node_alias, + graph__slug=graph, + graph__is_active=True, + graph__publication__isnull=False, + ) + page_number = request.GET.get("page", 1) + items_per_page = request.GET.get("items", 25) + + config = JSONDeserializer().deserialize(node.config.value) + graphs = [graph["graphid"] for graph in config.get("graphs", [])] + + graph_models = GraphModel.objects.filter(graphid__in=graphs).values( + "name", "graphid" + ) + + resources = ResourceInstance.objects.filter(graph_id__in=graphs).order_by( + "descriptors__{}__name".format(get_language()) + ) + + paginator = Paginator(resources, items_per_page) + page_object = paginator.get_page(page_number) + language = get_language() + data = [ + { + "resourceinstanceid": resource.resourceinstanceid, + "display_value": resource.descriptors[language]["name"], + } + for resource in page_object + ] + + return JSONResponse( + { + "graphs": graph_models, + "current_page": paginator.get_page(page_number).number, + "total_pages": paginator.num_pages, + "results_per_page": paginator.per_page, + "total_results": paginator.count, + "data": data, + } + ) diff --git a/arches_component_lab/views/api/widgets.py b/arches_component_lab/views/api/widgets.py new file mode 100644 index 0000000..f5b491d --- /dev/null +++ b/arches_component_lab/views/api/widgets.py @@ -0,0 +1,18 @@ +import json + +from django.views.generic import View + +from arches.app.models import models +from arches.app.utils.response import JSONResponse + + +class WidgetConfigurationView(View): + def get(self, request, graph_slug, node_alias): + card_x_node_x_widget = models.CardXNodeXWidget.objects.get( + node__graph__slug=graph_slug, + node__alias=node_alias, + node__source_identifier_id__isnull=True, + ) + card_x_node_x_widget_config = json.loads(card_x_node_x_widget.config.value) + + return JSONResponse(card_x_node_x_widget_config) From 8719e377f98a5cb099c5c7654da02767221b021b Mon Sep 17 00:00:00 2001 From: Christopher Byrd Date: Fri, 14 Feb 2025 15:40:30 -0800 Subject: [PATCH 2/9] merge --- .../ResourceInstanceSelectWidget.vue | 20 +++++++---- .../ResourceInstanceSelectWidgetEditor.vue | 35 ++++++++++++------- .../ResourceInstanceSelectWidgetViewer.vue | 4 ++- 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/arches_component_lab/src/arches_component_lab/widgets/ResourceInstanceSelectWidget/ResourceInstanceSelectWidget.vue b/arches_component_lab/src/arches_component_lab/widgets/ResourceInstanceSelectWidget/ResourceInstanceSelectWidget.vue index d1c8e99..41b1d40 100644 --- a/arches_component_lab/src/arches_component_lab/widgets/ResourceInstanceSelectWidget/ResourceInstanceSelectWidget.vue +++ b/arches_component_lab/src/arches_component_lab/widgets/ResourceInstanceSelectWidget/ResourceInstanceSelectWidget.vue @@ -5,7 +5,10 @@ import ResourceInstanceSelectWidgetEditor from "@/arches_component_lab/widgets/R import ResourceInstanceSelectWidgetViewer from "@/arches_component_lab/widgets/ResourceInstanceSelectWidget/components/ResourceInstanceSelectWidgetViewer.vue"; import { fetchWidgetConfiguration } from "@/arches_component_lab/widgets/api.ts"; import { EDIT, VIEW } from "@/arches_component_lab/widgets/constants.ts"; -import type { ResourceInstanceReference, WidgetMode } from "@/arches_component_lab/widgets/types.ts"; +import type { + ResourceInstanceReference, + WidgetMode, +} from "@/arches_component_lab/widgets/types.ts"; const props = defineProps<{ mode?: WidgetMode; @@ -25,13 +28,16 @@ interface ChildComponentInterface { } onMounted(async () => { - const widgetConfig = await fetchWidgetConfiguration(props.configuration.graphSlug, props.configuration.nodeAlias); + const widgetConfig = await fetchWidgetConfiguration( + props.configuration.graphSlug, + props.configuration.nodeAlias, + ); childConfiguration.value = { ...props.configuration, - ...widgetConfig - } -});; + ...widgetConfig, + }; +}); const childRef = useTemplateRef("childRef"); @@ -49,14 +55,14 @@ defineExpose({
-
- (); @@ -21,14 +26,14 @@ const props = defineProps<{ ptAriaLabeledBy?: string; itemHeight?: number; resultsPerPage?: number; - } + }; }>(); const itemHeight = 38; const resultsPerPage = 25; interface MessageData { - severity: 'successs' | 'info' | 'warn' | 'error'; + severity: "successs" | "info" | "warn" | "error"; detail: string; } @@ -41,17 +46,17 @@ const rawSelectedResources = computed({ return rawValue.value; }, set(value) { - rawValue.value = options.value.find(option => option.resourceId == value)?.resourceId - } -} -); + rawValue.value = options.value.find( + (option) => option.resourceId == value, + )?.resourceId; + }, +}); defineExpose({ rawValue, isDirty, }); - const options = ref([]); const newElements = ref([]); const isLoading = ref(false); @@ -81,7 +86,7 @@ watch(options, (resourceResults) => { }); onMounted(() => { - console.log('here i am') + console.log("here i am"); fetchData(1); }); @@ -124,7 +129,7 @@ async function fetchData(page: number) { message.value = { detail: `Failed to fetch data. ${error instanceof Error ? error.message : undefined}`, severity: "error", - } + }; options.value = []; resourceResultsPage.value = 1; @@ -163,7 +168,7 @@ function toggleSelectAll() { this.selectAll = true; } -