Skip to content

Commit

Permalink
Adds note editor (#177)
Browse files Browse the repository at this point in the history
  • Loading branch information
aarongundel committed Jan 9, 2025
1 parent 510f59c commit a82fcad
Show file tree
Hide file tree
Showing 4 changed files with 285 additions and 4 deletions.
27 changes: 26 additions & 1 deletion arches_lingo/src/arches_lingo/api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import arches from "arches";
import Cookies from "js-cookie";
import type { AppellativeStatus, SchemeInstance } from "@/arches_lingo/types";
import type {
AppellativeStatus,
SchemeInstance,
SchemeStatement,
} from "@/arches_lingo/types";

function getToken() {
const token = Cookies.get("csrftoken");
Expand Down Expand Up @@ -148,6 +152,27 @@ export const fetchSchemeNotes = async (schemeId: string) => {
return parsed;
};

export const updateSchemeNote = async (
schemeId: string,
tileId: string,
schemeStatement: SchemeStatement,
) => {
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 parsed = await response.json();
if (!response.ok) throw new Error(parsed.message || response.statusText);
return parsed;
};

export const deleteSchemeNoteTile = async (
schemeId: string,
tileId: string,
Expand Down
243 changes: 243 additions & 0 deletions arches_lingo/src/arches_lingo/components/generic/NoteEditor.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
<script setup lang="ts">
import { computed, inject, onMounted, ref, toRaw, toRef, type Ref } from "vue";
import Button from "primevue/button";
import { useGettext } from "vue3-gettext";
import { useRoute } from "vue-router";
import { useToast } from "primevue/usetoast";
import {
fetchControlledListOptions,
fetchGroupRdmSystemList,
fetchPersonRdmSystemList,
fetchTextualWorkRdmSystemList,
updateSchemeNote,
} from "@/arches_lingo/api.ts";
import DateDatatype from "@/arches_lingo/components/generic/DateDatatype.vue";
import NonLocalizedString from "@/arches_lingo/components/generic/NonLocalizedString.vue";
import ReferenceDatatype from "@/arches_lingo/components/generic/ReferenceDatatype.vue";
import ResourceInstanceRelationships from "@/arches_lingo/components/generic/ResourceInstanceRelationships.vue";
import {
EDIT,
ERROR,
EVENT_TYPES_CONTROLLED_LIST,
LABEL_CONTROLLED_LIST,
LANGUAGE_CONTROLLED_LIST,
METATYPES_CONTROLLED_LIST,
selectedLanguageKey,
STATUSES_CONTROLLED_LIST,
} from "@/arches_lingo/constants.ts";
import type {
ControlledListItem,
ControlledListItemResult,
ResourceInstanceReference,
ResourceInstanceResult,
SchemeStatement,
} from "@/arches_lingo/types.ts";
import type { Language } from "@/arches_vue_utils/types.ts";
const emit = defineEmits(["update"]);
const toast = useToast();
const route = useRoute();
const selectedLanguage = inject(selectedLanguageKey) as Ref<Language>;
const { $gettext } = useGettext();
const props = withDefaults(
defineProps<{
value?: SchemeStatement;
}>(),
{
value: () => ({}) as SchemeStatement,
},
);
const valueRef = toRef(props, "value");
const formValue = computed({
get: () => valueRef.value,
set: (newVal: SchemeStatement) => {
valueRef.value = newVal;
},
});
const languageOptions = ref<ControlledListItem[]>([]);
const typeOptions = ref<ControlledListItem[]>([]);
const statusOptions = ref<ControlledListItem[]>([]);
const metatypeOptions = ref<ControlledListItem[]>([]);
const eventTypeOptions = ref<ControlledListItem[]>([]);
const groupAndPersonOptions = ref<ResourceInstanceReference[]>();
const textualWorkOptions = ref<ResourceInstanceReference[]>();
function onUpdate(
node: keyof SchemeStatement,
val: ControlledListItem[] | ResourceInstanceReference[] | string,
) {
if (Array.isArray(val)) {
(formValue.value[node] as unknown) = val.map((item) => toRaw(item));
} else {
(formValue.value[node] as unknown) = toRaw(val);
}
}
async function save() {
try {
await updateSchemeNote(
route.params.id as string,
formValue.value.tileid as string,
formValue.value,
);
emit("update");
} catch (error) {
toast.add({
severity: ERROR,
summary: $gettext("Error saving scheme"),
detail: (error as Error).message,
});
}
}
async function getControlledListOptions(
listId: string,
): Promise<ControlledListItem[]> {
const parsed = await fetchControlledListOptions(listId);
const options = parsed.items.map(
(item: ControlledListItemResult): ControlledListItem => ({
list_id: item.list_id,
uri: item.uri,
labels: item.values,
}),
);
return options;
}
async function getResourceInstanceOptions(
fetchOptions: () => Promise<ResourceInstanceResult[]>,
): Promise<ResourceInstanceReference[]> {
const options = await fetchOptions();
const results = options.map((option: ResourceInstanceResult) => {
const result: ResourceInstanceReference = {
display_value: option.descriptors[selectedLanguage.value.code].name,
resourceId: option.resourceinstanceid,
ontologyProperty: "ac41d9be-79db-4256-b368-2f4559cfbe55",
inverseOntologyProperty: "ac41d9be-79db-4256-b368-2f4559cfbe55",
};
return result;
});
return results;
}
onMounted(async () => {
const [languageOpts, typeOpts, statusOpts, metatypeOpts, eventTypeOpts] =
await Promise.all([
getControlledListOptions(LANGUAGE_CONTROLLED_LIST),
getControlledListOptions(LABEL_CONTROLLED_LIST),
getControlledListOptions(STATUSES_CONTROLLED_LIST),
getControlledListOptions(METATYPES_CONTROLLED_LIST),
getControlledListOptions(EVENT_TYPES_CONTROLLED_LIST),
]);
languageOptions.value = languageOpts;
typeOptions.value = typeOpts;
statusOptions.value = statusOpts;
metatypeOptions.value = metatypeOpts;
eventTypeOptions.value = eventTypeOpts;
groupAndPersonOptions.value = await getResourceInstanceOptions(
fetchGroupRdmSystemList,
);
groupAndPersonOptions.value = [
...(groupAndPersonOptions.value || []),
...(await getResourceInstanceOptions(fetchPersonRdmSystemList)),
];
textualWorkOptions.value = await getResourceInstanceOptions(
fetchTextualWorkRdmSystemList,
);
});
</script>

<template>
<!-- Statement: string -->
<label for="">{{ $gettext("Statement") }}</label>
<NonLocalizedString
:value="value?.statement_content_n1 ?? ''"
:mode="EDIT"
@update="(val) => onUpdate('statement_content_n1', val)"
/>
<!-- Statement Language: reference datatype -->
<label for="">{{ $gettext("Statement Language") }}</label>
<ReferenceDatatype
:value="value?.statement_language_n1"
:mode="EDIT"
:multi-value="false"
:options="languageOptions"
@update="(val) => onUpdate('statement_language_n1', val)"
/>
<!-- Statement Type: reference datatype -->
<label for="">{{ $gettext("Statement Type") }}</label>
<ReferenceDatatype
:value="value?.statement_type_n1"
:mode="EDIT"
:multi-value="false"
:options="typeOptions"
@update="(val) => onUpdate('statement_type_n1', val)"
/>

<!-- Statement Status Metatype: reference datatype -->
<label for="">{{ $gettext("Statement Metatype") }}</label>
<ReferenceDatatype
:value="value?.statement_type_metatype_n1"
:mode="EDIT"
:multi-value="false"
:options="metatypeOptions"
@update="(val) => onUpdate('statement_type_metatype_n1', val)"
/>

<!-- Statement Temporal Validity Start: date -->
<label for="">{{ $gettext("Label Temporal Validity Start") }}</label>
<DateDatatype
:value="value?.statement_data_assignment_timespan_begin_of_the_begin"
:mode="EDIT"
@update="onUpdate"
/>

<!-- Statement Temporal Validity End: date -->
<label for="">{{ $gettext("Label Temporal Validity End") }}</label>
<DateDatatype
:value="value?.statement_data_assignment_timespan_end_of_the_end"
:mode="EDIT"
@update="onUpdate"
/>

<!-- Contributor: resource instance -->
<label for="">{{ $gettext("Contributor") }}</label>
<ResourceInstanceRelationships
:value="value?.statement_data_assignment_actor"
:mode="EDIT"
:options="groupAndPersonOptions"
@update="(val) => onUpdate('statement_data_assignment_actor', val)"
/>
<!-- Sources: resource instance -->
<label for="">{{ $gettext("Sources") }}</label>
<ResourceInstanceRelationships
:value="value?.statement_data_assignment_object_used"
:mode="EDIT"
:options="textualWorkOptions"
@update="
(val) => onUpdate('statement_data_assignment_object_used', val)
"
/>
<!-- Warrant Type: reference datatype -->
<label for="">{{ $gettext("Warrant Type") }}</label>
<ReferenceDatatype
:value="value?.statement_data_assignment_type"
:mode="EDIT"
:multi-value="false"
:options="eventTypeOptions"
@update="(val) => onUpdate('statement_data_assignment_type', val)"
/>
<Button
:label="$gettext('Update')"
@click="save"
></Button>
</template>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { computed, onMounted, ref } from "vue";
import { useGettext } from "vue3-gettext";
import { useRoute } from "vue-router";
import { useToast } from "primevue/usetoast";
Expand All @@ -13,6 +13,7 @@ import {
VIEW,
EDIT,
} from "@/arches_lingo/constants.ts";
import NoteEditor from "@/arches_lingo/components/generic/NoteEditor.vue";
import type {
DataComponentMode,
MetaStringText,
Expand All @@ -34,7 +35,7 @@ const metaStringLabel: MetaStringText = {
noRecords: $gettext("No scheme notes were found."),
};
withDefaults(
const props = withDefaults(
defineProps<{
mode?: DataComponentMode;
tileId?: string | null;
Expand All @@ -53,6 +54,12 @@ onMounted(() => {
getSectionValue();
});
const selectedNote = computed(() => {
return schemeInstance.value?.statement?.find(
(tile) => tile.tileid === props.tileId,
);
});
async function getSectionValue() {
if (route.params.id === NEW) {
return;
Expand Down Expand Up @@ -165,5 +172,7 @@ function editSectionValue(tileId: string) {
</MetaStringViewer>
</SchemeReportSection>
</div>
<div v-if="mode === EDIT"></div>
<div v-if="mode === EDIT">
<NoteEditor :value="selectedNote" />
</div>
</template>
4 changes: 4 additions & 0 deletions arches_lingo/src/arches_lingo/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,12 @@ export interface SchemeStatement {
statement_content_n1: string;
statement_language_n1?: ControlledListItem[];
statement_type_n1?: ControlledListItem[];
statement_type_metatype_n1?: ControlledListItem[];
statement_data_assignment_object_used: ResourceInstanceReference[];
statement_data_assignment_actor: ResourceInstanceReference[];
statement_data_assignment_type: ControlledListItem[];
statement_data_assignment_timespan_begin_of_the_begin: string;
statement_data_assignment_timespan_end_of_the_end: string;
}

export interface SchemeInstance {
Expand Down

0 comments on commit a82fcad

Please sign in to comment.