[!WARNING] This package is deprecated and no longer maintained. Please migrate to arches-vue-components instead.
Arches Component Lab
A Vue 3 / PrimeVue component library for building custom Arches applications.
Installation
pip install arches-component-lab
Project Configuration
-
If you do not already have an Arches project, create one by following the instructions in the Arches documentation.
-
Add
arches_querysetsandarches_component_labtoINSTALLED_APPSbelow the name of your project but abovearches. For Arches >= 8.x, also addpgtrigger:
INSTALLED_APPS = (
"my_project_name",
...
"arches_querysets",
"arches_component_lab",
"arches",
...
"pgtrigger",
)
- Add
arches_component_labas a dependency inpackage.json:
"dependencies": {
"arches_component_lab": "archesproject/arches-component-lab#main"
}
- Add the
arches_component_labURLs tourls.py:
urlpatterns = [
path("", include("arches_component_lab.urls")),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
- Start your project and install frontend dependencies:
python manage.py runserver
npm install && npm run build_development
- Check for missing
WidgetMappingrecords:
python manage.py validate --codes 2001 --verbosity 2
See Extending Arches Component Lab if any are missing.
Frontend API
Bootstrapping an app
import MyComponent from '@/my_project/MyComponent.vue';
import { createVueApplication } from '@/arches_component_lab/application';
createVueApplication({ component: MyComponent }).then(app => app.mount('#app'));
Widgets
GenericWidget looks up the widget mapped to a node (see Extending Arches Component Lab) and resolves the real component at runtime. In edit mode it wraps the resolved widget in a GenericFormField, which registers the node as a PrimeVue Forms FormField keyed by nodeAlias, ties its dirty/touched state and validation errors into an ancestor <Form>, and renders those errors:
<script setup lang="ts">
import { ref } from 'vue';
import GenericWidget from '@/arches_component_lab/generics/GenericWidget/GenericWidget.vue';
import type { WidgetMode } from '@/arches_component_lab/widgets';
import type { AliasedNodeData } from '@/arches_component_lab/generics';
const MODE: WidgetMode = 'edit';
const nodeData = ref<AliasedNodeData | null>(null);
</script>
<template>
<GenericWidget
node-alias="my_text_node"
graph-slug="my_graph"
:mode="MODE"
:aliased-node-data="nodeData"
@update:aliased-node-data="nodeData = $event"
/>
</template>
aliasedNodeData/value are both optional. Without either, GenericWidget falls back to the node's configured default (cardXNodeXWidgetData.config.defaultValue, part of the widget config it already fetches), so it renders from just graphSlug/nodeAlias/mode:
<template>
<GenericWidget
node-alias="my_text_node"
graph-slug="my_graph"
mode="edit"
/>
</template>
Importing a widget directly skips the runtime resolution and the FormField integration described above. The widget emits update:aliasedNodeData/update:value on its own (some widgets also emit update:isDirty); the caller wires that into any surrounding form:
<script setup lang="ts">
import { ref } from 'vue';
import { TextWidget } from '@/arches_component_lab/widgets';
import type { WidgetMode } from '@/arches_component_lab/widgets';
import type { StringAliasedNodeData } from '@/arches_component_lab/datatypes';
const MODE: WidgetMode = 'edit';
const nodeData = ref<StringAliasedNodeData | null>(null);
</script>
<template>
<TextWidget
:mode="MODE"
:aliased-node-data="nodeData"
@update:aliased-node-data="nodeData = $event"
/>
</template>
Cards
GenericCard renders a whole nodegroup. It fetches the tile (fetchTileData) and every node's widget config, then renders GenericCardEditor or GenericCardViewer depending on mode. The editor wraps a PrimeVue Form and renders one GenericWidget per node, and saves the collected tile with upsertTile — from its own save button, or by calling .save() on it directly (exposed via defineExpose).
<script setup lang="ts">
import { ref } from 'vue';
import GenericCard from '@/arches_component_lab/generics/GenericCard/GenericCard.vue';
import type { AliasedTileData } from '@/arches_component_lab/generics';
const tileData = ref<AliasedTileData>();
</script>
<template>
<GenericCard
graph-slug="my_graph"
nodegroup-alias="my_nodegroup"
:resource-instance-id="resourceInstanceId"
:tile-id="tileId"
:tile-data="tileData"
mode="edit"
@update:tile-data="tileData = $event"
@save="tileData = $event"
@reset="() => {}"
/>
</template>
Reference
@/arches_component_lab/widgets
| Name | Type | Description |
|---|---|---|
WidgetMode |
'edit' | 'view' | 'configure' |
The three states a widget can render in |
BaseWidgetProps |
{ mode: WidgetMode; nodeAlias?: string; graphSlug?: string } |
Props every widget accepts |
Every widget's aliasedNodeData/cardXNodeXWidgetData prop is typed to one specific datatype. Where no widget-specific cardXNodeXWidgetData type is listed, the widget uses the base CardXNodeXWidgetData (no extra config fields). Both columns import from @/arches_component_lab/datatypes:
| Widget | aliasedNodeData type |
cardXNodeXWidgetData type |
|---|---|---|
TextWidget, RichTextWidget |
StringAliasedNodeData |
StringCardXNodeXWidgetData |
NonLocalizedTextWidget |
NonLocalizedTextAliasedNodeData |
CardXNodeXWidgetData |
NumberWidget |
NumberAliasedNodeData |
NumberCardXNodeXWidgetData |
DatePickerWidget |
DateAliasedNodeData |
DateCardXNodeXWidgetData |
EDTFWidget |
EDTFAliasedNodeData |
CardXNodeXWidgetData |
ConceptSelectWidget |
ConceptAliasedNodeData |
CardXNodeXWidgetData |
ConceptRadioWidget |
ConceptAliasedNodeData |
ConceptCardXNodeXWidgetData |
ConceptMultiselectWidget |
ConceptListAliasedNodeData |
CardXNodeXWidgetData |
DomainSelectWidget, DomainRadioWidget |
DomainAliasedNodeData |
DomainCardXNodeXWidgetData |
DomainCheckboxWidget, DomainMultiselectWidget |
DomainListAliasedNodeData |
DomainCardXNodeXWidgetData |
LanguageSelectWidget |
LanguageAliasedNodeData |
CardXNodeXWidgetData |
RadioBooleanWidget, SwitchWidget |
BooleanAliasedNodeData |
BooleanCardXNodeXWidgetData |
ResourceInstanceSelectWidget |
ResourceInstanceAliasedNodeData |
ResourceInstanceCardXNodeXWidgetData |
ResourceInstanceMultiselectWidget |
ResourceInstanceListAliasedNodeData |
ResourceInstanceListCardXNodeXWidgetData |
FileListWidget |
FileListAliasedNodeData |
FileListCardXNodeXWidgetData |
NodeValueSelectWidget |
NodeValueAliasedNodeData |
CardXNodeXWidgetData |
URLWidget |
URLAliasedNodeData |
CardXNodeXWidgetData |
MapWidget |
GeoJSONFeatureCollectionAliasedNodeData |
MapCardXNodeXWidgetData |
@/arches_component_lab/generics
GenericWidget/GenericCard resolve their concrete component at runtime instead of being imported directly — that is the "generic" here, not a TypeScript <T>.
| Export | Description |
|---|---|
GenericCard |
Card editor/viewer for a nodegroup |
GenericWidget |
Single widget resolved from widget config |
GenericCardProps, GenericWidgetProps |
Props interfaces |
AliasedNodeData, AliasedTileData |
Node/tile value types |
GenericWidgetProps:
| Name | Type | Description |
|---|---|---|
graphSlug |
string |
Graph the node belongs to |
nodeAlias |
string |
Node to render |
mode |
WidgetMode |
'edit', 'view', or 'configure' |
aliasedNodeData |
AliasedNodeData | null |
Current value; takes priority over value |
value |
unknown |
Raw value fallback, used only if aliasedNodeData is omitted |
cardXNodeXWidgetData |
CardXNodeXWidgetData |
Pre-fetched widget config; skips GenericWidget's own fetch |
cardXNodeXWidgetDataOverrides |
Partial<CardXNodeXWidgetData> |
Merged into the fetched config after fetching |
isDirty |
boolean |
Marks the field dirty on the surrounding <Form> |
shouldShowLabel |
boolean |
Show the node's label (default true) |
GenericCardProps:
| Name | Type | Description |
|---|---|---|
graphSlug |
string |
Graph the nodegroup belongs to |
nodegroupAlias |
string |
Nodegroup to render |
mode |
WidgetMode |
'edit', 'view', or 'configure' |
resourceInstanceId |
string | null |
Resource this tile belongs to, for a new tile |
selectedNodeAlias |
string | null |
Node to focus within the card |
shouldShowFormButtons |
boolean |
Show the built-in save/reset buttons (default true) |
tileData |
AliasedTileData |
Pre-fetched tile; skips GenericCard's own fetch |
tileId |
string | null |
Tile to fetch when tileData is not provided |
@/arches_component_lab/datatypes
*AliasedNodeData types are listed in the widget table above. Supporting types:
| Export | Description |
|---|---|
LanguageValue |
Per-language string value ({ value: string; direction: 'ltr' | 'rtl' }) |
URLNodeValue |
URL node value ({ url: string; url_label: string }) |
FileReference |
File attachment reference |
ResourceInstanceReference |
Resource instance link reference |
DomainOption |
Domain value option |
@/arches_component_lab/application
| Name | Type |
|---|---|
createVueApplication |
(options: CreateVueApplicationOptions) => Promise<App> |
generateArchesURL |
(urlName: string, urlParameters?: Record<string, string | number>, queryParameters?: Record<string, string | number>, languageCode?: string) => string |
CreateVueApplicationOptions |
{ component: Component; themeConfiguration?: ArchesThemeConfiguration; initialProps?: Record<string, unknown> } |
@/arches_component_lab/themes
| Name | Type | Description |
|---|---|---|
DEFAULT_THEME |
ArchesThemeConfiguration |
Theme createVueApplication uses when themeConfiguration is not passed |
ArchesThemeConfiguration |
— | PrimeVue theme configuration shape |
Creating a Custom Widget
A widget is an editor/viewer pair plus a dispatcher that picks between them by mode. The example below, RatingWidget, is a new widget for the existing number datatype.
[!IMPORTANT] Use
defineProps([...])/defineEmits([...])castasthe real type, shown below — neverdefineProps<T>()/defineEmits<T>()with a generic argument. That generic argument makes@vue/compiler-sfcresolve types via its own tsconfig walk, separate from webpack, which breaks on a real (non-editable) pip install.
- Create
widgets/RatingWidget/with atypes.tsextendingBaseWidgetProps:
import type { BaseWidgetProps } from "@/arches_component_lab/widgets/types.ts";
import type {
NumberAliasedNodeData,
NumberCardXNodeXWidgetData,
} from "@/arches_component_lab/datatypes/number/types.ts";
export interface RatingWidgetProps extends BaseWidgetProps {
cardXNodeXWidgetData?: NumberCardXNodeXWidgetData;
aliasedNodeData?: NumberAliasedNodeData | null;
value?: number | null;
}
- Add
RatingWidget.vue, the dispatcher — switches onmode, re-emitsupdate:aliasedNodeData,update:value,initialized:
<script setup lang="ts">
import { computed } from "vue";
import RatingWidgetEditor from "@/arches_component_lab/widgets/RatingWidget/components/RatingWidgetEditor.vue";
import RatingWidgetViewer from "@/arches_component_lab/widgets/RatingWidget/components/RatingWidgetViewer.vue";
import { EDIT, VIEW } from "@/arches_component_lab/widgets/constants.ts";
import { buildNumberAliasedNodeData } from "@/arches_component_lab/datatypes/number/utils.ts";
import type { NumberAliasedNodeData } from "@/arches_component_lab/datatypes/number/types.ts";
import type { RatingWidgetProps } from "@/arches_component_lab/widgets/RatingWidget/types.ts";
const { aliasedNodeData, value } = defineProps([
"mode",
"nodeAlias",
"graphSlug",
"cardXNodeXWidgetData",
"aliasedNodeData",
"value",
]) as RatingWidgetProps;
const emit = defineEmits([
"update:value",
"update:aliasedNodeData",
"initialized",
]) as {
(event: "update:value", updatedValue: number | null): void;
(event: "update:aliasedNodeData", updatedValue: NumberAliasedNodeData): void;
(event: "initialized", updatedValue: NumberAliasedNodeData): void;
};
const resolvedAliasedNodeData = computed(
() => aliasedNodeData ?? buildNumberAliasedNodeData(value ?? null),
);
function onUpdateAliasedNodeData(updated: NumberAliasedNodeData) {
emit("update:aliasedNodeData", updated);
emit("update:value", updated.node_value);
}
</script>
<template>
<RatingWidgetEditor
v-if="mode === EDIT"
:card-x-node-x-widget-data="cardXNodeXWidgetData"
:aliased-node-data="resolvedAliasedNodeData"
@update:aliased-node-data="onUpdateAliasedNodeData"
@initialized="emit('initialized', $event)"
/>
<RatingWidgetViewer
v-else-if="mode === VIEW"
:aliased-node-data="resolvedAliasedNodeData"
@initialized="emit('initialized', $event)"
/>
</template>
- Add the editor and viewer. Both emit
initializedon mount:
<!-- components/RatingWidgetEditor.vue -->
<script setup lang="ts">
import { onMounted } from "vue";
import Rating from "primevue/rating";
import { buildNumberAliasedNodeData } from "@/arches_component_lab/datatypes/number/utils.ts";
import type { NumberAliasedNodeData } from "@/arches_component_lab/datatypes/number/types.ts";
const { aliasedNodeData } = defineProps(["aliasedNodeData"]) as {
aliasedNodeData: NumberAliasedNodeData | null;
};
const emit = defineEmits(["update:aliasedNodeData", "initialized"]) as {
(event: "update:aliasedNodeData", updatedValue: NumberAliasedNodeData): void;
(event: "initialized", updatedValue: NumberAliasedNodeData): void;
};
onMounted(() => {
emit("initialized", aliasedNodeData ?? buildNumberAliasedNodeData(null));
});
function onUpdateModelValue(updatedValue: number | null) {
emit("update:aliasedNodeData", buildNumberAliasedNodeData(updatedValue));
}
</script>
<template>
<Rating
:model-value="aliasedNodeData?.node_value ?? null"
@update:model-value="onUpdateModelValue($event)"
/>
</template>
<!-- components/RatingWidgetViewer.vue -->
<script setup lang="ts">
import { onMounted } from "vue";
import type { NumberAliasedNodeData } from "@/arches_component_lab/datatypes/number/types.ts";
const { aliasedNodeData } = defineProps(["aliasedNodeData"]) as {
aliasedNodeData: NumberAliasedNodeData;
};
const emit = defineEmits(["initialized"]) as {
(event: "initialized", updatedValue: NumberAliasedNodeData): void;
};
onMounted(() => emit("initialized", aliasedNodeData));
</script>
<template>
<div>{{ aliasedNodeData?.display_value }}</div>
</template>
-
Reuse an existing datatype module (
@/arches_component_lab/datatypes— string, number, boolean, concept, domain, etc.) for the value shape, as above, or add a new one following the sametypes.ts+build<Datatype>AliasedNodeDatautils.tspattern. -
If contributing to Arches Component Lab, export it from
widgets/index.ts:
export { default as RatingWidget } from "@/arches_component_lab/widgets/RatingWidget/RatingWidget.vue";
export type { RatingWidgetProps } from "@/arches_component_lab/widgets/RatingWidget/types.ts";
- Register it — see Extending Arches Component Lab.
Extending Arches Component Lab
Arches Component Lab uses the WidgetMapping model to map widgets to their Vue components. To check for missing mappings:
python manage.py widget check_mappings
To add a mapping:
python manage.py widget add_mapping -wn language-select -cp arches_component_lab/widgets/LanguageSelectWidget/LanguageSelectWidget.vue
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file arches_component_lab-0.1.0.tar.gz.
File metadata
- Download URL: arches_component_lab-0.1.0.tar.gz
- Upload date:
- Size: 317.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f31341ea85039dd402f189ebaafe8d4915c059592d30302644954d5be5626919
|
|
| MD5 |
1ce7240bb2664a347feec7efada9ebb1
|
|
| BLAKE2b-256 |
443b91edcddc2abcbe07f92705669beaf519e230c258e482b9082363271043be
|
File details
Details for the file arches_component_lab-0.1.0-py3-none-any.whl.
File metadata
- Download URL: arches_component_lab-0.1.0-py3-none-any.whl
- Upload date:
- Size: 219.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
796d416aa232f3b64c30f505ea93e7a39a945937e8fb825c9d4f03fee9c48e07
|
|
| MD5 |
7742b21b7dce4b328d25d5f795c89bfd
|
|
| BLAKE2b-256 |
95773333a1315ab3c02051bca6438e887f012c1bc836a1734819622f0abfdbab
|