mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-25 08:05:00 +00:00
Add support for person identifiers workflow: update PersonEdit
component, API methods, and modals for identifier handling during person creation. Adjust related types for improved consistency.
This commit is contained in:
@@ -64,6 +64,8 @@ const props = withDefaults(defineProps<CreateComponentConfig>(), {
|
||||
action: "create",
|
||||
query: "",
|
||||
});
|
||||
|
||||
|
||||
const type = ref<CreatableEntityType | null>(null);
|
||||
|
||||
const radioType = computed<CreatableEntityType | null>({
|
||||
@@ -74,12 +76,14 @@ const radioType = computed<CreatableEntityType | null>({
|
||||
},
|
||||
});
|
||||
|
||||
type PersonEditComponent = InstanceType<typeof PersonEdit>;
|
||||
|
||||
type AnyComponentInstance =
|
||||
| InstanceType<typeof OnTheFlyPerson>
|
||||
| InstanceType<typeof OnTheFlyThirdparty>
|
||||
| null;
|
||||
|
||||
const castPerson = ref<AnyComponentInstance>(null);
|
||||
const castPerson = ref<PersonEditComponent>(null);
|
||||
const castThirdparty = ref<AnyComponentInstance>(null);
|
||||
|
||||
onMounted(() => {
|
||||
@@ -100,31 +104,13 @@ const containsPerson = computed<boolean>(() => {
|
||||
return props.allowedTypes.includes("person");
|
||||
});
|
||||
|
||||
// Types for data structures coming from child components are not declared in TS yet.
|
||||
// We conservatively type them as any to preserve runtime behavior while enabling TS in this component.
|
||||
function castDataByType(): any {
|
||||
switch (radioType.value) {
|
||||
case "person":
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return (castPerson.value as any)?.$data?.person;
|
||||
case "thirdparty": {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let data: any = (castThirdparty.value as any)?.$data?.thirdparty;
|
||||
if (data && data.address !== undefined && data.address !== null) {
|
||||
data.address = { id: data.address.address_id };
|
||||
} else if (data) {
|
||||
data.address = null;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
default:
|
||||
throw Error("Invalid type of entity");
|
||||
}
|
||||
function save(): void {
|
||||
castPerson.value.postPerson();
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
castDataByType,
|
||||
});
|
||||
defineExpose({save});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
|
@@ -2,11 +2,25 @@
|
||||
import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
|
||||
import Create from "ChillMainAssets/vuejs/OnTheFly/components/Create.vue";
|
||||
import { CreateComponentConfig } from "ChillMainAssets/types";
|
||||
import {trans, SAVE} from "translator";
|
||||
import {useTemplateRef} from "vue";
|
||||
|
||||
const emit = defineEmits<(e: "close") => void>();
|
||||
|
||||
const props = defineProps<CreateComponentConfig>();
|
||||
const modalDialogClass = { "modal-xl": true, "modal-scrollable": true };
|
||||
|
||||
type CreateComponentType = InstanceType<typeof Create>
|
||||
|
||||
const create = useTemplateRef<CreateComponentType>("create");
|
||||
|
||||
function save(): void {
|
||||
console.log('save from CreateModal');
|
||||
create.value?.save();
|
||||
}
|
||||
|
||||
defineExpose({save})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -22,12 +36,16 @@ const modalDialogClass = { "modal-xl": true, "modal-scrollable": true };
|
||||
<template #body-head>
|
||||
<div class="modal-body">
|
||||
<Create
|
||||
ref="create"
|
||||
:allowedTypes="props.allowedTypes"
|
||||
:action="props.action"
|
||||
:query="props.query"
|
||||
></Create>
|
||||
</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<button class="btn btn-save" type="button" @click.prevent="save">{{ trans(SAVE) }}</button>
|
||||
</template>
|
||||
</modal>
|
||||
</teleport>
|
||||
</template>
|
||||
|
@@ -18,9 +18,14 @@ import { Calendar } from "../../../ChillCalendarBundle/Resources/public/types";
|
||||
import Person from "./vuejs/_components/OnTheFly/Person.vue";
|
||||
|
||||
export interface AltName {
|
||||
label: TranslatableString;
|
||||
labels: TranslatableString;
|
||||
key: string;
|
||||
}
|
||||
|
||||
export interface AltNameWrite {
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
export interface Person {
|
||||
id: number;
|
||||
type: "person";
|
||||
@@ -44,14 +49,20 @@ export interface Person {
|
||||
current_residential_addresses: Address[];
|
||||
}
|
||||
|
||||
export interface PersonIdentifierWrite {
|
||||
type: "person_identifier";
|
||||
definition_id: number;
|
||||
value: object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Person representation to create or update a Person
|
||||
*/
|
||||
export interface PersonEdit {
|
||||
export interface PersonWrite {
|
||||
type: "person";
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
altNames: AltName[];
|
||||
altNames: AltNameWrite[];
|
||||
// address: number | null;
|
||||
birthdate: DateTimeCreate | null;
|
||||
deathdate: DateTimeCreate | null;
|
||||
@@ -61,6 +72,7 @@ export interface PersonEdit {
|
||||
gender: SetGender | null;
|
||||
center: SetCenter | null;
|
||||
civility: SetCivility | null;
|
||||
identifiers: PersonIdentifierWrite[];
|
||||
}
|
||||
|
||||
export interface AccompanyingPeriod {
|
||||
@@ -408,6 +420,14 @@ export interface SearchOptions {
|
||||
};
|
||||
}
|
||||
|
||||
export interface PersonIdentifierWorker {
|
||||
type: "person_identifier_worker";
|
||||
definition_id: number;
|
||||
engine: string;
|
||||
label: TranslatableString;
|
||||
isActive: boolean;
|
||||
}
|
||||
|
||||
export class MakeFetchException extends Error {
|
||||
sta: number;
|
||||
txt: string;
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import { fetchResults, makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
||||
import { Center, Civility, Gender } from "ChillMainAssets/types";
|
||||
import { AltName, Person } from "ChillPersonAssets/types";
|
||||
import {AltName, Person, PersonIdentifierWorker, PersonWrite} from "ChillPersonAssets/types";
|
||||
import person from "ChillPersonAssets/vuejs/_components/OnTheFly/Person.vue";
|
||||
|
||||
/*
|
||||
* GET a person by id
|
||||
@@ -31,3 +32,10 @@ export const getGenders = async (): Promise<Gender[]> =>
|
||||
|
||||
export const getCentersForPersonCreation = async (): Promise<{showCenters: boolean; centers: Center[];}> =>
|
||||
makeFetch("GET", "/api/1.0/person/creation/authorized-centers", null);
|
||||
|
||||
export const getPersonIdentifiers = async (): Promise<PersonIdentifierWorker[]> =>
|
||||
fetchResults("/api/1.0/person/identifiers/workers");
|
||||
|
||||
export const createPerson = async (person: PersonWrite): Promise<Person> => {
|
||||
return makeFetch("POST", "/api/1.0/person/person.json", person);
|
||||
}
|
||||
|
@@ -35,7 +35,7 @@ const { person, isCut = false, addAge = true } = toRefs(props);
|
||||
|
||||
const altNameLabel = computed(() => {
|
||||
if (!person.value.altNames) return "";
|
||||
return person.value.altNames.map((a: AltName) => a.label).join("");
|
||||
return person.value.altNames.map((a: AltName) => a.labels).join("");
|
||||
});
|
||||
|
||||
const altNameKey = computed(() => {
|
||||
|
@@ -56,10 +56,26 @@
|
||||
<input
|
||||
class="form-control form-control-lg"
|
||||
:id="a.key"
|
||||
:value="personAltNamesLabels[i]"
|
||||
@input="onAltNameInput"
|
||||
:name="'label_'+a.key"
|
||||
value=""
|
||||
@input="onAltNameInput($event, a.key)"
|
||||
/>
|
||||
<label :for="a.key">{{ localizeString(a.labels) }}</label>
|
||||
<label :for="'label_'+a.key">{{ localizeString(a.labels) }}</label>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-for="worker in config.identifiers"
|
||||
:key="worker.definition_id"
|
||||
class="form-floating mb-3"
|
||||
>
|
||||
<input
|
||||
class="form-control form-control-lg"
|
||||
type="text"
|
||||
:name="'worker_'+worker.definition_id"
|
||||
:placeholder="localizeString(worker.label)"
|
||||
@input="onIdentifierInput($event, worker.definition_id)"
|
||||
/>
|
||||
<label :for="'worker_'+worker.definition_id">{{ localizeString(worker.label) }}</label>
|
||||
</div>
|
||||
|
||||
<div class="form-floating mb-3">
|
||||
@@ -181,11 +197,12 @@ import { ref, reactive, computed, onMounted } from "vue";
|
||||
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
|
||||
import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue";
|
||||
import {
|
||||
createPerson,
|
||||
getCentersForPersonCreation,
|
||||
getCivilities,
|
||||
getGenders,
|
||||
getPerson,
|
||||
getPersonAltNames,
|
||||
getPersonAltNames, getPersonIdentifiers,
|
||||
} from "../../_api/OnTheFly";
|
||||
import {
|
||||
trans,
|
||||
@@ -209,7 +226,14 @@ import {
|
||||
Gender,
|
||||
DateTimeCreate,
|
||||
} from "ChillMainAssets/types";
|
||||
import {AltName, PersonEdit} from "ChillPersonAssets/types";
|
||||
import {
|
||||
AltName,
|
||||
Person,
|
||||
PersonWrite,
|
||||
PersonIdentifierWorker,
|
||||
type Suggestion,
|
||||
type EntitiesOrMe
|
||||
} from "ChillPersonAssets/types";
|
||||
|
||||
|
||||
interface PersonEditComponentConfig {
|
||||
@@ -224,7 +248,13 @@ const props = withDefaults(defineProps<PersonEditComponentConfig>(), {
|
||||
type: "TODO",
|
||||
});
|
||||
|
||||
const person = reactive<PersonEdit>({
|
||||
const emit = defineEmits<{
|
||||
(e: "onPersonCreated", payload: { person: Person }): void;
|
||||
}>();
|
||||
|
||||
defineExpose({postPerson});
|
||||
|
||||
const person = reactive<PersonWrite>({
|
||||
type: "person",
|
||||
firstName: "",
|
||||
lastName: "",
|
||||
@@ -238,6 +268,7 @@ const person = reactive<PersonEdit>({
|
||||
gender: null,
|
||||
center: null,
|
||||
civility: null,
|
||||
identifiers: [],
|
||||
});
|
||||
|
||||
const config = reactive<{
|
||||
@@ -245,11 +276,13 @@ const config = reactive<{
|
||||
civilities: Civility[];
|
||||
centers: Center[];
|
||||
genders: Gender[];
|
||||
identifiers: PersonIdentifierWorker[];
|
||||
}>({
|
||||
altNames: [],
|
||||
civilities: [],
|
||||
centers: [],
|
||||
genders: [],
|
||||
identifiers: [],
|
||||
});
|
||||
|
||||
const showCenters = ref(false);
|
||||
@@ -350,9 +383,9 @@ const center = computed({
|
||||
},
|
||||
});
|
||||
|
||||
const personAltNamesLabels = computed(() =>
|
||||
person.altNames.map((a) => (a ? a.label : "")),
|
||||
);
|
||||
/**
|
||||
* Find the query items to display for suggestion
|
||||
*/
|
||||
const queryItems = computed(() => {
|
||||
const words: null|string[] = props.query ? props.query.split(" ") : null;
|
||||
|
||||
@@ -387,21 +420,30 @@ function checkErrors() {
|
||||
async function loadData() {
|
||||
if (props.id !== undefined && props.id !== null) {
|
||||
const person = await getPerson(props.id);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
function onAltNameInput(event: Event) {
|
||||
|
||||
function onAltNameInput(event: Event, key: string): void {
|
||||
const target = event.target as HTMLInputElement;
|
||||
const key = target.id;
|
||||
const label = target.value;
|
||||
const updateAltNames = person.altNames.filter((a) => a.key !== key);
|
||||
updateAltNames.push({ key, label });
|
||||
person.altNames = updateAltNames;
|
||||
const value = target.value;
|
||||
const updateAltNamesKey = person.altNames.findIndex((a) => a.key === key);
|
||||
if (-1 === updateAltNamesKey) {
|
||||
person.altNames.push({key, value})
|
||||
} else {
|
||||
person.altNames[updateAltNamesKey].value = value;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
function onIdentifierInput(event: Event, definition_id: number): void {
|
||||
const target = event.target as HTMLInputElement;
|
||||
const value = target.value;
|
||||
const updateIdentifierKey = person.identifiers.findIndex((w) => w.definition_id === definition_id);
|
||||
if (-1 === updateIdentifierKey) {
|
||||
person.identifiers.push({type: "person_identifier", definition_id, value: { content: value }})
|
||||
} else {
|
||||
person.identifiers[updateIdentifierKey].value = {content: value}
|
||||
}
|
||||
}
|
||||
|
||||
function addQueryItem(field: "lastName" | "firstName", queryItem: string) {
|
||||
switch (field) {
|
||||
@@ -422,6 +464,13 @@ function submitNewAddress(payload: { addressId: number }) {
|
||||
// person.addressId = payload.addressId;
|
||||
}
|
||||
|
||||
async function postPerson(): Promise<void> {
|
||||
console.log('postPerson');
|
||||
const createdPerson = await createPerson(person);
|
||||
|
||||
emit('onPersonCreated', {person: createdPerson});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getPersonAltNames().then((altNames) => {
|
||||
config.altNames = altNames;
|
||||
@@ -432,6 +481,9 @@ onMounted(() => {
|
||||
getGenders().then((genders) => {
|
||||
config.genders = genders;
|
||||
});
|
||||
getPersonIdentifiers().then((identifiers) => {
|
||||
config.identifiers = identifiers;
|
||||
});
|
||||
if (props.action !== "create") {
|
||||
loadData();
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user