Apply prettier rules

This commit is contained in:
2024-11-14 18:47:38 +01:00
parent 610227815a
commit aa0785fc71
291 changed files with 23646 additions and 22071 deletions

View File

@@ -1,7 +1,7 @@
//still used ?
//require('./css/person.css');
require('./chillperson.scss');
require("./chillperson.scss");
require('./svg/phone-alt-solid.svg');
require('./svg/mobile-alt-solid.svg');
require("./svg/phone-alt-solid.svg");
require("./svg/mobile-alt-solid.svg");

View File

@@ -1,10 +1,8 @@
import { fetchResults } from 'ChillMainAssets/lib/api/apiMethods.ts';
import { fetchResults } from "ChillMainAssets/lib/api/apiMethods.ts";
const fetchHouseholdByAddressReference = async (reference) => {
const url = `/api/1.0/person/household/by-address-reference/${reference.id}.json`
const url = `/api/1.0/person/household/by-address-reference/${reference.id}.json`;
return fetchResults(url);
};
export {
fetchHouseholdByAddressReference
};
export { fetchHouseholdByAddressReference };

View File

@@ -1,6 +1,6 @@
import {createApp} from 'vue';
import SetReferrer from 'ChillPersonAssets/vuejs/_components/AccompanyingPeriod/SetReferrer.vue';
import {fetchResults} from 'ChillMainAssets/lib/api/apiMethods.ts';
import { createApp } from "vue";
import SetReferrer from "ChillPersonAssets/vuejs/_components/AccompanyingPeriod/SetReferrer.vue";
import { fetchResults } from "ChillMainAssets/lib/api/apiMethods.ts";
/**
*
@@ -18,13 +18,15 @@ import {fetchResults} from 'ChillMainAssets/lib/api/apiMethods.ts';
* The app will update the referrer displayed into dedicated span
*/
document.querySelectorAll('[data-set-referrer-app]').forEach(function (el) {
document.querySelectorAll("[data-set-referrer-app]").forEach(function (el) {
const periodId = Number.parseInt(el.dataset.setReferrerAccompanyingPeriodId);
const jobId = Number.parseInt(el.dataset.setReferrerJobId);
const url = `/api/1.0/person/accompanying-course/${periodId}/referrers-suggested.json`;
fetchResults(url).then(suggested => {
const filteredSuggested = suggested.filter((s) => s.user_job ? s.user_job.id === jobId : false);
fetchResults(url).then((suggested) => {
const filteredSuggested = suggested.filter((s) =>
s.user_job ? s.user_job.id === jobId : false,
);
const app = createApp({
components: {
SetReferrer,
@@ -33,34 +35,38 @@ document.querySelectorAll('[data-set-referrer-app]').forEach(function (el) {
'<set-referrer :suggested="filteredSuggested" :periodId="periodId" @referrerSet="onReferrerSet"></set-referrer>',
data() {
return {
periodId, filteredSuggested, original: filteredSuggested,
}
periodId,
filteredSuggested,
original: filteredSuggested,
};
},
methods: {
onReferrerSet(ref) {
const bloc = document.querySelector(`[data-accompanying-period-id="${this.periodId}"]`);
const bloc = document.querySelector(
`[data-accompanying-period-id="${this.periodId}"]`,
);
if (bloc === null) {
console.error('bloc not found');
console.error("bloc not found");
return;
}
const label = bloc.querySelector('[data-referrer-text]');
const label = bloc.querySelector("[data-referrer-text]");
if (label === null) {
console.error('label not found');
console.error("label not found");
return;
}
label.textContent = ref.text;
label.classList.remove('chill-no-data-statement');
label.classList.remove("chill-no-data-statement");
this.filteredSuggested = this.original.filter(user => user.id !== ref.id);
}
}
this.filteredSuggested = this.original.filter(
(user) => user.id !== ref.id,
);
},
},
});
app.mount(el);
})
})
});
});

View File

@@ -1,6 +1,6 @@
import Masonry from 'masonry-layout/masonry';
import Masonry from "masonry-layout/masonry";
let elem = document.querySelector('#dashboards');
let msnry = new Masonry( elem, {
// options
let elem = document.querySelector("#dashboards");
let msnry = new Masonry(elem, {
// options
});

View File

@@ -1,49 +1,47 @@
const onSubmit = function(e) {
e.preventDefault();
let
form = e.target,
formData = new FormData(form),
url = form.action,
payload = {
type: 'accompanying_period',
id: Number.parseInt(formData.get('periodId'), 10),
personLocation: {
type: 'person',
id: Number.parseInt(formData.get('personLocation'), 10)
}
}
;
const onSubmit = function (e) {
e.preventDefault();
let form = e.target,
formData = new FormData(form),
url = form.action,
payload = {
type: "accompanying_period",
id: Number.parseInt(formData.get("periodId"), 10),
personLocation: {
type: "person",
id: Number.parseInt(formData.get("personLocation"), 10),
},
};
console.log("event", e);
console.log("form", form);
console.log("formData", formData);
console.log("url", url);
console.log("payload", payload);
console.log('event', e);
console.log('form', form);
console.log('formData', formData);
console.log('url', url);
console.log('payload', payload);
window.fetch(url, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload),
window
.fetch(url, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
})
.then(r => {
if (r.ok) {
console.log('response ok');
window.location.reload();
} else {
console.err("could not patch accompanying course");
}
});
}
.then((r) => {
if (r.ok) {
console.log("response ok");
window.location.reload();
} else {
console.err("could not patch accompanying course");
}
});
};
window.addEventListener('DOMContentLoaded', function() {
let forms = document.querySelectorAll('.quickLocationForm');
window.addEventListener("DOMContentLoaded", function () {
let forms = document.querySelectorAll(".quickLocationForm");
console.log(forms);
forms.forEach(function(form){
console.log('form quickLocation found', form);
form.addEventListener('submit', onSubmit);
})
forms.forEach(function (form) {
console.log("form quickLocation found", form);
form.addEventListener("submit", onSubmit);
});
});

View File

@@ -1,25 +1,22 @@
import { ShowHide } from 'ShowHide';
import { ShowHide } from "ShowHide";
let
k = document.getElementById('waitingForBirthContainer'),
waitingForBirthDate = document.getElementById('waitingForBirthDateContainer')
;
let k = document.getElementById("waitingForBirthContainer"),
waitingForBirthDate = document.getElementById("waitingForBirthDateContainer");
console.log(k);
console.log(k );
new ShowHide({
'container': [waitingForBirthDate],
'froms': [k ],
'event_name': 'input',
'debug': true,
'test': function(froms) {
for (let f of froms.values()) {
console.log(f);
for (let input of f.querySelectorAll('input').values()) {
return input.checked;
}
new ShowHide({
container: [waitingForBirthDate],
froms: [k],
event_name: "input",
debug: true,
test: function (froms) {
for (let f of froms.values()) {
console.log(f);
for (let input of f.querySelectorAll("input").values()) {
return input.checked;
}
return false;
}
});
return false;
},
});

View File

@@ -1,18 +1,18 @@
import { ShowHide } from 'ShowHide';
import { ShowHide } from "ShowHide";
const addressForm = document.getElementById("addressForm");
const address = document.getElementById("address");
new ShowHide({
froms: [addressForm],
container: [address],
test: function(froms) {
for (let f of froms.values()) {
for (let input of f.querySelectorAll('input').values()) {
return input.checked;
}
}
return false;
},
event_name: 'change'
froms: [addressForm],
container: [address],
test: function (froms) {
for (let f of froms.values()) {
for (let input of f.querySelectorAll("input").values()) {
return input.checked;
}
}
return false;
},
event_name: "change",
});

View File

@@ -1,4 +1,4 @@
import { ShowHide } from 'ShowHide';
import { ShowHide } from "ShowHide";
const maritalStatus = document.getElementById("maritalStatus");
const maritalStatusDate = document.getElementById("maritalStatusDate");
@@ -8,52 +8,51 @@ const personPhoneNumber = document.getElementById("personPhoneNumber");
const personAcceptSMS = document.getElementById("personAcceptSMS");
new ShowHide({
froms: [maritalStatus],
container: [maritalStatusDate],
test: function(froms) {
for (let f of froms.values()) {
for (let input of f.querySelectorAll('select').values()) {
if (input.value) {
return true
}
}
froms: [maritalStatus],
container: [maritalStatusDate],
test: function (froms) {
for (let f of froms.values()) {
for (let input of f.querySelectorAll("select").values()) {
if (input.value) {
return true;
}
return false;
},
event_name: 'change'
}
}
return false;
},
event_name: "change",
});
if (personAcceptEmail) {
new ShowHide({
froms: [personEmail],
container: [personAcceptEmail],
test: function(froms) {
for (let f of froms.values()) {
for (let input of f.querySelectorAll('input').values()) {
if (input.value) {
return true
}
}
}
return false;
},
event_name: 'input'
});
new ShowHide({
froms: [personEmail],
container: [personAcceptEmail],
test: function (froms) {
for (let f of froms.values()) {
for (let input of f.querySelectorAll("input").values()) {
if (input.value) {
return true;
}
}
}
return false;
},
event_name: "input",
});
}
new ShowHide({
froms: [personPhoneNumber],
container: [personAcceptSMS],
test: function(froms) {
for (let f of froms.values()) {
for (let input of f.querySelectorAll('input').values()) {
if (input.value) {
return true
}
}
froms: [personPhoneNumber],
container: [personAcceptSMS],
test: function (froms) {
for (let f of froms.values()) {
for (let input of f.querySelectorAll("input").values()) {
if (input.value) {
return true;
}
return false;
},
event_name: 'input'
}
}
return false;
},
event_name: "input",
});

View File

@@ -1,61 +1,76 @@
function capitalizeFirstLetter(string) {
return string.charAt(0).toLocaleUpperCase() + string.slice(1);
return string.charAt(0).toLocaleUpperCase() + string.slice(1);
}
window.addEventListener('DOMContentLoaded', function() {
const uri = decodeURI(location.hash.substring(1))
let searchFragments = uri.split(' ')
searchFragments = searchFragments.filter((el) => {
if ( ( el.startsWith("firstname") || el.startsWith("lastname") ) || (el !== '' && !el.startsWith('birthdate') && !el.startsWith('gender') && !el.startsWith('city') && !el.startsWith('phonenumber') && !el.startsWith('@'))) {
return el
}
})
searchFragments = searchFragments.map((el) => {
if (el.startsWith("firstname")) {
return el.slice(10)
} else if (el.startsWith("lastname")) {
return el.slice(10)
}
return el.replace('\"', '')
})
if (searchFragments) {
const pre = '<ul class="list-suggest add-items inline">';
const after = '</ul>';
document.querySelectorAll('[data-suggest-container]').forEach(function(container) {
const suggestions = searchFragments.map((el) => `<li class="suggest-item-name"><span data-suggest-target="${container.dataset.suggestContainer}">${capitalizeFirstLetter(el)}</span></li>`);
container.innerHTML = pre + suggestions.join(' ') + after;
})
window.addEventListener("DOMContentLoaded", function () {
const uri = decodeURI(location.hash.substring(1));
let searchFragments = uri.split(" ");
searchFragments = searchFragments.filter((el) => {
if (
el.startsWith("firstname") ||
el.startsWith("lastname") ||
(el !== "" &&
!el.startsWith("birthdate") &&
!el.startsWith("gender") &&
!el.startsWith("city") &&
!el.startsWith("phonenumber") &&
!el.startsWith("@"))
) {
return el;
}
});
const tags = document.querySelectorAll('[data-suggest-target]').forEach((tag) => {
tag.addEventListener('click', function(e) {
const field = document.querySelector(`[name="${e.target.dataset.suggestTarget}"]`);
let suggestion = e.target.textContent.trim();
switch (field.dataset.suggestTransform) {
case 'uppercase_all':
suggestion = suggestion.toLocaleUpperCase();
break;
case 'uppercase_first_letter':
default:
suggestion = capitalizeFirstLetter(suggestion);
}
searchFragments = searchFragments.map((el) => {
if (el.startsWith("firstname")) {
return el.slice(10);
} else if (el.startsWith("lastname")) {
return el.slice(10);
}
return el.replace('"', "");
});
if (field.value === '') {
field.value = suggestion;
} else {
field.value = `${field.value} ${suggestion}`
}
e.target.style.display = "none";
if (searchFragments) {
const pre = '<ul class="list-suggest add-items inline">';
const after = "</ul>";
[...document.querySelectorAll("[data-suggest-target]")]
.filter(p => p.textContent.includes(e.target.textContent))
.forEach(p => p.remove());
})
})
document
.querySelectorAll("[data-suggest-container]")
.forEach(function (container) {
const suggestions = searchFragments.map(
(el) =>
`<li class="suggest-item-name"><span data-suggest-target="${container.dataset.suggestContainer}">${capitalizeFirstLetter(el)}</span></li>`,
);
container.innerHTML = pre + suggestions.join(" ") + after;
});
}
})
const tags = document
.querySelectorAll("[data-suggest-target]")
.forEach((tag) => {
tag.addEventListener("click", function (e) {
const field = document.querySelector(
`[name="${e.target.dataset.suggestTarget}"]`,
);
let suggestion = e.target.textContent.trim();
switch (field.dataset.suggestTransform) {
case "uppercase_all":
suggestion = suggestion.toLocaleUpperCase();
break;
case "uppercase_first_letter":
default:
suggestion = capitalizeFirstLetter(suggestion);
}
if (field.value === "") {
field.value = suggestion;
} else {
field.value = `${field.value} ${suggestion}`;
}
e.target.style.display = "none";
[...document.querySelectorAll("[data-suggest-target]")]
.filter((p) => p.textContent.includes(e.target.textContent))
.forEach((p) => p.remove());
});
});
});

View File

@@ -1,55 +1,53 @@
import {ShowHide} from 'ChillMainAssets/lib/show_hide/show_hide.js';
import { ShowHide } from "ChillMainAssets/lib/show_hide/show_hide.js";
window.addEventListener('DOMContentLoaded', function() {
let
personContainer = document.querySelector('#person-entity'),
entitySelector = document.querySelector('#entity-selector'),
freetextContainer = document.querySelector('#freetext-entity'),
thirdpartyContainer = document.querySelector('#thirdparty-entity')
;
if (null === entitySelector) {
return;
}
window.addEventListener("DOMContentLoaded", function () {
let personContainer = document.querySelector("#person-entity"),
entitySelector = document.querySelector("#entity-selector"),
freetextContainer = document.querySelector("#freetext-entity"),
thirdpartyContainer = document.querySelector("#thirdparty-entity");
if (null === entitySelector) {
return;
}
new ShowHide({
debug: false,
load_event: null,
froms: [entitySelector],
container: [personContainer],
test: function(froms) {
for (let container of froms) {
return container.querySelector('input[value="person"]').checked;
}
console.log('we couldnt find the input');
return false;
},
})
new ShowHide({
debug: false,
load_event: null,
froms: [entitySelector],
container: [personContainer],
test: function (froms) {
for (let container of froms) {
return container.querySelector('input[value="person"]').checked;
}
console.log("we couldnt find the input");
return false;
},
});
new ShowHide({
debug: false,
load_event: null,
froms: [entitySelector],
container: [thirdpartyContainer],
test: function(froms) {
for (let container of froms) {
return container.querySelector('input[value="thirdparty"]').checked;
}
console.log('we couldnt find the input');
return false;
},
})
new ShowHide({
debug: false,
load_event: null,
froms: [entitySelector],
container: [thirdpartyContainer],
test: function (froms) {
for (let container of froms) {
return container.querySelector('input[value="thirdparty"]').checked;
}
console.log("we couldnt find the input");
return false;
},
});
new ShowHide({
debug: false,
load_event: null,
froms: [entitySelector],
container: [freetextContainer],
test: function(froms) {
for (let container of froms) {
return container.querySelector('input[value="freetext"]').checked;
}
console.log('we couldnt find the input');
return false;
},
})
new ShowHide({
debug: false,
load_event: null,
froms: [entitySelector],
container: [freetextContainer],
test: function (froms) {
for (let container of froms) {
return container.querySelector('input[value="freetext"]').checked;
}
console.log("we couldnt find the input");
return false;
},
});
});

View File

@@ -1,22 +1,27 @@
import {Address, Center, Civility, DateTime} from "../../../ChillMainBundle/Resources/public/types";
import {
Address,
Center,
Civility,
DateTime,
} from "../../../ChillMainBundle/Resources/public/types";
export interface Person {
id: number;
type: "person";
text: string;
textAge: string;
firstName: string;
lastName: string;
current_household_address: Address | null;
birthdate: DateTime | null;
deathdate: DateTime | null;
age: number;
phonenumber: string;
mobilenumber: string;
email: string;
gender: "woman" | "man" | "other";
centers: Center[];
civility: Civility | null;
current_household_id: number;
current_residential_addresses: Address[];
id: number;
type: "person";
text: string;
textAge: string;
firstName: string;
lastName: string;
current_household_address: Address | null;
birthdate: DateTime | null;
deathdate: DateTime | null;
age: number;
phonenumber: string;
mobilenumber: string;
email: string;
gender: "woman" | "man" | "other";
centers: Center[];
civility: Civility | null;
current_household_id: number;
current_residential_addresses: Address[];
}

View File

@@ -3,10 +3,10 @@
<sticky-nav />
<h1 v-if="accompanyingCourse.step === 'DRAFT'">
{{ $t('course.title.draft') }}
{{ $t("course.title.draft") }}
</h1>
<h1 v-else>
{{ $t('course.title.active') }}
{{ $t("course.title.active") }}
</h1>
<persons-associated />
@@ -30,110 +30,107 @@
</div> -->
</template>
<script>
import { mapState } from 'vuex'
import Banner from './components/Banner.vue';
import StickyNav from './components/StickyNav.vue';
import OriginDemand from './components/OriginDemand.vue';
import AdminLocation from './components/AdminLocation.vue';
import PersonsAssociated from './components/PersonsAssociated.vue';
import Requestor from './components/Requestor.vue';
import SocialIssue from './components/SocialIssue.vue';
import CourseLocation from './components/CourseLocation.vue';
import Scopes from './components/Scopes.vue';
import Referrer from './components/Referrer.vue';
import Resources from './components/Resources.vue';
import Comment from './components/Comment.vue';
import Confirm from './components/Confirm.vue';
import StartDate from './components/StartDate.vue';
import { mapState } from "vuex";
import Banner from "./components/Banner.vue";
import StickyNav from "./components/StickyNav.vue";
import OriginDemand from "./components/OriginDemand.vue";
import AdminLocation from "./components/AdminLocation.vue";
import PersonsAssociated from "./components/PersonsAssociated.vue";
import Requestor from "./components/Requestor.vue";
import SocialIssue from "./components/SocialIssue.vue";
import CourseLocation from "./components/CourseLocation.vue";
import Scopes from "./components/Scopes.vue";
import Referrer from "./components/Referrer.vue";
import Resources from "./components/Resources.vue";
import Comment from "./components/Comment.vue";
import Confirm from "./components/Confirm.vue";
import StartDate from "./components/StartDate.vue";
export default {
name: 'App',
components: {
Banner,
StickyNav,
OriginDemand,
AdminLocation,
PersonsAssociated,
Requestor,
SocialIssue,
CourseLocation,
Scopes,
Referrer,
Resources,
Comment,
Confirm,
StartDate
},
computed: {
...mapState([
'accompanyingCourse',
'addressContext'
]),
}
name: "App",
components: {
Banner,
StickyNav,
OriginDemand,
AdminLocation,
PersonsAssociated,
Requestor,
SocialIssue,
CourseLocation,
Scopes,
Referrer,
Resources,
Comment,
Confirm,
StartDate,
},
computed: {
...mapState(["accompanyingCourse", "addressContext"]),
},
};
</script>
<style lang="scss">
@import 'ChillMainAssets/module/bootstrap/shared';
$chill-accourse-context: #718596;
@import "ChillMainAssets/module/bootstrap/shared";
$chill-accourse-context: #718596;
div#accompanying-course {
div.vue-component {
h2 {
margin: 1em 0.7em;
position: relative;
&:before {
position: absolute;
content: "\f142"; //ellipsis-v
font-family: "ForkAwesome";
color: tint-color($chill-accourse-context, 10%);
left: -22px;
top: 4px;
}
a[id^="section"] {
position: absolute;
top: -2.5em; // reference for stickNav
}
}
padding: 0em 0em;
margin: 1em 0;
border-radius: 5px;
border: 1px dotted tint-color($chill-accourse-context, 10%);
border-left: 1px dotted tint-color($chill-accourse-context, 10%);
border-right: 1px dotted tint-color($chill-accourse-context, 10%);
dd {
margin-left: 1em;
}
& > div {
margin: 1em 3em 0;
&.flex-table,
&.flex-bloc {
margin: 1em 0 0;
}
&.alert.to-confirm {
margin: 1em 0 0;
padding: 1em 3em;
}
}
div.flex-table {
div.item-row {
div.item-col:first-child {
flex-basis: 33%;
}
}
}
&.errors {
//display: flex;
//position: sticky;
//bottom: 0.3em;
//z-index: 1000;
margin: 1em 0;
padding: 1em;
border-radius: 0;
}
div#accompanying-course {
div.vue-component {
h2 {
margin: 1em 0.7em;
position: relative;
&:before {
position: absolute;
content: "\f142"; //ellipsis-v
font-family: "ForkAwesome";
color: tint-color($chill-accourse-context, 10%);
left: -22px;
top: 4px;
}
}
a[id^="section"] {
position: absolute;
top: -2.5em; // reference for stickNav
}
}
padding: 0em 0em;
margin: 1em 0;
border-radius: 5px;
border: 1px dotted tint-color($chill-accourse-context, 10%);
border-left: 1px dotted tint-color($chill-accourse-context, 10%);
border-right: 1px dotted tint-color($chill-accourse-context, 10%);
dd {
margin-left: 1em;
}
& > div {
margin: 1em 3em 0;
&.flex-table,
&.flex-bloc {
margin: 1em 0 0;
}
&.alert.to-confirm {
margin: 1em 0 0;
padding: 1em 3em;
}
}
div.flex-table {
div.item-row {
div.item-col:first-child {
flex-basis: 33%;
}
}
}
&.errors {
//display: flex;
//position: sticky;
//bottom: 0.3em;
//z-index: 1000;
margin: 1em 0;
padding: 1em;
border-radius: 0;
}
}
}
</style>

View File

@@ -1,52 +1,73 @@
import { fetchResults } from 'ChillMainAssets/lib/api/apiMethods.ts';
import { fetchResults } from "ChillMainAssets/lib/api/apiMethods.ts";
/*
* Endpoint v.2 chill_api_single_accompanying_course__entity
* method GET/HEAD, get AccompanyingCourse Instance
*
* @id integer - id of accompanyingCourse
*/
* Endpoint v.2 chill_api_single_accompanying_course__entity
* method GET/HEAD, get AccompanyingCourse Instance
*
* @id integer - id of accompanyingCourse
*/
const getAccompanyingCourse = (id) => {
const url = `/api/1.0/person/accompanying-course/${id}.json`;
return fetch(url)
.then(response => {
if (response.ok) { return response.json(); }
throw { msg: 'Error while retriving AccompanyingPeriod Course.', sta: response.status, txt: response.statusText, err: new Error(), body: response.body };
});
const url = `/api/1.0/person/accompanying-course/${id}.json`;
return fetch(url).then((response) => {
if (response.ok) {
return response.json();
}
throw {
msg: "Error while retriving AccompanyingPeriod Course.",
sta: response.status,
txt: response.statusText,
err: new Error(),
body: response.body,
};
});
};
const getUsers = () => fetchResults('/api/1.0/main/user.json');
const getUsers = () => fetchResults("/api/1.0/main/user.json");
const getReferrersSuggested = (course) => {
const url = `/api/1.0/person/accompanying-course/${course.id}/referrers-suggested.json`;
return fetchResults(url);
}
const url = `/api/1.0/person/accompanying-course/${course.id}/referrers-suggested.json`;
return fetchResults(url);
};
const getUserJobs = () => fetchResults('/api/1.0/main/user-job.json');
const getUserJobs = () => fetchResults("/api/1.0/main/user-job.json");
const getSocialIssues = () => {
const url = `/api/1.0/person/social-work/social-issue.json`;
return fetch(url)
.then(response => {
if (response.ok) { return response.json(); }
throw { msg: 'Error while retriving Social Issues.', sta: response.status, txt: response.statusText, err: new Error(), body: response.body };
});
const url = `/api/1.0/person/social-work/social-issue.json`;
return fetch(url).then((response) => {
if (response.ok) {
return response.json();
}
throw {
msg: "Error while retriving Social Issues.",
sta: response.status,
txt: response.statusText,
err: new Error(),
body: response.body,
};
});
};
const whoami = () => {
const url = `/api/1.0/main/whoami.json`;
return fetch(url)
.then(response => {
if (response.ok) { return response.json(); }
throw { msg: 'Error while getting whoami.', sta: response.status, txt: response.statusText, err: new Error(), body: response.body };
});
const url = `/api/1.0/main/whoami.json`;
return fetch(url).then((response) => {
if (response.ok) {
return response.json();
}
throw {
msg: "Error while getting whoami.",
sta: response.status,
txt: response.statusText,
err: new Error(),
body: response.body,
};
});
};
export {
whoami,
getSocialIssues,
getAccompanyingCourse,
getUsers,
getReferrersSuggested,
getUserJobs
whoami,
getSocialIssues,
getAccompanyingCourse,
getUsers,
getReferrersSuggested,
getUserJobs,
};

View File

@@ -1,10 +1,10 @@
<template>
<div class="vue-component">
<h2><a id="section-40" />{{ $t('admin_location.title') }}</h2>
<h2><a id="section-40" />{{ $t("admin_location.title") }}</h2>
<div class="mb-4">
<label for="selectAdminLocation">
{{ $t('admin_location.title') }}
{{ $t("admin_location.title") }}
</label>
<VueMultiselect
@@ -26,78 +26,79 @@
/>
</div>
<div
v-if="!isAdminLocationValid"
class="alert alert-warning to-confirm"
>
{{ $t('admin_location.not_valid') }}
<div v-if="!isAdminLocationValid" class="alert alert-warning to-confirm">
{{ $t("admin_location.not_valid") }}
</div>
</div>
</template>
<script>
import VueMultiselect from 'vue-multiselect';
import { fetchResults } from 'ChillMainAssets/lib/api/apiMethods';
import { mapState, mapGetters } from 'vuex';
import VueMultiselect from "vue-multiselect";
import { fetchResults } from "ChillMainAssets/lib/api/apiMethods";
import { mapState, mapGetters } from "vuex";
export default {
name: 'AdminLocation',
components: { VueMultiselect },
data() {
return {
options: []
}
},
computed: {
...mapState({
value: state => state.accompanyingCourse.administrativeLocation,
}),
...mapGetters([
'isAdminLocationValid'
])
},
mounted() {
this.getOptions();
},
methods: {
getOptions() {
fetchResults(`/api/1.0/main/location.json`)
.then(response => {
let uniqueLocationTypeId = [...new Set(response.map(o => o.locationType.id))];
let results = [];
for (let id of uniqueLocationTypeId) {
results.push({
locationCategories: response.filter(o => o.locationType.id === id)[0].locationType.title.fr,
locations: response.filter(o => o.locationType.id === id)
})
}
this.options = results;
})
},
updateAdminLocation(value) {
this.$store.dispatch('updateAdminLocation', value)
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
},
customLabel(value) {
return value.locationType
? value.name
? `${value.name} (${value.locationType.title.fr})`
: value.locationType.title.fr
: '';
},
}
}
name: "AdminLocation",
components: { VueMultiselect },
data() {
return {
options: [],
};
},
computed: {
...mapState({
value: (state) => state.accompanyingCourse.administrativeLocation,
}),
...mapGetters(["isAdminLocationValid"]),
},
mounted() {
this.getOptions();
},
methods: {
getOptions() {
fetchResults(`/api/1.0/main/location.json`).then((response) => {
let uniqueLocationTypeId = [
...new Set(response.map((o) => o.locationType.id)),
];
let results = [];
for (let id of uniqueLocationTypeId) {
results.push({
locationCategories: response.filter(
(o) => o.locationType.id === id,
)[0].locationType.title.fr,
locations: response.filter((o) => o.locationType.id === id),
});
}
this.options = results;
});
},
updateAdminLocation(value) {
this.$store
.dispatch("updateAdminLocation", value)
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
customLabel(value) {
return value.locationType
? value.name
? `${value.name} (${value.locationType.title.fr})`
: value.locationType.title.fr
: "";
},
},
};
</script>
<style src="vue-multiselect/dist/vue-multiselect.css"></style>
<style lang="css" scoped>
label {
display: none;
}
label {
display: none;
}
</style>

View File

@@ -9,11 +9,15 @@
class="text-md-end d-md-block"
>
<span class="badge bg-secondary">
{{ $t('course.step.draft') }}
{{ $t("course.step.draft") }}
</span>
</span>
<span
v-else-if="accompanyingCourse.step === 'CONFIRMED' || accompanyingCourse.step === 'CONFIRMED_INACTIVE_SHORT' || accompanyingCourse.step === 'CONFIRMED_INACTIVE_LONG'"
v-else-if="
accompanyingCourse.step === 'CONFIRMED' ||
accompanyingCourse.step === 'CONFIRMED_INACTIVE_SHORT' ||
accompanyingCourse.step === 'CONFIRMED_INACTIVE_LONG'
"
class="text-md-end"
>
<span
@@ -21,7 +25,7 @@
class="d-md-block mb-md-3"
>
<span class="badge bg-primary">
{{ $t('course.step.active') }}
{{ $t("course.step.active") }}
</span>
</span>
<span
@@ -29,7 +33,7 @@
class="d-md-block mb-md-3"
>
<span class="badge bg-chill-yellow text-primary">
{{ $t('course.step.inactive_short') }}
{{ $t("course.step.inactive_short") }}
</span>
</span>
<span
@@ -37,45 +41,40 @@
class="d-md-block mb-md-3"
>
<span class="badge bg-chill-pink">
{{ $t('course.step.inactive_long') }}
{{ $t("course.step.inactive_long") }}
</span>
</span>
<span class="d-md-block">
<span class="d-md-block ms-3 ms-md-0">
<i>{{ $t('course.open_at') }}{{ $d(accompanyingCourse.openingDate.datetime, 'text') }}</i>
<i
>{{ $t("course.open_at")
}}{{ $d(accompanyingCourse.openingDate.datetime, "text") }}</i
>
</span>
<span
v-if="accompanyingCourse.user"
class="d-md-block ms-3 ms-md-0"
>
<span class="item-key">{{ $t('course.referrer') }}:</span>&nbsp;
<span v-if="accompanyingCourse.user" class="d-md-block ms-3 ms-md-0">
<span class="item-key">{{ $t("course.referrer") }}:</span>&nbsp;
<b>{{ accompanyingCourse.user.text }}</b>
<template v-if="accompanyingCourse.user.isAbsent">
&nbsp;
<span
class="badge bg-danger rounded-pill"
title="Absent"
>A</span>
&nbsp;
<span class="badge bg-danger rounded-pill" title="Absent">A</span>
</template>
</span>
</span>
</span>
<span
v-else
class="text-md-end d-md-block"
>
<span v-else class="text-md-end d-md-block">
<span class="badge bg-danger">
{{ $t('course.step.closed') }}
{{ $t("course.step.closed") }}
</span>
<span class="d-md-block">
<span class="d-md-block ms-3 ms-md-0">
<i>{{ $d(accompanyingCourse.openingDate.datetime, 'text') }} - {{ $d(accompanyingCourse.closingDate.datetime, 'text') }}</i>
<i
>{{ $d(accompanyingCourse.openingDate.datetime, "text") }} -
{{ $d(accompanyingCourse.closingDate.datetime, "text") }}</i
>
</span>
<span
v-if="accompanyingCourse.user"
class="d-md-block ms-3 ms-md-0"
>
<span class="item-key">{{ $t('course.referrer') }}:</span> <b>{{ accompanyingCourse.user.text }}</b>
<span v-if="accompanyingCourse.user" class="d-md-block ms-3 ms-md-0">
<span class="item-key">{{ $t("course.referrer") }}:</span>
<b>{{ accompanyingCourse.user.text }}</b>
</span>
</span>
</span>
@@ -95,35 +94,35 @@
</template>
<script>
import ToggleFlags from './Banner/ToggleFlags';
import SocialIssue from './Banner/SocialIssue.vue';
import PersonsAssociated from './Banner/PersonsAssociated.vue';
import ToggleFlags from "./Banner/ToggleFlags";
import SocialIssue from "./Banner/SocialIssue.vue";
import PersonsAssociated from "./Banner/PersonsAssociated.vue";
export default {
name: 'Banner',
components: {
ToggleFlags,
SocialIssue,
PersonsAssociated,
},
computed: {
accompanyingCourse() {
return this.$store.state.accompanyingCourse
}
}
}
name: "Banner",
components: {
ToggleFlags,
SocialIssue,
PersonsAssociated,
},
computed: {
accompanyingCourse() {
return this.$store.state.accompanyingCourse;
},
},
};
</script>
<style lang="scss">
div#banner-flags,
div#banner-status {
.badge {
text-transform: uppercase;
}
}
div#banner-status {
span.badge {
font-size: 90%;
}
}
div#banner-flags,
div#banner-status {
.badge {
text-transform: uppercase;
}
}
div#banner-status {
span.badge {
font-size: 90%;
}
}
</style>

View File

@@ -1,23 +1,19 @@
<template>
<span
v-for="h in personsByHousehold()"
:class="{ 'household': householdExists(h.id), 'no-household': !householdExists(h.id) }"
:class="{
household: householdExists(h.id),
'no-household': !householdExists(h.id),
}"
:key="h.id"
>
<a
v-if="householdExists(h.id)"
:href="householdLink(h.id)"
>
<a v-if="householdExists(h.id)" :href="householdLink(h.id)">
<i
class="fa fa-home fa-fw text-light"
:title="$t('persons_associated.show_household_number', { id: h.id })"
/>
</a>
<span
v-for="person in h.persons"
class="me-1"
:key="person.id"
>
<span v-for="person in h.persons" class="me-1" :key="person.id">
<on-the-fly
:type="person.type"
:id="person.id"
@@ -30,64 +26,67 @@
</template>
<script>
import OnTheFly from 'ChillMainAssets/vuejs/OnTheFly/components/OnTheFly'
import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly";
export default {
name: "PersonsAssociated",
components: {
OnTheFly
},
props: [ 'accompanyingCourse' ],
computed: {
participations() {
return this.accompanyingCourse.participations.filter(p => p.endDate === null)
},
persons() {
return this.participations.map(p => p.person)
},
resources() {
return this.accompanyingCourse.resources
},
requestor() {
return this.accompanyingCourse.requestor
}
},
methods: {
uniq(array) {
return [...new Set(array)]
},
personsByHousehold() {
name: "PersonsAssociated",
components: {
OnTheFly,
},
props: ["accompanyingCourse"],
computed: {
participations() {
return this.accompanyingCourse.participations.filter(
(p) => p.endDate === null,
);
},
persons() {
return this.participations.map((p) => p.person);
},
resources() {
return this.accompanyingCourse.resources;
},
requestor() {
return this.accompanyingCourse.requestor;
},
},
methods: {
uniq(array) {
return [...new Set(array)];
},
personsByHousehold() {
let households = [];
this.persons.forEach((p) => {
households.push(p.current_household_id);
});
let households = []
this.persons.forEach(p => { households.push(p.current_household_id) })
let personsByHousehold = []
this.uniq(households).forEach(h => {
personsByHousehold.push({
id: h !== null ? h : 0,
persons: this.persons.filter(p => p.current_household_id === h)
})
})
//console.log(personsByHousehold)
return personsByHousehold
},
householdExists(id) {
return id !== 0
},
householdLink(id) {
return `/fr/person/household/${id}/summary`
}
}
}
let personsByHousehold = [];
this.uniq(households).forEach((h) => {
personsByHousehold.push({
id: h !== null ? h : 0,
persons: this.persons.filter((p) => p.current_household_id === h),
});
});
//console.log(personsByHousehold)
return personsByHousehold;
},
householdExists(id) {
return id !== 0;
},
householdLink(id) {
return `/fr/person/household/${id}/summary`;
},
},
};
</script>
<style lang="scss" scoped>
span.household {
display: inline-block;
border-top: 1px solid rgba(255, 255, 255, 0.3);
background-color: rgba(255, 255, 255, 0.1);
border-radius: 10px;
margin-right: 0.3em;
padding: 5px;
display: inline-block;
border-top: 1px solid rgba(255, 255, 255, 0.3);
background-color: rgba(255, 255, 255, 0.1);
border-radius: 10px;
margin-right: 0.3em;
padding: 5px;
}
</style>

View File

@@ -4,19 +4,19 @@
<script>
export default {
name: "SocialIssues",
props: ['issue']
}
name: "SocialIssues",
props: ["issue"],
};
</script>
<style lang="scss" scoped>
@import 'ChillMainAssets/module/bootstrap/shared';
@import 'ChillPersonAssets/chill/scss/mixins';
@import 'ChillMainAssets/chill/scss/chill_variables';
@import "ChillMainAssets/module/bootstrap/shared";
@import "ChillPersonAssets/chill/scss/mixins";
@import "ChillMainAssets/chill/scss/chill_variables";
span.badge {
@include badge_social($social-issue-color);
font-size: 95%;
margin-bottom: 5px;
margin-right: 1em;
@include badge_social($social-issue-color);
font-size: 95%;
margin-bottom: 5px;
margin-right: 1em;
}
</style>

View File

@@ -1,16 +1,16 @@
<template>
<div class="text-md-end">
<span class="d-block d-sm-inline-block mb-md-2">
<a
@click="toggleIntensity"
class="flag-toggle"
>
<span :class="{ 'on': !isRegular }">{{ $t('course.occasional') }}</span>
<a @click="toggleIntensity" class="flag-toggle">
<span :class="{ on: !isRegular }">{{ $t("course.occasional") }}</span>
<i
class="fa"
:class="{ 'fa-toggle-on': isRegular, 'fa-toggle-on fa-flip-horizontal': !isRegular }"
:class="{
'fa-toggle-on': isRegular,
'fa-toggle-on fa-flip-horizontal': !isRegular,
}"
/>
<span :class="{ 'on': isRegular }">{{ $t('course.regular') }}</span>
<span :class="{ on: isRegular }">{{ $t("course.regular") }}</span>
</a>
</span>
@@ -20,111 +20,123 @@
:class="{ 'bg-danger': isEmergency, 'bg-secondary': !isEmergency }"
@click="toggleEmergency"
>
{{ $t('course.emergency') }}
{{ $t("course.emergency") }}
</button>
<button
class="badge rounded-pill"
:class="{ 'bg-danger': isConfidential, 'bg-secondary': !isConfidential }"
:class="{
'bg-danger': isConfidential,
'bg-secondary': !isConfidential,
}"
@click="toggleConfidential"
>
{{ $t('course.confidential') }}
{{ $t("course.confidential") }}
</button>
</span>
</div>
</template>
<script>
import { mapState } from 'vuex';
import { mapState } from "vuex";
export default {
name: "ToggleFlags",
computed: {
...mapState({
intensity: state => state.accompanyingCourse.intensity,
emergency: state => state.accompanyingCourse.emergency,
confidential: state => state.accompanyingCourse.confidential,
permissions: state => state.permissions,
}),
isRegular() {
return (this.intensity === 'regular') ? true : false;
},
isEmergency() {
return (this.emergency) ? true : false;
},
isConfidential() {
return (this.confidential) ? true : false;
},
},
methods: {
toggleIntensity() {
let value;
switch (this.intensity) {
case "occasional":
value = "regular";
break;
case "regular":
value = "occasional";
break;
default:
//temporaire (modif backend)
value = "occasional";
}
this.$store.dispatch('toggleIntensity', value)
.catch(({name}) => {
if (name === 'ValidationException' || name === 'AccessException') {
this.$toast.open({message: this.$t('Only the referrer can toggle the intensity of an accompanying course')})
} else {
this.$toast.open({message: 'An error occurred'})
}
});
},
toggleEmergency() {
this.$store.dispatch('toggleEmergency', (!this.isEmergency))
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
},
toggleConfidential() {
this.$store.dispatch('toggleConfidential')
.catch(({name}) => {
console.log(name);
if (name === 'ValidationException' || name === 'AccessException') {
this.$toast.open({message: this.$t('Only the referrer can toggle the confidentiality of an accompanying course')})
} else {
this.$toast.open({message: 'An error occurred'})
}
});
},
},
}
name: "ToggleFlags",
computed: {
...mapState({
intensity: (state) => state.accompanyingCourse.intensity,
emergency: (state) => state.accompanyingCourse.emergency,
confidential: (state) => state.accompanyingCourse.confidential,
permissions: (state) => state.permissions,
}),
isRegular() {
return this.intensity === "regular" ? true : false;
},
isEmergency() {
return this.emergency ? true : false;
},
isConfidential() {
return this.confidential ? true : false;
},
},
methods: {
toggleIntensity() {
let value;
switch (this.intensity) {
case "occasional":
value = "regular";
break;
case "regular":
value = "occasional";
break;
default:
//temporaire (modif backend)
value = "occasional";
}
this.$store.dispatch("toggleIntensity", value).catch(({ name }) => {
if (name === "ValidationException" || name === "AccessException") {
this.$toast.open({
message: this.$t(
"Only the referrer can toggle the intensity of an accompanying course",
),
});
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
toggleEmergency() {
this.$store
.dispatch("toggleEmergency", !this.isEmergency)
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
toggleConfidential() {
this.$store.dispatch("toggleConfidential").catch(({ name }) => {
console.log(name);
if (name === "ValidationException" || name === "AccessException") {
this.$toast.open({
message: this.$t(
"Only the referrer can toggle the confidentiality of an accompanying course",
),
});
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
},
};
</script>
<style lang="scss" scoped>
a.flag-toggle {
color: white;
cursor: pointer;
&:hover {
color: white;
text-decoration: underline;
border-radius: 20px;
}
i {
margin: auto 0.4em;
}
span.on {
font-weight: bolder;
}
}
button.badge {
&.bg-secondary {
opacity: 0.5;
&:hover {
opacity: 0.7;
}
}
a.flag-toggle {
color: white;
cursor: pointer;
&:hover {
color: white;
text-decoration: underline;
border-radius: 20px;
}
i {
margin: auto 0.4em;
}
span.on {
font-weight: bolder;
}
}
button.badge {
&.bg-secondary {
opacity: 0.5;
&:hover {
opacity: 0.7;
}
}
}
</style>

View File

@@ -17,19 +17,16 @@
>
<template #header>
<h2 class="modal-title">
{{ $t('courselocation.sure') }}
{{ $t("courselocation.sure") }}
</h2>
</template>
<template #body>
<address-render-box :address="person.current_household_address" />
<p>{{ $t('courselocation.sure_description') }}</p>
<p>{{ $t("courselocation.sure_description") }}</p>
</template>
<template #footer>
<button
class="btn btn-danger"
@click="assignAddress"
>
{{ $t('courselocation.ok') }}
<button class="btn btn-danger" @click="assignAddress">
{{ $t("courselocation.ok") }}
</button>
</template>
</modal>
@@ -37,51 +34,54 @@
</template>
<script>
import {mapState} from "vuex";
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
import { mapState } from "vuex";
import Modal from "ChillMainAssets/vuejs/_components/Modal";
import AddressRenderBox from "ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue";
export default {
name: "ButtonLocation",
components: {
AddressRenderBox,
Modal,
},
props: ['person'],
data() {
return {
modal: {
showModal: false,
modalDialogClass: "modal-dialog-centered modal-md"
}
}
},
computed: {
...mapState({
context: state => state.addressContext
}),
},
methods: {
assignAddress() {
//console.log('assignAddress id', this.person.current_household_address);
let payload = {
target: this.context.target.name,
targetId: this.context.target.id,
locationStatusTo: 'person',
personId: this.person.id
};
this.$store.dispatch('updateLocation', payload)
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
window.location.assign('#section-20');
this.modal.showModal = false;
}
}
}
name: "ButtonLocation",
components: {
AddressRenderBox,
Modal,
},
props: ["person"],
data() {
return {
modal: {
showModal: false,
modalDialogClass: "modal-dialog-centered modal-md",
},
};
},
computed: {
...mapState({
context: (state) => state.addressContext,
}),
},
methods: {
assignAddress() {
//console.log('assignAddress id', this.person.current_household_address);
let payload = {
target: this.context.target.name,
targetId: this.context.target.id,
locationStatusTo: "person",
personId: this.person.id,
};
this.$store
.dispatch("updateLocation", payload)
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
window.location.assign("#section-20");
this.modal.showModal = false;
},
},
};
</script>

View File

@@ -1,6 +1,6 @@
<template>
<div class="vue-component">
<h2><a id="section-100" />{{ $t('comment.title') }}</h2>
<h2><a id="section-100" />{{ $t("comment.title") }}</h2>
<!--div class="error flash_message" v-if="errors.length > 0">
{{ errors[0] }}
@@ -9,10 +9,9 @@
<div>
<form @submit.prevent="submitform">
<label
class="col-form-label"
for="content"
>{{ $t('comment.label') }}</label>
<label class="col-form-label" for="content">{{
$t("comment.label")
}}</label>
<ckeditor
name="content"
@@ -24,13 +23,17 @@
<div class="sub-comment">
<div
v-if="pinnedComment !== null && typeof pinnedComment.creator !== 'undefined'"
v-if="
pinnedComment !== null &&
typeof pinnedComment.creator !== 'undefined'
"
class="metadata"
>
{{ $t('comment.created_by', [
pinnedComment.creator.text,
$d(pinnedComment.updatedAt.datetime, 'long')
])
{{
$t("comment.created_by", [
pinnedComment.creator.text,
$d(pinnedComment.updatedAt.datetime, "long"),
])
}}
</div>
<div class="loading">
@@ -45,11 +48,8 @@
<div>
<ul class="record_actions">
<li v-if="pinnedComment !== null">
<a
class="btn btn-delete"
@click="removeComment"
>
{{ $t('action.delete') }}
<a class="btn btn-delete" @click="removeComment">
{{ $t("action.delete") }}
</a>
</li>
</ul>
@@ -60,101 +60,117 @@
</template>
<script>
import CKEditor from '@ckeditor/ckeditor5-vue';
import CKEditor from "@ckeditor/ckeditor5-vue";
import ClassicEditor from "../../../../../../ChillMainBundle/Resources/public/module/ckeditor5/editor_config";
import { mapState } from "vuex";
export default {
name: "Comment",
components: {
ckeditor: CKEditor.component,
},
data() {
return {
editor: ClassicEditor,
loading: false,
lastRecordedContent: null,
}
},
computed: {
...mapState({
pinnedComment: state => state.accompanyingCourse.pinnedComment,
}),
content: {
set(value) {
console.log('new comment value', value);
console.log('previous value', this.lastRecordedContent);
this.lastRecordedContent = value;
name: "Comment",
components: {
ckeditor: CKEditor.component,
},
data() {
return {
editor: ClassicEditor,
loading: false,
lastRecordedContent: null,
};
},
computed: {
...mapState({
pinnedComment: (state) => state.accompanyingCourse.pinnedComment,
}),
content: {
set(value) {
console.log("new comment value", value);
console.log("previous value", this.lastRecordedContent);
this.lastRecordedContent = value;
setTimeout(() => {
console.log('performing test on ', value);
if (this.lastRecordedContent === value) {
this.loading = true;
if (value !== '') {
this.$store.dispatch('updatePinnedComment', value)
.then(() => {
this.loading = false;
})
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
} else {
if (this.$store.state.accompanyingCourse.pinnedComment !== null) {
this.$store.dispatch('removePinnedComment', {id: this.pinnedComment.id})
.then(() => {
this.loading = false;
this.lastRecoredContent = null;
})
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
}
}
}
}, 3000);
},
get() {
return this.pinnedComment ? this.pinnedComment.content : '';
}
setTimeout(() => {
console.log("performing test on ", value);
if (this.lastRecordedContent === value) {
this.loading = true;
if (value !== "") {
this.$store
.dispatch("updatePinnedComment", value)
.then(() => {
this.loading = false;
})
.catch(({ name, violations }) => {
if (
name === "ValidationException" ||
name === "AccessException"
) {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
} else {
if (this.$store.state.accompanyingCourse.pinnedComment !== null) {
this.$store
.dispatch("removePinnedComment", {
id: this.pinnedComment.id,
})
.then(() => {
this.loading = false;
this.lastRecoredContent = null;
})
.catch(({ name, violations }) => {
if (
name === "ValidationException" ||
name === "AccessException"
) {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
}
}
}
}, 3000);
},
errors() {
return this.$store.state.errorMsg;
}
},
methods: {
removeComment() {
this.$store.dispatch('removePinnedComment', {id: this.pinnedComment.id})
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
}
}
}
get() {
return this.pinnedComment ? this.pinnedComment.content : "";
},
},
errors() {
return this.$store.state.errorMsg;
},
},
methods: {
removeComment() {
this.$store
.dispatch("removePinnedComment", { id: this.pinnedComment.id })
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
},
};
</script>
<style lang="scss">
div.ck-editor.ck-reset {
margin: 0.6em 0;
margin: 0.6em 0;
}
div.sub-comment {
display: flex;
justify-content: space-between;
div.loading {
margin-right: 6px;
margin-left: 6px;
}
display: flex;
justify-content: space-between;
div.loading {
margin-right: 6px;
margin-left: 6px;
}
}
</style>

View File

@@ -2,19 +2,16 @@
<div class="vue-component">
<h2>
<a id="section-110" />
{{ $t('confirm.title') }}
{{ $t("confirm.title") }}
</h2>
<div>
<p v-html="$t('confirm.text_draft', [$t('course.step.draft')])" />
<div v-if="!isValidToBeConfirmed">
<div class="alert alert-warning">
{{ $t('confirm.alert_validation') }}
{{ $t("confirm.alert_validation") }}
<ul class="mt-2">
<li
v-for="k in validationKeys"
:key="k"
>
<li v-for="k in validationKeys" :key="k">
{{ $t(notValidMessages[k].msg) }}
<a :href="notValidMessages[k].anchor">
<i class="fa fa-level-up fa-fw" />
@@ -24,19 +21,13 @@
</div>
<ul class="record_actions">
<li>
<button
class="btn btn-save"
disabled
>
{{ $t('confirm.ok') }}
<button class="btn btn-save" disabled>
{{ $t("confirm.ok") }}
</button>
</li>
<li>
<a
class="btn btn-delete"
:href="deleteLink"
>
{{ $t('confirm.delete') }}
<a class="btn btn-delete" :href="deleteLink">
{{ $t("confirm.delete") }}
</a>
</li>
</ul>
@@ -46,19 +37,13 @@
<p v-html="$t('confirm.text_active', [$t('course.step.active')])" />
<ul class="record_actions">
<li>
<button
class="btn btn-save"
@click="modal.showModal = true"
>
{{ $t('confirm.ok') }}
<button class="btn btn-save" @click="modal.showModal = true">
{{ $t("confirm.ok") }}
</button>
</li>
<li>
<a
class="btn btn-delete"
:href="deleteLink"
>
{{ $t('confirm.delete') }}
<a class="btn btn-delete" :href="deleteLink">
{{ $t("confirm.delete") }}
</a>
</li>
</ul>
@@ -73,35 +58,37 @@
>
<template #header>
<h2 class="modal-title">
{{ $t('confirm.sure') }}
{{ $t("confirm.sure") }}
</h2>
</template>
<template #body>
<p>{{ $t('confirm.sure_description') }}</p>
<p>{{ $t("confirm.sure_description") }}</p>
<div v-if="accompanyingCourse.user === null">
<div v-if="usersSuggestedFilteredByJob.length === 0">
<p class="alert alert-warning">
{{ $t('confirm.no_suggested_referrer') }}
{{ $t("confirm.no_suggested_referrer") }}
</p>
</div>
<div
v-if="usersSuggestedFilteredByJob.length === 1"
class="alert alert-info"
>
<p>{{ $t('confirm.one_suggested_referrer') }}:</p>
<p>{{ $t("confirm.one_suggested_referrer") }}:</p>
<ul class="list-suggest add-items inline">
<li>
<user-render-box-badge :user="usersSuggestedFilteredByJob[0]" />
<user-render-box-badge
:user="usersSuggestedFilteredByJob[0]"
/>
</li>
</ul>
<p>{{ $t('confirm.choose_suggested_referrer') }}</p>
<p>{{ $t("confirm.choose_suggested_referrer") }}</p>
<ul class="record_actions">
<li>
<button
class="btn btn-save mr-5"
@click="chooseSuggestedReferrer"
>
{{ $t('confirm.choose_button') }}
{{ $t("confirm.choose_button") }}
</button>
</li>
<li>
@@ -109,7 +96,7 @@
class="btn btn-secondary"
@click="doNotChooseSuggestedReferrer"
>
{{ $t('confirm.do_not_choose_button') }}
{{ $t("confirm.do_not_choose_button") }}
</button>
</li>
</ul>
@@ -122,7 +109,7 @@
:disabled="disableConfirm"
@click="confirmCourse"
>
{{ $t('confirm.ok') }}
{{ $t("confirm.ok") }}
</button>
</template>
</modal>
@@ -131,103 +118,111 @@
</template>
<script>
import {mapGetters, mapState} from "vuex";
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
import { mapGetters, mapState } from "vuex";
import Modal from "ChillMainAssets/vuejs/_components/Modal";
import UserRenderBoxBadge from "ChillMainAssets/vuejs/_components/Entity/UserRenderBoxBadge";
export default {
name: "Confirm",
components: {
Modal,
UserRenderBoxBadge
},
data() {
return {
modal: {
showModal: false,
modalDialogClass: "modal-dialog-centered modal-md"
},
notValidMessages: {
participation: {
msg: 'confirm.participation_not_valid',
anchor: '#section-10'
},
location: {
msg: 'confirm.location_not_valid',
anchor: '#section-20'
},
origin: {
msg: 'confirm.origin_not_valid',
anchor: '#section-30'
},
adminLocation: {
msg: 'confirm.adminLocation_not_valid',
anchor: '#section-40'
},
socialIssue: {
msg: 'confirm.socialIssue_not_valid',
anchor: '#section-60'
},
scopes: {
msg: 'confirm.set_a_scope',
anchor: '#section-70'
},
job: {
msg: 'confirm.job_not_valid',
anchor: '#section-80'
},
},
clickedDoNotChooseReferrer: false
}
},
computed: {
...mapState({
accompanyingCourse: state => state.accompanyingCourse,
}),
...mapGetters([
'isParticipationValid',
'isSocialIssueValid',
'isOriginValid',
'isAdminLocationValid',
'isLocationValid',
'isJobValid',
'validationKeys',
'isValidToBeConfirmed',
'usersSuggestedFilteredByJob',
]),
deleteLink() {
return `/fr/parcours/${this.accompanyingCourse.id}/delete`; //TODO locale
name: "Confirm",
components: {
Modal,
UserRenderBoxBadge,
},
data() {
return {
modal: {
showModal: false,
modalDialogClass: "modal-dialog-centered modal-md",
},
disableConfirm() {
return (this.accompanyingCourse.user === null
&& this.usersSuggestedFilteredByJob.length === 1
&& this.clickedDoNotChooseReferrer === false);
}
},
methods: {
confirmCourse() {
this.$store.dispatch('confirmAccompanyingCourse')
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
notValidMessages: {
participation: {
msg: "confirm.participation_not_valid",
anchor: "#section-10",
},
location: {
msg: "confirm.location_not_valid",
anchor: "#section-20",
},
origin: {
msg: "confirm.origin_not_valid",
anchor: "#section-30",
},
adminLocation: {
msg: "confirm.adminLocation_not_valid",
anchor: "#section-40",
},
socialIssue: {
msg: "confirm.socialIssue_not_valid",
anchor: "#section-60",
},
scopes: {
msg: "confirm.set_a_scope",
anchor: "#section-70",
},
job: {
msg: "confirm.job_not_valid",
anchor: "#section-80",
},
},
chooseSuggestedReferrer() {
this.$store.dispatch('updateReferrer', this.usersSuggestedFilteredByJob[0])
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
},
doNotChooseSuggestedReferrer() {
this.clickedDoNotChooseReferrer = true;
}
}
}
clickedDoNotChooseReferrer: false,
};
},
computed: {
...mapState({
accompanyingCourse: (state) => state.accompanyingCourse,
}),
...mapGetters([
"isParticipationValid",
"isSocialIssueValid",
"isOriginValid",
"isAdminLocationValid",
"isLocationValid",
"isJobValid",
"validationKeys",
"isValidToBeConfirmed",
"usersSuggestedFilteredByJob",
]),
deleteLink() {
return `/fr/parcours/${this.accompanyingCourse.id}/delete`; //TODO locale
},
disableConfirm() {
return (
this.accompanyingCourse.user === null &&
this.usersSuggestedFilteredByJob.length === 1 &&
this.clickedDoNotChooseReferrer === false
);
},
},
methods: {
confirmCourse() {
this.$store
.dispatch("confirmAccompanyingCourse")
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
chooseSuggestedReferrer() {
this.$store
.dispatch("updateReferrer", this.usersSuggestedFilteredByJob[0])
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
doNotChooseSuggestedReferrer() {
this.clickedDoNotChooseReferrer = true;
},
},
};
</script>

View File

@@ -2,7 +2,7 @@
<div class="vue-component">
<h2>
<a id="section-20" />
{{ $t('courselocation.title') }}
{{ $t("courselocation.title") }}
</h2>
<div
@@ -15,34 +15,27 @@
<div v-if="hasNoLocation">
<label class="chill-no-data-statement">
{{ $t('courselocation.no_address') }}
{{ $t("courselocation.no_address") }}
</label>
</div>
<div
class="flex-table"
v-if="accompanyingCourse.location"
>
<div class="flex-table" v-if="accompanyingCourse.location">
<div class="item-bloc">
<address-render-box
:address="accompanyingCourse.location"
/>
<address-render-box :address="accompanyingCourse.location" />
<div
v-if="isPersonLocation"
class="alert alert-secondary separator"
>
<div v-if="isPersonLocation" class="alert alert-secondary separator">
<label class="col-form-label">
{{ $t('courselocation.person_locator', [ accompanyingCourse.personLocation.text ]) }}
{{
$t("courselocation.person_locator", [
accompanyingCourse.personLocation.text,
])
}}
</label>
</div>
<div
v-if="isTemporaryAddress"
class="alert alert-warning separator"
>
<div v-if="isTemporaryAddress" class="alert alert-warning separator">
<p>
{{ $t('courselocation.temporary_address_must_be_changed') }}
{{ $t("courselocation.temporary_address_must_be_changed") }}
<i class="fa fa-fw fa-map-marker" />
</p>
</div>
@@ -56,7 +49,11 @@
<i class="fa fa-warning fa-2x" />
<div>
<p>
{{ $t('courselocation.associate_at_least_one_person_with_one_household_with_address') }}
{{
$t(
"courselocation.associate_at_least_one_person_with_one_household_with_address",
)
}}
<a href="#section-10">
<i class="fa fa-level-up fa-fw" />
</a>
@@ -79,178 +76,183 @@
</ul>
</div>
<div
v-if="!isLocationValid"
class="alert alert-warning to-confirm"
>
{{ $t('courselocation.not_valid') }}
<div v-if="!isLocationValid" class="alert alert-warning to-confirm">
{{ $t("courselocation.not_valid") }}
</div>
</div>
</template>
<script>
import {mapGetters, mapState} from "vuex";
import AddAddress from 'ChillMainAssets/vuejs/Address/components/AddAddress.vue';
import AddressRenderBox from 'ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue';
import { mapGetters, mapState } from "vuex";
import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue";
import AddressRenderBox from "ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue";
export default {
name: "CourseLocation",
components: {
AddAddress,
AddressRenderBox
},
data() {
return {
addAddress: {
options: {
button: {
text: {
create: 'courselocation.add_temporary_address',
edit: 'courselocation.edit_temporary_address'
}
},
title: {
create: 'courselocation.add_temporary_address',
edit: 'courselocation.edit_temporary_address'
},
onlyButton: true
}
}
}
},
computed: {
...mapState({
accompanyingCourse: state => state.accompanyingCourse,
context: state => state.addressContext
}),
...mapGetters([
'isLocationValid'
]),
options() {
return this.addAddress.options;
},
key() {
return (this.context.edit) ? 'address_' + this.context.addressId
: this.accompanyingCourse.type + '_' + this.accompanyingCourse.id ;
},
isTemporaryAddress() {
return this.accompanyingCourse.locationStatus === 'address';
},
isPersonLocation() {
return this.accompanyingCourse.locationStatus === 'person';
},
hasNoLocation() {
return this.accompanyingCourse.locationStatus === 'none';
},
currentParticipations() {
return this.accompanyingCourse.participations.filter(p => p.enddate !== null);
},
hasNoPersonLocation() {
let addressInParticipations_ = []
this.currentParticipations.forEach(p => {
addressInParticipations_.push(this.checkHouseholdAddressForParticipation(p));
});
const booleanReducer = (previousValue, currentValue) => previousValue || currentValue;
let addressInParticipations = (addressInParticipations_.length > 0) ?
addressInParticipations_.reduce(booleanReducer) : false;
//console.log(addressInParticipations_, addressInParticipations);
return (
this.accompanyingCourse.step !== 'DRAFT'
&& this.isTemporaryAddress
&& !addressInParticipations
)
;
},
isContextEdit() {
return this.context.edit;
}
},
methods: {
checkHouseholdAddressForParticipation(participation) {
if (participation.person.current_household_id === null) {
return false;
}
return participation.person.current_household_address !== null;
},
initAddressContext() {
let context = {
target: {
name: this.accompanyingCourse.type,
id: this.accompanyingCourse.id
name: "CourseLocation",
components: {
AddAddress,
AddressRenderBox,
},
data() {
return {
addAddress: {
options: {
button: {
text: {
create: "courselocation.add_temporary_address",
edit: "courselocation.edit_temporary_address",
},
edit: false,
addressId: null,
defaults: window.addaddress
}
if (this.accompanyingCourse.location) {
context['edit'] = true;
context['addressId'] = this.accompanyingCourse.location.address_id
}
this.$store.commit('setAddressContext', context);
},
title: {
create: "courselocation.add_temporary_address",
edit: "courselocation.edit_temporary_address",
},
onlyButton: true,
},
},
displayErrors() {
return this.$refs.addAddress.errorMsg;
},
submitTemporaryAddress(payload) {
//console.log('@@@ click on Submit Temporary Address Button', payload);
payload['locationStatusTo'] = 'address'; // <== temporary, not none, not person
this.$store.dispatch('updateLocation', payload)
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
};
},
computed: {
...mapState({
accompanyingCourse: (state) => state.accompanyingCourse,
context: (state) => state.addressContext,
}),
...mapGetters(["isLocationValid"]),
options() {
return this.addAddress.options;
},
key() {
return this.context.edit
? "address_" + this.context.addressId
: this.accompanyingCourse.type + "_" + this.accompanyingCourse.id;
},
isTemporaryAddress() {
return this.accompanyingCourse.locationStatus === "address";
},
isPersonLocation() {
return this.accompanyingCourse.locationStatus === "person";
},
hasNoLocation() {
return this.accompanyingCourse.locationStatus === "none";
},
currentParticipations() {
return this.accompanyingCourse.participations.filter(
(p) => p.enddate !== null,
);
},
hasNoPersonLocation() {
let addressInParticipations_ = [];
this.currentParticipations.forEach((p) => {
addressInParticipations_.push(
this.checkHouseholdAddressForParticipation(p),
);
});
this.$store.commit('setEditContextTrue', payload);
const booleanReducer = (previousValue, currentValue) =>
previousValue || currentValue;
let addressInParticipations =
addressInParticipations_.length > 0
? addressInParticipations_.reduce(booleanReducer)
: false;
//console.log(addressInParticipations_, addressInParticipations);
return (
this.accompanyingCourse.step !== "DRAFT" &&
this.isTemporaryAddress &&
!addressInParticipations
);
},
isContextEdit() {
return this.context.edit;
},
},
methods: {
checkHouseholdAddressForParticipation(participation) {
if (participation.person.current_household_id === null) {
return false;
}
},
created() {
this.initAddressContext();
return participation.person.current_household_address !== null;
},
initAddressContext() {
let context = {
target: {
name: this.accompanyingCourse.type,
id: this.accompanyingCourse.id,
},
edit: false,
addressId: null,
defaults: window.addaddress,
};
if (this.accompanyingCourse.location) {
context["edit"] = true;
context["addressId"] = this.accompanyingCourse.location.address_id;
}
this.$store.commit("setAddressContext", context);
},
displayErrors() {
return this.$refs.addAddress.errorMsg;
},
submitTemporaryAddress(payload) {
//console.log('@@@ click on Submit Temporary Address Button', payload);
payload["locationStatusTo"] = "address"; // <== temporary, not none, not person
this.$store
.dispatch("updateLocation", payload)
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
//console.log('ac.locationStatus', this.accompanyingCourse.locationStatus);
//console.log('ac.location (temporary location)', this.accompanyingCourse.location);
//console.log('ac.personLocation', this.accompanyingCourse.personLocation);
}
}
this.$store.commit("setEditContextTrue", payload);
},
},
created() {
this.initAddressContext();
//console.log('ac.locationStatus', this.accompanyingCourse.locationStatus);
//console.log('ac.location (temporary location)', this.accompanyingCourse.location);
//console.log('ac.personLocation', this.accompanyingCourse.personLocation);
},
};
</script>
<style lang="scss" scoped>
div#accompanying-course {
div.vue-component {
& > div.alert.no-person-location {
margin: 1px 0 0;
div.vue-component {
& > div.alert.no-person-location {
margin: 1px 0 0;
}
div.no-person-location {
padding-top: 1.5em;
display: flex;
flex-direction: row;
& > i {
flex-basis: 1.5em;
flex-grow: 0;
flex-shrink: 0;
padding-top: 0.2em;
opacity: 0.75;
}
div.no-person-location {
padding-top: 1.5em;
display: flex;
flex-direction: row;
& > i {
flex-basis: 1.5em; flex-grow: 0; flex-shrink: 0;
padding-top: 0.2em;
opacity: 0.75;
}
& > div {
flex-basis: auto;
div.action {
button.btn-update {
margin-right: 2em;
}
}
}
& > div {
flex-basis: auto;
div.action {
button.btn-update {
margin-right: 2em;
}
}
}
div.flex-table {
div.item-bloc {
div.alert {
margin: 0 -0.9em -1em;
}
}
}
div.flex-table {
div.item-bloc {
div.alert {
margin: 0 -0.9em -1em;
}
}
}
}
}
}
</style>

View File

@@ -1,10 +1,10 @@
<template>
<div class="vue-component">
<h2><a id="section-30" />{{ $t('origin.title') }}</h2>
<h2><a id="section-30" />{{ $t("origin.title") }}</h2>
<div class="mb-4">
<label for="selectOrigin">
{{ $t('origin.title') }}
{{ $t("origin.title") }}
</label>
<VueMultiselect
@@ -24,72 +24,70 @@
/>
</div>
<div
v-if="!isOriginValid"
class="alert alert-warning to-confirm"
>
{{ $t('origin.not_valid') }}
<div v-if="!isOriginValid" class="alert alert-warning to-confirm">
{{ $t("origin.not_valid") }}
</div>
</div>
</template>
<script>
import VueMultiselect from 'vue-multiselect';
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods';
import { mapState, mapGetters } from 'vuex';
import VueMultiselect from "vue-multiselect";
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
import { mapState, mapGetters } from "vuex";
export default {
name: 'OriginDemand',
components: { VueMultiselect },
data() {
return {
options: []
}
},
computed: {
...mapState({
value: state => state.accompanyingCourse.origin,
}),
...mapGetters([
'isOriginValid'
])
},
mounted() {
this.getOptions();
},
methods: {
getOptions() {
const url = `/api/1.0/person/accompanying-period/origin.json`;
makeFetch('GET', url)
.then(response => {
this.options = response.results;
return response;
})
.catch((error) => {
commit('catchError', error);
this.$toast.open({message: error.txt})
})
},
updateOrigin(value) {
this.$store.dispatch('updateOrigin', value)
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
},
transText ({ text }) {
return text.fr;
},
}
}
name: "OriginDemand",
components: { VueMultiselect },
data() {
return {
options: [],
};
},
computed: {
...mapState({
value: (state) => state.accompanyingCourse.origin,
}),
...mapGetters(["isOriginValid"]),
},
mounted() {
this.getOptions();
},
methods: {
getOptions() {
const url = `/api/1.0/person/accompanying-period/origin.json`;
makeFetch("GET", url)
.then((response) => {
this.options = response.results;
return response;
})
.catch((error) => {
commit("catchError", error);
this.$toast.open({ message: error.txt });
});
},
updateOrigin(value) {
this.$store
.dispatch("updateOrigin", value)
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
transText({ text }) {
return text.fr;
},
},
};
</script>
<style src="vue-multiselect/dist/vue-multiselect.css"></style>
<style lang="css" scoped>
label {
display: none;
}
label {
display: none;
}
</style>

View File

@@ -1,12 +1,16 @@
<template>
<div class="vue-component">
<h2><a id="section-10" />{{ $t('persons_associated.title') }}</h2>
<h2><a id="section-10" />{{ $t("persons_associated.title") }}</h2>
<div v-if="currentParticipations.length > 0">
<label class="col-form-label">{{ $tc('persons_associated.counter', counter) }}</label>
<label class="col-form-label">{{
$tc("persons_associated.counter", counter)
}}</label>
</div>
<div v-else>
<label class="chill-no-data-statement">{{ $tc('persons_associated.counter', counter) }}</label>
<label class="chill-no-data-statement">{{
$tc("persons_associated.counter", counter)
}}</label>
</div>
<div
@@ -14,22 +18,16 @@
class="alert alert-warning no-household"
>
<i class="fa fa-warning fa-2x" />
<form
method="GET"
action="/fr/person/household/members/editor"
>
<form method="GET" action="/fr/person/household/members/editor">
<div class="float-button bottom">
<div class="box">
<div class="action">
<button
class="btn btn-update"
type="submit"
>
{{ $t('persons_associated.update_household') }}
<button class="btn btn-update" type="submit">
{{ $t("persons_associated.update_household") }}
</button>
</div>
<p class="mb-3">
{{ $t('persons_associated.person_without_household_warning') }}
{{ $t("persons_associated.person_without_household_warning") }}
</p>
<div
class="form-check"
@@ -43,26 +41,18 @@
checked="checked"
:id="p.person.id"
:value="p.person.id"
>
/>
<label class="form-check-label">
<person-text :person="p.person" />
</label>
</div>
<input
type="hidden"
name="expand_suggestions"
value="true"
>
<input
type="hidden"
name="returnPath"
:value="getReturnPath"
>
<input type="hidden" name="expand_suggestions" value="true" />
<input type="hidden" name="returnPath" :value="getReturnPath" />
<input
type="hidden"
name="accompanying_period_id"
:value="courseId"
>
/>
</div>
</div>
</form>
@@ -107,155 +97,170 @@
</ul>
</div>
<div
v-if="!isParticipationValid"
class="alert alert-warning to-confirm"
>
{{ $t('persons_associated.participation_not_valid') }}
<div v-if="!isParticipationValid" class="alert alert-warning to-confirm">
{{ $t("persons_associated.participation_not_valid") }}
</div>
</div>
</template>
<script>
import {mapGetters, mapState} from 'vuex';
import { mapGetters, mapState } from "vuex";
import ParticipationItem from "./PersonsAssociated/ParticipationItem.vue";
import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue';
import PersonText from 'ChillPersonAssets/vuejs/_components/Entity/PersonText.vue';
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
export default {
name: 'PersonsAssociated',
components: {
ParticipationItem,
AddPersons,
PersonText
},
data() {
return {
addPersons: {
key: 'persons_associated',
options: {
type: ['person'],
priority: null,
uniq: false,
name: "PersonsAssociated",
components: {
ParticipationItem,
AddPersons,
PersonText,
},
data() {
return {
addPersons: {
key: "persons_associated",
options: {
type: ["person"],
priority: null,
uniq: false,
},
},
};
},
computed: {
...mapState({
courseId: (state) => state.accompanyingCourse.id,
participations: (state) => state.accompanyingCourse.participations,
suggestedPersons: (state) =>
[
state.accompanyingCourse.requestor,
...state.accompanyingCourse.resources.map((r) => r.resource),
]
.filter((e) => e !== null)
.filter((e) => e.type === "person")
.filter(
(p) =>
!state.accompanyingCourse.participations
.filter((pa) => pa.endDate === null)
.map((pa) => pa.person.id)
.includes(p.id),
)
// filter persons appearing twice in requestor and resources
.filter((e, index, suggested) => {
for (let i = 0; i < suggested.length; i = i + 1) {
if (i < index && e.id === suggested[i].id) {
return false;
}
}
}
}
},
computed: {
...mapState({
courseId: state => state.accompanyingCourse.id,
participations: state => state.accompanyingCourse.participations,
suggestedPersons: state => [
state.accompanyingCourse.requestor,
...state.accompanyingCourse.resources.map(r => r.resource)
]
.filter((e) => e !== null)
.filter((e) => e.type === 'person')
.filter(
(p) => !state.accompanyingCourse.participations.filter(pa => pa.endDate === null).map((pa) => pa.person.id).includes(p.id)
)
// filter persons appearing twice in requestor and resources
.filter(
(e, index, suggested) => {
for (let i = 0; i < suggested.length; i = i+1) {
if (i < index && e.id === suggested[i].id) {
return false
}
}
return true;
return true;
}),
}),
...mapGetters(["isParticipationValid"]),
currentParticipations() {
return this.participations.filter((p) => p.endDate === null);
},
counter() {
return this.currentParticipations.length;
},
participationWithoutHousehold() {
return this.currentParticipations.filter(
(p) => p.person.current_household_id === null,
);
},
getReturnPath() {
return (
window.location.pathname + window.location.search + window.location.hash
);
},
},
methods: {
removeParticipation(item) {
this.$store
.dispatch("removeParticipation", item)
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
closeParticipation(item) {
this.$store
.dispatch("closeParticipation", item)
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
addNewPersons({ selected, modal }) {
selected.forEach(function (item) {
this.$store
.dispatch("addParticipation", item)
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
)
}),
...mapGetters([
'isParticipationValid'
]),
currentParticipations() {
return this.participations.filter(p => p.endDate === null)
},
counter() {
return this.currentParticipations.length;
},
participationWithoutHousehold() {
return this.currentParticipations.filter(p => p.person.current_household_id === null);
},
getReturnPath() {
return window.location.pathname + window.location.search + window.location.hash;
},
},
methods: {
removeParticipation(item) {
this.$store.dispatch('removeParticipation', item)
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
},
closeParticipation(item) {
this.$store.dispatch('closeParticipation', item)
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
},
addNewPersons({ selected, modal }) {
selected.forEach(function(item) {
this.$store.dispatch('addParticipation', item)
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
}, this
);
this.$refs.addPersons.resetSearch(); // to cast child method
modal.showModal = false;
},
addSuggestedPerson(person) {
this.$store.dispatch('addParticipation', { result: person, type: 'person' })
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
})
},
}
}
});
}, this);
this.$refs.addPersons.resetSearch(); // to cast child method
modal.showModal = false;
},
addSuggestedPerson(person) {
this.$store
.dispatch("addParticipation", { result: person, type: "person" })
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
},
};
</script>
<style lang="scss" scoped>
div#accompanying-course {
div.vue-component {
& > div.alert.no-household {
margin: 0 0 -1em;
div.vue-component {
& > div.alert.no-household {
margin: 0 0 -1em;
}
div.no-household {
padding-bottom: 1.5em;
display: flex;
flex-direction: row;
& > i {
flex-basis: 1.5em;
flex-grow: 0;
flex-shrink: 0;
padding-top: 0.2em;
opacity: 0.75;
}
div.no-household {
padding-bottom: 1.5em;
display: flex;
flex-direction: row;
& > i {
flex-basis: 1.5em; flex-grow: 0; flex-shrink: 0;
padding-top: 0.2em;
opacity: 0.75;
}
& > form {
flex-basis: auto;
div.action {
button.btn-update {
margin-right: 2em;
}
}
}
& > form {
flex-basis: auto;
div.action {
button.btn-update {
margin-right: 2em;
}
}
}
}
}
}
}
</style>

View File

@@ -2,15 +2,15 @@
<person-render-box
render="bloc"
:options="{
addInfo : true,
addId : false,
addInfo: true,
addId: false,
addEntity: false,
addLink: false,
addHouseholdLink: false,
addAltNames: true,
addAge : true,
hLevel : 3,
isConfidential : false,
addAge: true,
hLevel: 3,
isConfidential: false,
isMultiline: true,
}"
:person="participation.person"
@@ -20,14 +20,21 @@
<div class="item-row separator">
<ul class="record_actions">
<button-location
v-if="hasCurrentHouseholdAddress && !isPersonLocatingCourse(participation.person)"
v-if="
hasCurrentHouseholdAddress &&
!isPersonLocatingCourse(participation.person)
"
:person="participation.person"
/>
<li v-if="participation.person.current_household_id">
<a
class="btn btn-sm btn-chill-beige"
:href="getCurrentHouseholdUrl"
:title="$t('persons_associated.show_household_number', { id: participation.person.current_household_id })"
:title="
$t('persons_associated.show_household_number', {
id: participation.person.current_household_id,
})
"
>
<i class="fa fa-fw fa-home" />
</a>
@@ -61,7 +68,6 @@
</template>
</person-render-box>
<teleport to="body">
<modal
v-if="modal.showModal"
@@ -70,18 +76,18 @@
>
<template #header>
<h2 class="modal-title">
{{ $t('persons_associated.sure') }}
{{ $t("persons_associated.sure") }}
</h2>
</template>
<template #body>
<p>{{ $t('persons_associated.sure_description') }}</p>
<p>{{ $t("persons_associated.sure_description") }}</p>
</template>
<template #footer>
<button
class="btn btn-danger"
@click.prevent="$emit('close', participation)"
>
{{ $t('persons_associated.ok') }}
{{ $t("persons_associated.ok") }}
</button>
</template>
</modal>
@@ -89,112 +95,141 @@
</template>
<script>
import OnTheFly from 'ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue';
import ButtonLocation from '../ButtonLocation.vue';
import PersonRenderBox from 'ChillPersonAssets/vuejs/_components/Entity/PersonRenderBox.vue';
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods';
import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue";
import ButtonLocation from "../ButtonLocation.vue";
import PersonRenderBox from "ChillPersonAssets/vuejs/_components/Entity/PersonRenderBox.vue";
import Modal from "ChillMainAssets/vuejs/_components/Modal";
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
export default {
name: 'ParticipationItem',
components: {
OnTheFly,
ButtonLocation,
PersonRenderBox,
Modal
},
props: ['participation'],
emits: ['remove', 'close'],
data() {
return {
modal: {
showModal: false,
modalDialogClass: "modal-dialog-centered modal-md"
},
PersonRenderBox: {
participation: 'participation',
options: {
addInfo: false,
addId: true,
addAge: false,
hLevel: 1
name: "ParticipationItem",
components: {
OnTheFly,
ButtonLocation,
PersonRenderBox,
Modal,
},
props: ["participation"],
emits: ["remove", "close"],
data() {
return {
modal: {
showModal: false,
modalDialogClass: "modal-dialog-centered modal-md",
},
PersonRenderBox: {
participation: "participation",
options: {
addInfo: false,
addId: true,
addAge: false,
hLevel: 1,
},
},
};
},
computed: {
hasCurrentHouseholdAddress() {
if (
!this.participation.endDate &&
this.participation.person.current_household_address !== null
) {
return true;
}
return false;
},
getAccompanyingCourseReturnPath() {
return `fr/parcours/${this.$store.state.accompanyingCourse.id}/edit#section-10`;
},
getCurrentHouseholdUrl() {
return `/fr/person/household/${this.participation.person.current_household_id}/summary?returnPath=${this.getAccompanyingCourseReturnPath}`;
},
},
methods: {
isPersonLocatingCourse(person) {
return this.$store.getters.isPersonLocatingCourse(person);
},
saveFormOnTheFly(payload) {
console.log(
"saveFormOnTheFly: type",
payload.type,
", data",
payload.data,
);
payload.target = "participation";
let body = { type: payload.type };
if (payload.type === "person") {
body.firstName = payload.data.firstName;
body.lastName = payload.data.lastName;
if (payload.data.birthdate !== null) {
body.birthdate = payload.data.birthdate;
}
body.phonenumber = payload.data.phonenumber;
body.mobilenumber = payload.data.mobilenumber;
body.email = payload.data.email;
body.altNames = payload.data.altNames;
body.gender = {
id: payload.data.gender.id,
type: payload.data.gender.type,
};
if (payload.data.civility !== null) {
body.civility = {
id: payload.data.civility.id,
type: payload.data.civility.type,
};
}
makeFetch(
"PATCH",
`/api/1.0/person/person/${payload.data.id}.json`,
body,
)
.then((response) => {
this.$store.dispatch("addPerson", {
target: payload.target,
body: response,
});
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === "ValidationException") {
for (let v of error.violations) {
this.$toast.open({ message: v });
}
} else {
this.$toast.open({ message: "An error occurred" });
}
},
});
} else if (payload.type === "thirdparty") {
body.name = payload.data.text;
body.email = payload.data.email;
body.telephone = payload.data.phonenumber;
body.address = { id: payload.data.address.address_id };
makeFetch(
"PATCH",
`/api/1.0/thirdparty/thirdparty/${payload.data.id}.json`,
body,
)
.then((response) => {
this.$store.dispatch("addThirdparty", {
target: payload.target,
body: response,
});
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === "ValidationException") {
for (let v of error.violations) {
this.$toast.open({ message: v });
}
} else {
this.$toast.open({ message: "An error occurred" });
}
});
}
},
computed: {
hasCurrentHouseholdAddress() {
if ( !this.participation.endDate
&& this.participation.person.current_household_address !== null ) {
return true;
}
return false;
},
getAccompanyingCourseReturnPath() {
return `fr/parcours/${this.$store.state.accompanyingCourse.id}/edit#section-10`;
},
getCurrentHouseholdUrl() {
return `/fr/person/household/${this.participation.person.current_household_id}/summary?returnPath=${this.getAccompanyingCourseReturnPath}`
},
},
methods: {
isPersonLocatingCourse(person) {
return this.$store.getters.isPersonLocatingCourse(person);
},
saveFormOnTheFly(payload) {
console.log('saveFormOnTheFly: type', payload.type, ', data', payload.data);
payload.target = 'participation';
let body = { type: payload.type };
if (payload.type === 'person') {
body.firstName = payload.data.firstName;
body.lastName = payload.data.lastName;
if (payload.data.birthdate !== null) { body.birthdate = payload.data.birthdate; }
body.phonenumber = payload.data.phonenumber;
body.mobilenumber = payload.data.mobilenumber;
body.email = payload.data.email;
body.altNames = payload.data.altNames;
body.gender = {id: payload.data.gender.id, type: payload.data.gender.type };
if (payload.data.civility !== null) { body.civility = {id: payload.data.civility.id, type: payload.data.civility.type }; }
makeFetch('PATCH', `/api/1.0/person/person/${payload.data.id}.json`, body)
.then(response => {
this.$store.dispatch('addPerson', { target: payload.target, body: response });
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {
for (let v of error.violations) {
this.$toast.open({message: v });
}
} else {
this.$toast.open({message: 'An error occurred'});
}
})
}
else if (payload.type === 'thirdparty') {
body.name = payload.data.text;
body.email = payload.data.email;
body.telephone = payload.data.phonenumber;
body.address = { id: payload.data.address.address_id };
makeFetch('PATCH', `/api/1.0/thirdparty/thirdparty/${payload.data.id}.json`, body)
.then(response => {
this.$store.dispatch('addThirdparty', { target: payload.target, body: response })
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {
for (let v of error.violations) {
this.$toast.open({message: v });
}
} else {
this.$toast.open({message: 'An error occurred'});
}
})
}
}
}
}
},
},
};
</script>

View File

@@ -1,6 +1,6 @@
<template>
<div class="vue-component">
<h2><a id="section-80" />{{ $t('referrer.title') }}</h2>
<h2><a id="section-80" />{{ $t("referrer.title") }}</h2>
<teleport to="body">
<modal
@@ -10,33 +10,31 @@
>
<template #header>
<h3 class="modal-title">
{{ $t('confirm.title') }}
{{ $t("confirm.title") }}
</h3>
</template>
<template #body-head>
<div class="modal-body">
<p v-html="$t('confirm.sure_referrer', { referrer: this.value.text })" />
<p
v-html="
$t('confirm.sure_referrer', { referrer: this.value.text })
"
/>
</div>
</template>
<template #footer>
<button
class="btn btn-save"
@click.prevent="this.confirmReferrer"
>
{{ $t('confirm.ok_referrer') }}
<button class="btn btn-save" @click.prevent="this.confirmReferrer">
{{ $t("confirm.ok_referrer") }}
</button>
</template>
</modal>
</teleport>
<div>
<label
class="col-form-label"
for="selectJob"
>
{{ $t('job.label') }}
<label class="col-form-label" for="selectJob">
{{ $t("job.label") }}
</label>
<VueMultiselect
@@ -54,11 +52,8 @@
:selected-label="$t('multiselect.selected_label')"
/>
<label
class="col-form-label"
for="selectReferrer"
>
{{ $t('referrer.label') }}
<label class="col-form-label" for="selectReferrer">
{{ $t("referrer.label") }}
</label>
<VueMultiselect
@@ -101,55 +96,57 @@
name="button"
@click="assignMe"
>
{{ $t('referrer.assign_me') }}
{{ $t("referrer.assign_me") }}
</button>
</li>
</ul>
</div>
<div
v-if="!isJobValid"
class="alert alert-warning to-confirm"
>
{{ $t('job.not_valid') }}
<div v-if="!isJobValid" class="alert alert-warning to-confirm">
{{ $t("job.not_valid") }}
</div>
</div>
</template>
<script>
import VueMultiselect from 'vue-multiselect';
import {makeFetch} from 'ChillMainAssets/lib/api/apiMethods';
import {mapState, mapGetters} from 'vuex';
import VueMultiselect from "vue-multiselect";
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
import { mapState, mapGetters } from "vuex";
import UserRenderBoxBadge from "ChillMainAssets/vuejs/_components/Entity/UserRenderBoxBadge";
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
import Modal from "ChillMainAssets/vuejs/_components/Modal";
export default {
name: "Referrer",
components: {
UserRenderBoxBadge,
VueMultiselect,
Modal
Modal,
},
data() {
return {
jobs: [],
modal: {
showModal: false,
modalDialogClass: "modal-dialog-scrollable modal-xl"
modalDialogClass: "modal-dialog-scrollable modal-xl",
},
value: this.$store.state.accompanyingCourse.user,
confirmed: false
}
confirmed: false,
};
},
computed: {
...mapState({
valueJob: state => state.accompanyingCourse.job,
valueJob: (state) => state.accompanyingCourse.job,
}),
...mapGetters(['isJobValid', 'usersSuggestedFilteredByJob']),
...mapGetters(["isJobValid", "usersSuggestedFilteredByJob"]),
users: function () {
let users = this.$store.getters.usersFilteredByJob;
// ensure that the selected user is in the list. add it if necessary
if (this.$store.state.accompanyingCourse.user !== null && users.find(u => this.$store.state.accompanyingCourse.user.id === u.id) === undefined) {
if (
this.$store.state.accompanyingCourse.user !== null &&
users.find(
(u) => this.$store.state.accompanyingCourse.user.id === u.id,
) === undefined
) {
users.push(this.$store.state.accompanyingCourse.user);
}
return users;
@@ -159,15 +156,18 @@ export default {
return this.$store.state.accompanyingCourse.job;
},
set(value) {
this.$store.dispatch('updateJob', value)
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
}
this.$store
.dispatch("updateJob", value)
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
},
},
mounted() {
@@ -179,57 +179,62 @@ export default {
this.toggleModal();
},
getJobs() {
const url = '/api/1.0/main/user-job.json';
makeFetch('GET', url)
.then(response => {
this.jobs = response.results;
})
.catch((error) => {
this.$toast.open({message: error.txt})
})
const url = "/api/1.0/main/user-job.json";
makeFetch("GET", url)
.then((response) => {
this.jobs = response.results;
})
.catch((error) => {
this.$toast.open({ message: error.txt });
});
},
customJobLabel(value) {
return value.label.fr;
},
assignMe() {
const url = `/api/1.0/main/whoami.json`;
makeFetch('GET', url)
.then(user => {
// this.value = user
this.updateReferrer(user);
})
makeFetch("GET", url).then((user) => {
// this.value = user
this.updateReferrer(user);
});
},
toggleModal() {
this.modal.showModal = !this.modal.showModal;
},
confirmReferrer() {
this.$store.dispatch('updateReferrer', this.value)
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
this.toggleModal()
this.$store
.dispatch("updateReferrer", this.value)
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
this.toggleModal();
},
removeReferrer() {
console.log('remove option')
this.$store.dispatch('updateReferrer', null)
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
console.log("remove option");
this.$store
.dispatch("updateReferrer", null)
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
cancelChange() {
this.value = this.$store.state.accompanyingCourse.user
this.toggleModal()
}
}
}
this.value = this.$store.state.accompanyingCourse.user;
this.toggleModal();
},
},
};
</script>
<style src="vue-multiselect/dist/vue-multiselect.css"></style>

View File

@@ -1,18 +1,11 @@
<template>
<div class="vue-component">
<h2><a id="section-50" />{{ $t('requestor.title') }}</h2>
<h2><a id="section-50" />{{ $t("requestor.title") }}</h2>
<div
v-if="accompanyingCourse.requestor && isAnonymous"
class="flex-table"
>
<div v-if="accompanyingCourse.requestor && isAnonymous" class="flex-table">
<label>
<input
type="checkbox"
v-model="requestorIsAnonymous"
class="me-2"
>
{{ $t('requestor.is_anonymous') }}
<input type="checkbox" v-model="requestorIsAnonymous" class="me-2" />
{{ $t("requestor.is_anonymous") }}
</label>
<confidential v-if="accompanyingCourse.requestor.type === 'thirdparty'">
<template #confidential-content>
@@ -25,7 +18,7 @@
addInfo: false,
hLevel: 3,
isMultiline: true,
isConfidential: true
isConfidential: true,
}"
>
<template #record-actions>
@@ -100,7 +93,7 @@
:title="$t('action.remove')"
@click="removeRequestor"
>
{{ $t('action.remove') }}
{{ $t("action.remove") }}
</button>
</li>
</ul>
@@ -111,12 +104,8 @@
class="flex-table"
>
<label>
<input
type="checkbox"
v-model="requestorIsAnonymous"
class="me-2"
>
{{ $t('requestor.is_anonymous') }}
<input type="checkbox" v-model="requestorIsAnonymous" class="me-2" />
{{ $t("requestor.is_anonymous") }}
</label>
<third-party-render-box
@@ -129,7 +118,7 @@
addInfo: false,
hLevel: 3,
isMultiline: true,
isConfidential: true
isConfidential: true,
}"
>
<template #record-actions>
@@ -166,7 +155,7 @@
addInfo: true,
hLevel: 3,
isMultiline: true,
isConfidential: false
isConfidential: false,
}"
>
<template #record-actions>
@@ -198,27 +187,30 @@
:title="$t('action.remove')"
@click="removeRequestor"
>
{{ $t('action.remove') }}
{{ $t("action.remove") }}
</button>
</li>
</ul>
</div>
<div v-else>
<label class="chill-no-data-statement">{{ $t('requestor.counter') }}</label>
<label class="chill-no-data-statement">{{
$t("requestor.counter")
}}</label>
</div>
<div v-if="accompanyingCourse.requestor === null && suggestedEntities.length > 0">
<div
v-if="
accompanyingCourse.requestor === null && suggestedEntities.length > 0
"
>
<ul class="list-suggest add-items inline">
<li
v-for="p in suggestedEntities"
:key="uniqueId(p)"
@click="addSuggestedEntity(p)"
>
<person-text
v-if="p.type === 'person'"
:person="p"
/>
<person-text v-if="p.type === 'person'" :person="p" />
<span v-else>{{ p.text }}</span>
</li>
</ul>
@@ -245,183 +237,217 @@
</template>
<script>
import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue';
import OnTheFly from 'ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue';
import PersonRenderBox from '../../_components/Entity/PersonRenderBox.vue';
import ThirdPartyRenderBox from 'ChillThirdPartyAssets/vuejs/_components/Entity/ThirdPartyRenderBox.vue';
import Confidential from 'ChillMainAssets/vuejs/_components/Confidential.vue';
import { mapState } from 'vuex';
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods';
import PersonText from 'ChillPersonAssets/vuejs/_components/Entity/PersonText.vue';
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue";
import PersonRenderBox from "../../_components/Entity/PersonRenderBox.vue";
import ThirdPartyRenderBox from "ChillThirdPartyAssets/vuejs/_components/Entity/ThirdPartyRenderBox.vue";
import Confidential from "ChillMainAssets/vuejs/_components/Confidential.vue";
import { mapState } from "vuex";
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
export default {
name: 'Requestor',
components: {
AddPersons,
OnTheFly,
PersonRenderBox,
ThirdPartyRenderBox,
Confidential,
PersonText
},
props: ['isAnonymous'],
data() {
return {
addPersons: {
key: 'requestor',
options: {
type: ['person', 'thirdparty'],
priority: null,
uniq: true,
}
},
}
},
computed: {
...mapState({
suggestedEntities: state => {
return [
...state.accompanyingCourse.participations.filter((p) => p.endDate === null).map((p) => p.person),
...state.accompanyingCourse.resources.map(r => r.resource)
]
.filter((e) => e !== null)
// filter for same entity appearing twice
.filter((e, index, suggested) => {
for (let i = 0; i < suggested.length; i = i+1) {
if (i < index && e.id === suggested[i].id && e.type === suggested[i].type) {
return false
}
}
return true;
})
}
}),
accompanyingCourse() {
return this.$store.state.accompanyingCourse
name: "Requestor",
components: {
AddPersons,
OnTheFly,
PersonRenderBox,
ThirdPartyRenderBox,
Confidential,
PersonText,
},
props: ["isAnonymous"],
data() {
return {
addPersons: {
key: "requestor",
options: {
type: ["person", "thirdparty"],
priority: null,
uniq: true,
},
},
requestorIsAnonymous: {
set(value) {
this.$store.dispatch('requestorIsAnonymous', value);
},
get() {
return this.$store.state.accompanyingCourse.requestorAnonymous;
}
}
},
methods: {
removeRequestor() {
//console.log('@@ CLICK remove requestor: item');
this.$store.dispatch('removeRequestor')
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
},
addNewPersons({ selected, modal }) {
//console.log('@@@ CLICK button addNewPersons', selected);
this.$store.dispatch('addRequestor', selected.shift())
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
};
},
computed: {
...mapState({
suggestedEntities: (state) => {
return (
[
...state.accompanyingCourse.participations
.filter((p) => p.endDate === null)
.map((p) => p.person),
...state.accompanyingCourse.resources.map((r) => r.resource),
]
.filter((e) => e !== null)
// filter for same entity appearing twice
.filter((e, index, suggested) => {
for (let i = 0; i < suggested.length; i = i + 1) {
if (
i < index &&
e.id === suggested[i].id &&
e.type === suggested[i].type
) {
return false;
}
}
this.$refs.addPersons.resetSearch(); // to cast child method
modal.showModal = false;
},
saveFormOnTheFly(payload) {
console.log('saveFormOnTheFly: type', payload.type, ', data', payload.data);
payload.target = 'requestor';
let body = { type: payload.type };
if (payload.type === 'person') {
body.firstName = payload.data.firstName;
body.lastName = payload.data.lastName;
if (payload.data.birthdate !== null) { body.birthdate = payload.data.birthdate; }
body.phonenumber = payload.data.phonenumber;
body.mobilenumber = payload.data.mobilenumber;
body.email = payload.data.email;
body.altNames = payload.data.altNames;
body.gender = payload.data.gender;
makeFetch('PATCH', `/api/1.0/person/person/${payload.data.id}.json`, body)
.then(response => {
this.$store.dispatch('addPerson', { target: payload.target, body: response })
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {
for (let v of error.violations) {
this.$toast.open({message: v });
}
} else {
this.$toast.open({message: 'An error occurred'});
}
})
}
else if (payload.type === 'thirdparty') {
body.name = payload.data.text;
body.email = payload.data.email;
body.telephone = payload.data.phonenumber;
if (payload.data.address) {
body.address = { id: payload.data.address.address_id };
}
makeFetch('PATCH', `/api/1.0/thirdparty/thirdparty/${payload.data.id}.json`, body)
.then(response => {
this.$store.dispatch('addThirdparty', { target: payload.target, body: response })
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {
for (let v of error.violations) {
this.$toast.open({message: v });
}
} else {
this.$toast.open({message: 'An error occurred'});
}
})
}
},
addSuggestedEntity(e) {
this.$store.dispatch('addRequestor', { result: e, type: e.type })
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
return true;
})
);
},
uniqueId(e) {
return `${e.type}-${e.id}`;
}),
accompanyingCourse() {
return this.$store.state.accompanyingCourse;
},
requestorIsAnonymous: {
set(value) {
this.$store.dispatch("requestorIsAnonymous", value);
},
get() {
return this.$store.state.accompanyingCourse.requestorAnonymous;
},
},
},
methods: {
removeRequestor() {
//console.log('@@ CLICK remove requestor: item');
this.$store.dispatch("removeRequestor").catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
addNewPersons({ selected, modal }) {
//console.log('@@@ CLICK button addNewPersons', selected);
this.$store
.dispatch("addRequestor", selected.shift())
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
this.$refs.addPersons.resetSearch(); // to cast child method
modal.showModal = false;
},
saveFormOnTheFly(payload) {
console.log(
"saveFormOnTheFly: type",
payload.type,
", data",
payload.data,
);
payload.target = "requestor";
let body = { type: payload.type };
if (payload.type === "person") {
body.firstName = payload.data.firstName;
body.lastName = payload.data.lastName;
if (payload.data.birthdate !== null) {
body.birthdate = payload.data.birthdate;
}
body.phonenumber = payload.data.phonenumber;
body.mobilenumber = payload.data.mobilenumber;
body.email = payload.data.email;
body.altNames = payload.data.altNames;
body.gender = payload.data.gender;
makeFetch(
"PATCH",
`/api/1.0/person/person/${payload.data.id}.json`,
body,
)
.then((response) => {
this.$store.dispatch("addPerson", {
target: payload.target,
body: response,
});
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === "ValidationException") {
for (let v of error.violations) {
this.$toast.open({ message: v });
}
} else {
this.$toast.open({ message: "An error occurred" });
}
});
} else if (payload.type === "thirdparty") {
body.name = payload.data.text;
body.email = payload.data.email;
body.telephone = payload.data.phonenumber;
if (payload.data.address) {
body.address = { id: payload.data.address.address_id };
}
makeFetch(
"PATCH",
`/api/1.0/thirdparty/thirdparty/${payload.data.id}.json`,
body,
)
.then((response) => {
this.$store.dispatch("addThirdparty", {
target: payload.target,
body: response,
});
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === "ValidationException") {
for (let v of error.violations) {
this.$toast.open({ message: v });
}
} else {
this.$toast.open({ message: "An error occurred" });
}
});
}
}
}
},
addSuggestedEntity(e) {
this.$store
.dispatch("addRequestor", { result: e, type: e.type })
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
uniqueId(e) {
return `${e.type}-${e.id}`;
},
},
};
</script>
<style lang="scss" scoped>
div.flex-table {
margin: 1em 0 0 !important;
& > label,
& > ul.record_actions {
margin: 1em 3em 0 !important;
}
div.item-bloc {
background-color: white !important;
margin-top: 1em;
}
margin: 1em 0 0 !important;
& > label,
& > ul.record_actions {
margin: 1em 3em 0 !important;
}
div.item-bloc {
background-color: white !important;
margin-top: 1em;
}
}
.confidential {
display: block;
margin-right: 0px !important;
display: block;
margin-right: 0px !important;
}
</style>

View File

@@ -1,12 +1,16 @@
<template>
<div class="vue-component">
<h2><a id="section-90" />{{ $t('resources.title') }}</h2>
<h2><a id="section-90" />{{ $t("resources.title") }}</h2>
<div v-if="resources.length > 0">
<label class="col-form-label">{{ $tc('resources.counter', counter) }}</label>
<label class="col-form-label">{{
$tc("resources.counter", counter)
}}</label>
</div>
<div v-else>
<label class="chill-no-data-statement">{{ $tc('resources.counter', counter) }}</label>
<label class="chill-no-data-statement">{{
$tc("resources.counter", counter)
}}</label>
</div>
<div class="flex-table mb-3">
@@ -25,10 +29,7 @@
:key="uniqueId(p)"
@click="addSuggestedEntity(p)"
>
<person-text
v-if="p.type === 'person'"
:person="p"
/>
<person-text v-if="p.type === 'person'" :person="p" />
<span v-else>{{ p.text }}</span>
</li>
</ul>
@@ -54,115 +55,123 @@
</template>
<script>
import { mapState } from 'vuex';
import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue';
import ResourceItem from './Resources/ResourceItem.vue';
import PersonText from 'ChillPersonAssets/vuejs/_components/Entity/PersonText.vue';
import { mapState } from "vuex";
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
import ResourceItem from "./Resources/ResourceItem.vue";
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
export default {
name: 'Resources',
components: {
AddPersons,
ResourceItem,
PersonText
},
data() {
return {
addPersons: {
key: 'resources',
options: {
type: ['person', 'thirdparty'],
priority: null,
uniq: false,
name: "Resources",
components: {
AddPersons,
ResourceItem,
PersonText,
},
data() {
return {
addPersons: {
key: "resources",
options: {
type: ["person", "thirdparty"],
priority: null,
uniq: false,
},
},
};
},
computed: mapState({
resources: (state) => state.accompanyingCourse.resources,
counter: (state) => state.accompanyingCourse.resources.length,
suggestedEntities: (state) =>
[
state.accompanyingCourse.requestor,
...state.accompanyingCourse.participations
.filter((p) => p.endDate === null)
.map((p) => p.person),
]
.filter((e) => e !== null)
.filter((e) => {
if (e.type === "person") {
return !state.accompanyingCourse.resources
.filter((r) => r.resource.type === "person")
.map((r) => r.resource.id)
.includes(e.id);
}
if (e.type === "thirdparty") {
return !state.accompanyingCourse.resources
.filter((r) => r.resource.type === "thirdparty")
.map((r) => r.resource.id)
.includes(e.id);
}
})
// filter persons appearing twice in requestor and resources
.filter((e, index, suggested) => {
for (let i = 0; i < suggested.length; i = i + 1) {
if (i < index && e.id === suggested[i].id) {
return false;
}
}
}
},
computed: mapState({
resources: state => state.accompanyingCourse.resources,
counter: state => state.accompanyingCourse.resources.length,
suggestedEntities: state => [
state.accompanyingCourse.requestor,
...state.accompanyingCourse.participations.filter((p) => p.endDate === null).map((p) => p.person),
]
.filter((e) => e !== null)
.filter(
(e) => {
if (e.type === 'person') {
return !state.accompanyingCourse.resources
.filter((r) => r.resource.type === 'person')
.map((r) => r.resource.id).includes(e.id)
}
if (e.type === 'thirdparty') {
return !state.accompanyingCourse.resources
.filter((r) => r.resource.type === 'thirdparty')
.map((r) => r.resource.id).includes(e.id)
}
}
)
// filter persons appearing twice in requestor and resources
.filter(
(e, index, suggested) => {
for (let i = 0; i < suggested.length; i = i+1) {
if (i < index && e.id === suggested[i].id) {
return false
}
}
}
return true;
return true;
}),
}),
methods: {
removeResource(item) {
//console.log('@@ CLICK remove resource: item', item);
this.$store
.dispatch("removeResource", item)
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
addNewPersons({ selected, modal }) {
//console.log('@@@ CLICK button addNewPersons', selected);
selected.forEach(function (item) {
this.$store
.dispatch("addResource", item)
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: violations });
}
)
}),
methods: {
removeResource(item) {
//console.log('@@ CLICK remove resource: item', item);
this.$store.dispatch('removeResource', item)
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
},
addNewPersons({ selected, modal }) {
//console.log('@@@ CLICK button addNewPersons', selected);
selected.forEach(function(item) {
this.$store.dispatch('addResource', item)
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: violations})
}
});
}, this
);
this.$refs.addPersons.resetSearch(); // to cast child method
modal.showModal = false;
},
addSuggestedEntity(e) {
this.$store.dispatch('addResource', { result: e, type: e.type})
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
})
},
uniqueId(e) {
return `${e.type}-${e.id}`;
}
}
}
});
}, this);
this.$refs.addPersons.resetSearch(); // to cast child method
modal.showModal = false;
},
addSuggestedEntity(e) {
this.$store
.dispatch("addResource", { result: e, type: e.type })
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
uniqueId(e) {
return `${e.type}-${e.id}`;
},
},
};
</script>
<style lang="scss">
div.flex-bloc {
div.item-bloc {
flex-basis: 50%;
}
div.item-bloc {
flex-basis: 50%;
}
}
</style>

View File

@@ -4,14 +4,14 @@
v-if="resource.resource.type === 'person'"
:person="resource.resource"
:options="{
addInfo : true,
addId : false,
addInfo: true,
addId: false,
addEntity: true,
addLink: false,
addAltNames: true,
addAge : false,
hLevel : 3,
isConfidential : true
addAge: false,
hLevel: 3,
isConfidential: true,
}"
>
<template #end-bloc>
@@ -57,11 +57,11 @@
v-if="resource.resource.type === 'thirdparty'"
:thirdparty="resource.resource"
:options="{
addLink : false,
addId : false,
addLink: false,
addId: false,
addEntity: true,
addInfo: false,
hLevel: 3
hLevel: 3,
}"
>
<template #end-bloc>
@@ -105,108 +105,136 @@
</template>
<script>
import OnTheFly from 'ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue';
import PersonRenderBox from 'ChillPersonAssets/vuejs/_components/Entity/PersonRenderBox.vue';
import ThirdPartyRenderBox from 'ChillThirdPartyAssets/vuejs/_components/Entity/ThirdPartyRenderBox.vue';
import WriteComment from './WriteComment';
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods';
import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue";
import PersonRenderBox from "ChillPersonAssets/vuejs/_components/Entity/PersonRenderBox.vue";
import ThirdPartyRenderBox from "ChillThirdPartyAssets/vuejs/_components/Entity/ThirdPartyRenderBox.vue";
import WriteComment from "./WriteComment";
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
export default {
name: 'ResourceItem',
components: {
OnTheFly,
PersonRenderBox,
ThirdPartyRenderBox,
WriteComment
},
props: ['resource'],
emits: ['remove'],
computed: {
parent() {
return {
'type': this.resource.type,
'id': this.resource.id,
'comment': this.resource.comment,
'parent': {
'type': this.$store.state.accompanyingCourse.type,
'id': this.$store.state.accompanyingCourse.id
}
}
},
hasCurrentHouseholdAddress() {
if ( this.resource.resource.current_household_address !== null ) {
return true;
}
return false;
name: "ResourceItem",
components: {
OnTheFly,
PersonRenderBox,
ThirdPartyRenderBox,
WriteComment,
},
props: ["resource"],
emits: ["remove"],
computed: {
parent() {
return {
type: this.resource.type,
id: this.resource.id,
comment: this.resource.comment,
parent: {
type: this.$store.state.accompanyingCourse.type,
id: this.$store.state.accompanyingCourse.id,
},
};
},
hasCurrentHouseholdAddress() {
if (this.resource.resource.current_household_address !== null) {
return true;
}
},
methods: {
saveFormOnTheFly(payload) {
// console.log('saveFormOnTheFly: type', payload.type, ', data', payload.data);
payload.target = 'resource';
return false;
},
},
methods: {
saveFormOnTheFly(payload) {
// console.log('saveFormOnTheFly: type', payload.type, ', data', payload.data);
payload.target = "resource";
let body = { type: payload.type };
if (payload.type === 'person') {
body.firstName = payload.data.firstName;
body.lastName = payload.data.lastName;
if (payload.data.birthdate !== null) { body.birthdate = payload.data.birthdate; }
body.phonenumber = payload.data.phonenumber;
body.mobilenumber = payload.data.mobilenumber;
body.email = payload.data.email;
body.altNames = payload.data.altNames;
body.gender = {id: payload.data.gender.id, type: payload.data.gender.type };
if (payload.data.civility !== null) { body.civility = {id: payload.data.civility.id, type: payload.data.civility.type}; }
let body = { type: payload.type };
if (payload.type === "person") {
body.firstName = payload.data.firstName;
body.lastName = payload.data.lastName;
if (payload.data.birthdate !== null) {
body.birthdate = payload.data.birthdate;
}
body.phonenumber = payload.data.phonenumber;
body.mobilenumber = payload.data.mobilenumber;
body.email = payload.data.email;
body.altNames = payload.data.altNames;
body.gender = {
id: payload.data.gender.id,
type: payload.data.gender.type,
};
if (payload.data.civility !== null) {
body.civility = {
id: payload.data.civility.id,
type: payload.data.civility.type,
};
}
makeFetch('PATCH', `/api/1.0/person/person/${payload.data.id}.json`, body)
.then(response => {
this.$store.dispatch('addPerson', { target: payload.target, body: response })
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {
for (let v of error.violations) {
this.$toast.open({message: v });
}
} else {
this.$toast.open({message: 'An error occurred'});
}
})
}
else if (payload.type === 'thirdparty') {
// console.log('data', payload.data)
body.firstname = payload.data.firstname;
body.name = payload.data.name;
body.email = payload.data.email;
body.telephone = payload.data.telephone;
body.address = payload.data.address ? { id: payload.data.address.address_id } : null;
if (null !== payload.data.civility) {
body.civility = {type: 'chill_main_civility', id: payload.data.civility.id};
makeFetch(
"PATCH",
`/api/1.0/person/person/${payload.data.id}.json`,
body,
)
.then((response) => {
this.$store.dispatch("addPerson", {
target: payload.target,
body: response,
});
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === "ValidationException") {
for (let v of error.violations) {
this.$toast.open({ message: v });
}
} else {
this.$toast.open({ message: "An error occurred" });
}
if (null !== payload.data.profession) {
body.profession = payload.data.profession;
}
// console.log('body', body);
});
} else if (payload.type === "thirdparty") {
// console.log('data', payload.data)
body.firstname = payload.data.firstname;
body.name = payload.data.name;
body.email = payload.data.email;
body.telephone = payload.data.telephone;
body.address = payload.data.address
? { id: payload.data.address.address_id }
: null;
if (null !== payload.data.civility) {
body.civility = {
type: "chill_main_civility",
id: payload.data.civility.id,
};
}
if (null !== payload.data.profession) {
body.profession = payload.data.profession;
}
// console.log('body', body);
makeFetch('PATCH', `/api/1.0/thirdparty/thirdparty/${payload.data.id}.json`, body)
.then(response => {
this.$store.dispatch('addThirdparty', { target: payload.target, body: response })
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {
for (let v of error.violations) {
this.$toast.open({message: v });
}
} else {
this.$toast.open({message: 'An error occurred'});
}
})
}
},
updateComment(resource) {
console.log('updateComment', resource);
this.$store.commit('updateResource', resource);
makeFetch(
"PATCH",
`/api/1.0/thirdparty/thirdparty/${payload.data.id}.json`,
body,
)
.then((response) => {
this.$store.dispatch("addThirdparty", {
target: payload.target,
body: response,
});
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === "ValidationException") {
for (let v of error.violations) {
this.$toast.open({ message: v });
}
} else {
this.$toast.open({ message: "An error occurred" });
}
});
}
}
}
},
updateComment(resource) {
console.log("updateComment", resource);
this.$store.commit("updateResource", resource);
},
},
};
</script>

View File

@@ -3,7 +3,7 @@
class="btn btn-sm btn-misc change-icon"
:title="$t('write_comment')"
@click="openModal"
><i class="fa fa-pencil-square-o" />
><i class="fa fa-pencil-square-o" />
</a>
<teleport to="body">
@@ -14,7 +14,7 @@
>
<template #header>
<h3 class="modal-title">
{{ $t('write_comment_about', { 'r': resource.resource.text }) }}
{{ $t("write_comment_about", { r: resource.resource.text }) }}
</h3>
</template>
<template #body>
@@ -27,11 +27,8 @@
/>
</template>
<template #footer>
<a
class="btn btn-save"
@click="saveAction"
>
{{ $t('action.save') }}
<a class="btn btn-save" @click="saveAction">
{{ $t("action.save") }}
</a>
</template>
</modal>
@@ -39,79 +36,76 @@
</template>
<script>
import Modal from 'ChillMainAssets/vuejs/_components/Modal.vue';
import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
import CKEditor from '@ckeditor/ckeditor5-vue';
import CKEditor from "@ckeditor/ckeditor5-vue";
import ClassicEditor from "ChillMainAssets/module/ckeditor5/editor_config";
export default {
name: "WriteComment",
components: {
Modal,
ckeditor: CKEditor.component,
},
props: ['resource'],
emits: ['updateComment'],
data() {
return {
modal: {
showModal: false,
modalDialogClass: "modal-dialog-scrollable modal-xl"
},
editor: ClassicEditor,
formdata: {
content: this.resource.comment
}
}
},
i18n: {
messages: {
fr: {
write_comment: "Écrire un commentaire",
write_comment_about: "Écrire un commentaire à propos de {r}",
comment_placeholder: "Commencez à écrire..."
}
}
},
computed: {
content: {
set(value) {
this.formdata.content = value;
},
get() {
return this.formdata.content;
}
name: "WriteComment",
components: {
Modal,
ckeditor: CKEditor.component,
},
props: ["resource"],
emits: ["updateComment"],
data() {
return {
modal: {
showModal: false,
modalDialogClass: "modal-dialog-scrollable modal-xl",
},
},
methods: {
openModal() {
//console.log('write comment for', this.resource.resource.type, this.resource.resource.id);
this.modal.showModal = true;
editor: ClassicEditor,
formdata: {
content: this.resource.comment,
},
saveAction() {
//console.log('save comment', this.resource.id, this.formdata.content);
this.patchResource(this.resource.id, this.formdata.content);
};
},
i18n: {
messages: {
fr: {
write_comment: "Écrire un commentaire",
write_comment_about: "Écrire un commentaire à propos de {r}",
comment_placeholder: "Commencez à écrire...",
},
patchResource(id, comment) {
let url = `/api/1.0/person/accompanying-period/resource/${id}.json`,
body = {
"type": "accompanying_period_resource",
"comment": comment
}
;
makeFetch('PATCH', url, body)
.then(r => {
let resource = {
'type': 'accompanying_period_resource',
'id': r.id,
'comment': r.comment,
'resource': r.resource
}
this.$emit('updateComment', resource);
this.modal.showModal = false;
}
)
}
}
}
},
},
computed: {
content: {
set(value) {
this.formdata.content = value;
},
get() {
return this.formdata.content;
},
},
},
methods: {
openModal() {
//console.log('write comment for', this.resource.resource.type, this.resource.resource.id);
this.modal.showModal = true;
},
saveAction() {
//console.log('save comment', this.resource.id, this.formdata.content);
this.patchResource(this.resource.id, this.formdata.content);
},
patchResource(id, comment) {
let url = `/api/1.0/person/accompanying-period/resource/${id}.json`,
body = {
type: "accompanying_period_resource",
comment: comment,
};
makeFetch("PATCH", url, body).then((r) => {
let resource = {
type: "accompanying_period_resource",
id: r.id,
comment: r.comment,
resource: r.resource,
};
this.$emit("updateComment", resource);
this.modal.showModal = false;
});
},
},
};
</script>

View File

@@ -1,72 +1,58 @@
<template>
<div class="vue-component">
<h2><a id="section-70" />{{ $t('scopes.title') }}</h2>
<h2><a id="section-70" />{{ $t("scopes.title") }}</h2>
<div class="mb-4">
<div
class="form-check"
v-for="s in scopes"
:key="s.id"
>
<div class="form-check" v-for="s in scopes" :key="s.id">
<input
class="form-check-input"
type="checkbox"
v-model="checkedScopes"
:value="s"
>
/>
<label class="form-check-label">
{{ s.name.fr }}
</label>
</div>
</div>
<div
v-if="!isScopeValid"
class="alert alert-warning to-confirm"
>
{{ $t('scopes.add_at_least_one') }}
<div v-if="!isScopeValid" class="alert alert-warning to-confirm">
{{ $t("scopes.add_at_least_one") }}
</div>
</div>
</template>
<script>
import { mapState, mapGetters } from 'vuex';
import { mapState, mapGetters } from "vuex";
export default {
name: "Scopes",
computed: {
...mapState([
'scopes',
'scopesAtStart'
]),
...mapGetters([
'isScopeValid'
]),
...mapState(["scopes", "scopesAtStart"]),
...mapGetters(["isScopeValid"]),
checkedScopes: {
get: function() {
get: function () {
return this.$store.state.accompanyingCourse.scopes;
},
set: function(v) {
this.$store.dispatch('setScopes', v)
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
}
}
set: function (v) {
this.$store.dispatch("setScopes", v).catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
},
},
methods: {
restore() {
console.log('restore');
}
console.log("restore");
},
},
}
};
</script>
<style scoped>
</style>
<style scoped></style>

View File

@@ -1,6 +1,6 @@
<template>
<div class="vue-component">
<h2><a id="section-60" />{{ $t('social_issue.title') }}</h2>
<h2><a id="section-60" />{{ $t("social_issue.title") }}</h2>
<div class="my-4">
<!--label for="field">{{ $t('social_issue.label') }}</label
@@ -21,100 +21,95 @@
/>
</div>
<div
v-if="!isSocialIssueValid"
class="alert alert-warning to-confirm"
>
{{ $t('social_issue.not_valid') }}
<div v-if="!isSocialIssueValid" class="alert alert-warning to-confirm">
{{ $t("social_issue.not_valid") }}
</div>
</div>
</template>
<script>
import VueMultiselect from 'vue-multiselect';
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods';
import {mapGetters, mapState} from 'vuex';
import VueMultiselect from "vue-multiselect";
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
import { mapGetters, mapState } from "vuex";
export default {
name: "SocialIssue",
components: { VueMultiselect },
data() {
return {
options: []
}
},
computed: {
...mapState({
value: state => state.accompanyingCourse.socialIssues,
}),
...mapGetters([
'isSocialIssueValid'
])
},
mounted() {
this.getOptions();
},
methods: {
getOptions() {
const url = `/api/1.0/person/social-work/social-issue.json`;
makeFetch('GET', url)
.then(response => {
this.options = response.results;
return response;
})
.catch((error) => {
commit('catchError', error);
this.$toast.open({message: error.txt})
})
},
updateSocialIssues(value) {
this.$store.dispatch('updateSocialIssues', this.transformValue(value))
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
},
transformValue(updated) {
let stored = this.value;
let added = updated.filter(x => stored.indexOf(x) === -1).shift();
let removed = stored.filter(x => updated.indexOf(x) === -1).shift();
let method = (typeof removed === 'undefined') ? 'POST' : 'DELETE';
let changed = (typeof removed === 'undefined') ? added : removed;
let body = { type: "social_issue", id: changed.id };
let payload = updated;
return { payload, body, method };
}
}
}
name: "SocialIssue",
components: { VueMultiselect },
data() {
return {
options: [],
};
},
computed: {
...mapState({
value: (state) => state.accompanyingCourse.socialIssues,
}),
...mapGetters(["isSocialIssueValid"]),
},
mounted() {
this.getOptions();
},
methods: {
getOptions() {
const url = `/api/1.0/person/social-work/social-issue.json`;
makeFetch("GET", url)
.then((response) => {
this.options = response.results;
return response;
})
.catch((error) => {
commit("catchError", error);
this.$toast.open({ message: error.txt });
});
},
updateSocialIssues(value) {
this.$store
.dispatch("updateSocialIssues", this.transformValue(value))
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
transformValue(updated) {
let stored = this.value;
let added = updated.filter((x) => stored.indexOf(x) === -1).shift();
let removed = stored.filter((x) => updated.indexOf(x) === -1).shift();
let method = typeof removed === "undefined" ? "POST" : "DELETE";
let changed = typeof removed === "undefined" ? added : removed;
let body = { type: "social_issue", id: changed.id };
let payload = updated;
return { payload, body, method };
},
},
};
</script>
<style src="vue-multiselect/dist/vue-multiselect.css"></style>
<style lang="scss">
@import 'ChillMainAssets/module/bootstrap/shared';
@import 'ChillPersonAssets/chill/scss/mixins';
@import 'ChillMainAssets/chill/scss/chill_variables';
@import "ChillMainAssets/module/bootstrap/shared";
@import "ChillPersonAssets/chill/scss/mixins";
@import "ChillMainAssets/chill/scss/chill_variables";
div#accompanying-course {
span.multiselect__tag {
@include badge_social($social-issue-color);
background: $chill-l-gray;
color: $dark;
}
span.multiselect__option--highlight {
span.multiselect__tag {
@include badge_social($social-issue-color);
background: $chill-l-gray;
color: $dark;
}
span.multiselect__option--highlight {
&::after {
background: $green;
}
&.multiselect__option--selected {
&::after {
background: $green;
background: $red;
}
&.multiselect__option--selected {
&::after {
background: $red;
}
}
}
}
}
}
</style>

View File

@@ -2,7 +2,7 @@
<div class="vue-component">
<h2>
<a id="section-110" />
{{ $t('startdate.change') }}
{{ $t("startdate.change") }}
</h2>
<div>
<div class="mb-3 row">
@@ -12,7 +12,7 @@
type="date"
id="startDate"
v-model="startDateInput"
>
/>
</div>
</div>
</div>
@@ -20,55 +20,60 @@
</template>
<script>
import { dateToISO, ISOToDatetime} from 'ChillMainAssets/chill/js/date';
import { mapState } from 'vuex';
import { dateToISO, ISOToDatetime } from "ChillMainAssets/chill/js/date";
import { mapState } from "vuex";
export default {
name: 'StartDate',
data() {
return {
lastRecordedDate: null
}
name: "StartDate",
data() {
return {
lastRecordedDate: null,
};
},
computed: {
...mapState({
startDate: (state) =>
dateToISO(ISOToDatetime(state.accompanyingCourse.openingDate.datetime)),
}),
startDateInput: {
get() {
return this.startDate;
},
set(value) {
this.lastRecordedDate = value;
setTimeout(() => {
console.log("timeout finished");
if (this.lastRecordedDate === value) {
console.log("last recorded", this.lastRecordedDate, "value", value);
this.$store
.dispatch("updateStartDate", value)
.catch(({ name, violations }) => {
if (
name === "ValidationException" ||
name === "AccessException"
) {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
}
}, 3000);
},
},
computed: {
...mapState({
startDate: state => dateToISO(ISOToDatetime(state.accompanyingCourse.openingDate.datetime))
}),
startDateInput: {
get() {
return this.startDate;
},
set(value) {
this.lastRecordedDate = value;
setTimeout(() => {
console.log('timeout finished')
if (this.lastRecordedDate === value) {
console.log('last recorded', this.lastRecordedDate, 'value', value)
this.$store.dispatch('updateStartDate', value)
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
})
}
}, 3000)
}
}
}
}
},
};
</script>
<style lang="scss" scoped>
.date-update {
display: flex;
justify-content: space-between;
&-btn {
margin-left: 1rem;
}
display: flex;
justify-content: space-between;
&-btn {
margin-left: 1rem;
}
}
</style>

View File

@@ -2,198 +2,194 @@
<teleport to="#content">
<div id="navmap">
<nav>
<a
class="top"
href="#top"
>
<a class="top" href="#top">
<i class="fa fa-fw fa-square" />
<span>{{ $t('nav.top') }}</span>
<span>{{ $t("nav.top") }}</span>
</a>
<item
v-for="item of items"
:key="item.key"
:item="item"
:step="step"
/>
<item v-for="item of items" :key="item.key" :item="item" :step="step" />
</nav>
</div>
</teleport>
</template>
<script>
import Item from './StickyNav/Item.vue';
import Item from "./StickyNav/Item.vue";
export default {
name: "StickyNav",
components: {
Item
},
data() {
return {
header: document.querySelector("header nav.navbar"),
bannerName: document.querySelector("#header-accompanying_course-name"),
bannerDetails: document.querySelector("#header-accompanying_course-details"),
container: null,
heightSum: null,
stickyNav: null,
limit: 25,
anchors: null,
items: [],
name: "StickyNav",
components: {
Item,
},
data() {
return {
header: document.querySelector("header nav.navbar"),
bannerName: document.querySelector("#header-accompanying_course-name"),
bannerDetails: document.querySelector(
"#header-accompanying_course-details",
),
container: null,
heightSum: null,
stickyNav: null,
limit: 25,
anchors: null,
items: [],
};
},
computed: {
accompanyingCourse() {
return this.$store.state.accompanyingCourse;
},
step() {
return this.accompanyingCourse.step;
},
top() {
return parseInt(
window
.getComputedStyle(this.stickyNav)
.getPropertyValue("top")
.slice(0, -2),
);
},
},
mounted() {
this.ready();
window.addEventListener("scroll", this.handleScroll);
},
unmounted() {
window.removeEventListener("scroll", this.handleScroll);
},
methods: {
ready() {
// load datas DOM when mounted ready
this.container = document.querySelector("#content");
this.stickyNav = document.querySelector("#navmap");
this.anchors = document.querySelectorAll("h2 a[id^='section']");
this.initItemsMap();
// TODO resizeObserver not supports IE !
// Listen when elements change size, then recalculate heightSum and initItemsMap
const resizeObserver = new ResizeObserver(() => {
this.refreshPos();
});
resizeObserver.observe(this.header);
resizeObserver.observe(this.bannerName);
resizeObserver.observe(this.bannerDetails);
resizeObserver.observe(this.container);
},
initItemsMap() {
this.anchors.forEach((anchor) => {
this.items.push({
pos: null,
active: false,
key: parseInt(anchor.id.slice(8).slice(0, -1)),
id: "#" + anchor.id,
});
});
},
refreshPos() {
//console.log('refreshPos');
this.heightSum =
this.header.offsetHeight +
this.bannerName.offsetHeight +
this.bannerDetails.offsetHeight;
this.anchors.forEach((anchor, i) => {
this.items[i].pos = this.findPos(anchor)["y"];
});
},
findPos(element) {
let posX = 0,
posY = 0;
do {
posX += element.offsetLeft;
posY += element.offsetTop;
element = element.offsetParent;
} while (element != null);
let pos = [];
pos["x"] = posX;
pos["y"] = posY;
return pos;
},
handleScroll(event) {
let pos = this.findPos(this.stickyNav);
let top = this.heightSum + this.top - window.scrollY;
//console.log(window.scrollY);
if (top > this.limit) {
this.stickyNav.style.position = "absolute";
this.stickyNav.style.left = "10px";
} else {
this.stickyNav.style.position = "fixed";
this.stickyNav.style.left = pos["x"] + "px";
}
},
computed: {
accompanyingCourse() {
return this.$store.state.accompanyingCourse;
},
step() {
return this.accompanyingCourse.step;
},
top() {
return parseInt(window.getComputedStyle(this.stickyNav).getPropertyValue('top').slice(0, -2));
},
},
mounted() {
this.ready();
window.addEventListener('scroll', this.handleScroll);
},
unmounted() {
window.removeEventListener('scroll', this.handleScroll);
},
methods: {
ready() {
// load datas DOM when mounted ready
this.container = document.querySelector("#content");
this.stickyNav = document.querySelector('#navmap');
this.anchors = document.querySelectorAll("h2 a[id^='section']");
this.initItemsMap();
this.switchActive();
},
switchActive() {
this.items.forEach((item, i) => {
let next = this.items[i + 1] ? this.items[i + 1].pos : "100000";
item.active =
(window.scrollY >= item.pos) & (window.scrollY < next) ? true : false;
}, this);
// TODO resizeObserver not supports IE !
// Listen when elements change size, then recalculate heightSum and initItemsMap
const resizeObserver = new ResizeObserver(() => {
this.refreshPos();
});
resizeObserver.observe(this.header);
resizeObserver.observe(this.bannerName);
resizeObserver.observe(this.bannerDetails);
resizeObserver.observe(this.container);
},
initItemsMap() {
this.anchors.forEach(anchor => {
this.items.push({
pos: null,
active: false,
key: parseInt(anchor.id.slice(8).slice(0, -1)),
id: '#' + anchor.id
})
});
},
refreshPos() {
//console.log('refreshPos');
this.heightSum = this.header.offsetHeight + this.bannerName.offsetHeight + this.bannerDetails.offsetHeight;
this.anchors.forEach((anchor, i) => {
this.items[i].pos = this.findPos(anchor)['y'];
});
},
findPos(element) {
let posX = 0, posY = 0;
do {
posX += element.offsetLeft;
posY += element.offsetTop;
element = element.offsetParent;
}
while( element != null );
let pos = [];
pos['x'] = posX;
pos['y'] = posY;
return pos;
},
handleScroll(event) {
let pos = this.findPos(this.stickyNav);
let top = this.heightSum + this.top - window.scrollY;
//console.log(window.scrollY);
if (top > this.limit) {
this.stickyNav.style.position = 'absolute';
this.stickyNav.style.left = '10px';
} else {
this.stickyNav.style.position = 'fixed';
this.stickyNav.style.left = pos['x'] + 'px';
}
this.switchActive();
},
switchActive() {
this.items.forEach((item, i) => {
let next = (this.items[i+1]) ? this.items[i+1].pos : '100000';
item.active =
(window.scrollY >= item.pos & window.scrollY < next) ? true : false;
}, this);
// last item never switch active because scroll reach bottom of page
if (document.body.scrollHeight == window.scrollY + window.innerHeight) {
this.items[this.items.length-1].active = true;
this.items[this.items.length-2].active = false;
} else {
this.items[this.items.length-1].active = false;
}
// last item never switch active because scroll reach bottom of page
if (document.body.scrollHeight == window.scrollY + window.innerHeight) {
this.items[this.items.length - 1].active = true;
this.items[this.items.length - 2].active = false;
} else {
this.items[this.items.length - 1].active = false;
}
}
}
},
},
};
</script>
<style lang="scss">
div#content {
position: relative;
position: relative;
div#navmap {
position: absolute;
top: 30px;
left: 10px; //-10%;
nav {
font-size: small;
a {
display: block;
box-sizing: border-box;
margin-bottom: -3px;
color: #71859669;
text-decoration: none;
&.top {
color: #718596;
}
span {
display: none;
}
&:hover,
&.active {
span {
display: inline;
padding-left: 8px;
}
}
&:hover {
color: #718596b5;
}
&.active {
color: #e2793d; //orange
//color: #eec84a; //jaune
}
}
div#navmap {
position: absolute;
top: 30px;
left: 10px; //-10%;
nav {
font-size: small;
a {
display: block;
box-sizing: border-box;
margin-bottom: -3px;
color: #71859669;
text-decoration: none;
&.top {
color: #718596;
}
span {
display: none;
}
&:hover,
&.active {
span {
display: inline;
padding-left: 8px;
}
}
&:hover {
color: #718596b5;
}
&.active {
color: #e2793d; //orange
//color: #eec84a; //jaune
}
}
}
}
}
}
@media only screen and (max-width: 768px) {
div#navmap {
display: none;
}
div#navmap {
display: none;
}
}
</style>

View File

@@ -1,17 +1,9 @@
<template>
<a
v-if="item.key <= 8"
:href="item.id"
:class="{ 'active': isActive }"
>
<a v-if="item.key <= 8" :href="item.id" :class="{ active: isActive }">
<i class="fa fa-fw fa-square" />
<span>{{ item.key }}</span>
</a>
<a
v-else-if="step === 'DRAFT'"
:href="item.id"
:class="{ 'active': isActive }"
>
<a v-else-if="step === 'DRAFT'" :href="item.id" :class="{ active: isActive }">
<i class="fa fa-fw fa-square" />
<span>{{ item.key }}</span>
</a>
@@ -19,12 +11,12 @@
<script>
export default {
name: "Item",
props: ['item', 'step'],
computed: {
isActive() {
return this.item.active;
}
}
}
name: "Item",
props: ["item", "step"],
computed: {
isActive() {
return this.item.active;
},
},
};
</script>

View File

@@ -1,77 +1,118 @@
<template>
<div class="vue-component">
<h2>Tests</h2>
<!-- Modal -->
<ul class="record_actions">
<li>
<button
class="btn btn-create"
@click="modal1.showModal = true"
>
{{ $t('action.show_modal') }}
<button class="btn btn-create" @click="modal1.showModal = true">
{{ $t("action.show_modal") }}
</button>
</li>
<li>
<button
class="btn btn-create"
@click="modal2.showModal = true"
>
<button class="btn btn-create" @click="modal2.showModal = true">
Ouvrir une seconde modale
</button>
</li>
</ul>
<teleport to="body">
<modal
v-if="modal1.showModal"
:modal-dialog-class="modal1.modalDialogClass"
@close="modal1.showModal = false"
>
>
<template #header>
<h2 class="modal-title">
Le titre de ma modale
</h2>
<h2 class="modal-title">Le titre de ma modale</h2>
</template>
<template #body>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus luctus facilisis suscipit. Cras pulvinar, purus sagittis pulvinar porta, enim ex posuere lacus, in pulvinar lectus magna in odio. Nullam iaculis congue lorem ac suscipit. Proin ut rutrum augue. Ut vehicula risus nec hendrerit ullamcorper. Ut volutpat eu mi eget viverra. Morbi dictum placerat suscipit. </p>
<p>Quisque non erat tincidunt, lacinia justo ut, pulvinar nisl. Nunc id enim ut sem pretium interdum consectetur eu quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Etiam posuere erat eget augue finibus luctus. Maecenas auctor, tortor non luctus ultrices, neque neque porttitor ex, nec lacinia lorem ligula et elit. Sed tempor nulla vitae lorem sollicitudin dictum. Vestibulum nec arcu eget elit pulvinar pretium. Phasellus facilisis metus sed diam luctus, feugiat scelerisque velit dignissim.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus luctus facilisis suscipit. Cras pulvinar, purus sagittis pulvinar porta, enim ex posuere lacus, in pulvinar lectus magna in odio. Nullam iaculis congue lorem ac suscipit. Proin ut rutrum augue. Ut vehicula risus nec hendrerit ullamcorper. Ut volutpat eu mi eget viverra. Morbi dictum placerat suscipit. </p>
<p>Quisque non erat tincidunt, lacinia justo ut, pulvinar nisl. Nunc id enim ut sem pretium interdum consectetur eu quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Etiam posuere erat eget augue finibus luctus. Maecenas auctor, tortor non luctus ultrices, neque neque porttitor ex, nec lacinia lorem ligula et elit. Sed tempor nulla vitae lorem sollicitudin dictum. Vestibulum nec arcu eget elit pulvinar pretium. Phasellus facilisis metus sed diam luctus, feugiat scelerisque velit dignissim.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus luctus facilisis suscipit. Cras pulvinar, purus sagittis pulvinar porta, enim ex posuere lacus, in pulvinar lectus magna in odio. Nullam iaculis congue lorem ac suscipit. Proin ut rutrum augue. Ut vehicula risus nec hendrerit ullamcorper. Ut volutpat eu mi eget viverra. Morbi dictum placerat suscipit. </p>
<p>Quisque non erat tincidunt, lacinia justo ut, pulvinar nisl. Nunc id enim ut sem pretium interdum consectetur eu quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Etiam posuere erat eget augue finibus luctus. Maecenas auctor, tortor non luctus ultrices, neque neque porttitor ex, nec lacinia lorem ligula et elit. Sed tempor nulla vitae lorem sollicitudin dictum. Vestibulum nec arcu eget elit pulvinar pretium. Phasellus facilisis metus sed diam luctus, feugiat scelerisque velit dignissim.</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus
luctus facilisis suscipit. Cras pulvinar, purus sagittis pulvinar
porta, enim ex posuere lacus, in pulvinar lectus magna in odio.
Nullam iaculis congue lorem ac suscipit. Proin ut rutrum augue. Ut
vehicula risus nec hendrerit ullamcorper. Ut volutpat eu mi eget
viverra. Morbi dictum placerat suscipit.
</p>
<p>
Quisque non erat tincidunt, lacinia justo ut, pulvinar nisl. Nunc id
enim ut sem pretium interdum consectetur eu quam. Vestibulum ante
ipsum primis in faucibus orci luctus et ultrices posuere cubilia
curae; Etiam posuere erat eget augue finibus luctus. Maecenas
auctor, tortor non luctus ultrices, neque neque porttitor ex, nec
lacinia lorem ligula et elit. Sed tempor nulla vitae lorem
sollicitudin dictum. Vestibulum nec arcu eget elit pulvinar pretium.
Phasellus facilisis metus sed diam luctus, feugiat scelerisque velit
dignissim.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus
luctus facilisis suscipit. Cras pulvinar, purus sagittis pulvinar
porta, enim ex posuere lacus, in pulvinar lectus magna in odio.
Nullam iaculis congue lorem ac suscipit. Proin ut rutrum augue. Ut
vehicula risus nec hendrerit ullamcorper. Ut volutpat eu mi eget
viverra. Morbi dictum placerat suscipit.
</p>
<p>
Quisque non erat tincidunt, lacinia justo ut, pulvinar nisl. Nunc id
enim ut sem pretium interdum consectetur eu quam. Vestibulum ante
ipsum primis in faucibus orci luctus et ultrices posuere cubilia
curae; Etiam posuere erat eget augue finibus luctus. Maecenas
auctor, tortor non luctus ultrices, neque neque porttitor ex, nec
lacinia lorem ligula et elit. Sed tempor nulla vitae lorem
sollicitudin dictum. Vestibulum nec arcu eget elit pulvinar pretium.
Phasellus facilisis metus sed diam luctus, feugiat scelerisque velit
dignissim.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus
luctus facilisis suscipit. Cras pulvinar, purus sagittis pulvinar
porta, enim ex posuere lacus, in pulvinar lectus magna in odio.
Nullam iaculis congue lorem ac suscipit. Proin ut rutrum augue. Ut
vehicula risus nec hendrerit ullamcorper. Ut volutpat eu mi eget
viverra. Morbi dictum placerat suscipit.
</p>
<p>
Quisque non erat tincidunt, lacinia justo ut, pulvinar nisl. Nunc id
enim ut sem pretium interdum consectetur eu quam. Vestibulum ante
ipsum primis in faucibus orci luctus et ultrices posuere cubilia
curae; Etiam posuere erat eget augue finibus luctus. Maecenas
auctor, tortor non luctus ultrices, neque neque porttitor ex, nec
lacinia lorem ligula et elit. Sed tempor nulla vitae lorem
sollicitudin dictum. Vestibulum nec arcu eget elit pulvinar pretium.
Phasellus facilisis metus sed diam luctus, feugiat scelerisque velit
dignissim.
</p>
</template>
<template #footer>
<button
class="btn btn-create"
@click="modal1.showModal = false; modal2.showModal = true"
@click="
modal1.showModal = false;
modal2.showModal = true;
"
>
{{ $t('action.next') }}
{{ $t("action.next") }}
</button>
</template>
</modal>
</teleport>
<teleport to="body">
<modal
v-if="modal2.showModal"
:modal-dialog-class="modal2.modalDialogClass"
@close="modal2.showModal = false"
>
>
<template #header>
<h2 class="modal-title">
Une autre modale
</h2>
<h2 class="modal-title">Une autre modale</h2>
</template>
<template #body>
<p>modal 2</p>
</template>
<template #footer>
<button
class="btn btn-create"
@click="modal2.showModal = false"
>
{{ $t('action.save') }}
<button class="btn btn-create" @click="modal2.showModal = false">
{{ $t("action.save") }}
</button>
</template>
</modal>
@@ -81,26 +122,25 @@
</template>
<script>
import Modal from 'ChillMainAssets/vuejs/_components/Modal'
import Modal from "ChillMainAssets/vuejs/_components/Modal";
export default {
name: 'Test',
components: {
Modal,
},
data() {
return {
modal1: {
showModal: false,
modalDialogClass: "modal-dialog-scrollable modal-xl" // modal-lg modal-md modal-sm
},
modal2: {
showModal: false,
modalDialogClass: "modal-dialog-centered modal-sm" // modal-lg modal-md modal-sm
}
}
},
computed: {
}
}
name: "Test",
components: {
Modal,
},
data() {
return {
modal1: {
showModal: false,
modalDialogClass: "modal-dialog-scrollable modal-xl", // modal-lg modal-md modal-sm
},
modal2: {
showModal: false,
modalDialogClass: "modal-dialog-centered modal-sm", // modal-lg modal-md modal-sm
},
};
},
computed: {},
};
</script>

View File

@@ -1,59 +1,56 @@
import { createApp } from 'vue'
import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n'
import { appMessages } from './js/i18n'
import { initPromise } from './store'
import 'vue-toast-notification/dist/theme-sugar.css';
import App from './App.vue';
import Banner from './components/Banner.vue';
import { createApp } from "vue";
import { _createI18n } from "ChillMainAssets/vuejs/_js/i18n";
import { appMessages } from "./js/i18n";
import { initPromise } from "./store";
import "vue-toast-notification/dist/theme-sugar.css";
import App from "./App.vue";
import Banner from "./components/Banner.vue";
import ToastPlugin from "vue-toast-notification";
const root = window.vueRootComponent;
/*
* Load all App component, for AccompanyingCourse edition page
*/
if (root === 'app') {
initPromise(root).then(store => {
* Load all App component, for AccompanyingCourse edition page
*/
if (root === "app") {
initPromise(root).then((store) => {
const i18n = _createI18n(appMessages);
const i18n = _createI18n(appMessages);
const app = createApp({
template: `<app></app>`,
})
const app = createApp({
template: `<app></app>`,
})
.use(store)
.use(i18n)
.use(ToastPlugin, {
position: "bottom-right",
type: "error",
duration: 5000,
dismissible: true
position: "bottom-right",
type: "error",
duration: 5000,
dismissible: true,
})
.component('app', App)
.mount('#accompanying-course')
});
.component("app", App)
.mount("#accompanying-course");
});
}
/*
* Load only Banner sub-component, for all others AccompanyingCourse page
*/
if (root === 'banner') {
initPromise(root).then(store => {
* Load only Banner sub-component, for all others AccompanyingCourse page
*/
if (root === "banner") {
initPromise(root).then((store) => {
const i18n = _createI18n(appMessages);
const i18n = _createI18n(appMessages);
const app = createApp({
template: `<banner></banner>`,
})
const app = createApp({
template: `<banner></banner>`,
})
.use(store)
.use(i18n)
.use(ToastPlugin, {
position: "bottom-right",
type: "error",
duration: 5000,
dismissible: true
position: "bottom-right",
type: "error",
duration: 5000,
dismissible: true,
})
.component('banner', Banner)
.mount('#banner-accompanying-course');
});
.component("banner", Banner)
.mount("#banner-accompanying-course");
});
}

View File

@@ -1,184 +1,217 @@
import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n';
import { thirdpartyMessages } from 'ChillThirdPartyAssets/vuejs/_js/i18n';
import { addressMessages } from 'ChillMainAssets/vuejs/Address/i18n';
import { ontheflyMessages } from 'ChillMainAssets/vuejs/OnTheFly/i18n';
import { personMessages } from "ChillPersonAssets/vuejs/_js/i18n";
import { thirdpartyMessages } from "ChillThirdPartyAssets/vuejs/_js/i18n";
import { addressMessages } from "ChillMainAssets/vuejs/Address/i18n";
import { ontheflyMessages } from "ChillMainAssets/vuejs/OnTheFly/i18n";
const appMessages = {
fr: {
course: {
id: "id",
title: {
draft: "Création d'un nouveau parcours",
active: "Modification du parcours"
},
opening_date: "Date d'ouverture",
closing_date: "Date de clôture",
remark: "Commentaire",
closing_motive: "Motif de clôture",
user: "TMS",
flags: "Indicateurs",
status: "État",
step: {
draft: "Brouillon",
active: "En file active",
closed: "Cloturé",
inactive_short: "Hors file active",
inactive_long: "Pré-archivé",
},
open_at: "ouvert le ",
by: "par ",
referrer: "Référent",
emergency: "urgent",
confidential: "confidentiel",
regular: "régulier",
occasional: "ponctuel",
absent: "Absent",
fr: {
course: {
id: "id",
title: {
draft: "Création d'un nouveau parcours",
active: "Modification du parcours",
},
origin: {
title: "Origine de la demande",
label: "Origine de la demande",
placeholder: "Renseignez l'origine de la demande",
not_valid: "Indiquez une origine à la demande",
opening_date: "Date d'ouverture",
closing_date: "Date de clôture",
remark: "Commentaire",
closing_motive: "Motif de clôture",
user: "TMS",
flags: "Indicateurs",
status: "État",
step: {
draft: "Brouillon",
active: "En file active",
closed: "Cloturé",
inactive_short: "Hors file active",
inactive_long: "Pré-archivé",
},
admin_location: {
title: "Localisation administrative",
label: "Localisation administrative",
placeholder: "Renseignez la localisation administrative",
not_valid: "Indiquez une localisation administrative",
},
persons_associated: {
title: "Usagers concernés",
counter: "Il n'y a pas encore d'usagers | 1 usager | {count} usagers",
firstname: "Prénom",
lastname: "Nom",
name: "Nom",
startdate: "Date d'entrée",
enddate: "Date de sortie",
add_persons: "Ajouter des usagers",
date_start_to_end: "Participation du {start} au {end}",
leave_course: "L'usager quitte le parcours",
sure: "Êtes-vous sûr ?",
sure_description: "Une fois confirmé, il ne sera pas possible de faire marche arrière ! La sortie reste cependant consignée dans l'historique du parcours.",
ok: "Oui, l'usager quitte le parcours",
show_household_number: "Voir le ménage (n° {id})",
show_household: "Voir le ménage",
person_without_household_warning: "Certaines usagers n'appartiennent actuellement à aucun ménage. Veuillez les associer à un ménage dès que possible.",
update_household: "Associer à un ménage",
participation_not_valid: "Sélectionnez ou créez au minimum 1 usager",
},
requestor: {
title: "Demandeur",
add_requestor: "Ajouter un demandeur",
is_anonymous: "Le demandeur est anonyme",
counter: "Il n'y a pas encore de demandeur",
type: "Type",
person_id: "id",
text: "Dénomination",
firstName: "Prénom",
lastName: "Nom",
birthdate: "Date de naissance",
center: "Centre",
phonenumber: "Téléphone",
mobilenumber: "Mobile",
altNames: "Autres noms",
address: "Adresse",
location: "Localité",
},
social_issue: {
title: "Problématiques sociales",
label: "Choisir les problématiques sociales",
not_valid: "Sélectionnez au minimum une problématique sociale",
},
courselocation: {
title: "Localisation du parcours",
add_temporary_address: "Ajouter une adresse temporaire",
edit_temporary_address: "Modifier l'adresse temporaire",
assign_course_address: "Désigner comme l'adresse du parcours",
remove_button: "Enlever l'adresse",
temporary_address_must_be_changed: "Cette adresse est temporaire. Le parcours devrait être localisé auprès d'un usager concerné.",
associate_at_least_one_person_with_one_household_with_address: "Commencez d'abord par associer un membre du parcours à un ménage, et indiquez une adresse à ce ménage.",
sure: "Êtes-vous sûr ?",
sure_description: "Voulez-vous faire de cette adresse l'adresse du parcours ?",
ok: "Désigner comme adresse du parcours",
person_locator: "Parcours localisé auprès de {0}",
not_valid: "Indiquez au minimum une localisation temporaire du parcours",
no_address: "Il n'y a pas d'adresse associée au parcours"
},
scopes: {
title: "Services concernés",
add_at_least_one: "Indiquez au moins un service",
},
referrer: {
title: "Référent du parcours",
label: "Vous pouvez choisir un TMS ou vous assigner directement comme référent",
placeholder: "Choisir un TMS",
assign_me: "M'assigner comme référent",
},
resources: {
title: "Interlocuteurs privilégiés",
counter: "Il n'y a pas encore d'interlocuteur | 1 interlocuteur | {count} interlocuteurs",
text: "Dénomination",
description: "Description",
add_resources: "Ajouter des interlocuteurs",
},
comment: {
title: "Observations",
label: "Ajout d'une note",
content: "Rédigez une première note…",
created_by: "créé par {0}, mis à jour le {1}"
},
confirm: {
title: "Confirmation",
text_draft: "Le parcours est actuellement à l'état de <b>{0}</b>.",
text_active: "En validant cette étape, vous lui donnez le statut <b>{0}</b>.",
alert_validation: "Certaines conditions ne sont pas remplies pour pouvoir confirmer le parcours :",
participation_not_valid: "sélectionnez au minimum 1 usager",
socialIssue_not_valid: "sélectionnez au minimum une problématique sociale",
location_not_valid: "indiquez au minimum une localisation temporaire du parcours",
origin_not_valid: "Indiquez une origine à la demande",
adminLocation_not_valid: "Indiquez une localisation administrative à la demande",
job_not_valid: "Indiquez un métier du référent",
set_a_scope: "indiquez au moins un service",
sure: "Êtes-vous sûr ?",
sure_description: "Une fois le changement confirmé, il ne sera plus possible de le remettre à l'état de brouillon !",
sure_referrer: "Êtes-vous sûr de vouloir assigner ce parcours à <b>{referrer}</b>",
ok: "Confirmer le parcours",
delete: "Supprimer le parcours",
ok_referrer: "Confirmer le référent",
no_suggested_referrer: "Il n'y a aucun référent qui puisse être suggéré pour ce parcours. Vérifiez la localisation du parcours, les métiers et service indiqués. Si les données sont correctes, vous pouvez confirmer ce parcours.",
one_suggested_referrer: "Un unique référent peut être suggéré pour ce parcours",
choose_suggested_referrer: "Voulez-vous le désigner directement ?",
choose_button: "Désigner",
do_not_choose_button: "Ne pas désigner"
},
job: {
label: "Métier",
placeholder: "Choisir un métier",
not_valid: "Sélectionnez un métier du référent"
},
startdate: {
change: "Date d'ouverture",
// update: "La nouvelle date d'ouverture a été enregistrée"
},
// catch errors
'Error while updating AccompanyingPeriod Course.': "Erreur du serveur lors de la mise à jour du parcours d'accompagnement.",
'Error while retriving AccompanyingPeriod Course.': "Erreur du serveur lors du chargement du parcours d'accompagnement.",
'Error while confirming AccompanyingPeriod Course.': "Erreur du serveur lors de la confirmation du parcours d'accompagnement.",
'Error while retriving Social Issues.': "Erreur du serveur lors du chargement des problématique sociales.",
'Error while sending AccompanyingPeriod Course participation.': "Erreur du serveur lors de l'envoi des infos d'un usager.",
'Error while sending AccompanyingPeriod Course requestor': "Erreur du serveur lors de l'envoi des infos du demandeur.",
'Error while sending AccompanyingPeriod Course resource.': "Erreur du serveur lors de l'envoi des infos d'un interlocuteur privilégié.",
'Error while updating SocialIssue.': "Erreur du serveur lors de la mise à jour d'une problématique sociale.",
'Error while retriving users.': "Erreur du serveur lors du chargement de la liste des travailleurs.",
'Error while getting whoami.': "Erreur du serveur lors de la requête 'qui suis-je ?'",
'Error while retriving origin\'s list.': "Erreur du serveur lors du chargement de la liste des origines de la demande.",
'Only the referrer can toggle the intensity of an accompanying course': "Seul le référent peut modifier l'intensité d'un parcours.",
'Only the referrer can toggle the confidentiality of an accompanying course': "Seul le référent peut modifier la confidentialité d'un parcours."
}
open_at: "ouvert le ",
by: "par ",
referrer: "Référent",
emergency: "urgent",
confidential: "confidentiel",
regular: "régulier",
occasional: "ponctuel",
absent: "Absent",
},
origin: {
title: "Origine de la demande",
label: "Origine de la demande",
placeholder: "Renseignez l'origine de la demande",
not_valid: "Indiquez une origine à la demande",
},
admin_location: {
title: "Localisation administrative",
label: "Localisation administrative",
placeholder: "Renseignez la localisation administrative",
not_valid: "Indiquez une localisation administrative",
},
persons_associated: {
title: "Usagers concernés",
counter: "Il n'y a pas encore d'usagers | 1 usager | {count} usagers",
firstname: "Prénom",
lastname: "Nom",
name: "Nom",
startdate: "Date d'entrée",
enddate: "Date de sortie",
add_persons: "Ajouter des usagers",
date_start_to_end: "Participation du {start} au {end}",
leave_course: "L'usager quitte le parcours",
sure: "Êtes-vous sûr ?",
sure_description:
"Une fois confirmé, il ne sera pas possible de faire marche arrière ! La sortie reste cependant consignée dans l'historique du parcours.",
ok: "Oui, l'usager quitte le parcours",
show_household_number: "Voir le ménage (n° {id})",
show_household: "Voir le ménage",
person_without_household_warning:
"Certaines usagers n'appartiennent actuellement à aucun ménage. Veuillez les associer à un ménage dès que possible.",
update_household: "Associer à un ménage",
participation_not_valid: "Sélectionnez ou créez au minimum 1 usager",
},
requestor: {
title: "Demandeur",
add_requestor: "Ajouter un demandeur",
is_anonymous: "Le demandeur est anonyme",
counter: "Il n'y a pas encore de demandeur",
type: "Type",
person_id: "id",
text: "Dénomination",
firstName: "Prénom",
lastName: "Nom",
birthdate: "Date de naissance",
center: "Centre",
phonenumber: "Téléphone",
mobilenumber: "Mobile",
altNames: "Autres noms",
address: "Adresse",
location: "Localité",
},
social_issue: {
title: "Problématiques sociales",
label: "Choisir les problématiques sociales",
not_valid: "Sélectionnez au minimum une problématique sociale",
},
courselocation: {
title: "Localisation du parcours",
add_temporary_address: "Ajouter une adresse temporaire",
edit_temporary_address: "Modifier l'adresse temporaire",
assign_course_address: "Désigner comme l'adresse du parcours",
remove_button: "Enlever l'adresse",
temporary_address_must_be_changed:
"Cette adresse est temporaire. Le parcours devrait être localisé auprès d'un usager concerné.",
associate_at_least_one_person_with_one_household_with_address:
"Commencez d'abord par associer un membre du parcours à un ménage, et indiquez une adresse à ce ménage.",
sure: "Êtes-vous sûr ?",
sure_description:
"Voulez-vous faire de cette adresse l'adresse du parcours ?",
ok: "Désigner comme adresse du parcours",
person_locator: "Parcours localisé auprès de {0}",
not_valid: "Indiquez au minimum une localisation temporaire du parcours",
no_address: "Il n'y a pas d'adresse associée au parcours",
},
scopes: {
title: "Services concernés",
add_at_least_one: "Indiquez au moins un service",
},
referrer: {
title: "Référent du parcours",
label:
"Vous pouvez choisir un TMS ou vous assigner directement comme référent",
placeholder: "Choisir un TMS",
assign_me: "M'assigner comme référent",
},
resources: {
title: "Interlocuteurs privilégiés",
counter:
"Il n'y a pas encore d'interlocuteur | 1 interlocuteur | {count} interlocuteurs",
text: "Dénomination",
description: "Description",
add_resources: "Ajouter des interlocuteurs",
},
comment: {
title: "Observations",
label: "Ajout d'une note",
content: "Rédigez une première note…",
created_by: "créé par {0}, mis à jour le {1}",
},
confirm: {
title: "Confirmation",
text_draft: "Le parcours est actuellement à l'état de <b>{0}</b>.",
text_active:
"En validant cette étape, vous lui donnez le statut <b>{0}</b>.",
alert_validation:
"Certaines conditions ne sont pas remplies pour pouvoir confirmer le parcours :",
participation_not_valid: "sélectionnez au minimum 1 usager",
socialIssue_not_valid:
"sélectionnez au minimum une problématique sociale",
location_not_valid:
"indiquez au minimum une localisation temporaire du parcours",
origin_not_valid: "Indiquez une origine à la demande",
adminLocation_not_valid:
"Indiquez une localisation administrative à la demande",
job_not_valid: "Indiquez un métier du référent",
set_a_scope: "indiquez au moins un service",
sure: "Êtes-vous sûr ?",
sure_description:
"Une fois le changement confirmé, il ne sera plus possible de le remettre à l'état de brouillon !",
sure_referrer:
"Êtes-vous sûr de vouloir assigner ce parcours à <b>{referrer}</b>",
ok: "Confirmer le parcours",
delete: "Supprimer le parcours",
ok_referrer: "Confirmer le référent",
no_suggested_referrer:
"Il n'y a aucun référent qui puisse être suggéré pour ce parcours. Vérifiez la localisation du parcours, les métiers et service indiqués. Si les données sont correctes, vous pouvez confirmer ce parcours.",
one_suggested_referrer:
"Un unique référent peut être suggéré pour ce parcours",
choose_suggested_referrer: "Voulez-vous le désigner directement ?",
choose_button: "Désigner",
do_not_choose_button: "Ne pas désigner",
},
job: {
label: "Métier",
placeholder: "Choisir un métier",
not_valid: "Sélectionnez un métier du référent",
},
startdate: {
change: "Date d'ouverture",
// update: "La nouvelle date d'ouverture a été enregistrée"
},
// catch errors
"Error while updating AccompanyingPeriod Course.":
"Erreur du serveur lors de la mise à jour du parcours d'accompagnement.",
"Error while retriving AccompanyingPeriod Course.":
"Erreur du serveur lors du chargement du parcours d'accompagnement.",
"Error while confirming AccompanyingPeriod Course.":
"Erreur du serveur lors de la confirmation du parcours d'accompagnement.",
"Error while retriving Social Issues.":
"Erreur du serveur lors du chargement des problématique sociales.",
"Error while sending AccompanyingPeriod Course participation.":
"Erreur du serveur lors de l'envoi des infos d'un usager.",
"Error while sending AccompanyingPeriod Course requestor":
"Erreur du serveur lors de l'envoi des infos du demandeur.",
"Error while sending AccompanyingPeriod Course resource.":
"Erreur du serveur lors de l'envoi des infos d'un interlocuteur privilégié.",
"Error while updating SocialIssue.":
"Erreur du serveur lors de la mise à jour d'une problématique sociale.",
"Error while retriving users.":
"Erreur du serveur lors du chargement de la liste des travailleurs.",
"Error while getting whoami.":
"Erreur du serveur lors de la requête 'qui suis-je ?'",
"Error while retriving origin's list.":
"Erreur du serveur lors du chargement de la liste des origines de la demande.",
"Only the referrer can toggle the intensity of an accompanying course":
"Seul le référent peut modifier l'intensité d'un parcours.",
"Only the referrer can toggle the confidentiality of an accompanying course":
"Seul le référent peut modifier la confidentialité d'un parcours.",
},
};
Object.assign(appMessages.fr, personMessages.fr, thirdpartyMessages.fr, addressMessages.fr, ontheflyMessages.fr);
Object.assign(
appMessages.fr,
personMessages.fr,
thirdpartyMessages.fr,
addressMessages.fr,
ontheflyMessages.fr,
);
export {
appMessages
};
export { appMessages };

View File

@@ -1,23 +1,16 @@
<template>
<h2>{{ $t('pick_social_issue') }}</h2>
<h2>{{ $t("pick_social_issue") }}</h2>
<div id="awc_create_form">
<div
id="picking"
class=""
>
<p>{{ $t('pick_social_issue_linked_with_action') }}</p>
<div
v-for="si in socialIssues"
:key="si.id"
>
<div id="picking" class="">
<p>{{ $t("pick_social_issue_linked_with_action") }}</p>
<div v-for="si in socialIssues" :key="si.id">
<input
type="radio"
:value="si.id"
name="socialIssue"
v-model="socialIssuePicked"
><span class="badge bg-chill-l-gray text-dark">{{ si.text }}</span>
/><span class="badge bg-chill-l-gray text-dark">{{ si.text }}</span>
</div>
<div class="my-3">
<div class="col-11">
@@ -42,11 +35,8 @@
/>
</div>
</div>
<div
v-if="hasSocialIssuePicked"
class="mb-3"
>
<h2>{{ $t('pick_an_action') }}</h2>
<div v-if="hasSocialIssuePicked" class="mb-3">
<h2>{{ $t("pick_an_action") }}</h2>
<div class="col-11">
<vue-multiselect
v-model="socialActionPicked"
@@ -64,30 +54,20 @@
<i class="fa fa-circle-o-notch fa-spin fa-fw" />
</div>
<div
v-if="hasSocialActionPicked"
id="persons"
class="mb-5"
>
<h2>{{ $t('persons_involved') }}</h2>
<div v-if="hasSocialActionPicked" id="persons" class="mb-5">
<h2>{{ $t("persons_involved") }}</h2>
<ul>
<li
v-for="p in personsReachables"
:key="p.id"
>
<li v-for="p in personsReachables" :key="p.id">
<div class="form-check">
<input
type="checkbox"
:value="p.id"
v-model="personsPicked"
class="form-check-input"
:id="'person_check'+p.id"
>
<label
class="form-check-label"
:for="'person_check' + p.id"
>
:id="'person_check' + p.id"
/>
<label class="form-check-label" :for="'person_check' + p.id">
<person-text :person="p" />
</label>
</div>
@@ -99,48 +79,29 @@
<p><label>{{ $t('startDate') }}</label> <input type="date" v-model="startDate" /></p>
</div> -->
<div class="row">
<div
v-if="hasSocialActionPicked"
id="start_date"
class="mb-3 row"
>
<label class="col-form-label col-sm-4">{{ $t('startDate') }}</label>
<div v-if="hasSocialActionPicked" id="start_date" class="mb-3 row">
<label class="col-form-label col-sm-4">{{ $t("startDate") }}</label>
<div class="col-sm-8">
<input
class="form-control"
type="date"
v-model="startDate"
>
<input class="form-control" type="date" v-model="startDate" />
</div>
</div>
<!-- <div v-if="hasSocialActionPicked" id="end_date">
<p><label>{{ $t('endDate') }}</label> <input type="date" v-model="endDate" /></p>
</div> -->
<div
v-if="hasSocialActionPicked"
id="end_date"
class="mb-3 row"
>
<label class="col-form-label col-sm-4">{{ $t('endDate') }}</label>
<div v-if="hasSocialActionPicked" id="end_date" class="mb-3 row">
<label class="col-form-label col-sm-4">{{ $t("endDate") }}</label>
<div class="col-sm-8">
<input
class="form-control"
type="date"
v-model="endDate"
>
<input class="form-control" type="date" v-model="endDate" />
</div>
</div>
</div>
<div id="confirm">
<div v-if="hasErrors">
<p>{{ $t('form_has_errors') }}</p>
<p>{{ $t("form_has_errors") }}</p>
<ul>
<li
v-for="e in errors"
:key="e.id"
>
<li v-for="e in errors" :key="e.id">
{{ e }}
</li>
</ul>
@@ -149,11 +110,8 @@
<div>
<ul class="record_actions">
<li class="cancel">
<button
class="btn btn-cancel"
@click="goToPrevious"
>
{{ $t('action.cancel') }}
<button class="btn btn-cancel" @click="goToPrevious">
{{ $t("action.cancel") }}
</button>
</li>
<li v-if="hasSocialActionPicked">
@@ -162,14 +120,10 @@
v-show="!isPostingWork"
@click="submit"
>
{{ $t('action.save') }}
{{ $t("action.save") }}
</button>
<button
class="btn btn-save"
v-show="isPostingWork"
disabled
>
{{ $t('action.save') }}
<button class="btn btn-save" v-show="isPostingWork" disabled>
{{ $t("action.save") }}
</button>
</li>
</ul>
@@ -178,12 +132,10 @@
</div>
</template>
<script>
import { mapState, mapGetters } from 'vuex';
import VueMultiselect from 'vue-multiselect';
import PersonText from 'ChillPersonAssets/vuejs/_components/Entity/PersonText.vue';
import { mapState, mapGetters } from "vuex";
import VueMultiselect from "vue-multiselect";
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
const i18n = {
messages: {
@@ -194,39 +146,41 @@ const i18n = {
pick_social_issue: "Choisir une problématique sociale",
pick_other_social_issue: "Veuillez choisir un autre problématique",
pick_an_action: "Choisir une action d'accompagnement",
pick_social_issue_linked_with_action: "Indiquez la problématique sociale liée à l'action d'accompagnement",
pick_social_issue_linked_with_action:
"Indiquez la problématique sociale liée à l'action d'accompagnement",
persons_involved: "Usagers concernés",
choose_other_social_issue: "Veuillez choisir un autre problématique",
}
}
}
},
},
};
export default {
name: 'App',
name: "App",
components: {
VueMultiselect,
PersonText,
},
methods: {
submit() {
this.$store.dispatch('submit')
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
this.$store.dispatch("submit").catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
addIssueInList(value) {
this.$store.commit('addIssueInList', value);
this.$store.commit('removeIssueInOther', value);
this.$store.dispatch('pickSocialIssue', value.id);
this.$store.commit("addIssueInList", value);
this.$store.commit("removeIssueInOther", value);
this.$store.dispatch("pickSocialIssue", value.id);
},
goToPrevious() {
let params = new URLSearchParams(window.location.search);
if (params.has('returnPath')) {
window.location.replace(params.get('returnPath'));
if (params.has("returnPath")) {
window.location.replace(params.get("returnPath"));
} else {
return;
}
@@ -235,28 +189,28 @@ export default {
i18n,
computed: {
...mapState([
'socialIssues',
'socialIssuesOther',
'socialActionsReachables',
'errors',
'personsReachables',
"socialIssues",
"socialIssuesOther",
"socialActionsReachables",
"errors",
"personsReachables",
]),
...mapGetters([
'hasSocialIssuePicked',
'hasSocialActionPicked',
'isLoadingSocialActions',
'isPostingWork',
'hasErrors',
"hasSocialIssuePicked",
"hasSocialActionPicked",
"isLoadingSocialActions",
"isPostingWork",
"hasErrors",
]),
personsPicked: {
get() {
let s = this.$store.state.personsPicked.map(p => p.id);
let s = this.$store.state.personsPicked.map((p) => p.id);
return s;
},
set(v) {
this.$store.commit('setPersonsPickedIds', v);
}
this.$store.commit("setPersonsPickedIds", v);
},
},
socialIssuePicked: {
get() {
@@ -269,47 +223,49 @@ export default {
return s.id;
},
set(value) {
this.$store.dispatch('pickSocialIssue', value);
}
this.$store.dispatch("pickSocialIssue", value);
},
},
socialActionPicked: {
get() {
return this.$store.state.socialActionPicked;
},
set(value) {
this.$store.commit('setSocialAction', value);
}
this.$store.commit("setSocialAction", value);
},
},
startDate: {
get() {
return this.$store.state.startDate;
},
set(value) {
this.$store.commit('setStartDate', value);
}
this.$store.commit("setStartDate", value);
},
},
endDate: {
get() {
return this.$store.state.endDate;
},
set(value) {
this.$store.commit('setEndDate', value);
}
this.$store.commit("setEndDate", value);
},
},
setSocialIssue: {
set() {
this.$store.dispatch('setSocialIssue', socialIssues[socialIssues.length - 1])
}
}
}
}
this.$store.dispatch(
"setSocialIssue",
socialIssues[socialIssues.length - 1],
);
},
},
},
};
</script>
<style lang="scss" scoped>
@import 'ChillMainAssets/module/bootstrap/shared';
@import 'ChillPersonAssets/chill/scss/mixins';
@import 'ChillMainAssets/chill/scss/chill_variables';
@import "ChillMainAssets/module/bootstrap/shared";
@import "ChillPersonAssets/chill/scss/mixins";
@import "ChillMainAssets/chill/scss/chill_variables";
span.badge {
@include badge_social($social-issue-color);
font-size: 95%;
@@ -320,14 +276,12 @@ span.badge {
</style>
<style lang="scss">
#awc_create_form {
display: grid;
grid-template-areas:
"picking picking"
"start_date end_date"
"confirm confirm"
;
"confirm confirm";
grid-template-columns: 50% 50%;
column-gap: 1.5rem;

View File

@@ -1,8 +1,8 @@
import {createApp} from 'vue';
import {_createI18n} from 'ChillMainAssets/vuejs/_js/i18n';
import {store} from './store';
import {personMessages} from 'ChillPersonAssets/vuejs/_js/i18n'
import App from './App.vue';
import { createApp } from "vue";
import { _createI18n } from "ChillMainAssets/vuejs/_js/i18n";
import { store } from "./store";
import { personMessages } from "ChillPersonAssets/vuejs/_js/i18n";
import App from "./App.vue";
import ToastPlugin from "vue-toast-notification";
const i18n = _createI18n(personMessages);
@@ -10,15 +10,15 @@ const i18n = _createI18n(personMessages);
/*eslint no-unused-vars: "error"*/
/* exported app */
const app = createApp({
template: `<app></app>`,
template: `<app></app>`,
})
.use(store)
.use(i18n)
.use(ToastPlugin, {
position: "bottom-right",
type: "error",
duration: 10000,
dismissible: true,
})
.component('app', App)
.mount('#accompanying_course_work_create');
.use(store)
.use(i18n)
.use(ToastPlugin, {
position: "bottom-right",
type: "error",
duration: 10000,
dismissible: true,
})
.component("app", App)
.mount("#accompanying_course_work_create");

View File

@@ -1,11 +1,14 @@
import { createStore } from 'vuex';
import { datetimeToISO, dateToISO, ISOToDate } from 'ChillMainAssets/chill/js/date';
import { findSocialActionsBySocialIssue } from 'ChillPersonAssets/vuejs/_api/SocialWorkSocialAction.js';
import { createStore } from "vuex";
import {
datetimeToISO,
dateToISO,
ISOToDate,
} from "ChillMainAssets/chill/js/date";
import { findSocialActionsBySocialIssue } from "ChillPersonAssets/vuejs/_api/SocialWorkSocialAction.js";
// import { create } from 'ChillPersonAssets/vuejs/_api/AccompanyingCourseWork.js';
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods';
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
const debug = process.env.NODE_ENV !== 'production';
const debug = process.env.NODE_ENV !== "production";
const store = createStore({
strict: debug,
@@ -16,10 +19,12 @@ const store = createStore({
socialIssuesOther: [],
socialActionsReachables: [],
socialActionPicked: null,
personsPicked: window.accompanyingCourse.participations.filter(p => p.endDate == null)
.map(p => p.person),
personsReachables: window.accompanyingCourse.participations.filter(p => p.endDate == null)
.map(p => p.person),
personsPicked: window.accompanyingCourse.participations
.filter((p) => p.endDate == null)
.map((p) => p.person),
personsReachables: window.accompanyingCourse.participations
.filter((p) => p.endDate == null)
.map((p) => p.person),
startDate: dateToISO(new Date()),
endDate: null,
isLoadingSocialActions: false,
@@ -41,27 +46,27 @@ const store = createStore({
},
buildPayloadCreate(state) {
let payload = {
type: 'accompanying_period_work',
type: "accompanying_period_work",
socialAction: {
type: 'social_work_social_action',
id: state.socialActionPicked.id
type: "social_work_social_action",
id: state.socialActionPicked.id,
},
startDate: {
datetime: datetimeToISO(ISOToDate(state.startDate))
datetime: datetimeToISO(ISOToDate(state.startDate)),
},
persons: []
persons: [],
};
for (let i in state.personsPicked) {
payload.persons.push({
id: state.personsPicked[i].id,
type: 'person'
type: "person",
});
}
if (null !== state.endDate) {
payload.endDate = {
datetime: datetimeToISO(ISOToDate(state.endDate))
datetime: datetimeToISO(ISOToDate(state.endDate)),
};
}
@@ -82,8 +87,7 @@ const store = createStore({
if (socialIssueId === null) {
state.socialIssuePicked = null;
} else {
let mapped = state.socialIssues
.find(e => e.id === socialIssueId);
let mapped = state.socialIssues.find((e) => e.id === socialIssueId);
state.socialIssuePicked = mapped;
}
},
@@ -95,7 +99,7 @@ const store = createStore({
},
removeIssueInOther(state, issue) {
state.socialIssuesOther = state.socialIssuesOther.filter(
(i) => i.id !== issue.id
(i) => i.id !== issue.id,
);
},
updateSelected(state, payload) {
@@ -114,16 +118,15 @@ const store = createStore({
state.startDate = date;
},
setEndDate(state, date) {
console.log(date)
console.log(date);
state.endDate = date;
},
setPersonsPickedIds(state, ids) {
state.personsPicked = state.personsReachables
.filter(p => ids.includes(p.id))
state.personsPicked = state.personsReachables.filter((p) =>
ids.includes(p.id),
);
},
addErrors(state, { errors, cancel_posting }) {
state.errors = errors;
if (cancel_posting) {
state.isPostingWork = false;
@@ -132,52 +135,50 @@ const store = createStore({
},
actions: {
pickSocialIssue({ commit }, socialIssueId) {
commit('setIsLoadingSocialActions', true);
commit('setSocialAction', null);
commit('setSocialActionsReachables', []);
commit('setSocialIssue', null);
commit("setIsLoadingSocialActions", true);
commit("setSocialAction", null);
commit("setSocialActionsReachables", []);
commit("setSocialIssue", null);
findSocialActionsBySocialIssue(socialIssueId).then(
(response) => {
commit('setSocialIssue', socialIssueId);
commit('setSocialActionsReachables', response.results);
commit('setIsLoadingSocialActions', false);
findSocialActionsBySocialIssue(socialIssueId)
.then((response) => {
commit("setSocialIssue", socialIssueId);
commit("setSocialActionsReachables", response.results);
commit("setIsLoadingSocialActions", false);
})
.catch(err => {
.catch((err) => {
console.error(err);
});
},
submit({ commit, getters, state }) {
let payload = getters.buildPayloadCreate;
const url = `/api/1.0/person/accompanying-course/${state.accompanyingCourse.id}/work.json`;
commit('setPostingWork');
commit("setPostingWork");
return makeFetch('POST', url, payload)
return makeFetch("POST", url, payload)
.then((response) => {
window.location.assign(`/fr/person/accompanying-period/work/${response.id}/edit`)
window.location.assign(
`/fr/person/accompanying-period/work/${response.id}/edit`,
);
})
.catch((error) => {
commit('setPostingWorkDone');
commit("setPostingWorkDone");
throw error;
});
},
fetchOtherSocialIssues({commit}) {
fetchOtherSocialIssues({ commit }) {
const url = `/api/1.0/person/social-work/social-issue.json`;
return makeFetch('GET', url)
return makeFetch("GET", url)
.then((response) => {
commit('updateIssuesOther', response.results);
commit("updateIssuesOther", response.results);
})
.catch((error) => {
throw error;
})
}
});
},
},
});
store.dispatch('fetchOtherSocialIssues');
store.dispatch("fetchOtherSocialIssues");
export { store };

View File

@@ -1,22 +1,15 @@
<template>
<div>
<a id="evaluations" />
<div
class="item-title"
:title="evaluation.id || 'no id yet'"
>
<div class="item-title" :title="evaluation.id || 'no id yet'">
<span>{{ evaluation.evaluation.title.fr }}</span>
</div>
<div
class="item-url mt-3 mb-4"
v-if="evaluation.evaluation.url"
>
<div class="item-url mt-3 mb-4" v-if="evaluation.evaluation.url">
<i class="fa fa-link fa-lg" />
<a
:href="evaluation.evaluation.url"
target="_blank"
>{{ evaluation.evaluation.url }}</a>
<a :href="evaluation.evaluation.url" target="_blank">{{
evaluation.evaluation.url
}}</a>
</div>
<div>
@@ -43,7 +36,8 @@
class="btn btn-delete"
@click="modal.showModal = true"
:title="$t('action.delete')"
>{{ $t('delete_evaluation') }}</a>
>{{ $t("delete_evaluation") }}</a
>
</li>
</ul>
</div>
@@ -56,18 +50,15 @@
>
<template #header>
<h2 class="modal-title">
{{ $t('delete.sure') }}
{{ $t("delete.sure") }}
</h2>
</template>
<template #body>
<p>{{ $t('delete.sure_description') }}</p>
<p>{{ $t("delete.sure_description") }}</p>
</template>
<template #footer>
<button
class="btn btn-danger"
@click="removeEvaluation(evaluation)"
>
{{ $t('delete.ok') }}
<button class="btn btn-danger" @click="removeEvaluation(evaluation)">
{{ $t("delete.ok") }}
</button>
</template>
</modal>
@@ -76,107 +67,117 @@
</template>
<script>
import FormEvaluation from './FormEvaluation.vue';
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
import ListWorkflowModal from 'ChillMainAssets/vuejs/_components/EntityWorkflow/ListWorkflowModal.vue';
import {buildLinkCreate} from 'ChillMainAssets/lib/entity-workflow/api.js';
import FormEvaluation from "./FormEvaluation.vue";
import Modal from "ChillMainAssets/vuejs/_components/Modal";
import ListWorkflowModal from "ChillMainAssets/vuejs/_components/EntityWorkflow/ListWorkflowModal.vue";
import { buildLinkCreate } from "ChillMainAssets/lib/entity-workflow/api.js";
const i18n = {
messages: {
fr: {
no_evaluation_associated: "Aucune évaluation associée",
add_an_evaluation: "Évaluations disponibles",
evaluation_has_no_evaluation: "Aucune évaluation disponible",
startDate: "Date d'ouverture",
endDate: "Date de fin",
maxDate: "Date d'échéance",
warningInterval: "Rappel (jours)",
comment: "Note publique",
documents: "Documents",
delete: {
sure: "Êtes-vous sûr?",
sure_description: "Cette évaluation sera supprimée de cette action d'accompagnement",
ok: "Supprimer"
},
delete_evaluation: "Supprimer l'évaluation",
}
}
messages: {
fr: {
no_evaluation_associated: "Aucune évaluation associée",
add_an_evaluation: "Évaluations disponibles",
evaluation_has_no_evaluation: "Aucune évaluation disponible",
startDate: "Date d'ouverture",
endDate: "Date de fin",
maxDate: "Date d'échéance",
warningInterval: "Rappel (jours)",
comment: "Note publique",
documents: "Documents",
delete: {
sure: "Êtes-vous sûr?",
sure_description:
"Cette évaluation sera supprimée de cette action d'accompagnement",
ok: "Supprimer",
},
delete_evaluation: "Supprimer l'évaluation",
},
},
};
export default {
name: "AddEvaluation",
components: {
FormEvaluation,
Modal,
ListWorkflowModal,
},
props: ['evaluation', 'docAnchorId'],
i18n,
data() {
return {
modal: {
showModal: false,
modalDialogClass: "modal-dialog-centered modal-md"
}
};
},
computed: {
pickedEvaluations() {
return this.$store.state.evaluationsPicked;
name: "AddEvaluation",
components: {
FormEvaluation,
Modal,
ListWorkflowModal,
},
props: ["evaluation", "docAnchorId"],
i18n,
data() {
return {
modal: {
showModal: false,
modalDialogClass: "modal-dialog-centered modal-md",
},
canDelete() {
if (this.evaluation.workflows.length > 0) {
};
},
computed: {
pickedEvaluations() {
return this.$store.state.evaluationsPicked;
},
canDelete() {
if (this.evaluation.workflows.length > 0) {
return false;
}
for (let doc of this.evaluation.documents) {
if (doc.workflows.length > 0) {
return false;
}
for (let doc of this.evaluation.documents) {
if (doc.workflows.length > 0) {
return false;
}
}
return true;
},
},
methods: {
removeEvaluation(e) {
this.$store.commit('removeEvaluation', e);
return;
},
toggleEditEvaluation() {
this.$store.commit('toggleEvaluationEdit', { key: this.evaluation.key });
},
submitForm() {
this.toggleEditEvaluation();
},
goToGenerateWorkflow({workflowName}) {
const callback = (data) => {
let evaluationId = data.accompanyingPeriodWorkEvaluations.find(e => e.key === this.evaluation.key).id;
window.location.assign(buildLinkCreate(workflowName,
'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluation', evaluationId));
};
return this.$store.dispatch('submit', callback)
.catch(e => { console.log(e); throw e; });
}
}
}
return true;
},
},
methods: {
removeEvaluation(e) {
this.$store.commit("removeEvaluation", e);
return;
},
toggleEditEvaluation() {
this.$store.commit("toggleEvaluationEdit", { key: this.evaluation.key });
},
submitForm() {
this.toggleEditEvaluation();
},
goToGenerateWorkflow({ workflowName }) {
const callback = (data) => {
let evaluationId = data.accompanyingPeriodWorkEvaluations.find(
(e) => e.key === this.evaluation.key,
).id;
window.location.assign(
buildLinkCreate(
workflowName,
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluation",
evaluationId,
),
);
};
return this.$store.dispatch("submit", callback).catch((e) => {
console.log(e);
throw e;
});
},
},
};
</script>
<style lang="scss" scoped>
div.item-title{
.evaluation-title{
cursor: default;
&::before{
content: "";
}
}
}
div.item-url {
i {
color: unset!important;
margin-left: 1rem;
margin-right: 0.5rem;
}
}
div.item-title {
.evaluation-title {
cursor: default;
&::before {
content: "";
}
}
}
div.item-url {
i {
color: unset !important;
margin-left: 1rem;
margin-right: 0.5rem;
}
}
</style>

View File

@@ -1,36 +1,20 @@
<template>
<div
v-if="hasResult"
class="addResult"
>
<p
v-if="pickedResults.length ===0"
class="chill-no-data-statement"
>
<div v-if="hasResult" class="addResult">
<p v-if="pickedResults.length === 0" class="chill-no-data-statement">
Aucun résultat associé
</p>
<ul class="list-suggest remove-items">
<li
v-for="r in pickedResults"
@click="removeResult(r)"
:key="r.id"
>
<li v-for="r in pickedResults" @click="removeResult(r)" :key="r.id">
<span>
{{ r.title.fr }}
</span>
</li>
</ul>
<div
class="accordion"
id="expandedSuggestions"
>
<div class="accordion" id="expandedSuggestions">
<div class="accordion-item">
<h2
class="accordion-header"
id="heading_expanded_suggestions"
>
<h2 class="accordion-header" id="heading_expanded_suggestions">
<button
v-if="isExpanded"
class="accordion-button"
@@ -74,105 +58,107 @@
</div>
</div>
</div>
<div
v-if="!hasResult"
class="noResult"
>
<div v-if="!hasResult" class="noResult">
<div class="chill-no-data-statement">
{{ $t('goal_has_no_result') }}
{{ $t("goal_has_no_result") }}
</div>
</div>
</template>
<script>
const i18n = {
messages: {
fr: {
add_a_result: "Résultat - orientation disponibles",
goal_has_no_result: "Aucun résultat - orientation disponible",
}
}
messages: {
fr: {
add_a_result: "Résultat - orientation disponibles",
goal_has_no_result: "Aucun résultat - orientation disponible",
},
},
};
export default {
name: "AddResult",
props: ['destination', 'goal', 'availableResults'],
i18n,
data() {
return {
isExpanded: false,
};
},
computed: {
hasResult() {
if (this.destination === 'action') {
return this.$store.state.resultsForAction.length > 0;
} else if (this.destination === 'goal') {
return this.$store.getters.resultsForGoal(this.goal).length > 0;
}
throw Error(`this.destination is not implemented: ${this.destination}`);
},
pickedResults() {
if (this.destination === 'action') {
return this.$store.state.resultsPicked;
} else if (this.destination === 'goal') {
return this.$store.getters.resultsPickedForGoal(this.goal);
}
throw Error(`this.destination is not implemented: ${this.destination}`);
},
availableForCheckResults() {
if (this.destination === 'action') {
let pickedIds = this.$store.state.resultsPicked.map(r => r.id);
return this.$store.state.resultsForAction.filter(r => !pickedIds.includes(r.id));
} else if (this.destination === 'goal') {
let pickedIds = this.$store.getters.resultsPickedForGoal(this.goal).map(r => r.id);
return this.$store.getters.resultsForGoal(this.goal).filter(r => !pickedIds.includes(r.id));
}
throw Error(`this.destination is not implemented: ${this.destination}`);
name: "AddResult",
props: ["destination", "goal", "availableResults"],
i18n,
data() {
return {
isExpanded: false,
};
},
computed: {
hasResult() {
if (this.destination === "action") {
return this.$store.state.resultsForAction.length > 0;
} else if (this.destination === "goal") {
return this.$store.getters.resultsForGoal(this.goal).length > 0;
}
},
methods: {
toggleSelect() {
this.isExpanded = !this.isExpanded;
},
addResult(r) {
if (this.destination === 'action') {
this.$store.commit('addResultPicked', r);
return;
} else if (this.destination === 'goal') {
this.$store.commit('addResultForGoalPicked', {goal: this.goal, result: r});
return;
}
throw Error(`this.destination is not implemented: ${this.destination}`);
},
removeResult(r) {
if (this.destination === 'action') {
this.$store.commit('removeResultPicked', r);
return;
} else if (this.destination === 'goal') {
this.$store.commit('removeResultForGoalPicked', {goal: this.goal, result: r});
return;
}
throw Error(`this.destination is not implemented: ${this.destination}`);
throw Error(`this.destination is not implemented: ${this.destination}`);
},
pickedResults() {
if (this.destination === "action") {
return this.$store.state.resultsPicked;
} else if (this.destination === "goal") {
return this.$store.getters.resultsPickedForGoal(this.goal);
}
}
}
throw Error(`this.destination is not implemented: ${this.destination}`);
},
availableForCheckResults() {
if (this.destination === "action") {
let pickedIds = this.$store.state.resultsPicked.map((r) => r.id);
return this.$store.state.resultsForAction.filter(
(r) => !pickedIds.includes(r.id),
);
} else if (this.destination === "goal") {
let pickedIds = this.$store.getters
.resultsPickedForGoal(this.goal)
.map((r) => r.id);
return this.$store.getters
.resultsForGoal(this.goal)
.filter((r) => !pickedIds.includes(r.id));
}
throw Error(`this.destination is not implemented: ${this.destination}`);
},
},
methods: {
toggleSelect() {
this.isExpanded = !this.isExpanded;
},
addResult(r) {
if (this.destination === "action") {
this.$store.commit("addResultPicked", r);
return;
} else if (this.destination === "goal") {
this.$store.commit("addResultForGoalPicked", {
goal: this.goal,
result: r,
});
return;
}
throw Error(`this.destination is not implemented: ${this.destination}`);
},
removeResult(r) {
if (this.destination === "action") {
this.$store.commit("removeResultPicked", r);
return;
} else if (this.destination === "goal") {
this.$store.commit("removeResultForGoalPicked", {
goal: this.goal,
result: r,
});
return;
}
throw Error(`this.destination is not implemented: ${this.destination}`);
},
},
};
</script>
<style lang="scss" scoped>
.accordion-button {
padding: .25rem;
padding: 0.25rem;
}
</style>

View File

@@ -19,55 +19,55 @@
<div class="row mb-3">
<label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label">
{{ $t('evaluation_startdate') }}
{{ $t("evaluation_startdate") }}
</label>
<div class="col-8 col-sm-4 col-md-8 col-lg-4">
<input
class="form-control form-control-sm"
type="date"
v-model="startDate"
>
/>
</div>
<label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label">
{{ $t('evaluation_enddate') }}
{{ $t("evaluation_enddate") }}
</label>
<div class="col-8 col-sm-4 col-md-8 col-lg-4">
<input
class="form-control form-control-sm"
type="date"
v-model="endDate"
>
/>
</div>
</div>
<div class="row mb-3">
<label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label">
{{ $t('evaluation_maxdate') }}
{{ $t("evaluation_maxdate") }}
</label>
<div class="col-8 col-sm-4 col-md-8 col-lg-4">
<input
class="form-control form-control-sm"
type="date"
v-model="maxDate"
>
/>
</div>
<label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label">
{{ $t('evaluation_warning_interval') }}
{{ $t("evaluation_warning_interval") }}
</label>
<div class="col-8 col-sm-4 col-md-8 col-lg-4">
<input
class="form-control form-control-sm"
type="number"
v-model.number="warningInterval"
>
/>
</div>
</div>
<div class="row mb-3">
<label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label">
{{ $t('evaluation_time_spent') }}
{{ $t("evaluation_time_spent") }}
</label>
<div class="col-8 col-sm-4 col-md-8 col-lg-4">
<select
@@ -75,11 +75,8 @@
type="time"
v-model="timeSpent"
>
<option
disabled
value=""
>
{{ $t('select_time_spent') }}
<option disabled value="">
{{ $t("select_time_spent") }}
</option>
<option
v-for="(time, index) in timeSpentChoices"
@@ -93,7 +90,9 @@
</div>
<div class="row mb-3">
<label class="col-sm-4 col-form-label visually-hidden">{{ $t('evaluation_public_comment') }}</label>
<label class="col-sm-4 col-form-label visually-hidden">{{
$t("evaluation_public_comment")
}}</label>
<div class="col-sm-12">
<ckeditor
:editor="editor"
@@ -104,25 +103,23 @@
</div>
</div>
<div
v-if="evaluation.documents.length > 0"
class="row mb-3"
>
<h5>{{ $t('Documents') }} :</h5>
<div v-if="evaluation.documents.length > 0" class="row mb-3">
<h5>{{ $t("Documents") }} :</h5>
<div class="flex-table">
<div
class="item-bloc"
v-for="(d, i) in evaluation.documents"
:key="d.id"
:class="[parseInt(this.docAnchorId) === d.id ? 'bg-blink' : 'nothing']"
:class="[
parseInt(this.docAnchorId) === d.id ? 'bg-blink' : 'nothing',
]"
>
<div
:id="`document_${d.id}`"
class="item-row"
>
<div :id="`document_${d.id}`" class="item-row">
<div class="input-group input-group-lg mb-3 row">
<label class="col-sm-3 col-form-label">Titre du document:</label>
<label class="col-sm-3 col-form-label"
>Titre du document:</label
>
<div class="col-sm-9">
<input
class="form-control document-title"
@@ -131,18 +128,15 @@
:id="d.id"
:data-key="i"
@input="onInputDocumentTitle"
>
/>
</div>
</div>
</div>
<div class="item-row">
<div class="item-col item-meta">
<p
v-if="d.createdBy"
class="createdBy"
>
Créé par {{ d.createdBy.text }}<br>
Le {{ $d(ISOToDatetime(d.createdAt.datetime), 'long') }}
<p v-if="d.createdBy" class="createdBy">
Créé par {{ d.createdBy.text }}<br />
Le {{ $d(ISOToDatetime(d.createdAt.datetime), "long") }}
</p>
</div>
</div>
@@ -157,8 +151,10 @@
:related-entity-id="d.id"
:workflows-availables="d.workflows_availables"
:prevent-default-move-to-generate="true"
:go-to-generate-workflow-payload="{doc: d}"
@go-to-generate-workflow="goToGenerateWorkflowEvaluationDocument"
:go-to-generate-workflow-payload="{ doc: d }"
@go-to-generate-workflow="
goToGenerateWorkflowEvaluationDocument
"
/>
</li>
<li>
@@ -176,7 +172,7 @@
data-bs-toggle="dropdown"
aria-expanded="false"
>
&nbsp;
&nbsp;
</button>
<ul
class="dropdown-menu"
@@ -186,13 +182,15 @@
<a
class="dropdown-item"
@click="goToGenerateDocumentNotification(d, true)"
>{{ $t('notification_notify_referrer') }}</a>
>{{ $t("notification_notify_referrer") }}</a
>
</li>
<li>
<a
class="dropdown-item"
@click="goToGenerateDocumentNotification(d, false)"
>{{ $t('notification_notify_any') }}</a>
>{{ $t("notification_notify_any") }}</a
>
</li>
</ul>
</template>
@@ -204,7 +202,9 @@
:can-edit="true"
:execute-before-leave="submitBeforeLeaveToEditor"
:dav-link="d.storedObject._links?.dav_link.href"
:dav-link-expiration="d.storedObject._links?.dav_link.expiration"
:dav-link-expiration="
d.storedObject._links?.dav_link.expiration
"
@on-stored-object-status-change="onStatusDocumentChanged"
/>
</li>
@@ -212,15 +212,12 @@
<add-async-upload
:button-title="$t('replace')"
:options="asyncUploadOptions"
:btn-classes="{'btn': true, 'btn-edit': true}"
:btn-classes="{ btn: true, 'btn-edit': true }"
@add-document="(arg) => replaceDocument(d, arg)"
/>
</li>
<li v-if="d.workflows.length === 0">
<a
class="btn btn-delete"
@click="removeDocument(d)"
/>
<a class="btn btn-delete" @click="removeDocument(d)" />
</li>
</ul>
</div>
@@ -230,7 +227,7 @@
</div>
<div class="row mb-3">
<h6>{{ $t('document_add') }} :</h6>
<h6>{{ $t("document_add") }} :</h6>
<pick-template
entity-class="Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation"
:id="evaluation.id"
@@ -239,11 +236,13 @@
@go-to-generate-document="submitBeforeGenerate"
>
<template #title>
<label class="col-form-label">{{ $t('evaluation_generate_a_document') }}</label>
<label class="col-form-label">{{
$t("evaluation_generate_a_document")
}}</label>
</template>
</pick-template>
<div>
<label class="col-form-label">{{ $t('document_upload') }}</label>
<label class="col-form-label">{{ $t("document_upload") }}</label>
<ul class="record_actions document-upload">
<li>
<add-async-upload
@@ -260,266 +259,395 @@
</template>
<script>
import {ISOToDatetime} from 'ChillMainAssets/chill/js/date';
import CKEditor from '@ckeditor/ckeditor5-vue';
import ClassicEditor from 'ChillMainAssets/module/ckeditor5/editor_config';
import { mapState } from 'vuex';
import PickTemplate from 'ChillDocGeneratorAssets/vuejs/_components/PickTemplate.vue';
import {buildLink} from 'ChillDocGeneratorAssets/lib/document-generator';
import AddAsyncUpload from 'ChillDocStoreAssets/vuejs/_components/AddAsyncUpload.vue';
import ListWorkflowModal from 'ChillMainAssets/vuejs/_components/EntityWorkflow/ListWorkflowModal.vue';
import {buildLinkCreate} from 'ChillMainAssets/lib/entity-workflow/api.js';
import {buildLinkCreate as buildLinkCreateNotification} from 'ChillMainAssets/lib/entity-notification/api';
import { ISOToDatetime } from "ChillMainAssets/chill/js/date";
import CKEditor from "@ckeditor/ckeditor5-vue";
import ClassicEditor from "ChillMainAssets/module/ckeditor5/editor_config";
import { mapState } from "vuex";
import PickTemplate from "ChillDocGeneratorAssets/vuejs/_components/PickTemplate.vue";
import { buildLink } from "ChillDocGeneratorAssets/lib/document-generator";
import AddAsyncUpload from "ChillDocStoreAssets/vuejs/_components/AddAsyncUpload.vue";
import ListWorkflowModal from "ChillMainAssets/vuejs/_components/EntityWorkflow/ListWorkflowModal.vue";
import { buildLinkCreate } from "ChillMainAssets/lib/entity-workflow/api.js";
import { buildLinkCreate as buildLinkCreateNotification } from "ChillMainAssets/lib/entity-notification/api";
import DocumentActionButtonsGroup from "ChillDocStoreAssets/vuejs/DocumentActionButtonsGroup.vue";
const i18n = {
messages: {
fr: {
evaluation_title: "Ecrire une évaluation",
evaluation_status: "Statut",
evaluation_choose_a_status: "Choisir un statut",
evaluation_startdate: "Date d'ouverture",
evaluation_enddate: "Date de fin",
evaluation_maxdate: "Date d'échéance",
evaluation_warning_interval: "Rappel (jours)",
evaluation_public_comment: "Note publique",
evaluation_comment_placeholder: "Commencez à écrire ...",
evaluation_generate_a_document: "Générer un document",
evaluation_choose_a_template: "Choisir un modèle",
evaluation_add_a_document: "Ajouter un document",
evaluation_add: "Ajouter une évaluation",
evaluation_time_spent: "Temps de rédaction",
select_time_spent: "Indiquez le temps de rédaction",
Documents: "Documents",
document_add: "Générer ou téléverser un document",
document_upload: "Téléverser un document",
document_title: "Titre du document",
template_title: "Nom du template",
browse: "Ajouter un document",
replace: "Remplacer",
download: "Télécharger le fichier existant",
notification_notify_referrer: "Notifier le référent",
notification_notify_any: "Notifier d'autres utilisateurs",
notification_send: "Envoyer une notification",
}
}
messages: {
fr: {
evaluation_title: "Ecrire une évaluation",
evaluation_status: "Statut",
evaluation_choose_a_status: "Choisir un statut",
evaluation_startdate: "Date d'ouverture",
evaluation_enddate: "Date de fin",
evaluation_maxdate: "Date d'échéance",
evaluation_warning_interval: "Rappel (jours)",
evaluation_public_comment: "Note publique",
evaluation_comment_placeholder: "Commencez à écrire ...",
evaluation_generate_a_document: "Générer un document",
evaluation_choose_a_template: "Choisir un modèle",
evaluation_add_a_document: "Ajouter un document",
evaluation_add: "Ajouter une évaluation",
evaluation_time_spent: "Temps de rédaction",
select_time_spent: "Indiquez le temps de rédaction",
Documents: "Documents",
document_add: "Générer ou téléverser un document",
document_upload: "Téléverser un document",
document_title: "Titre du document",
template_title: "Nom du template",
browse: "Ajouter un document",
replace: "Remplacer",
download: "Télécharger le fichier existant",
notification_notify_referrer: "Notifier le référent",
notification_notify_any: "Notifier d'autres utilisateurs",
notification_send: "Envoyer une notification",
},
},
};
export default {
name: "FormEvaluation",
props: ['evaluation', 'docAnchorId'],
components: {
ckeditor: CKEditor.component,
PickTemplate,
AddAsyncUpload,
ListWorkflowModal,
DocumentActionButtonsGroup,
},
i18n,
data() {
return {
editor: ClassicEditor,
template: null,
asyncUploadOptions: {
maxFiles: 1,
maxPostSize: 15000000,
required: false,
},
timeSpentChoices: [
{ text: '1 minute', value: 60 }, { text: '2 minutes', value: 120 },
{ text: '3 minutes', value: 180 }, { text: '4 minutes', value: 240 },
{ text: '5 minutes', value: 300 }, { text: '10 minutes', value: 600 },
{ text: '15 minutes', value: 900 },{ text: '20 minutes', value: 1200 },
{ text: '25 minutes', value: 1500 }, { text: '30 minutes', value: 1800 },
{ text: '45 minutes', value: 2700 },{ text: '1 hour', value: 3600 },
{ text: '1 hour 15 minutes', value: 4500 }, { text: '1 hour 30 minutes', value: 5400 },
{ text: '1 hour 45 minutes', value: 6300 }, { text: '2 hours', value: 7200 },
{ text: '2 hours 30 minutes', value: 9000 }, { text: '3 hours', value: 10800 },
{ text: '3 hours 30 minutes', value: 12600 },{ text: '4 hours', value: 14400 },
{ text: '4 hours 30 minutes', value: 16200 },{ text: '5 hours', value: 18000 },
{ text: '5 hours 30 minutes', value: 19800 },{ text: '6 hours', value: 21600 },
{ text: '6 hours 30 minutes', value: 23400 },{ text: '7 hours', value: 25200 },
{ text: '7 hours 30 minutes', value: 27000 },{ text: '8 hours', value: 28800 },
]
name: "FormEvaluation",
props: ["evaluation", "docAnchorId"],
components: {
ckeditor: CKEditor.component,
PickTemplate,
AddAsyncUpload,
ListWorkflowModal,
DocumentActionButtonsGroup,
},
i18n,
data() {
return {
editor: ClassicEditor,
template: null,
asyncUploadOptions: {
maxFiles: 1,
maxPostSize: 15000000,
required: false,
},
timeSpentChoices: [
{ text: "1 minute", value: 60 },
{ text: "2 minutes", value: 120 },
{ text: "3 minutes", value: 180 },
{ text: "4 minutes", value: 240 },
{ text: "5 minutes", value: 300 },
{ text: "10 minutes", value: 600 },
{ text: "15 minutes", value: 900 },
{ text: "20 minutes", value: 1200 },
{ text: "25 minutes", value: 1500 },
{ text: "30 minutes", value: 1800 },
{ text: "45 minutes", value: 2700 },
{ text: "1 hour", value: 3600 },
{ text: "1 hour 15 minutes", value: 4500 },
{ text: "1 hour 30 minutes", value: 5400 },
{ text: "1 hour 45 minutes", value: 6300 },
{ text: "2 hours", value: 7200 },
{ text: "2 hours 30 minutes", value: 9000 },
{ text: "3 hours", value: 10800 },
{ text: "3 hours 30 minutes", value: 12600 },
{ text: "4 hours", value: 14400 },
{ text: "4 hours 30 minutes", value: 16200 },
{ text: "5 hours", value: 18000 },
{ text: "5 hours 30 minutes", value: 19800 },
{ text: "6 hours", value: 21600 },
{ text: "6 hours 30 minutes", value: 23400 },
{ text: "7 hours", value: 25200 },
{ text: "7 hours 30 minutes", value: 27000 },
{ text: "8 hours", value: 28800 },
],
};
},
computed: {
...mapState(["isPosting", "work", "me"]),
AmIRefferer() {
return !(
this.$store.state.work.accompanyingPeriod.user &&
this.$store.state.me &&
this.$store.state.work.accompanyingPeriod.user.id !==
this.$store.state.me.id
);
},
getTemplatesAvailables() {
return this.$store.getters.getTemplatesAvailablesForEvaluation(
this.evaluation.evaluation,
);
},
canGenerate() {
return !this.$store.state.isPosting && this.template !== null;
},
startDate: {
get() {
console.log("evaluation", this.evaluation);
return this.evaluation.startDate;
},
set(v) {
this.$store.commit("setEvaluationStartDate", {
key: this.evaluation.key,
date: v,
});
},
},
endDate: {
get() {
return this.evaluation.endDate;
},
set(v) {
this.$store.commit("setEvaluationEndDate", {
key: this.evaluation.key,
date: v,
});
},
},
maxDate: {
get() {
return this.evaluation.maxDate;
},
set(v) {
this.$store.commit("setEvaluationMaxDate", {
key: this.evaluation.key,
date: v,
});
},
},
warningInterval: {
get() {
return this.evaluation.warningInterval;
},
set(v) {
this.$store.commit("setEvaluationWarningInterval", {
key: this.evaluation.key,
days: v,
});
},
},
timeSpent: {
get() {
return this.evaluation.timeSpent;
},
set(v) {
this.$store.commit("setEvaluationTimeSpent", {
key: this.evaluation.key,
time: v,
});
},
},
comment: {
get() {
return this.evaluation.comment;
},
set(v) {
this.$store.commit("setEvaluationComment", {
key: this.evaluation.key,
comment: v,
});
},
},
},
methods: {
ISOToDatetime,
listAllStatus() {
console.log("load all status");
let url = `/api/`;
fetch(url).then((response) => {
if (response.ok) {
return response.json();
}
throw { m: "yeeah", s: response.status, b: response.body };
});
},
buildEditLink(document) {
return (
`/chill/wopi/edit/${document.storedObject.uuid}?returnPath=` +
encodeURIComponent(
window.location.pathname +
window.location.search +
window.location.hash,
)
);
},
submitBeforeLeaveToEditor() {
console.log("submit beore edit 2");
// empty callback
const callback = () => null;
return this.$store.dispatch("submit", callback).catch((e) => {
console.log(e);
throw e;
});
},
submitBeforeEdit(storedObject) {
const callback = (data) => {
let evaluation = data.accompanyingPeriodWorkEvaluations.find(
(e) => e.key === this.evaluation.key,
);
let document = evaluation.documents.find(
(d) => d.storedObject.id === storedObject.id,
);
//console.log('=> document', document);
window.location.assign(this.buildEditLink(document));
};
return this.$store.dispatch("submit", callback).catch((e) => {
console.log(e);
throw e;
});
},
submitBeforeGenerate({ template }) {
const callback = (data) => {
let evaluationId = data.accompanyingPeriodWorkEvaluations.find(
(e) => e.key === this.evaluation.key,
).id;
window.location.assign(
buildLink(
template,
evaluationId,
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluation",
),
);
};
return this.$store.dispatch("submit", callback).catch((e) => {
console.log(e);
throw e;
});
},
onInputDocumentTitle(event) {
const id = Number(event.target.id);
const key = Number(event.target.dataset.key) + 1;
const title = event.target.value;
this.$store.commit("updateDocumentTitle", {
id: id,
key: key,
evaluationKey: this.evaluation.key,
title: title,
});
},
addDocument(storedObject) {
let document = {
type: "accompanying_period_work_evaluation_document",
storedObject: storedObject,
title: "Nouveau document",
};
this.$store.commit("addDocument", {
key: this.evaluation.key,
document: document,
});
},
replaceDocument(oldDocument, storedObject) {
let document = {
type: "accompanying_period_work_evaluation_document",
storedObject: storedObject,
title: oldDocument.title,
};
this.$store.commit("replaceDocument", {
key: this.evaluation.key,
document: document,
oldDocument: oldDocument,
});
},
removeDocument(document) {
if (
window.confirm(
'Êtes-vous sûr·e de vouloir supprimer le document qui a pour titre "' +
document.title +
'" ?',
)
) {
this.$store.commit("removeDocument", {
key: this.evaluation.key,
document: document,
});
}
},
computed: {
...mapState([
'isPosting',
'work',
'me',
]),
AmIRefferer() {
return (!(this.$store.state.work.accompanyingPeriod.user && this.$store.state.me
&& (this.$store.state.work.accompanyingPeriod.user.id !== this.$store.state.me.id)));
},
getTemplatesAvailables() {
return this.$store.getters.getTemplatesAvailablesForEvaluation(this.evaluation.evaluation);
},
canGenerate() {
return !this.$store.state.isPosting && this.template !== null;
},
startDate: {
get() {
console.log('evaluation', this.evaluation);
return this.evaluation.startDate;
},
set(v) {
this.$store.commit('setEvaluationStartDate', { key: this.evaluation.key, date: v });
}
},
endDate: {
get() {
return this.evaluation.endDate;
},
set(v) {
this.$store.commit('setEvaluationEndDate', { key: this.evaluation.key, date: v });
}
},
maxDate: {
get() {
return this.evaluation.maxDate;
},
set(v) {
this.$store.commit('setEvaluationMaxDate', { key: this.evaluation.key, date: v });
}
},
warningInterval: {
get() { return this.evaluation.warningInterval; },
set(v) { this.$store.commit('setEvaluationWarningInterval', { key: this.evaluation.key, days: v }); }
},
timeSpent: {
get() { return this.evaluation.timeSpent },
set(v) { this.$store.commit('setEvaluationTimeSpent', { key: this.evaluation.key, time: v}) }
},
comment: {
get() { return this.evaluation.comment; },
set(v) { this.$store.commit('setEvaluationComment', { key: this.evaluation.key, comment: v }); }
},
},
methods: {
ISOToDatetime,
listAllStatus() {
console.log('load all status');
let url = `/api/`;
fetch(url)
.then(response => {
if (response.ok) {
return response.json();
}
throw { m: 'yeeah', s: response.status, b: response.body };
})
;
},
buildEditLink(document) {
return `/chill/wopi/edit/${document.storedObject.uuid}?returnPath=` + encodeURIComponent(
window.location.pathname + window.location.search + window.location.hash);
},
submitBeforeLeaveToEditor() {
console.log('submit beore edit 2');
// empty callback
const callback = () => null;
return this.$store.dispatch('submit', callback).catch(e => { console.log(e); throw e; });
},
submitBeforeEdit(storedObject) {
const callback = (data) => {
let evaluation = data.accompanyingPeriodWorkEvaluations.find(e => e.key === this.evaluation.key);
let document = evaluation.documents.find(d => d.storedObject.id === storedObject.id);
//console.log('=> document', document);
window.location.assign(this.buildEditLink(document));
};
return this.$store.dispatch('submit', callback).catch(e => { console.log(e); throw e; });
},
submitBeforeGenerate({template}) {
const callback = (data) => {
let evaluationId = data.accompanyingPeriodWorkEvaluations.find(e => e.key === this.evaluation.key).id;
},
onStatusDocumentChanged(newStatus) {
console.log("onStatusDocumentChanged", newStatus);
this.$store.commit("statusDocumentChanged", {
key: this.evaluation.key,
newStatus: newStatus,
});
},
goToGenerateWorkflowEvaluationDocument({
event,
link,
workflowName,
payload,
}) {
const callback = (data) => {
let evaluation = data.accompanyingPeriodWorkEvaluations.find(
(e) => e.key === this.evaluation.key,
);
let updatedDocument = evaluation.documents.find(
(d) => d.key === payload.doc.key,
);
window.location.assign(
buildLinkCreate(
workflowName,
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument",
updatedDocument.id,
),
);
};
window.location.assign(buildLink(template, evaluationId, 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluation'));
};
return this.$store.dispatch('submit', callback).catch(e => { console.log(e); throw e; });
},
onInputDocumentTitle(event) {
const id = Number(event.target.id);
const key = Number(event.target.dataset.key) + 1;
const title = event.target.value;
this.$store.commit('updateDocumentTitle', {id: id, key: key, evaluationKey: this.evaluation.key, title: title});
},
addDocument(storedObject) {
let document = {
type: 'accompanying_period_work_evaluation_document',
storedObject: storedObject,
title: 'Nouveau document',
};
this.$store.commit('addDocument', {key: this.evaluation.key, document: document});
},
replaceDocument(oldDocument, storedObject) {
let document = {
type: 'accompanying_period_work_evaluation_document',
storedObject: storedObject,
title: oldDocument.title
};
this.$store.commit('replaceDocument', {key: this.evaluation.key, document: document, oldDocument: oldDocument});
},
removeDocument(document) {
if (window.confirm("Êtes-vous sûr·e de vouloir supprimer le document qui a pour titre \"" + document.title +"\" ?")) {
this.$store.commit('removeDocument', {key: this.evaluation.key, document: document});
}
},
onStatusDocumentChanged(newStatus) {
console.log('onStatusDocumentChanged', newStatus);
this.$store.commit('statusDocumentChanged', {key: this.evaluation.key, newStatus: newStatus});
},
goToGenerateWorkflowEvaluationDocument({event, link, workflowName, payload}) {
const callback = (data) => {
let evaluation = data.accompanyingPeriodWorkEvaluations.find(e => e.key === this.evaluation.key);
let updatedDocument = evaluation.documents.find(d => d.key === payload.doc.key);
window.location.assign(buildLinkCreate(workflowName,
'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument', updatedDocument.id));
};
return this.$store.dispatch('submit', callback)
.catch(e => { console.log(e); throw e; });
},
goToGenerateDocumentNotification(document, tos) {
const callback = (data) => {
let evaluation = data.accompanyingPeriodWorkEvaluations.find(e => e.key === this.evaluation.key);
let updatedDocument = evaluation.documents.find(d => d.key === document.key);
window.location.assign(buildLinkCreateNotification(
'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument',
updatedDocument.id,
tos === true ? this.$store.state.work.accompanyingPeriod.user.id : null,
window.location.pathname + window.location.search + window.location.hash
));
};
return this.$store.dispatch('submit', callback)
.catch(e => {console.log(e); throw e});
}
},
}
return this.$store.dispatch("submit", callback).catch((e) => {
console.log(e);
throw e;
});
},
goToGenerateDocumentNotification(document, tos) {
const callback = (data) => {
let evaluation = data.accompanyingPeriodWorkEvaluations.find(
(e) => e.key === this.evaluation.key,
);
let updatedDocument = evaluation.documents.find(
(d) => d.key === document.key,
);
window.location.assign(
buildLinkCreateNotification(
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluationDocument",
updatedDocument.id,
tos === true
? this.$store.state.work.accompanyingPeriod.user.id
: null,
window.location.pathname +
window.location.search +
window.location.hash,
),
);
};
return this.$store.dispatch("submit", callback).catch((e) => {
console.log(e);
throw e;
});
},
},
};
</script>
<style lang="scss" scoped>
input.document-title {
font-weight: bold;
font-size: 1rem;
}
ul.document-upload {
justify-content: flex-start;
}
input.document-title {
font-weight: bold;
font-size: 1rem;
}
ul.document-upload {
justify-content: flex-start;
}
.bg-blink{
color: #050000;
padding: 10px;
display: inline-block;
border-radius: 5px;
animation: blinkingBackground 2.2s infinite;
animation-iteration-count: 2;
}
.bg-blink {
color: #050000;
padding: 10px;
display: inline-block;
border-radius: 5px;
animation: blinkingBackground 2.2s infinite;
animation-iteration-count: 2;
}
@keyframes blinkingBackground{
0% { background-color: #ed776d;}
50% { background-color: #ffffff;}
100% { background-color: #ed776d;}
}
@keyframes blinkingBackground {
0% {
background-color: #ed776d;
}
50% {
background-color: #ffffff;
}
100% {
background-color: #ed776d;
}
}
</style>

View File

@@ -1,24 +1,24 @@
import { createApp } from 'vue';
import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n';
import { store } from './store';
import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n';
import 'vue-toast-notification/dist/theme-sugar.css';
import App from './App.vue';
import { createApp } from "vue";
import { _createI18n } from "ChillMainAssets/vuejs/_js/i18n";
import { store } from "./store";
import { personMessages } from "ChillPersonAssets/vuejs/_js/i18n";
import "vue-toast-notification/dist/theme-sugar.css";
import App from "./App.vue";
import ToastPlugin from "vue-toast-notification";
const i18n = _createI18n(personMessages);
/* exported app */
const app = createApp({
template: `<app></app>`,
template: `<app></app>`,
})
.use(store)
.use(ToastPlugin, {
position: "bottom-right",
type: "error",
duration: 10000,
dismissible: true
})
.use(i18n)
.component('app', App)
.mount('#accompanying_course_work_edit');
.use(store)
.use(ToastPlugin, {
position: "bottom-right",
type: "error",
duration: 10000,
dismissible: true,
})
.use(i18n)
.component("app", App)
.mount("#accompanying_course_work_edit");

View File

@@ -1,18 +1,28 @@
import { createStore } from 'vuex';
import { dateToISO, ISOToDate, datetimeToISO, intervalDaysToISO, intervalISOToDays } from 'ChillMainAssets/chill/js/date';
import { fetchResults, makeFetch } from 'ChillMainAssets/lib/api/apiMethods.ts';
import { fetchTemplates } from 'ChillDocGeneratorAssets/api/pickTemplate.js';
import { createStore } from "vuex";
import {
dateToISO,
ISOToDate,
datetimeToISO,
intervalDaysToISO,
intervalISOToDays,
} from "ChillMainAssets/chill/js/date";
import { fetchResults, makeFetch } from "ChillMainAssets/lib/api/apiMethods.ts";
import { fetchTemplates } from "ChillDocGeneratorAssets/api/pickTemplate.js";
const debug = process.env.NODE_ENV !== 'production';
const debug = process.env.NODE_ENV !== "production";
const store = createStore({
strict: debug,
state: {
work: window.accompanyingCourseWork,
startDate: window.accompanyingCourseWork.startDate !== null ?
dateToISO(new Date(window.accompanyingCourseWork.startDate.datetime)) : null,
endDate: window.accompanyingCourseWork.endDate !== null ?
dateToISO(new Date(window.accompanyingCourseWork.endDate.datetime)) : null,
startDate:
window.accompanyingCourseWork.startDate !== null
? dateToISO(new Date(window.accompanyingCourseWork.startDate.datetime))
: null,
endDate:
window.accompanyingCourseWork.endDate !== null
? dateToISO(new Date(window.accompanyingCourseWork.endDate.datetime))
: null,
note: window.accompanyingCourseWork.note,
privateComment: window.accompanyingCourseWork.privateComment,
goalsPicked: window.accompanyingCourseWork.goals,
@@ -25,15 +35,17 @@ const store = createStore({
templatesAvailablesForAction: [],
templatesAvailablesForEvaluation: new Map([]),
personsPicked: window.accompanyingCourseWork.persons,
personsReachables: window.accompanyingCourseWork.accompanyingPeriod.participations.filter(p => p.endDate == null)
.map(p => p.person),
personsReachables:
window.accompanyingCourseWork.accompanyingPeriod.participations
.filter((p) => p.endDate == null)
.map((p) => p.person),
handlingThirdParty: window.accompanyingCourseWork.handlingThierParty,
thirdParties: window.accompanyingCourseWork.thirdParties,
referrers: window.accompanyingCourseWork.referrers,
isPosting: false,
errors: [],
me: null,
version: window.accompanyingCourseWork.version
version: window.accompanyingCourseWork.version,
},
getters: {
socialAction(state) {
@@ -43,12 +55,12 @@ const store = createStore({
return state.resultsForAction.length > 0;
},
resultsForGoal: (state) => (goal) => {
let founds = state.resultsForGoal.filter(r => r.goalId === goal.id);
let founds = state.resultsForGoal.filter((r) => r.goalId === goal.id);
return founds === undefined ? [] : founds;
},
resultsPickedForGoal: (state) => (goal) => {
let found = state.goalsPicked.find(g => g.goal.id === goal.id);
let found = state.goalsPicked.find((g) => g.goal.id === goal.id);
return found === undefined ? [] : found.results;
},
@@ -70,26 +82,38 @@ const store = createStore({
},
buildPayload(state) {
return {
type: 'accompanying_period_work',
type: "accompanying_period_work",
id: state.work.id,
version: state.version,
startDate: state.startDate === null || state.startDate === '' ? null : {
datetime: datetimeToISO(ISOToDate(state.startDate))
},
endDate: state.endDate === null || state.endDate === '' ? null : {
datetime: datetimeToISO(ISOToDate(state.endDate))
},
startDate:
state.startDate === null || state.startDate === ""
? null
: {
datetime: datetimeToISO(ISOToDate(state.startDate)),
},
endDate:
state.endDate === null || state.endDate === ""
? null
: {
datetime: datetimeToISO(ISOToDate(state.endDate)),
},
note: state.note,
privateComment: state.privateComment,
persons: state.personsPicked.map(p => ({id: p.id, type: p.type})),
handlingThierParty: state.handlingThirdParty === null ? null : {
id: state.handlingThirdParty.id,
type: state.handlingThirdParty.type
},
results: state.resultsPicked.map(r => ({id: r.id, type: r.type})),
thirdParties: state.thirdParties.map(t => ({id: t.id, type: t.type})),
referrers: state.referrers.map(t => ({id: t.id, type: t.type})),
goals: state.goalsPicked.map(g => {
persons: state.personsPicked.map((p) => ({ id: p.id, type: p.type })),
handlingThierParty:
state.handlingThirdParty === null
? null
: {
id: state.handlingThirdParty.id,
type: state.handlingThirdParty.type,
},
results: state.resultsPicked.map((r) => ({ id: r.id, type: r.type })),
thirdParties: state.thirdParties.map((t) => ({
id: t.id,
type: t.type,
})),
referrers: state.referrers.map((t) => ({ id: t.id, type: t.type })),
goals: state.goalsPicked.map((g) => {
let o = {
type: g.type,
note: g.note,
@@ -97,55 +121,72 @@ const store = createStore({
type: g.goal.type,
id: g.goal.id,
},
results: g.results.map(r => ({id: r.id, type: r.type})),
results: g.results.map((r) => ({ id: r.id, type: r.type })),
};
if (g.id !== undefined) {
o.id = g.id;
}
return o;
}),
accompanyingPeriodWorkEvaluations: state.evaluationsPicked.map(e => {
accompanyingPeriodWorkEvaluations: state.evaluationsPicked.map((e) => {
let o = {
type: e.type,
key: e.key,
evaluation: {
id: e.evaluation.id,
type: e.evaluation.type
type: e.evaluation.type,
},
startDate: e.startDate === null || e.startDate === '' ? null : { datetime: datetimeToISO(ISOToDate(e.startDate)) },
endDate: e.endDate === null || e.endDate === '' ? null : { datetime: datetimeToISO(ISOToDate(e.endDate)) },
maxDate: e.maxDate === null || e.maxDate === '' ? null : { datetime: datetimeToISO(ISOToDate(e.maxDate)) },
startDate:
e.startDate === null || e.startDate === ""
? null
: { datetime: datetimeToISO(ISOToDate(e.startDate)) },
endDate:
e.endDate === null || e.endDate === ""
? null
: { datetime: datetimeToISO(ISOToDate(e.endDate)) },
maxDate:
e.maxDate === null || e.maxDate === ""
? null
: { datetime: datetimeToISO(ISOToDate(e.maxDate)) },
warningInterval: intervalDaysToISO(e.warningInterval),
timeSpent: e.timeSpent,
comment: e.comment,
documents: e.documents
documents: e.documents,
};
if (e.id !== undefined) {
o.id = e.id;
}
return o;
})
}),
};
}
},
},
mutations: {
setWhoAmiI(state, me) {
state.me = me;
state.me = me;
},
setEvaluationsPicked(state, evaluations) {
state.evaluationsPicked = evaluations.map((e, index) => {
var k = Object.assign(e, {
key: index,
editEvaluation: false,
startDate: e.startDate !== null ? dateToISO(new Date(e.startDate.datetime)) : null,
endDate: e.endDate !== null ? dateToISO(new Date(e.endDate.datetime)) : null,
maxDate: e.maxDate !== null ? dateToISO(new Date(e.maxDate.datetime)) : null,
warningInterval: e.warningInterval !== null ? intervalISOToDays(e.warningInterval) : null,
startDate:
e.startDate !== null
? dateToISO(new Date(e.startDate.datetime))
: null,
endDate:
e.endDate !== null ? dateToISO(new Date(e.endDate.datetime)) : null,
maxDate:
e.maxDate !== null ? dateToISO(new Date(e.maxDate.datetime)) : null,
warningInterval:
e.warningInterval !== null
? intervalISOToDays(e.warningInterval)
: null,
timeSpent: e.timeSpent !== null ? e.timeSpent : null,
documents: e.documents.map((d, docIndex) => {
return Object.assign(d, {
key: docIndex
key: docIndex,
});
}),
});
@@ -177,28 +218,30 @@ const store = createStore({
state.resultsPicked.push(result);
},
removeResultPicked(state, result) {
state.resultsPicked = state.resultsPicked.filter(r => r.id !== result.id);
state.resultsPicked = state.resultsPicked.filter(
(r) => r.id !== result.id,
);
},
addGoal(state, goal) {
let g = {
type: "accompanying_period_work_goal",
goal: goal,
note: '',
results: []
}
const tmpIndex = () => {
let ar = state.goalsPicked.map(g => g.id),
s = Math.min(...ar);
return (s < 0) ? s : 0
note: "",
results: [],
};
g.id = tmpIndex() -1
const tmpIndex = () => {
let ar = state.goalsPicked.map((g) => g.id),
s = Math.min(...ar);
return s < 0 ? s : 0;
};
g.id = tmpIndex() - 1;
state.goalsPicked.push(g);
},
removeGoal(state, goal) {
state.goalsPicked = state.goalsPicked.filter(g => g.id !== goal.id);
state.goalsPicked = state.goalsPicked.filter((g) => g.id !== goal.id);
},
addResultForGoalPicked(state, { goal, result}) {
let found = state.goalsPicked.find(g => g.goal.id === goal.id);
addResultForGoalPicked(state, { goal, result }) {
let found = state.goalsPicked.find((g) => g.goal.id === goal.id);
if (found === undefined) {
return;
@@ -207,52 +250,63 @@ const store = createStore({
found.results.push(result);
},
removeResultForGoalPicked(state, { goal, result }) {
let found = state.goalsPicked.find(g => g.goal.id === goal.id);
let found = state.goalsPicked.find((g) => g.goal.id === goal.id);
if (found === undefined) {
return;
}
found.results = found.results.filter(r => r.id !== result.id);
found.results = found.results.filter((r) => r.id !== result.id);
},
addDocument(state, payload) {
let evaluation = state.evaluationsPicked.find(e => e.key === payload.key);
evaluation.documents.push(Object.assign(
payload.document, {
let evaluation = state.evaluationsPicked.find(
(e) => e.key === payload.key,
);
evaluation.documents.push(
Object.assign(payload.document, {
key: evaluation.documents.length + 1,
workflows_availables: state.work.workflows_availables_evaluation_documents,
workflows_availables:
state.work.workflows_availables_evaluation_documents,
workflows: [],
}));
}),
);
},
removeDocument(state, {key, document}) {
let evaluation = state.evaluationsPicked.find(e => e.key === key);
removeDocument(state, { key, document }) {
let evaluation = state.evaluationsPicked.find((e) => e.key === key);
if (evaluation === undefined) {
return;
}
evaluation.documents = evaluation.documents.filter(d => d.key !== document.key);
evaluation.documents = evaluation.documents.filter(
(d) => d.key !== document.key,
);
},
replaceDocument(state, payload) {
let evaluation = state.evaluationsPicked.find(e => e.key === payload.key);
let evaluation = state.evaluationsPicked.find(
(e) => e.key === payload.key,
);
if (evaluation === undefined) {
return;
}
let doc = evaluation.documents.find(d => d.key === payload.oldDocument.key);
let doc = evaluation.documents.find(
(d) => d.key === payload.oldDocument.key,
);
if (typeof doc === 'undefined') {
console.error('doc not found');
if (typeof doc === "undefined") {
console.error("doc not found");
}
doc.storedObject = payload.document.storedObject;
return;
let newDocument = Object.assign(
payload.document, {
key: evaluation.documents.length + 1,
workflows_availables: state.work.workflows_availables_evaluation_documents,
workflows: [],
}
let newDocument = Object.assign(payload.document, {
key: evaluation.documents.length + 1,
workflows_availables:
state.work.workflows_availables_evaluation_documents,
workflows: [],
});
evaluation.documents = evaluation.documents.map((d) =>
d.id === payload.oldDocument.id ? newDocument : d,
);
evaluation.documents = evaluation.documents.map(d => d.id === payload.oldDocument.id ? newDocument : d);
},
addEvaluation(state, evaluation) {
let e = {
@@ -260,8 +314,8 @@ const store = createStore({
key: state.evaluationsPicked.length + 1,
evaluation: evaluation,
startDate: dateToISO(new Date()),
endDate: null,
maxDate: null,
endDate: null,
maxDate: null,
warningInterval: null,
timeSpent: null,
comment: "",
@@ -273,46 +327,43 @@ const store = createStore({
state.evaluationsPicked.push(e);
},
removeEvaluation(state, evaluation) {
state.evaluationsPicked = state.evaluationsPicked.filter(e => e.key !== evaluation.key);
state.evaluationsPicked = state.evaluationsPicked.filter(
(e) => e.key !== evaluation.key,
);
},
setEvaluationStartDate(state, {key, date}) {
state.evaluationsPicked.find(e => e.key === key)
.startDate = date;
setEvaluationStartDate(state, { key, date }) {
state.evaluationsPicked.find((e) => e.key === key).startDate = date;
},
setEvaluationEndDate(state, {key, date}) {
console.log('commit date', date)
state.evaluationsPicked.find(e => e.key === key)
.endDate = date;
setEvaluationEndDate(state, { key, date }) {
console.log("commit date", date);
state.evaluationsPicked.find((e) => e.key === key).endDate = date;
},
setEvaluationMaxDate(state, {key, date}) {
state.evaluationsPicked.find(e => e.key === key)
.maxDate = date;
setEvaluationMaxDate(state, { key, date }) {
state.evaluationsPicked.find((e) => e.key === key).maxDate = date;
},
setEvaluationWarningInterval(state, {key, days}) {
state.evaluationsPicked.find(e => e.key === key)
.warningInterval = days;
setEvaluationWarningInterval(state, { key, days }) {
state.evaluationsPicked.find((e) => e.key === key).warningInterval = days;
},
setEvaluationTimeSpent(state, {key, time}) {
state.evaluationsPicked.find(e => e.key === key)
.timeSpent = time;
setEvaluationTimeSpent(state, { key, time }) {
state.evaluationsPicked.find((e) => e.key === key).timeSpent = time;
},
setEvaluationComment(state, {key, comment}) {
state.evaluationsPicked.find(e => e.key === key)
.comment = comment;
setEvaluationComment(state, { key, comment }) {
state.evaluationsPicked.find((e) => e.key === key).comment = comment;
},
toggleEvaluationEdit(state, {key}) {
let evaluation = state.evaluationsPicked.find(e => e.key === key);
toggleEvaluationEdit(state, { key }) {
let evaluation = state.evaluationsPicked.find((e) => e.key === key);
evaluation.editEvaluation = !evaluation.editEvaluation;
},
setTemplatesForEvaluation(state, {templates, evaluation}) {
setTemplatesForEvaluation(state, { templates, evaluation }) {
state.templatesAvailablesForEvaluation.set(evaluation.id, templates);
},
setTemplatesAvailablesForAction(state, templates) {
state.templatesAvailablesForAction = templates;
},
setPersonsPickedIds(state, ids) {
state.personsPicked = state.personsReachables
.filter(p => ids.includes(p.id))
state.personsPicked = state.personsReachables.filter((p) =>
ids.includes(p.id),
);
},
setNote(state, note) {
state.note = note;
@@ -325,8 +376,8 @@ const store = createStore({
},
addThirdParties(state, thirdParties) {
// filter to remove existing thirdparties
let ids = state.thirdParties.map(t => t.id);
let unexistings = thirdParties.filter(t => !ids.includes(t.id));
let ids = state.thirdParties.map((t) => t.id);
let unexistings = thirdParties.filter((t) => !ids.includes(t.id));
for (let i in unexistings) {
state.thirdParties.push(unexistings[i]);
@@ -334,27 +385,29 @@ const store = createStore({
},
updateThirdParty(state, thirdParty) {
for (let t of state.thirdParties) {
if (t.id === thirdParty.id){
state.thirdParties = state.thirdParties.filter(t => t.id !== thirdParty.id);
if (t.id === thirdParty.id) {
state.thirdParties = state.thirdParties.filter(
(t) => t.id !== thirdParty.id,
);
state.thirdParties.push(thirdParty);
}
}
},
removeThirdParty(state, thirdParty) {
state.thirdParties = state.thirdParties
.filter(t => t.id !== thirdParty.id);
state.thirdParties = state.thirdParties.filter(
(t) => t.id !== thirdParty.id,
);
},
addReferrers(state, referrers) {
let ids = state.referrers.map(t => t.id);
let unexistings = referrers.filter(t => !ids.includes(t.id));
let ids = state.referrers.map((t) => t.id);
let unexistings = referrers.filter((t) => !ids.includes(t.id));
for (let i in unexistings) {
state.referrers.push(unexistings[i]);
}
},
removeReferrer(state, user) {
state.referrers = state.referrers
.filter(u => u.id !== user.id);
state.referrers = state.referrers.filter((u) => u.id !== user.id);
},
setErrors(state, errors) {
state.errors = errors;
@@ -364,22 +417,24 @@ const store = createStore({
},
updateDocumentTitle(state, payload) {
if (payload.id === 0) {
state.evaluationsPicked.find(e => e.key === payload.evaluationKey)
.documents.find(d => d.key === payload.key).title = payload.title;
state.evaluationsPicked
.find((e) => e.key === payload.evaluationKey)
.documents.find((d) => d.key === payload.key).title = payload.title;
} else {
state.evaluationsPicked.find(e => e.key === payload.evaluationKey)
.documents.find(d => d.id === payload.id).title = payload.title;
state.evaluationsPicked
.find((e) => e.key === payload.evaluationKey)
.documents.find((d) => d.id === payload.id).title = payload.title;
}
},
statusDocumentChanged(state, {newStatus, key}) {
const e = state.evaluationsPicked.find(e => e.key === key);
if (typeof e === 'undefined') {
console.error('evaluation not found for given key', {key});
statusDocumentChanged(state, { newStatus, key }) {
const e = state.evaluationsPicked.find((e) => e.key === key);
if (typeof e === "undefined") {
console.error("evaluation not found for given key", { key });
}
const doc = e.documents.find(d => d.storedObject?.id === newStatus.id);
if (typeof doc === 'undefined') {
console.error('document not found', {newStatus});
const doc = e.documents.find((d) => d.storedObject?.id === newStatus.id);
if (typeof doc === "undefined") {
console.error("document not found", { newStatus });
}
doc.storedObject.status = newStatus.status;
@@ -389,160 +444,184 @@ const store = createStore({
},
actions: {
getWhoAmI({ commit }) {
let url = `/api/1.0/main/whoami.json`;
window.fetch(url)
.then(response => {
if (response.ok) {
return response.json();
}
throw { m: 'Error while retriving results for goal', s: response.status, b: response.body };
})
.then(data => {
commit('setWhoAmiI', data);
});
},
updateThirdParty({ commit }, payload) {
commit('updateThirdParty', payload);
},
getReachablesGoalsForAction({ getters, commit, dispatch }) {
let
socialActionId = getters.socialAction.id,
url = `/api/1.0/person/social-work/goal/by-social-action/${socialActionId}.json`
;
let url = `/api/1.0/main/whoami.json`;
window
.fetch(
url
).then( response => {
.fetch(url)
.then((response) => {
if (response.ok) {
return response.json();
}
throw { m: 'Error while retriving goal for social action', s: response.status, b: response.body };
}).then( data => {
for (let i in data.results) {
dispatch('getReachablesResultsForGoal', data.results[i]);
}
}).catch( errors => {
commit('addErrors', errors);
throw {
m: "Error while retriving results for goal",
s: response.status,
b: response.body,
};
})
.then((data) => {
commit("setWhoAmiI", data);
});
},
updateThirdParty({ commit }, payload) {
commit("updateThirdParty", payload);
},
getReachablesGoalsForAction({ getters, commit, dispatch }) {
let socialActionId = getters.socialAction.id,
url = `/api/1.0/person/social-work/goal/by-social-action/${socialActionId}.json`;
window
.fetch(url)
.then((response) => {
if (response.ok) {
return response.json();
}
throw {
m: "Error while retriving goal for social action",
s: response.status,
b: response.body,
};
})
.then((data) => {
for (let i in data.results) {
dispatch("getReachablesResultsForGoal", data.results[i]);
}
})
.catch((errors) => {
commit("addErrors", errors);
});
},
getReachablesResultsForGoal({ commit }, goal) {
let
url = `/api/1.0/person/social-work/result/by-goal/${goal.id}.json`
;
window.fetch(url)
.then(response => {
let url = `/api/1.0/person/social-work/result/by-goal/${goal.id}.json`;
window
.fetch(url)
.then((response) => {
if (response.ok) {
return response.json();
}
throw { m: 'Error while retriving results for goal', s: response.status, b: response.body };
throw {
m: "Error while retriving results for goal",
s: response.status,
b: response.body,
};
})
.then(data => {
commit('setResultsForGoal', { goal, results: data.results });
.then((data) => {
commit("setResultsForGoal", { goal, results: data.results });
});
},
getReachablesResultsForAction({ getters, commit }) {
let
socialActionId = getters.socialAction.id,
url = `/api/1.0/person/social-work/result/by-social-action/${socialActionId}.json`
;
window.fetch(url)
.then(response => {
let socialActionId = getters.socialAction.id,
url = `/api/1.0/person/social-work/result/by-social-action/${socialActionId}.json`;
window
.fetch(url)
.then((response) => {
if (response.ok) {
return response.json();
}
throw { m: 'Error while retriving results for social action', s: response.status, b: response.body };
throw {
m: "Error while retriving results for social action",
s: response.status,
b: response.body,
};
})
.then(data => {
commit('setResultsForAction', data.results);
.then((data) => {
commit("setResultsForAction", data.results);
});
},
getReachablesEvaluationsForAction({ getters, commit }) {
let
socialActionId = getters.socialAction.id,
url = `/api/1.0/person/social-work/evaluation/by-social-action/${socialActionId}.json`
;
window.fetch(url)
.then(response => {
let socialActionId = getters.socialAction.id,
url = `/api/1.0/person/social-work/evaluation/by-social-action/${socialActionId}.json`;
window
.fetch(url)
.then((response) => {
if (response.ok) {
return response.json();
}
throw { m: 'Error while retriving evaluations for social action', s: response.status, b: response.body };
throw {
m: "Error while retriving evaluations for social action",
s: response.status,
b: response.body,
};
})
.then(data => {
commit('setEvaluationsForAction', data.results);
.then((data) => {
commit("setEvaluationsForAction", data.results);
});
},
addEvaluation({commit, dispatch}, evaluation) {
commit('addEvaluation', evaluation);
dispatch('fetchTemplatesAvailablesForEvaluation', evaluation);
addEvaluation({ commit, dispatch }, evaluation) {
commit("addEvaluation", evaluation);
dispatch("fetchTemplatesAvailablesForEvaluation", evaluation);
},
fetchTemplatesAvailablesForEvaluation({commit, state}, evaluation) {
fetchTemplatesAvailablesForEvaluation({ commit, state }, evaluation) {
if (!state.templatesAvailablesForEvaluation.has(evaluation.id)) {
// commit an empty array to avoid parallel fetching for same evaluation id
commit('setTemplatesForEvaluation', {templates: [], evaluation});
fetchResults(`/api/1.0/person/docgen/template/by-evaluation/${evaluation.id}.json`)
.then(templates => {
commit('setTemplatesForEvaluation', {templates, evaluation});
});
commit("setTemplatesForEvaluation", { templates: [], evaluation });
fetchResults(
`/api/1.0/person/docgen/template/by-evaluation/${evaluation.id}.json`,
).then((templates) => {
commit("setTemplatesForEvaluation", { templates, evaluation });
});
}
},
addDocument({commit}, payload) {
commit('addDocument', payload);
addDocument({ commit }, payload) {
commit("addDocument", payload);
},
removeDocument({commit}, payload) {
commit('removeDocument', payload);
removeDocument({ commit }, payload) {
commit("removeDocument", payload);
},
replaceDocument({commit}, payload) {
commit('replaceDocument', payload);
replaceDocument({ commit }, payload) {
commit("replaceDocument", payload);
},
submit({ getters, state, commit }, callback) {
let
payload = getters.buildPayload,
params = new URLSearchParams({'entity_version': state.version}),
url = `/api/1.0/person/accompanying-course/work/${state.work.id}.json?${params}`
;
commit('setIsPosting', true);
let payload = getters.buildPayload,
params = new URLSearchParams({ entity_version: state.version }),
url = `/api/1.0/person/accompanying-course/work/${state.work.id}.json?${params}`;
commit("setIsPosting", true);
// console.log('the social action', payload);
return makeFetch('PUT', url, payload)
.then(data => {
if (typeof(callback) !== 'undefined') {
return makeFetch("PUT", url, payload)
.then((data) => {
if (typeof callback !== "undefined") {
return callback(data);
} else {
// console.log('payload', payload.privateComment)
// console.info('nothing to do here, bye bye');
window.location.assign(`/fr/person/accompanying-period/${state.work.accompanyingPeriod.id}/work`);
window.location.assign(
`/fr/person/accompanying-period/${state.work.accompanyingPeriod.id}/work`,
);
}
}).catch(error => {
console.log('error', error)
commit('setIsPosting', false);
})
.catch((error) => {
console.log("error", error);
commit("setIsPosting", false);
throw error;
});
},
updateDocumentTitle({commit}, payload) {
commit('updateDocumentTitle', payload)
}
}
updateDocumentTitle({ commit }, payload) {
commit("updateDocumentTitle", payload);
},
},
});
store.commit('setEvaluationsPicked', window.accompanyingCourseWork.accompanyingPeriodWorkEvaluations);
store.dispatch('getReachablesResultsForAction');
store.dispatch('getReachablesGoalsForAction');
store.dispatch('getReachablesEvaluationsForAction');
store.dispatch('getWhoAmI');
store.commit(
"setEvaluationsPicked",
window.accompanyingCourseWork.accompanyingPeriodWorkEvaluations,
);
store.dispatch("getReachablesResultsForAction");
store.dispatch("getReachablesGoalsForAction");
store.dispatch("getReachablesEvaluationsForAction");
store.dispatch("getWhoAmI");
store.state.evaluationsPicked.forEach(evaluation => {
store.dispatch('fetchTemplatesAvailablesForEvaluation', evaluation.evaluation)
store.state.evaluationsPicked.forEach((evaluation) => {
store.dispatch(
"fetchTemplatesAvailablesForEvaluation",
evaluation.evaluation,
);
});
fetchTemplates('Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork')
.then(templates => {
store.commit('setTemplatesAvailablesForAction', templates);
}
)
fetchTemplates(
"Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork",
).then((templates) => {
store.commit("setTemplatesAvailablesForAction", templates);
});
export { store };

View File

@@ -1,11 +1,8 @@
<template>
<fieldset
class="mb-3"
id="actionType"
>
<fieldset class="mb-3" id="actionType">
<div class="row">
<legend class="col-sm-4 col-form-label">
{{ $t('action.label') }}
{{ $t("action.label") }}
</legend>
<div class="col-sm-8">
<VueMultiselect
@@ -24,13 +21,10 @@
</div>
</fieldset>
<fieldset
class="mb-3"
id="goal"
>
<fieldset class="mb-3" id="goal">
<div class="row">
<legend class="col-sm-4 col-form-label">
{{ $t('goal.label') }}
{{ $t("goal.label") }}
</legend>
<div class="col-sm-8">
<VueMultiselect
@@ -50,13 +44,10 @@
</div>
</fieldset>
<fieldset
class="mb-3"
id="result"
>
<fieldset class="mb-3" id="result">
<div class="row">
<legend class="col-sm-4 col-form-label">
{{ $t('result.label') }}
{{ $t("result.label") }}
</legend>
<div class="col-sm-8">
<VueMultiselect
@@ -78,353 +69,380 @@
</template>
<script>
import VueMultiselect from 'vue-multiselect';
import { getSocialActions, getGoalByAction, getResultByAction, getResultByGoal } from './api';
import VueMultiselect from "vue-multiselect";
import {
getSocialActions,
getGoalByAction,
getResultByAction,
getResultByGoal,
} from "./api";
export default {
name: "App",
components: {
VueMultiselect
},
i18n: {
messages: {
fr: {
action: {
label: 'Types d\'actions',
placeholder: 'Choisissez une ou plusieurs actions',
},
goal: {
label: 'Objectifs',
placeholder: 'Choisissez un ou plusieurs objectifs',
},
result: {
label: 'Résultats',
placeholder: 'Choisissez un ou plusieurs résultats',
}
}
}
},
data() {
return {
actions: {
options: [], // array with multiselect options
value: [], // array with selected values
hiddenField: document.getElementById(
'export_filters_social_work_type_filter_form_actionType'),
},
goals: {
options: [],
value: [],
hiddenField: document.getElementById(
'export_filters_social_work_type_filter_form_goal'),
},
results: {
options: [],
value: [],
hiddenField: document.getElementById(
'export_filters_social_work_type_filter_form_result'),
},
}
},
computed: {
action: {
get() {
return this.actions.value;
},
set(value) {
this.actions.value = value;
this.rebuildHiddenFieldValues('actions');
}
name: "App",
components: {
VueMultiselect,
},
i18n: {
messages: {
fr: {
action: {
label: "Types d'actions",
placeholder: "Choisissez une ou plusieurs actions",
},
goal: {
label: "Objectifs",
placeholder: "Choisissez un ou plusieurs objectifs",
},
result: {
label: "Résultats",
placeholder: "Choisissez un ou plusieurs résultats",
},
},
goal: {
get() {
return this.goals.value;
},
set(value) {
this.goals.value = value;
this.rebuildHiddenFieldValues('goals');
}
},
},
data() {
return {
actions: {
options: [], // array with multiselect options
value: [], // array with selected values
hiddenField: document.getElementById(
"export_filters_social_work_type_filter_form_actionType",
),
},
result: {
get() {
return this.results.value;
},
set(value) {
this.results.value = value;
this.rebuildHiddenFieldValues('results');
}
goals: {
options: [],
value: [],
hiddenField: document.getElementById(
"export_filters_social_work_type_filter_form_goal",
),
},
},
async mounted() {
await this.getSocialActionsList();
results: {
options: [],
value: [],
hiddenField: document.getElementById(
"export_filters_social_work_type_filter_form_result",
),
},
};
},
computed: {
action: {
get() {
return this.actions.value;
},
set(value) {
this.actions.value = value;
this.rebuildHiddenFieldValues("actions");
},
},
goal: {
get() {
return this.goals.value;
},
set(value) {
this.goals.value = value;
this.rebuildHiddenFieldValues("goals");
},
},
result: {
get() {
return this.results.value;
},
set(value) {
this.results.value = value;
this.rebuildHiddenFieldValues("results");
},
},
},
async mounted() {
await this.getSocialActionsList();
if ('' !== this.actions.hiddenField.value) {
const actionIds = this.actions.hiddenField.value.split(',');
for (const aid of actionIds) {
let action = this.actions.options.find(a => Number.parseInt(aid) === a.id);
if (undefined !== action) {
this.action.push(action);
await this.selectAction(action);
}
if ("" !== this.actions.hiddenField.value) {
const actionIds = this.actions.hiddenField.value.split(",");
for (const aid of actionIds) {
let action = this.actions.options.find(
(a) => Number.parseInt(aid) === a.id,
);
if (undefined !== action) {
this.action.push(action);
await this.selectAction(action);
}
}
}
if ('' !== this.goals.hiddenField.value) {
const goalsIds = this.goals.hiddenField.value.split(',').map(s => Number.parseInt(s));
for (const gid of goalsIds) {
let goal = this.goals.options.find(g => gid === g.id);
if (undefined !== goal) {
this.goal.push(goal);
await this.selectGoal(goal);
}
if ("" !== this.goals.hiddenField.value) {
const goalsIds = this.goals.hiddenField.value
.split(",")
.map((s) => Number.parseInt(s));
for (const gid of goalsIds) {
let goal = this.goals.options.find((g) => gid === g.id);
if (undefined !== goal) {
this.goal.push(goal);
await this.selectGoal(goal);
}
}
}
if ('' !== this.results.hiddenField.value) {
const resultsIds = this.results.hiddenField.value.split(',').map(s => Number.parseInt(s));
for (const rid of resultsIds) {
let result = this.results.options.find(r => rid === r.id);
if (undefined !== result) {
this.result.push(result);
}
if ("" !== this.results.hiddenField.value) {
const resultsIds = this.results.hiddenField.value
.split(",")
.map((s) => Number.parseInt(s));
for (const rid of resultsIds) {
let result = this.results.options.find((r) => rid === r.id);
if (undefined !== result) {
this.result.push(result);
}
}
},
methods: {
async getSocialActionsList() {
let actions = await getSocialActions();
this.actions.options = actions.toSorted(function (a, b) {
if (a.issue.ordering === b.issue.ordering) {
if (a.ordering === b.ordering) {
return 0;
}
if (a.ordering < b.ordering) {
return -1;
}
return 1;
}
}
},
methods: {
async getSocialActionsList() {
let actions = await getSocialActions();
this.actions.options = actions.toSorted(function (a, b) {
if (a.issue.ordering === b.issue.ordering) {
if (a.ordering === b.ordering) {
return 0;
}
if (a.ordering < b.ordering) {
return -1;
}
return 1;
}
if (a.issue.ordering < b.issue.ordering) {
return -1;
}
if (a.issue.ordering < b.issue.ordering) {
return -1;
}
return 1;
})
return 1;
});
return Promise.resolve();
},
return Promise.resolve();
},
formatSocialAction({text, issue}) {
return text + ' (' + issue.text + ')';
},
formatSocialAction({ text, issue }) {
return text + " (" + issue.text + ")";
},
/**
* Select/unselect in Action Multiselect
* @param value
*/
async selectAction(value) {
//console.log('----'); console.log('select action', value.id);
let children = this.getChildrensFromParent(value);
this.addSelectedElement('actions', children);
/**
* Select/unselect in Action Multiselect
* @param value
*/
async selectAction(value) {
//console.log('----'); console.log('select action', value.id);
let children = this.getChildrensFromParent(value);
this.addSelectedElement("actions", children);
let parentAndChildren = [...[value], ...children];
const promises = [];
parentAndChildren.forEach(elem => {
promises.push(getGoalByAction(elem.id).then(goals => {
this.addElementInData('goals', goals);
return Promise.resolve();
}));
promises.push(getResultByAction(elem.id).then(results => {
this.addElementInData('results', results);
return Promise.resolve();
}));
});
let parentAndChildren = [...[value], ...children];
const promises = [];
parentAndChildren.forEach((elem) => {
promises.push(
getGoalByAction(elem.id).then((goals) => {
this.addElementInData("goals", goals);
return Promise.resolve();
}),
);
promises.push(
getResultByAction(elem.id).then((results) => {
this.addElementInData("results", results);
return Promise.resolve();
}),
);
});
await Promise.all(promises);
return Promise.resolve();
},
await Promise.all(promises);
return Promise.resolve();
},
unselectAction(value) {
getGoalByAction(value.id).then(goals => {
[this.results.options, this.results.value ] = this.removeElementInData('goals', goals);
});
getResultByAction(value.id).then(results => {
[this.results.options, this.results.value ] = this.removeElementInData('results', results);
});
},
unselectAction(value) {
getGoalByAction(value.id).then((goals) => {
[this.results.options, this.results.value] = this.removeElementInData(
"goals",
goals,
);
});
getResultByAction(value.id).then((results) => {
[this.results.options, this.results.value] = this.removeElementInData(
"results",
results,
);
});
},
/**
* Select/unselect in Goal Multiselect
* @param value
*/
async selectGoal(value) {
return getResultByGoal(value.id).then(results => {
this.addElementInData('results', results);
})
},
/**
* Select/unselect in Goal Multiselect
* @param value
*/
async selectGoal(value) {
return getResultByGoal(value.id).then((results) => {
this.addElementInData("results", results);
});
},
unselectGoal(value) {
getResultByGoal(value.id)
.then(
results => [ this.results.options, this.results.value ] = this.removeElementInData('results', results)
).catch;
},
unselectGoal(value) {
getResultByGoal(value.id).then(
(results) =>
([this.results.options, this.results.value] =
this.removeElementInData("results", results)),
).catch;
},
// selectResult(value) {
//console.log('----'); console.log('select result', value.id);
// },
// selectResult(value) {
//console.log('----'); console.log('select result', value.id);
// },
// unselectResult(value) {
//console.log('----'); console.log('unselect result', value.id);
// },
// unselectResult(value) {
//console.log('----'); console.log('unselect result', value.id);
// },
/**
* Choose parent action will involve retaining the "children" actions.
* @param value
* @return array
*/
getChildrensFromParent(value) {
if (null === value.parent) {
let excludeParent = this.actions.options.filter(o => o.parent !== null);
let children = excludeParent.filter(o => o.parent.id === value.id);
//console.log("get childrens", children.map(e => e.id));
return children;
}
return [];
},
/**
* Choose parent action will involve retaining the "children" actions.
* @param value
* @return array
*/
getChildrensFromParent(value) {
if (null === value.parent) {
let excludeParent = this.actions.options.filter(
(o) => o.parent !== null,
);
let children = excludeParent.filter((o) => o.parent.id === value.id);
//console.log("get childrens", children.map(e => e.id));
return children;
}
return [];
},
/**
* Add response elements in data target
* @param target string -> 'actions', 'goals' or 'results'
* @param response array of objects with fetch results
*/
addElementInData(target, response) {
let data = this[target];
let dump = [];
response.forEach(elem => {
let found = data.options.some(e => e.id === elem.id);
if (!found) {
data.options.push(elem);
dump.push(elem.id);
}
})
if (dump.length > 0) {
//console.log('push ' + dump.length + ' elems in', target, dump);
}
data.options.sort();
},
/**
* Add response elements in data target
* @param target string -> 'actions', 'goals' or 'results'
* @param response array of objects with fetch results
*/
addElementInData(target, response) {
let data = this[target];
let dump = [];
response.forEach((elem) => {
let found = data.options.some((e) => e.id === elem.id);
if (!found) {
data.options.push(elem);
dump.push(elem.id);
}
});
if (dump.length > 0) {
//console.log('push ' + dump.length + ' elems in', target, dump);
}
data.options.sort();
},
/**
* Remove response elements from data target
* @param target string -> 'actions', 'goals' or 'results'
* @param response array of objects with fetch results
* @returns data.<target>.options
*/
removeElementInData(target, response) {
let data = this[target];
let dump = [];
response.forEach(elem => {
let found = data.options.some(e => e.id === elem.id);
if (found) {
data.options = data.options.filter(e => e.id !== elem.id);
dump.push(elem.id);
/**
* Remove response elements from data target
* @param target string -> 'actions', 'goals' or 'results'
* @param response array of objects with fetch results
* @returns data.<target>.options
*/
removeElementInData(target, response) {
let data = this[target];
let dump = [];
response.forEach((elem) => {
let found = data.options.some((e) => e.id === elem.id);
if (found) {
data.options = data.options.filter((e) => e.id !== elem.id);
dump.push(elem.id);
this.removeSelectedElement(target, elem);
}
})
if (dump.length > 0) {
//console.log('remove ' + dump.length + ' elems from ' + target + ' options', dump);
}
return [ data.options, data.value ];
},
this.removeSelectedElement(target, elem);
}
});
if (dump.length > 0) {
//console.log('remove ' + dump.length + ' elems from ' + target + ' options', dump);
}
return [data.options, data.value];
},
/**
*
* @param target
* @param elements
*/
addSelectedElement(target, elements) {
let data = this[target];
let dump = [];
elements.forEach(elem => {
let selected = data.value.some(e => e.id === elem.id);
if (!selected) {
/**
*
* @param target
* @param elements
*/
addSelectedElement(target, elements) {
let data = this[target];
let dump = [];
elements.forEach((elem) => {
let selected = data.value.some((e) => e.id === elem.id);
if (!selected) {
data.value.push(elem);
dump.push(elem.id);
data.value.push(elem);
dump.push(elem.id);
// add in hiddenField
this.rebuildHiddenFieldValues(target);
}
});
if (dump.length > 0) {
//console.log('add ' + dump.length + ' selected elems in', target, dump);
}
},
// add in hiddenField
this.rebuildHiddenFieldValues(target);
}
});
if (dump.length > 0) {
//console.log('add ' + dump.length + ' selected elems in', target, dump);
}
},
/**
* Remove element from selected and from hiddenField
* @param target
* @param elem
*/
removeSelectedElement(target, elem) {
let data = this[target];
let selected = data.value.some((e) => e.id === elem.id);
if (selected) {
// remove from selected
data.value = data.value.filter((e) => e.id !== elem.id);
//console.log('remove ' + elem.id + ' from selected ' + target);
/**
* Remove element from selected and from hiddenField
* @param target
* @param elem
*/
removeSelectedElement(target, elem) {
let data = this[target];
let selected = data.value.some(e => e.id === elem.id);
if (selected) {
// remove from hiddenField
this.rebuildHiddenFieldValues(target);
// remove from selected
data.value = data.value.filter(e => e.id !== elem.id);
//console.log('remove ' + elem.id + ' from selected ' + target);
// in any cases, remove should be recursive
this.unselectToNextField(target, elem);
}
},
// remove from hiddenField
this.rebuildHiddenFieldValues(target);
/**
* When unselect Action, it could remove elements in goals multiselect.
* In that case, we have to unselect Goal to remove elements in results too.
* @param target
* @param elem
*/
unselectToNextField(target, elem) {
if (target === "goals") {
//console.log('!!!! target is goal: unselect goal', elem.id);
this.unselectGoal(elem);
//console.log('!!!! done');
}
},
// in any cases, remove should be recursive
this.unselectToNextField(target, elem);
}
},
/**
* Rebuild values serie (string) in target HiddenField
* @param target
*/
rebuildHiddenFieldValues(target) {
let data = this[target];
//console.log('rebuild hiddenFields ' + target + ' values :');
data.hiddenField.value = ""; // reset
data.value.forEach((elem) => {
data.hiddenField.value = this.addIdToValue(
data.hiddenField.value,
elem.id,
);
});
//console.log(data.hiddenField);
},
/**
* When unselect Action, it could remove elements in goals multiselect.
* In that case, we have to unselect Goal to remove elements in results too.
* @param target
* @param elem
*/
unselectToNextField(target, elem) {
if (target === 'goals') {
//console.log('!!!! target is goal: unselect goal', elem.id);
this.unselectGoal(elem);
//console.log('!!!! done');
}
},
addIdToValue(string, id) {
let array = string ? string.split(",") : [];
array.push(id.toString());
let str = array.join();
return str;
},
/**
* Rebuild values serie (string) in target HiddenField
* @param target
*/
rebuildHiddenFieldValues(target) {
let data = this[target];
//console.log('rebuild hiddenFields ' + target + ' values :');
data.hiddenField.value = ''; // reset
data.value.forEach(elem => {
data.hiddenField.value = this.addIdToValue(data.hiddenField.value, elem.id);
})
//console.log(data.hiddenField);
},
addIdToValue(string, id) {
let array = string ? string.split(',') : [];
array.push(id.toString());
let str = array.join();
return str;
},
transTitle ({ title }) {
return title.fr //TODO multilang
},
},
}
transTitle({ title }) {
return title.fr; //TODO multilang
},
},
};
</script>
<style scoped>
</style>
<style scoped></style>

View File

@@ -1,29 +1,28 @@
import { fetchResults } from 'ChillMainAssets/lib/api/apiMethods';
import { fetchResults } from "ChillMainAssets/lib/api/apiMethods";
const getSocialActions = () => fetchResults(
'/api/1.0/person/social/social-action.json', {
item_per_page: 200
}
);
const getSocialActions = () =>
fetchResults("/api/1.0/person/social/social-action.json", {
item_per_page: 200,
});
const getGoalByAction = (id) => {
let url = `/api/1.0/person/social-work/goal/by-social-action/${id}.json`;
return fetchResults(url);
let url = `/api/1.0/person/social-work/goal/by-social-action/${id}.json`;
return fetchResults(url);
};
const getResultByAction = (id) => {
let url = `/api/1.0/person/social-work/result/by-social-action/${id}.json`;
return fetchResults(url);
let url = `/api/1.0/person/social-work/result/by-social-action/${id}.json`;
return fetchResults(url);
};
const getResultByGoal = (id) => {
let url = `/api/1.0/person/social-work/result/by-goal/${id}.json`;
return fetchResults(url);
let url = `/api/1.0/person/social-work/result/by-goal/${id}.json`;
return fetchResults(url);
};
export {
getSocialActions,
getGoalByAction,
getResultByAction,
getResultByGoal,
}
getSocialActions,
getGoalByAction,
getResultByAction,
getResultByGoal,
};

View File

@@ -1,17 +1,22 @@
import { createApp } from "vue";
import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n';
import App from './App.vue';
import { _createI18n } from "ChillMainAssets/vuejs/_js/i18n";
import App from "./App.vue";
if (null !== document.getElementById('export_filters_social_work_type_filter_enabled')) {
const i18n = _createI18n({});
const form = document.getElementById('export_filters_social_work_type_filter_form');
const after = form.appendChild(document.createElement('div'));
if (
null !==
document.getElementById("export_filters_social_work_type_filter_enabled")
) {
const i18n = _createI18n({});
const form = document.getElementById(
"export_filters_social_work_type_filter_form",
);
const after = form.appendChild(document.createElement("div"));
/* exported app */
const app = createApp({
template: `<app></app>`,
})
.use(i18n)
.component('app', App)
.mount(after);
/* exported app */
const app = createApp({
template: `<app></app>`,
})
.use(i18n)
.component("app", App)
.mount(after);
}

View File

@@ -6,40 +6,25 @@
class="breadcrumb-item"
:class="{ active: step === s }"
>
{{ $t('household_members_editor.app.steps.'+s) }}
{{ $t("household_members_editor.app.steps." + s) }}
</li>
</ol>
<concerned v-if="step === 'concerned'" />
<household
v-if="step === 'household'"
@ready-to-go="goToNext"
/>
<household v-if="step === 'household'" @ready-to-go="goToNext" />
<household-address v-if="step === 'household_address'" />
<positioning v-if="step === 'positioning'" />
<dates v-if="step === 'confirm'" />
<confirmation v-if="step === 'confirm'" />
<ul class="record_actions sticky-form-buttons">
<li
class="cancel"
v-if="step !== 'concerned'"
>
<button
class="btn btn-cancel"
@click="goToPrevious"
>
{{ $t('household_members_editor.app.previous') }}
<li class="cancel" v-if="step !== 'concerned'">
<button class="btn btn-cancel" @click="goToPrevious">
{{ $t("household_members_editor.app.previous") }}
</button>
</li>
<li
class="cancel"
v-else-if="hasReturnPath"
>
<button
class="btn btn-cancel"
@click="goToPrevious"
>
{{ $t('household_members_editor.app.cancel') }}
<li class="cancel" v-else-if="hasReturnPath">
<button class="btn btn-cancel" @click="goToPrevious">
{{ $t("household_members_editor.app.cancel") }}
</button>
</li>
<li v-if="step !== 'confirm'">
@@ -48,7 +33,9 @@
@click="goToNext"
:disabled="!isNextAllowed"
>
{{ $t('household_members_editor.app.next') }}&nbsp;<i class="fa fa-arrow-right" />
{{ $t("household_members_editor.app.next") }}&nbsp;<i
class="fa fa-arrow-right"
/>
</button>
</li>
<li v-else>
@@ -57,24 +44,23 @@
@click="confirm"
:disabled="hasWarnings || !lastStepIsSaveAllowed"
>
{{ $t('household_members_editor.app.save') }}
{{ $t("household_members_editor.app.save") }}
</button>
</li>
</ul>
</template>
<script>
import {mapState} from 'vuex';
import Concerned from './components/Concerned.vue';
import Household from './components/Household.vue';
import HouseholdAddress from './components/HouseholdAddress';
import Dates from './components/Dates.vue';
import Confirmation from './components/Confirmation.vue';
import { mapState } from "vuex";
import Concerned from "./components/Concerned.vue";
import Household from "./components/Household.vue";
import HouseholdAddress from "./components/HouseholdAddress";
import Dates from "./components/Dates.vue";
import Confirmation from "./components/Confirmation.vue";
import Positioning from "./components/Positioning";
export default {
name: 'App',
name: "App",
components: {
Positioning,
Concerned,
@@ -85,88 +71,96 @@ export default {
},
data() {
return {
step: 'concerned',
step: "concerned",
};
},
computed: {
...mapState({
hasWarnings: (state) => state.warnings.length > 0 || state.errors.length > 0,
hasWarnings: (state) =>
state.warnings.length > 0 || state.errors.length > 0,
}),
steps() {
let s = ['concerned', 'household'];
let s = ["concerned", "household"];
if (this.$store.getters.isHouseholdNew) {
s.push('household_address');
s.push("household_address");
}
if (!this.$store.getters.isModeLeave) {
s.push('positioning');
s.push("positioning");
}
s.push('confirm');
s.push("confirm");
return s;
},
hasReturnPath() {
let params = new URLSearchParams(window.location.search);
return params.has('returnPath');
return params.has("returnPath");
},
// return true if the next step is allowed
isNextAllowed() {
switch (this.$data.step) {
case 'concerned':
case "concerned":
return this.$store.state.concerned.length > 0;
case 'household':
case "household":
return this.$store.state.mode !== null;
case 'household_address':
return this.$store.getters.hasHouseholdAddress || this.$store.getters.isHouseholdForceNoAddress;
case 'positioning':
return this.$store.getters.hasHouseholdOrLeave
&& this.$store.getters.hasPersonsWellPositionnated;
case "household_address":
return (
this.$store.getters.hasHouseholdAddress ||
this.$store.getters.isHouseholdForceNoAddress
);
case "positioning":
return (
this.$store.getters.hasHouseholdOrLeave &&
this.$store.getters.hasPersonsWellPositionnated
);
}
return false;
},
lastStepIsSaveAllowed() {
let r = !this.$store.getters.isHouseholdNew ||
(this.$store.state.numberOfChildren !== null && this.$store.state.householdCompositionType !== null);
console.log('is saved allowed ?', r);
let r =
!this.$store.getters.isHouseholdNew ||
(this.$store.state.numberOfChildren !== null &&
this.$store.state.householdCompositionType !== null);
console.log("is saved allowed ?", r);
return r;
},
},
methods: {
goToNext() {
console.log('go to next');
console.log("go to next");
switch (this.$data.step) {
case 'concerned':
this.$data.step = 'household';
case "concerned":
this.$data.step = "household";
break;
case 'household':
case "household":
if (this.$store.getters.isHouseholdNew) {
this.$data.step = 'household_address';
this.$data.step = "household_address";
break;
} else if (this.$store.getters.isModeLeave) {
this.$data.step = 'confirm';
this.$data.step = "confirm";
break;
} else {
this.$data.step = 'positioning';
this.$data.step = "positioning";
break;
}
case 'household_address':
this.$data.step = 'positioning';
case "household_address":
this.$data.step = "positioning";
break;
case 'positioning':
this.$data.step = 'confirm';
case "positioning":
this.$data.step = "confirm";
break;
}
},
goToPrevious() {
if (this.$data.step === 'concerned') {
if (this.$data.step === "concerned") {
let params = new URLSearchParams(window.location.search);
if (params.has('returnPath')) {
window.location.replace(params.get('returnPath'));
if (params.has("returnPath")) {
window.location.replace(params.get("returnPath"));
} else {
return;
}
@@ -181,9 +175,8 @@ export default {
this.$data.step = s[index - 1];
},
confirm() {
this.$store.dispatch('confirm');
this.$store.dispatch("confirm");
},
}
}
},
};
</script>

View File

@@ -1,55 +1,60 @@
/*
*/
*/
const householdMove = (payload) => {
const url = `/api/1.0/person/household/members/move.json`;
console.log(payload);
console.log(JSON.stringify(payload));
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
})
.then(response => {
if (response.ok) {
return response.json();
}
if (response.status === 422) {
return response.json();
}
throw Error('Error with testing move');
});
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
}).then((response) => {
if (response.ok) {
return response.json();
}
if (response.status === 422) {
return response.json();
}
throw Error("Error with testing move");
});
};
const fetchHouseholdSuggestionByAccompanyingPeriod = (personId) => {
const url = `/api/1.0/person/household/suggest/by-person/${personId}/through-accompanying-period-participation.json`;
return window.fetch(url)
.then(response => {
return window
.fetch(url)
.then((response) => {
if (response.ok) {
return response.json();
}
throw Error ({m: 'Error while fetching household suggestion', status: response.status});
}).then(data => Promise.resolve(data.results))
.catch(e => console.error(e));
;
throw Error({
m: "Error while fetching household suggestion",
status: response.status,
});
})
.then((data) => Promise.resolve(data.results))
.catch((e) => console.error(e));
};
const fetchAddressSuggestionByPerson = (personId) => {
const url = `/api/1.0/person/address/suggest/by-person/${personId}.json`;
return window.fetch(url)
.then(response => {
if (response.ok) {
return response.json();
}
return window.fetch(url).then((response) => {
if (response.ok) {
return response.json();
}
throw Error({m: 'Error while fetch address suggestion', status: response.status});
throw Error({
m: "Error while fetch address suggestion",
status: response.status,
});
}
});
};
export {
export {
householdMove,
fetchHouseholdSuggestionByAccompanyingPeriod,
fetchAddressSuggestionByPerson,

View File

@@ -1,22 +1,22 @@
<template>
<h2 class="mt-4">
{{ $t('household_members_editor.concerned.title') }}
{{ $t("household_members_editor.concerned.title") }}
</h2>
<div v-if="noPerson">
<div class="alert alert-info">
{{ $t('household_members_editor.concerned.add_at_least_onePerson') }}
{{ $t("household_members_editor.concerned.add_at_least_onePerson") }}
</div>
</div>
<div v-else>
<p>{{ $t('household_members_editor.concerned.persons_will_be_moved') }}&nbsp;:</p>
<p>
{{
$t("household_members_editor.concerned.persons_will_be_moved")
}}&nbsp;:
</p>
<ul class="list-suggest remove-items inline">
<li
v-for="c in concerned"
:key="c.person.id"
@click="removeConcerned(c)"
>
<li v-for="c in concerned" :key="c.person.id" @click="removeConcerned(c)">
<span><person-text :person="c.person" /></span>
</li>
</ul>
@@ -25,18 +25,22 @@
class="alert alert-info"
v-if="concernedPersonsWithHouseholds.length > 0"
>
<p>{{ $t('household_members_editor.concerned.persons_with_household') }}</p>
<ul
v-for="c in concernedPersonsWithHouseholds"
:key="c.person.id"
>
<p>
{{ $t("household_members_editor.concerned.persons_with_household") }}
</p>
<ul v-for="c in concernedPersonsWithHouseholds" :key="c.person.id">
<li>
{{ c.person.text }}
{{ $t('household_members_editor.concerned.already_belongs_to_household') }}
{{
$t(
"household_members_editor.concerned.already_belongs_to_household",
)
}}
<a
target="_blank"
:href="this.makeHouseholdLink(c.person.current_household_id)"
>{{ c.person.current_household_id }}</a>.
>{{ c.person.current_household_id }}</a
>.
</li>
</ul>
</div>
@@ -59,79 +63,76 @@
</template>
<style lang="scss">
.move_to {
.move_hint {
text-align: center;
display: inline-block;
padding: 0.400rem 0.5rem;
padding: 0.4rem 0.5rem;
}
}
</style>
<script>
import { mapState, mapGetters } from 'vuex';
import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue';
import PersonText from 'ChillPersonAssets/vuejs/_components/Entity/PersonText.vue';
import { mapState, mapGetters } from "vuex";
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
export default {
name: 'Concerned',
name: "Concerned",
components: {
AddPersons,
PersonText,
},
computed: {
...mapState([
'concerned', 'household'
]),
...mapGetters([
'persons',
]),
noPerson () {
...mapState(["concerned", "household"]),
...mapGetters(["persons"]),
noPerson() {
return this.$store.getters.persons.length === 0;
},
concernedPersonsWithHouseholds () {
concernedPersonsWithHouseholds() {
if (this.$store.state.household) {
return this.$store.state.concerned.filter(c =>
c.person.current_household_id !== null && c.person.current_household_id !== this.$store.state.household.id
)
return this.$store.state.concerned.filter(
(c) =>
c.person.current_household_id !== null &&
c.person.current_household_id !== this.$store.state.household.id,
);
} else {
return [];
}
}
},
},
data() {
return {
addPersons: {
key: 'household_members_editor_concerned',
key: "household_members_editor_concerned",
options: {
type: ['person'],
priority: null,
uniq: false,
}
}
}
type: ["person"],
priority: null,
uniq: false,
},
},
};
},
methods: {
addNewPersons({ selected, modal }) {
selected.forEach(function(item) {
this.$store.dispatch('addConcerned', item.result);
selected.forEach(function (item) {
this.$store.dispatch("addConcerned", item.result);
}, this);
this.$refs.addPersons.resetSearch(); // to cast child method
modal.showModal = false;
},
removeConcerned(concerned) {
console.log('removedconcerned', concerned);
console.log("removedconcerned", concerned);
if (!concerned.allowRemove) {
return;
}
this.$store.dispatch('removePerson', concerned.person);
this.$store.dispatch("removePerson", concerned.person);
},
makeHouseholdLink(id) {
return `/fr/person/household/${id}/summary`
}
}
}
return `/fr/person/household/${id}/summary`;
},
},
};
</script>

View File

@@ -1,48 +1,36 @@
<template>
<div
v-if="hasWarning"
class="alert alert-warning"
>
{{ $t('household_members_editor.confirmation.there_are_warnings') }}
<div v-if="hasWarning" class="alert alert-warning">
{{ $t("household_members_editor.confirmation.there_are_warnings") }}
</div>
<p v-if="hasWarning">
{{ $t('household_members_editor.confirmation.check_those_items') }}
{{ $t("household_members_editor.confirmation.check_those_items") }}
</p>
<ul>
<li
v-for="(msg, i) in warnings"
class="warning"
:key="i"
>
<li v-for="(msg, i) in warnings" class="warning" :key="i">
{{ $t(msg.m, msg.a) }}
</li>
<li
v-for="(msg, i) in errors"
class="error"
:key="i"
>
<li v-for="(msg, i) in errors" class="error" :key="i">
{{ msg }}
</li>
</ul>
</template>
<style scoped lang="scss">
</style>
<style scoped lang="scss"></style>
<script>
import { mapState } from 'vuex';
import { mapState } from "vuex";
export default {
name: 'Confirmation',
name: "Confirmation",
computed: {
...mapState({
hasWarnings: (state) => state.warnings.length > 0 || state.errors.length > 0,
hasWarnings: (state) =>
state.warnings.length > 0 || state.errors.length > 0,
warnings: (state) => state.warnings,
errors: (state) => state.errors,
}),
},
}
};
</script>

View File

@@ -1,16 +1,10 @@
<template>
<div
class="flex-table mb-5"
v-if="hasHousehold"
>
<div class="flex-table mb-5" v-if="hasHousehold">
<div class="item-bloc">
<household-render-box :household="fakeHouseholdWithConcerned" />
</div>
</div>
<div
class="flex-table"
v-if="isModeLeave"
>
<div class="flex-table" v-if="isModeLeave">
<div class="item-bloc">
<section>
<div class="item-row">
@@ -20,12 +14,18 @@
<i class="fa fa-home fa-stack-1x" />
<i class="fa fa-ban fa-stack-2x text-danger" />
</span>
{{ $t('household_members_editor.household.leave_without_household') }}
{{
$t("household_members_editor.household.leave_without_household")
}}
</div>
</div>
</div>
<div class="item-row">
{{ $t('household_members_editor.household.will_leave_any_household_explanation') }}
{{
$t(
"household_members_editor.household.will_leave_any_household_explanation",
)
}}
</div>
</section>
</div>
@@ -33,8 +33,8 @@
</template>
<script>
import { mapGetters } from 'vuex';
import HouseholdRenderBox from 'ChillPersonAssets/vuejs/_components/Entity/HouseholdRenderBox.vue';
import { mapGetters } from "vuex";
import HouseholdRenderBox from "ChillPersonAssets/vuejs/_components/Entity/HouseholdRenderBox.vue";
export default {
name: "CurrentHousehold",
@@ -43,14 +43,12 @@ export default {
},
computed: {
...mapGetters([
'hasHousehold',
'fakeHouseholdWithConcerned',
'isModeLeave'
])
}
}
"hasHousehold",
"fakeHouseholdWithConcerned",
"isModeLeave",
]),
},
};
</script>
<style lang="scss" scoped>
</style>
<style lang="scss" scoped></style>

View File

@@ -1,28 +1,23 @@
<template>
<current-household />
<h2>{{ $t('household_members_editor.dates.dates_title') }}</h2>
<h2>{{ $t("household_members_editor.dates.dates_title") }}</h2>
<div class="mb-3 row">
<label
for="start_date"
class="col-form-label col-sm-4 required"
>
{{ $t('household_members_editor.dates.start_date') }}
<label for="start_date" class="col-form-label col-sm-4 required">
{{ $t("household_members_editor.dates.start_date") }}
</label>
<div class="col-sm-8">
<input
type="date"
v-model="startDate"
class="form-control"
>
<input type="date" v-model="startDate" class="form-control" />
</div>
</div>
<div v-if="this.isHouseholdNew">
<h2>{{ $t('household_members_editor.composition.composition') }}</h2>
<h2>{{ $t("household_members_editor.composition.composition") }}</h2>
<div class="mb-3 row">
<label class="col-form-label col-sm-4 required">{{ $t('household_members_editor.composition.household_composition') }}</label>
<label class="col-form-label col-sm-4 required">{{
$t("household_members_editor.composition.household_composition")
}}</label>
<div class="col-sm-8">
<select
v-model="householdCompositionType"
@@ -39,7 +34,9 @@
</div>
</div>
<div class="mb-3 row">
<label class="col-form-label col-sm-4 required">{{ $t('household_members_editor.composition.number_of_children') }}</label>
<label class="col-form-label col-sm-4 required">{{
$t("household_members_editor.composition.number_of_children")
}}</label>
<div class="col-sm-8">
<input
type="number"
@@ -47,25 +44,24 @@
min="0"
max="30"
class="form-control"
>
/>
</div>
</div>
</div>
</template>
<script>
import CurrentHousehold from "./CurrentHousehold";
import {mapGetters, mapState} from 'vuex';
import { mapGetters, mapState } from "vuex";
export default {
name: 'Dates',
name: "Dates",
components: {
CurrentHousehold
CurrentHousehold,
},
computed: {
...mapState(['householdCompositionTypes']),
...mapGetters(['isHouseholdNew']),
...mapState(["householdCompositionTypes"]),
...mapGetters(["isHouseholdNew"]),
householdCompositionType: {
get() {
if (this.$store.state.householdCompositionType !== null) {
@@ -74,7 +70,7 @@ export default {
return null;
},
set(value) {
this.$store.dispatch('setHouseholdCompositionType', value);
this.$store.dispatch("setHouseholdCompositionType", value);
},
},
numberOfChildren: {
@@ -82,8 +78,8 @@ export default {
return this.$store.state.numberOfChildren;
},
set(value) {
this.$store.commit('setNumberOfChildren', value);
}
this.$store.commit("setNumberOfChildren", value);
},
},
startDate: {
get() {
@@ -99,10 +95,9 @@ export default {
// [year, month, day] = value.split('-'),
// dValue = new Date(year, month-1, day);
this.$store.dispatch('setStartDate', value);
}
}
}
}
this.$store.dispatch("setStartDate", value);
},
},
},
};
</script>

View File

@@ -1,35 +1,27 @@
<template>
<h2 class="mt-4">
{{ $t('household_members_editor.household_part') }}
{{ $t("household_members_editor.household_part") }}
</h2>
<div
class="alert alert-info"
v-if="!hasHousehold"
>
{{ $t('household_members_editor.household.no_household_choose_one') }}
<div class="alert alert-info" v-if="!hasHousehold">
{{ $t("household_members_editor.household.no_household_choose_one") }}
</div>
<template v-else>
<current-household />
</template>
<div
v-if="hasHouseholdSuggestion"
class="householdSuggestions my-5"
>
<div v-if="hasHouseholdSuggestion" class="householdSuggestions my-5">
<h4 class="mb-3">
{{ $t('household_members_editor.household.household_suggested') }}
{{ $t("household_members_editor.household.household_suggested") }}
</h4>
<p>{{ $t('household_members_editor.household.household_suggested_explanation') }}</p>
<div
class="accordion"
id="householdSuggestions"
>
<p>
{{
$t("household_members_editor.household.household_suggested_explanation")
}}
</p>
<div class="accordion" id="householdSuggestions">
<div class="accordion-item">
<h2
class="accordion-header"
id="heading_household_suggestions"
>
<h2 class="accordion-header" id="heading_household_suggestions">
<button
v-if="!showHouseholdSuggestion"
class="accordion-button collapsed"
@@ -38,7 +30,12 @@
aria-expanded="false"
@click="toggleHouseholdSuggestion"
>
{{ $tc('household_members_editor.show_household_suggestion', countHouseholdSuggestion) }}
{{
$tc(
"household_members_editor.show_household_suggestion",
countHouseholdSuggestion,
)
}}
</button>
<button
v-if="showHouseholdSuggestion"
@@ -48,7 +45,7 @@
aria-expanded="true"
@click="toggleHouseholdSuggestion"
>
{{ $t('household_members_editor.hide_household_suggestion') }}
{{ $t("household_members_editor.hide_household_suggestion") }}
</button>
<!-- disabled bootstrap behaviour: data-bs-target="#collapse_household_suggestions" aria-controls="collapse_household_suggestions" -->
</h2>
@@ -72,7 +69,7 @@
class="btn btn-sm btn-choose"
@click="selectHousehold(s.household)"
>
{{ $t('household_members_editor.select_household') }}
{{ $t("household_members_editor.select_household") }}
</button>
</li>
</ul>
@@ -84,20 +81,13 @@
</div>
</div>
<ul class="record_actions">
<li v-if="hasHousehold">
<button
@click="resetMode"
class="btn btn-sm btn-misc"
>
{{ $t('household_members_editor.household.reset_mode') }}
<button @click="resetMode" class="btn btn-sm btn-misc">
{{ $t("household_members_editor.household.reset_mode") }}
</button>
</li>
<li
v-if="!hasHousehold"
class="add-persons"
>
<li v-if="!hasHousehold" class="add-persons">
<add-persons
modal-title="Chercher un ménage existant"
button-title="Chercher un ménage existant"
@@ -110,55 +100,49 @@
</add-persons>
</li>
<li v-if="!hasHousehold">
<button
@click="setModeNew"
class="btn btn-sm btn-create"
>
{{ $t('household_members_editor.household.create_household') }}
<button @click="setModeNew" class="btn btn-sm btn-create">
{{ $t("household_members_editor.household.create_household") }}
</button>
</li>
<li v-if="isModeLeaveAllowed && !hasHousehold">
<button
@click="setModeLeave"
class="btn btn-sm btn-misc"
>
<button @click="setModeLeave" class="btn btn-sm btn-misc">
<i class="fa fa-sign-out" />
{{ $t('household_members_editor.household.leave') }}
{{ $t("household_members_editor.household.leave") }}
</button>
</li>
</ul>
</template>
<script>
import { mapGetters, mapState } from 'vuex';
import HouseholdRenderBox from 'ChillPersonAssets/vuejs/_components/Entity/HouseholdRenderBox.vue';
import CurrentHousehold from './CurrentHousehold';
import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons';
import { mapGetters, mapState } from "vuex";
import HouseholdRenderBox from "ChillPersonAssets/vuejs/_components/Entity/HouseholdRenderBox.vue";
import CurrentHousehold from "./CurrentHousehold";
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons";
export default {
name: 'Household',
name: "Household",
components: {
AddPersons,
CurrentHousehold,
HouseholdRenderBox,
},
emits: ['readyToGo'],
emits: ["readyToGo"],
data() {
return {
addPersons: {
key: 'household_find',
key: "household_find",
options: {
type: ['household'],
type: ["household"],
priority: null,
uniq: true,
button: {
size: 'btn-sm',
type: 'btn-search',
}
}
size: "btn-sm",
type: "btn-search",
},
},
},
addAddress: {
key: 'household_new',
key: "household_new",
options: {
useDate: {
validFrom: false,
@@ -166,102 +150,106 @@ export default {
},
onlyButton: true,
button: {
text: {
create: 'household_members_editor.household.set_address',
edit: 'household_members_editor.household.update_address',
}
text: {
create: "household_members_editor.household.set_address",
edit: "household_members_editor.household.update_address",
},
},
title: {
create: 'household_members_editor.household.create_new_address',
edit: 'household_members_editor.household.update_address_title',
create: "household_members_editor.household.create_new_address",
edit: "household_members_editor.household.update_address_title",
},
}
}
},
},
};
},
computed: {
...mapGetters([
'isModeNewAllowed',
'isModeLeaveAllowed',
'getSuggestions',
'hasHousehold',
'isHouseholdNew',
'hasHouseholdSuggestion',
'countHouseholdSuggestion',
'filterHouseholdSuggestionByAccompanyingPeriod',
'hasAddressSuggestion',
'countAddressSuggestion',
'filterAddressesSuggestion',
'hasHouseholdAddress',
'isModeLeave',
'getAddressContext',
"isModeNewAllowed",
"isModeLeaveAllowed",
"getSuggestions",
"hasHousehold",
"isHouseholdNew",
"hasHouseholdSuggestion",
"countHouseholdSuggestion",
"filterHouseholdSuggestionByAccompanyingPeriod",
"hasAddressSuggestion",
"countAddressSuggestion",
"filterAddressesSuggestion",
"hasHouseholdAddress",
"isModeLeave",
"getAddressContext",
]),
...mapState([
'household',
'showHouseholdSuggestion',
'showAddressSuggestion',
'mode',
"household",
"showHouseholdSuggestion",
"showAddressSuggestion",
"mode",
]),
household() {
return this.$store.state.household;
},
allowHouseholdSearch() {
return false;
return this.$store.state.allowHouseholdSearch && !this.$store.getters.hasHousehold;
return (
this.$store.state.allowHouseholdSearch &&
!this.$store.getters.hasHousehold
);
},
isHouseholdNewDesactivated() {
return this.$store.state.mode !== null && !this.$store.getters.isHouseholdNew;
return (
this.$store.state.mode !== null && !this.$store.getters.isHouseholdNew
);
},
isHouseholdLeaveDesactivated() {
return this.$store.state.mode !== null && this.$store.state.mode !== "leave";
}
return (
this.$store.state.mode !== null && this.$store.state.mode !== "leave"
);
},
},
methods: {
setModeNew() {
this.$store.dispatch('createHousehold');
this.$emit('readyToGo');
this.$store.dispatch("createHousehold");
this.$emit("readyToGo");
},
setModeLeave() {
this.$store.dispatch('forceLeaveWithoutHousehold');
this.$emit('readyToGo');
this.$store.dispatch("forceLeaveWithoutHousehold");
this.$emit("readyToGo");
},
resetMode() {
this.$store.commit('resetMode');
this.$store.commit("resetMode");
},
addressChanged(payload) {
console.log("addressChanged", payload);
this.$store.dispatch('setHouseholdNewAddress', payload.address);
this.$store.dispatch("setHouseholdNewAddress", payload.address);
},
selectHousehold(h) {
this.$store.dispatch('selectHousehold', h);
this.$emit('readyToGo');
this.$store.dispatch("selectHousehold", h);
this.$emit("readyToGo");
},
pickHouseholdFound({selected, modal}) {
selected.forEach(function(item) {
pickHouseholdFound({ selected, modal }) {
selected.forEach(function (item) {
this.selectHousehold(item.result);
}, this);
this.$refs.pickHousehold.resetSearch(); // to cast child method
modal.showModal = false;
},
removeHouseholdAddress() {
this.$store.commit('removeHouseholdAddress');
this.$store.commit("removeHouseholdAddress");
},
toggleHouseholdSuggestion() {
this.$store.commit('toggleHouseholdSuggestion');
this.$store.commit("toggleHouseholdSuggestion");
},
},
};
</script>
<style lang="scss">
.filtered {
filter: grayscale(1) opacity(0.6);
}
.filteredButActive {
filter: grayscale(1) opacity(0.6);
&:hover {
filter: unset;
@@ -270,16 +258,16 @@ export default {
div#household_members_editor div,
div.householdSuggestionList {
&.flex-table {
margin: 0;
div.item-bloc div.item-row div.item-col {
&:first-child {
width: 25%;
}
&:last-child {
display: initial;
}
&.flex-table {
margin: 0;
div.item-bloc div.item-row div.item-col {
&:first-child {
width: 25%;
}
}
&:last-child {
display: initial;
}
}
}
}
</style>

View File

@@ -16,20 +16,17 @@
/>
</li>
<li v-if="hasHouseholdAddress">
<button
class="btn btn-remove"
@click="removeHouseholdAddress"
>
{{ $t('household_members_editor.household_address.remove_address') }}
<button class="btn btn-remove" @click="removeHouseholdAddress">
{{ $t("household_members_editor.household_address.remove_address") }}
</button>
</li>
</ul>
</template>
<script>
import AddAddress from 'ChillMainAssets/vuejs/Address/components/AddAddress.vue';
import CurrentHousehold from './CurrentHousehold';
import { mapGetters } from 'vuex';
import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue";
import CurrentHousehold from "./CurrentHousehold";
import { mapGetters } from "vuex";
export default {
name: "HouseholdAddress.vue",
@@ -40,7 +37,7 @@ export default {
data() {
return {
addAddress: {
key: 'household_new',
key: "household_new",
options: {
useDate: {
validFrom: false,
@@ -49,41 +46,40 @@ export default {
onlyButton: true,
button: {
text: {
create: 'household_members_editor.household_address.set_address',
edit: 'household_members_editor.household_address.update_address',
}
create: "household_members_editor.household_address.set_address",
edit: "household_members_editor.household_address.update_address",
},
},
title: {
create: 'household_members_editor.household_address.create_new_address',
edit: 'household_members_editor.household_address.update_address_title',
create:
"household_members_editor.household_address.create_new_address",
edit: "household_members_editor.household_address.update_address_title",
},
}
}
}
},
},
};
},
computed: {
...mapGetters([
'isHouseholdNew',
'hasHouseholdAddress',
'getAddressContext',
'isHouseholdForceNoAddress'
])
"isHouseholdNew",
"hasHouseholdAddress",
"getAddressContext",
"isHouseholdForceNoAddress",
]),
},
methods: {
addressChanged(payload) {
console.log("addressChanged", payload);
this.$store.dispatch('setHouseholdNewAddress', payload.address);
this.$store.dispatch("setHouseholdNewAddress", payload.address);
},
markNoAddress() {
this.$store.commit('markHouseholdNoAddress');
this.$store.commit("markHouseholdNoAddress");
},
removeHouseholdAddress() {
this.$store.commit('removeHouseholdAddress');
this.$store.commit("removeHouseholdAddress");
},
}
}
},
};
</script>
<style scoped>
</style>
<style scoped></style>

View File

@@ -8,15 +8,14 @@
:options="{}"
:person="conc.person"
/>
<span
v-if="isHolder"
class="badge bg-primary holder"
>
{{ $t('household_members_editor.holder') }}
<span v-if="isHolder" class="badge bg-primary holder">
{{ $t("household_members_editor.holder") }}
</span>
</div>
<div v-if="conc.person.birthdate !== null">
{{ $t('person.born', {'gender': conc.person.gender.genderTranslation} ) }}
{{
$t("person.born", { gender: conc.person.gender.genderTranslation })
}}
</div>
</div>
<div class="item-col">
@@ -30,33 +29,33 @@
</div>
<div class="item-row comment">
<ckeditor
:editor="editor"
v-model="comment"
tag-name="textarea"
/>
<ckeditor :editor="editor" v-model="comment" tag-name="textarea" />
</div>
<div class="item-row participation-details">
<div
v-if="conc.position.allowHolder"
class="action"
>
<div v-if="conc.position.allowHolder" class="action">
<button
class="btn"
:class="{ 'btn-primary': isHolder, 'btn-secondary': !isHolder}"
:class="{ 'btn-primary': isHolder, 'btn-secondary': !isHolder }"
@click="toggleHolder"
>
{{ $t(isHolder ? 'household_members_editor.is_holder' : 'household_members_editor.is_not_holder') }}
{{
$t(
isHolder
? "household_members_editor.is_holder"
: "household_members_editor.is_not_holder",
)
}}
</button>
</div>
<div>
<button
@click="removePosition"
class="btn btn-outline-primary"
>
{{ $t('household_members_editor.remove_position', {position: conc.position.label.fr}) }}
<button @click="removePosition" class="btn btn-outline-primary">
{{
$t("household_members_editor.remove_position", {
position: conc.position.label.fr,
})
}}
</button>
</div>
@@ -66,7 +65,7 @@
@click="removeConcerned"
class="btn btn-primary"
>
{{ $t('household_members_editor.remove_concerned') }}
{{ $t("household_members_editor.remove_concerned") }}
</button>
</div>
</div>
@@ -74,7 +73,6 @@
</template>
<style scoped lang="scss">
.drag-icon {
height: 1.1em;
margin-right: 0.5em;
@@ -95,59 +93,53 @@ div.participation-details {
vertical-align: super;
font-size: 0.6em;
}
</style>
<script>
import { mapGetters } from 'vuex';
import PersonRenderBox from 'ChillPersonAssets/vuejs/_components/Entity/PersonRenderBox.vue';
import CKEditor from '@ckeditor/ckeditor5-vue';
import ClassicEditor from 'ChillMainAssets/module/ckeditor5/editor_config';
import { mapGetters } from "vuex";
import PersonRenderBox from "ChillPersonAssets/vuejs/_components/Entity/PersonRenderBox.vue";
import CKEditor from "@ckeditor/ckeditor5-vue";
import ClassicEditor from "ChillMainAssets/module/ckeditor5/editor_config";
export default {
name: 'MemberDetails',
name: "MemberDetails",
components: {
PersonRenderBox,
ckeditor: CKEditor.component,
},
props: [
'conc'
],
data() {
props: ["conc"],
data() {
return {
editor: ClassicEditor,
};
},
computed: {
...mapGetters( [
'concByPersonId'
]),
isHolder() {
return this.conc.holder;
},
comment: {
},
computed: {
...mapGetters(["concByPersonId"]),
isHolder() {
return this.conc.holder;
},
comment: {
get() {
return this.conc.comment;
},
set(text) {
console.log('set comment');
console.log('comment', text);
console.log("set comment");
console.log("comment", text);
this.$store.dispatch('setComment', { conc: this.conc, comment: text });
}
},
},
methods: {
this.$store.dispatch("setComment", { conc: this.conc, comment: text });
},
},
},
methods: {
toggleHolder() {
this.$store.dispatch('toggleHolder', this.conc);
this.$store.dispatch("toggleHolder", this.conc);
},
removePosition() {
this.$store.dispatch('removePosition', this.conc);
this.$store.dispatch("removePosition", this.conc);
},
removeConcerned() {
this.$store.dispatch('removeConcerned', this.conc);
this.$store.dispatch("removeConcerned", this.conc);
},
}
},
};
</script>

View File

@@ -1,7 +1,9 @@
<template>
<ckeditor
name="content"
:placeholder="$t('household_members_editor.positioning.comment_placeholder')"
:placeholder="
$t('household_members_editor.positioning.comment_placeholder')
"
:editor="editor"
v-model="content"
tag-name="textarea"
@@ -9,7 +11,7 @@
</template>
<script>
import CKEditor from '@ckeditor/ckeditor5-vue';
import CKEditor from "@ckeditor/ckeditor5-vue";
import ClassicEditor from "ChillMainAssets/module/ckeditor5/editor_config";
export default {
@@ -17,26 +19,27 @@ export default {
components: {
ckeditor: CKEditor.component,
},
props: ['conc'],
props: ["conc"],
data() {
return {
editor: ClassicEditor,
}
};
},
computed: {
content: {
get() {
return this.$props.conc.comment || '';
return this.$props.conc.comment || "";
},
set(value) {
console.log('set content', value);
this.$store.commit('setComment', {conc: this.$props.conc, comment: value})
}
}
}
}
console.log("set content", value);
this.$store.commit("setComment", {
conc: this.$props.conc,
comment: value,
});
},
},
},
};
</script>
<style scoped>
</style>
<style scoped></style>

View File

@@ -1,14 +1,12 @@
<template>
<current-household />
<h2>{{ $t('household_members_editor.positioning.persons_to_positionnate') }}</h2>
<h2>
{{ $t("household_members_editor.positioning.persons_to_positionnate") }}
</h2>
<div class="list-household-members flex-table">
<div
v-for="conc in concerned"
class="item-bloc"
:key="conc.person.id"
>
<div v-for="conc in concerned" class="item-bloc" :key="conc.person.id">
<div class="pick-position item-row">
<div class="person">
<!-- <h3>{{ conc.person.text }}</h3> -->
@@ -18,10 +16,13 @@
<button
class="btn"
:disabled="!allowHolderForConcerned(conc)"
:class="{'btn-outline-chill-green': !conc.holder, 'btn-chill-green': conc.holder }"
:class="{
'btn-outline-chill-green': !conc.holder,
'btn-chill-green': conc.holder,
}"
@click="toggleHolder(conc)"
>
{{ $t('household_members_editor.positioning.holder') }}
{{ $t("household_members_editor.positioning.holder") }}
</button>
</div>
<div
@@ -31,7 +32,10 @@
>
<button
class="btn"
:class="{ 'btn-primary': conc.position === position, 'btn-outline-primary': conc.position !== position }"
:class="{
'btn-primary': conc.position === position,
'btn-outline-primary': conc.position !== position,
}"
@click="moveToPosition(conc.person.id, position.id)"
>
{{ position.label.fr }}
@@ -40,7 +44,7 @@
</div>
<div class="item-row">
<div>
<h6>{{ $t('household_members_editor.positioning.comment') }}</h6>
<h6>{{ $t("household_members_editor.positioning.comment") }}</h6>
<person-comment :conc="conc" />
</div>
</div>
@@ -49,55 +53,54 @@
</template>
<script>
import {mapGetters, mapState} from "vuex";
import { mapGetters, mapState } from "vuex";
import CurrentHousehold from "./CurrentHousehold";
import PersonComment from './PersonComment';
import PersonText from '../../_components/Entity/PersonText.vue';
import PersonComment from "./PersonComment";
import PersonText from "../../_components/Entity/PersonText.vue";
export default {
name: "Positioning",
components: {
CurrentHousehold,
PersonComment,
PersonText
PersonText,
},
computed: {
...mapState([
'concerned'
]),
...mapState(["concerned"]),
...mapGetters([
'persons',
'concUnpositionned',
'positions',
'concByPosition',
"persons",
"concUnpositionned",
"positions",
"concByPosition",
]),
allPersonsPositionnated () {
return this.$store.getters.persons.length > 0
&& this.$store.getters.concUnpositionned.length === 0;
allPersonsPositionnated() {
return (
this.$store.getters.persons.length > 0 &&
this.$store.getters.concUnpositionned.length === 0
);
},
allowHolderForConcerned: (app) => (conc) => {
console.log('allow holder for concerned', conc);
console.log("allow holder for concerned", conc);
if (conc.position === null) {
return false;
}
return conc.position.allowHolder;
}
},
},
methods: {
moveToPosition(person_id, position_id) {
this.$store.dispatch('markPosition', { person_id, position_id });
this.$store.dispatch("markPosition", { person_id, position_id });
},
toggleHolder(conc) {
console.log('toggle holder', conc);
this.$store.dispatch('toggleHolder', conc);
}
console.log("toggle holder", conc);
this.$store.dispatch("toggleHolder", conc);
},
},
}
};
</script>
<style lang="scss" scoped>
.pick-position {
margin: 0;
padding: 0;

View File

@@ -1,25 +1,25 @@
import { createApp } from 'vue';
import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n';
import { appMessages } from './js/i18n';
import { store } from './store';
import 'vue-toast-notification/dist/theme-sugar.css';
import ToastPlugin from 'vue-toast-notification';
import { createApp } from "vue";
import { _createI18n } from "ChillMainAssets/vuejs/_js/i18n";
import { appMessages } from "./js/i18n";
import { store } from "./store";
import "vue-toast-notification/dist/theme-sugar.css";
import ToastPlugin from "vue-toast-notification";
import App from './App.vue';
import App from "./App.vue";
const i18n = _createI18n(appMessages);
/* exported app */
const app = createApp({
template: `<app></app>`,
template: `<app></app>`,
})
.use(store)
.use(i18n)
.use(ToastPlugin, {
position: "bottom-right",
type: "error",
duration: 5000,
dismissible: true
})
.component('app', App)
.mount('#household_members_editor');
.use(store)
.use(i18n)
.use(ToastPlugin, {
position: "bottom-right",
type: "error",
duration: 5000,
dismissible: true,
})
.component("app", App)
.mount("#household_members_editor");

View File

@@ -1,23 +1,25 @@
import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n';
import { ontheflyMessages } from 'ChillMainAssets/vuejs/OnTheFly/i18n';
import { addressMessages } from 'ChillMainAssets/vuejs/Address/i18n';
import { personMessages } from "ChillPersonAssets/vuejs/_js/i18n";
import { ontheflyMessages } from "ChillMainAssets/vuejs/OnTheFly/i18n";
import { addressMessages } from "ChillMainAssets/vuejs/Address/i18n";
const appMessages = {
fr: {
household_members_editor: {
fr: {
household_members_editor: {
household: {
no_household_choose_one: "Aucun ménage de destination. Choisissez un ménage.",
// new_household: "Nouveau ménage",
no_household_choose_one:
"Aucun ménage de destination. Choisissez un ménage.",
// new_household: "Nouveau ménage",
create_household: "Créer",
search_household: "Chercher un ménage",
will_leave_any_household: "Les usagers ne rejoignent pas de ménage",
leave: "Quitter sans rejoindre un ménage",
will_leave_any_household_explanation: "Les usagers quitteront leur ménage actuel, et ne seront pas associés à un autre ménage. Par ailleurs, ils seront enregistrés comme étant sans adresse connue.",
will_leave_any_household_explanation:
"Les usagers quitteront leur ménage actuel, et ne seront pas associés à un autre ménage. Par ailleurs, ils seront enregistrés comme étant sans adresse connue.",
leave_without_household: "Sans nouveau ménage",
reset_mode: "Modifier la destination",
household_suggested: "Suggestions de ménage",
household_suggested_explanation: "Les ménages suivants sont connus et pourraient peut-être correspondre à des ménages recherchés."
household_suggested_explanation:
"Les ménages suivants sont connus et pourraient peut-être correspondre à des ménages recherchés.",
// remove ?
/*
where_live_the_household: "À quelle adresse habite ce ménage ?",
@@ -46,35 +48,39 @@ const appMessages = {
move_to: "Déplacer vers",
persons_leaving: "Usagers quittant leurs ménages",
no_person_in_position: "Aucun usager ne sera ajouté à cette position",
persons_with_household: "Les usagers suivants sont associés à ces ménages:",
already_belongs_to_household: "est associé au ménage"
persons_with_household:
"Les usagers suivants sont associés à ces ménages:",
already_belongs_to_household: "est associé au ménage",
},
positioning: {
persons_to_positionnate: "Usagers à positionner",
holder: "Titulaire",
comment: "Commentaire",
comment_placeholder: "Associer un commentaire",
},
positioning: {
persons_to_positionnate: 'Usagers à positionner',
holder: "Titulaire",
comment: "Commentaire",
comment_placeholder: "Associer un commentaire",
},
app: {
next: 'Suivant',
previous: 'Précédent',
cancel: 'Annuler',
save: 'Enregistrer',
next: "Suivant",
previous: "Précédent",
cancel: "Annuler",
save: "Enregistrer",
steps: {
concerned: 'Usagers concernés',
household: 'Ménage de destination',
household_address: 'Adresse du nouveau ménage',
positioning: 'Position dans le ménage',
confirm: 'Confirmation'
}
concerned: "Usagers concernés",
household: "Ménage de destination",
household_address: "Adresse du nouveau ménage",
positioning: "Position dans le ménage",
confirm: "Confirmation",
},
},
drop_persons_here: "Glissez-déposez ici les usagers pour la position \"{position}\"",
drop_persons_here:
'Glissez-déposez ici les usagers pour la position "{position}"',
all_positionnated: "Tous les usagers sont positionnés",
household_part: "Destination",
suggestions: "Suggestions",
hide_household_suggestion: "Masquer les suggestions",
show_household_suggestion: 'Aucune suggestion | Afficher une suggestion | Afficher {count} suggestions',
household_for_participants_accompanying_period: "Des ménages partagent le même parcours",
show_household_suggestion:
"Aucune suggestion | Afficher une suggestion | Afficher {count} suggestions",
household_for_participants_accompanying_period:
"Des ménages partagent le même parcours",
select_household: "Sélectionner le ménage",
dates: {
start_date: "Début de validité",
@@ -91,12 +97,15 @@ const appMessages = {
there_are_warnings: "Impossible de valider actuellement",
check_those_items: "Veuillez corriger les éléments suivants",
},
}
}
},
},
};
Object.assign(appMessages.fr, personMessages.fr, addressMessages.fr, ontheflyMessages.fr);
Object.assign(
appMessages.fr,
personMessages.fr,
addressMessages.fr,
ontheflyMessages.fr,
);
export {
appMessages
};
export { appMessages };

View File

@@ -1,13 +1,21 @@
import { createStore } from 'vuex';
import { householdMove, fetchHouseholdSuggestionByAccompanyingPeriod, fetchAddressSuggestionByPerson} from './../api.js';
import { fetchResults } from 'ChillMainAssets/lib/api/apiMethods.ts'
import { fetchHouseholdByAddressReference } from 'ChillPersonAssets/lib/household.js';
import { datetimeToISO, dateToISO, ISOToDate } from 'ChillMainAssets/chill/js/date';
import { createStore } from "vuex";
import {
householdMove,
fetchHouseholdSuggestionByAccompanyingPeriod,
fetchAddressSuggestionByPerson,
} from "./../api.js";
import { fetchResults } from "ChillMainAssets/lib/api/apiMethods.ts";
import { fetchHouseholdByAddressReference } from "ChillPersonAssets/lib/household.js";
import {
datetimeToISO,
dateToISO,
ISOToDate,
} from "ChillMainAssets/chill/js/date";
const debug = process.env.NODE_ENV !== 'production';
const debug = process.env.NODE_ENV !== "production";
//console.log('AJAJAJA', window.addaddress);
const concerned = window.household_members_editor_data.persons.map(p => {
const concerned = window.household_members_editor_data.persons.map((p) => {
return {
person: p,
position: null,
@@ -23,14 +31,14 @@ const store = createStore({
concerned,
household: window.household_members_editor_data.household,
positions: window.household_members_editor_data.positions.sort((a, b) => {
if (a.ordering < b.ordering) {
return -1;
}
if (a.ordering > b.ordering) {
return 1;
}
return 0;
}),
if (a.ordering < b.ordering) {
return -1;
}
if (a.ordering > b.ordering) {
return 1;
}
return 0;
}),
startDate: dateToISO(new Date()),
/**
* Indicates if the destination is:
@@ -40,10 +48,16 @@ const store = createStore({
* * "leave" => leave without household
* * null if not set
*/
mode: window.household_members_editor_data.household === null ? null : "existing",
allowHouseholdCreate: window.household_members_editor_data.allowHouseholdCreate,
allowHouseholdSearch: window.household_members_editor_data.allowHouseholdSearch,
allowLeaveWithoutHousehold: window.household_members_editor_data.allowLeaveWithoutHousehold,
mode:
window.household_members_editor_data.household === null
? null
: "existing",
allowHouseholdCreate:
window.household_members_editor_data.allowHouseholdCreate,
allowHouseholdSearch:
window.household_members_editor_data.allowHouseholdSearch,
allowLeaveWithoutHousehold:
window.household_members_editor_data.allowLeaveWithoutHousehold,
forceLeaveWithoutHousehold: false,
/**
* If true, the user explicitly said that no address is possible
@@ -55,14 +69,15 @@ const store = createStore({
* (this is not restricted to "suggestion by accompanying periods")
*/
householdSuggestionByAccompanyingPeriod: [], // TODO rename into householdsSuggestion
showHouseholdSuggestion: window.household_members_editor_expand_suggestions === 1,
showHouseholdSuggestion:
window.household_members_editor_expand_suggestions === 1,
householdCompositionType: null,
numberOfChildren: 0,
addressesSuggestion: [],
showAddressSuggestion: true,
householdCompositionTypes: [],
warnings: [],
errors: []
errors: [],
},
getters: {
/**
@@ -94,8 +109,8 @@ const store = createStore({
},
getSuggestions(state) {
let suggestions = [];
state.householdSuggestionByAccompanyingPeriod.forEach(h => {
suggestions.push({household: h});
state.householdSuggestionByAccompanyingPeriod.forEach((h) => {
suggestions.push({ household: h });
});
return suggestions;
@@ -114,10 +129,10 @@ const store = createStore({
addressId: null,
target: {
name: state.household.type,
id: state.household.id
id: state.household.id,
},
defaults: window.addaddress,
suggestions: state.addressesSuggestion
suggestions: state.addressesSuggestion,
};
} else {
return {
@@ -125,7 +140,7 @@ const store = createStore({
addressId: state.household.current_address.id,
target: {
name: state.household.type,
id: state.household.id
id: state.household.id,
},
defaults: window.addaddress,
};
@@ -154,9 +169,9 @@ const store = createStore({
return state.householdSuggestionByAccompanyingPeriod;
}
return state.householdSuggestionByAccompanyingPeriod
.filter(h => h.id !== state.household.id)
;
return state.householdSuggestionByAccompanyingPeriod.filter(
(h) => h.id !== state.household.id,
);
},
hasAddressSuggestion(state, getters) {
return getters.filterAddressesSuggestion.length > 0;
@@ -173,65 +188,61 @@ const store = createStore({
return state.addressesSuggestion;
}
return state.addressesSuggestion
.filter(a => a.address_id !== state.household.current_address.address_id);
return state.addressesSuggestion.filter(
(a) => a.address_id !== state.household.current_address.address_id,
);
},
hasPersonsWellPositionnated(state, getters) {
return getters.needsPositionning === false
|| (getters.persons.length > 0 && getters.concUnpositionned.length === 0);
return (
getters.needsPositionning === false ||
(getters.persons.length > 0 && getters.concUnpositionned.length === 0)
);
},
persons(state) {
return state.concerned.map(conc => conc.person);
return state.concerned.map((conc) => conc.person);
},
concUnpositionned(state) {
return state.concerned
.filter(conc => conc.position === null)
;
return state.concerned.filter((conc) => conc.position === null);
},
positions(state) {
return state.positions;
},
personByPosition: (state) => (position_id) => {
return state.concerned
.filter(conc =>
conc.position !== null ? conc.position.id === position_id : false
.filter((conc) =>
conc.position !== null ? conc.position.id === position_id : false,
)
.map(conc => conc.person)
;
.map((conc) => conc.person);
},
concByPosition: (state) => (position_id) => {
return state.concerned
.filter(conc =>
conc.position !== null ? conc.position.id === position_id : false
)
;
return state.concerned.filter((conc) =>
conc.position !== null ? conc.position.id === position_id : false,
);
},
concByPersonId: (state) => (person_id) => {
return state.concerned
.find(conc => conc.person.id === person_id)
;
return state.concerned.find((conc) => conc.person.id === person_id);
},
needsPositionning(state) {
return state.forceLeaveWithoutHousehold === false;
},
fakeHouseholdWithConcerned(state, getters) {
if (null === state.household) {
throw Error('cannot create fake household without household');
throw Error("cannot create fake household without household");
}
let h = {
type: 'household',
members: state.household.members,
current_address: state.household.current_address,
current_members_id: state.household.current_members_id,
new_members: [],
};
type: "household",
members: state.household.members,
current_address: state.household.current_address,
current_members_id: state.household.current_members_id,
new_members: [],
};
if (!getters.isHouseholdNew){
if (!getters.isHouseholdNew) {
h.id = state.household.id;
}
state.concerned.forEach((c, index) => {
if (!(h.members.map((m) => m.person.id)).includes(c.person.id)) {
if (!h.members.map((m) => m.person.id).includes(c.person.id)) {
let m = {
id: index * -1,
person: c.person,
@@ -240,36 +251,37 @@ const store = createStore({
};
if (c.position === null) {
m.position = {
ordering: 999999
}
ordering: 999999,
};
}
h.new_members.push(m);
}
});
})
console.log('fake household', h);
console.log("fake household", h);
return h;
},
buildPayload: (state, getters) => {
let
conc,
let conc,
payload_conc,
payload = {
concerned: [],
destination: null,
composition: null,
}
;
};
if (state.forceLeaveWithoutHousehold === false) {
payload.destination = {
id: state.household.id,
type: state.household.type,
};
id: state.household.id,
type: state.household.type,
};
if (getters.isHouseholdNew && state.household.current_address !== null) {
payload.destination.forceAddress = { id: state.household.current_address.address_id };
if (
getters.isHouseholdNew &&
state.household.current_address !== null
) {
payload.destination.forceAddress = {
id: state.household.current_address.address_id,
};
}
}
@@ -278,17 +290,20 @@ const store = createStore({
payload_conc = {
person: {
id: conc.person.id,
type: conc.person.type
type: conc.person.type,
},
start_date: {
datetime: state.startDate === null || state.startDate === '' ? null : datetimeToISO(ISOToDate(state.startDate))
}
datetime:
state.startDate === null || state.startDate === ""
? null
: datetimeToISO(ISOToDate(state.startDate)),
},
};
if (state.forceLeaveWithoutHousehold === false) {
payload_conc.position = {
id: conc.position.id,
type: conc.position.type
type: conc.position.type,
};
payload_conc.holder = conc.holder;
payload_conc.comment = conc.comment;
@@ -320,7 +335,7 @@ const store = createStore({
state.forceLeaveWithoutHousehold = false;
},
addConcerned(state, person) {
let persons = state.concerned.map(conc => conc.person.id);
let persons = state.concerned.map((conc) => conc.person.id);
if (!persons.includes(person.id)) {
state.concerned.push({
person,
@@ -333,17 +348,16 @@ const store = createStore({
console.error("person already included");
}
},
markPosition(state, { person_id, position_id}) {
let
position = state.positions.find(pos => pos.id === position_id),
conc = state.concerned.find(c => c.person.id === person_id);
markPosition(state, { person_id, position_id }) {
let position = state.positions.find((pos) => pos.id === position_id),
conc = state.concerned.find((c) => c.person.id === person_id);
conc.position = position;
// reset position if changed:
if (!position.allowHolder && conc.holder) {
conc.holder = false;
}
},
setComment(state, {conc, comment}) {
setComment(state, { conc, comment }) {
conc.comment = comment;
},
toggleHolder(state, conc) {
@@ -354,16 +368,16 @@ const store = createStore({
conc.position = null;
},
removePerson(state, person) {
state.concerned = state.concerned.filter(c =>
c.person.id !== person.id
)
state.concerned = state.concerned.filter(
(c) => c.person.id !== person.id,
);
},
createHousehold(state) {
state.household = {
type: 'household',
type: "household",
members: [],
current_address: null,
current_members_id: []
current_members_id: [],
};
state.mode = "new";
state.forceLeaveWithoutHousehold = false;
@@ -373,7 +387,7 @@ const store = createStore({
state.forceLeaveWithoutHousehold = false;
},
setHouseholdAddress(state, address) {
console.log('setHouseholdAddress commit', address);
console.log("setHouseholdAddress commit", address);
if (null === state.household) {
console.error("no household");
throw new Error("No household");
@@ -404,8 +418,9 @@ const store = createStore({
state.forceLeaveWithoutHousehold = false;
},
addHouseholdSuggestionByAccompanyingPeriod(state, households) {
let existingIds = state.householdSuggestionByAccompanyingPeriod
.map(h => h.id);
let existingIds = state.householdSuggestionByAccompanyingPeriod.map(
(h) => h.id,
);
for (let i in households) {
if (!existingIds.includes(households[i].id)) {
state.householdSuggestionByAccompanyingPeriod.push(households[i]);
@@ -433,14 +448,15 @@ const store = createStore({
state.householdCompositionTypes = types;
},
setHouseholdCompositionType(state, id) {
state.householdCompositionType = state.householdCompositionTypes.find(t => t.id === id);
state.householdCompositionType = state.householdCompositionTypes.find(
(t) => t.id === id,
);
},
setNumberOfChildren(state, number) {
state.numberOfChildren = Number.parseInt(number);
},
addAddressesSuggestion(state, addresses) {
let existingIds = state.addressesSuggestion
.map(a => a.address_id);
let existingIds = state.addressesSuggestion.map((a) => a.address_id);
for (let i in addresses) {
if (!existingIds.includes(addresses[i].address_id)) {
@@ -451,161 +467,175 @@ const store = createStore({
},
actions: {
addConcerned({ commit, dispatch }, person) {
commit('addConcerned', person);
dispatch('computeWarnings');
dispatch('fetchAddressSuggestions');
commit("addConcerned", person);
dispatch("computeWarnings");
dispatch("fetchAddressSuggestions");
},
markPosition({ commit, dispatch }, { person_id, position_id }) {
commit('markPosition', { person_id, position_id });
dispatch('computeWarnings');
commit("markPosition", { person_id, position_id });
dispatch("computeWarnings");
},
toggleHolder({ commit, dispatch }, conc) {
commit('toggleHolder', conc);
dispatch('computeWarnings');
commit("toggleHolder", conc);
dispatch("computeWarnings");
},
removePosition({ commit, dispatch }, conc) {
commit('removePosition', conc);
dispatch('computeWarnings');
commit("removePosition", conc);
dispatch("computeWarnings");
},
removePerson({ commit, dispatch }, person) {
commit('removePerson', person);
dispatch('computeWarnings');
dispatch('fetchAddressSuggestions');
commit("removePerson", person);
dispatch("computeWarnings");
dispatch("fetchAddressSuggestions");
},
removeHousehold({ commit, dispatch }) {
commit('removeHousehold');
dispatch('computeWarnings');
commit("removeHousehold");
dispatch("computeWarnings");
},
createHousehold({ commit, dispatch }) {
commit('createHousehold');
dispatch('computeWarnings');
commit("createHousehold");
dispatch("computeWarnings");
},
setHouseholdNewAddress({ commit }, address) {
commit('setHouseholdAddress', address);
commit("setHouseholdAddress", address);
},
forceLeaveWithoutHousehold({ commit, dispatch }) {
commit('forceLeaveWithoutHousehold');
dispatch('computeWarnings');
commit("forceLeaveWithoutHousehold");
dispatch("computeWarnings");
},
selectHousehold({ commit, dispatch }, h) {
commit('selectHousehold', h);
dispatch('computeWarnings');
commit("selectHousehold", h);
dispatch("computeWarnings");
},
setStartDate({ commit, dispatch }, date) {
commit('setStartDate', date);
dispatch('computeWarnings');
commit("setStartDate", date);
dispatch("computeWarnings");
},
setComment({ commit }, payload) {
commit('setComment', payload);
commit("setComment", payload);
},
setHouseholdCompositionTypes({ commit }, payload) {
commit('setHouseholdCompositionTypes', payload);
commit("setHouseholdCompositionTypes", payload);
},
setHouseholdCompositionType({ commit }, payload) {
commit('setHouseholdCompositionType', payload);
commit("setHouseholdCompositionType", payload);
},
fetchHouseholdSuggestionForConcerned({ commit }, person) {
fetchHouseholdSuggestionByAccompanyingPeriod(person.id)
.then(households => {
commit('addHouseholdSuggestionByAccompanyingPeriod', households);
});
fetchHouseholdSuggestionByAccompanyingPeriod(person.id).then(
(households) => {
commit("addHouseholdSuggestionByAccompanyingPeriod", households);
},
);
},
fetchAddressSuggestions({ commit, state, dispatch }) {
for (let i in state.concerned) {
fetchAddressSuggestionByPerson(state.concerned[i].person.id)
.then(addresses => {
commit('addAddressesSuggestion', addresses);
dispatch('fetchHouseholdSuggestionByAddresses', addresses);
.then((addresses) => {
commit("addAddressesSuggestion", addresses);
dispatch("fetchHouseholdSuggestionByAddresses", addresses);
})
.catch(e => {
.catch((e) => {
console.log(e);
});
}
},
async fetchHouseholdSuggestionByAddresses({commit}, addresses) {
console.log('fetchHouseholdSuggestionByAddresses', addresses);
async fetchHouseholdSuggestionByAddresses({ commit }, addresses) {
console.log("fetchHouseholdSuggestionByAddresses", addresses);
// foreach address, find household suggestions
addresses.forEach(async a => {
addresses.forEach(async (a) => {
if (a.addressReference !== null) {
let households = await fetchHouseholdByAddressReference(a.addressReference);
commit('addHouseholdSuggestionByAccompanyingPeriod', households);
let households = await fetchHouseholdByAddressReference(
a.addressReference,
);
commit("addHouseholdSuggestionByAccompanyingPeriod", households);
} else {
console.log('not an adresse reference')
console.log("not an adresse reference");
}
});
},
computeWarnings({ commit, state, getters }) {
let warnings = []
let warnings = [];
if (!getters.hasHousehold && !state.forceLeaveWithoutHousehold) {
warnings.push({ m: 'household_members_editor.add_destination', a: {} });
warnings.push({ m: "household_members_editor.add_destination", a: {} });
}
if (state.concerned.length === 0) {
warnings.push({ m: 'household_members_editor.add_at_least_onePerson', a: {} });
warnings.push({
m: "household_members_editor.add_at_least_onePerson",
a: {},
});
}
if (getters.concUnpositionned.length > 0
&& !state.forceLeaveWithoutHousehold) {
warnings.push({ m: 'household_members_editor.give_a_position_to_every_person', a: {} })
if (
getters.concUnpositionned.length > 0 &&
!state.forceLeaveWithoutHousehold
) {
warnings.push({
m: "household_members_editor.give_a_position_to_every_person",
a: {},
});
}
commit('setWarnings', warnings);
commit("setWarnings", warnings);
},
confirm({ getters, commit }) {
let payload = getters.buildPayload,
errors = [],
person_id,
household_id,
error
;
error;
householdMove(payload).then(household => {
if (household === null) {
person_id = getters.persons[0].id;
window.location.replace(`/fr/person/${person_id}/general`);
} else {
if (household.type === 'household') {
household_id = household.id;
householdMove(payload).then((household) => {
if (household === null) {
person_id = getters.persons[0].id;
window.location.replace(`/fr/person/${person_id}/general`);
} else {
if (household.type === "household") {
household_id = household.id;
// nothing to do anymore here, bye-bye !
let params = new URLSearchParams(window.location.search);
if (params.has('followAfter')) {
window.location.replace(`/fr/person/household/${household_id}/summary`);
} else {
if (params.has('returnPath')) {
window.location.replace(params.get('returnPath'));
} else {
window.location.replace(`/fr/person/household/${household_id}/summary`);
}
}
// nothing to do anymore here, bye-bye !
let params = new URLSearchParams(window.location.search);
if (params.has("followAfter")) {
window.location.replace(
`/fr/person/household/${household_id}/summary`,
);
} else {
// we assume the answer was 422...
error = household;
for (let i in error.violations) {
let e = error.violations[i];
errors.push(e.title);
if (params.has("returnPath")) {
window.location.replace(params.get("returnPath"));
} else {
window.location.replace(
`/fr/person/household/${household_id}/summary`,
);
}
commit('setErrors', errors);
}
} else {
// we assume the answer was 422...
error = household;
for (let i in error.violations) {
let e = error.violations[i];
errors.push(e.title);
}
commit("setErrors", errors);
}
}
});
},
}
},
});
store.dispatch('computeWarnings');
store.dispatch('fetchAddressSuggestions');
store.dispatch("computeWarnings");
store.dispatch("fetchAddressSuggestions");
if (concerned.length > 0) {
concerned.forEach(c => {
store.dispatch('fetchHouseholdSuggestionForConcerned', c.person);
concerned.forEach((c) => {
store.dispatch("fetchHouseholdSuggestionForConcerned", c.person);
});
}
fetchResults(`/api/1.0/person/houehold/composition/type.json`).then(types => {
store.dispatch('setHouseholdCompositionTypes', types);
})
fetchResults(`/api/1.0/person/houehold/composition/type.json`).then((types) => {
store.dispatch("setHouseholdCompositionTypes", types);
});
export { store };

View File

@@ -1,5 +1,5 @@
import { splitId } from './vis-network';
import {makeFetch} from 'ChillMainAssets/lib/api/apiMethods.ts';
import { splitId } from "./vis-network";
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods.ts";
/**
* @function postFetch
* @param url
@@ -7,8 +7,8 @@ import {makeFetch} from 'ChillMainAssets/lib/api/apiMethods.ts';
* @returns {Promise<Response>}
*/
const postFetch = (url, body) => {
return makeFetch('POST', url, body)
}
return makeFetch("POST", url, body);
};
/**
* @function patchFetch
@@ -17,8 +17,8 @@ const postFetch = (url, body) => {
* @returns {Promise<Response>}
*/
const patchFetch = (url, body) => {
return makeFetch('PATCH', url, body)
}
return makeFetch("PATCH", url, body);
};
/**
* @function deleteFetch
@@ -27,9 +27,8 @@ const patchFetch = (url, body) => {
* @returns {Promise<Response>}
*/
const deleteFetch = (url) => {
return makeFetch('DELETE', url, null)
}
return makeFetch("DELETE", url, null);
};
/**
* @function getHouseholdByPerson
@@ -37,15 +36,15 @@ const deleteFetch = (url) => {
* @returns {Promise<Response>}
*/
const getHouseholdByPerson = (person) => {
//console.log('getHouseholdByPerson', person.id)
if (person.current_household_id === null) {
throw 'Currently the person has not household!'
}
return makeFetch(
'GET',
`/api/1.0/person/household/${person.current_household_id}.json`
);
}
//console.log('getHouseholdByPerson', person.id)
if (person.current_household_id === null) {
throw "Currently the person has not household!";
}
return makeFetch(
"GET",
`/api/1.0/person/household/${person.current_household_id}.json`,
);
};
/**
* @function getCoursesByPerson
@@ -53,12 +52,12 @@ const getHouseholdByPerson = (person) => {
* @returns {Promise<Response>}
*/
const getCoursesByPerson = (person) => {
//console.log('getCoursesByPerson', person._id)
return makeFetch(
'GET',
`/api/1.0/person/accompanying-course/by-person/${person._id}.json`
);
}
//console.log('getCoursesByPerson', person._id)
return makeFetch(
"GET",
`/api/1.0/person/accompanying-course/by-person/${person._id}.json`,
);
};
/**
* @function getRelationshipsByPerson
@@ -66,20 +65,20 @@ const getCoursesByPerson = (person) => {
* @returns {Promise<Response>}
*/
const getRelationshipsByPerson = (person) => {
//console.log('getRelationshipsByPerson', person.id)
return makeFetch(
'GET',
`/api/1.0/relations/relationship/by-person/${person._id}.json`
);
}
//console.log('getRelationshipsByPerson', person.id)
return makeFetch(
"GET",
`/api/1.0/relations/relationship/by-person/${person._id}.json`,
);
};
/**
* Return list of relations
* @returns {Promise<Response>}
*/
const getRelationsList = () => {
return makeFetch('GET', `/api/1.0/relations/relation.json`);
}
return makeFetch("GET", `/api/1.0/relations/relation.json`);
};
/**
* @function postRelationship
@@ -87,18 +86,15 @@ const getRelationsList = () => {
* @returns {Promise<Response>}
*/
const postRelationship = (relationship) => {
//console.log(relationship);
return postFetch(
`/api/1.0/relations/relationship.json`,
{
type: 'relationship',
fromPerson: { type: 'person', id: splitId(relationship.from, 'id') },
toPerson: { type: 'person', id: splitId(relationship.to, 'id') },
relation: { type: 'relation', id: relationship.relation.id },
reverse: relationship.reverse
}
)
}
//console.log(relationship);
return postFetch(`/api/1.0/relations/relationship.json`, {
type: "relationship",
fromPerson: { type: "person", id: splitId(relationship.from, "id") },
toPerson: { type: "person", id: splitId(relationship.to, "id") },
relation: { type: "relation", id: relationship.relation.id },
reverse: relationship.reverse,
});
};
/**
* @function patchRelationship
@@ -106,20 +102,17 @@ const postRelationship = (relationship) => {
* @returns {Promise<Response>}
*/
const patchRelationship = (relationship) => {
//console.log(relationship)
let linkType = splitId(relationship.id, 'link')
let id = splitId(linkType, 'id')
return patchFetch(
`/api/1.0/relations/relationship/${id}.json`,
{
type: 'relationship',
fromPerson: { type: 'person', id: splitId(relationship.from, 'id') },
toPerson: { type: 'person', id: splitId(relationship.to, 'id') },
relation: { type: 'relation', id: relationship.relation.id },
reverse: relationship.reverse
}
)
}
//console.log(relationship)
let linkType = splitId(relationship.id, "link");
let id = splitId(linkType, "id");
return patchFetch(`/api/1.0/relations/relationship/${id}.json`, {
type: "relationship",
fromPerson: { type: "person", id: splitId(relationship.from, "id") },
toPerson: { type: "person", id: splitId(relationship.to, "id") },
relation: { type: "relation", id: relationship.relation.id },
reverse: relationship.reverse,
});
};
/**
* @function deleteRelationship
@@ -127,20 +120,18 @@ const patchRelationship = (relationship) => {
* @returns {Promise<Response>}
*/
const deleteRelationship = (relationship) => {
//console.log(relationship)
let linkType = splitId(relationship.id, 'link')
let id = splitId(linkType, 'id')
return deleteFetch(
`/api/1.0/relations/relationship/${id}.json`
)
}
//console.log(relationship)
let linkType = splitId(relationship.id, "link");
let id = splitId(linkType, "id");
return deleteFetch(`/api/1.0/relations/relationship/${id}.json`);
};
export {
getHouseholdByPerson,
getCoursesByPerson,
getRelationshipsByPerson,
getRelationsList,
postRelationship,
patchRelationship,
deleteRelationship
}
getHouseholdByPerson,
getCoursesByPerson,
getRelationshipsByPerson,
getRelationsList,
postRelationship,
patchRelationship,
deleteRelationship,
};

View File

@@ -1,6 +1,6 @@
export const lightGreen = '#43b29d';
export const darkGreen = '#368e7e';
export const lightBrown = '#a2ac80';
export const darkBrown = '#929d69';
export const lightBlue = '#8d9dab';
export const darkBlue = '#718596';
export const lightGreen = "#43b29d";
export const darkGreen = "#368e7e";
export const lightBrown = "#a2ac80";
export const darkBrown = "#929d69";
export const lightBlue = "#8d9dab";
export const darkBlue = "#718596";

View File

@@ -1,103 +1,106 @@
const visMessages = {
fr: {
add_persons: {
title: "Ajouter des usagers",
suggested_counter: "Pas de résultats | 1 résultat | {count} résultats",
selected_counter: " 1 sélectionné | {count} sélectionnés",
search_some_persons: "Rechercher des personnes..",
},
visgraph: {
Course: 'Parcours',
Household: 'Ménage',
Holder: 'Titulaire',
Legend: 'Calques',
concerned: 'concerné',
years: 'ans',
click_to_expand: 'cliquez pour étendre',
add_relationship_link: "Créer un lien de filiation",
edit_relationship_link: "Modifier le lien de filiation",
delete_relationship_link: "Êtes-vous sûr ?",
delete_confirmation_text: "Vous allez supprimer le lien entre ces 2 usagers.",
reverse_relation: "Inverser la relation",
relation_from_to_like: "{2} de {1}", // disable {0}
between: "entre",
and: "et",
add_link: "Créer un lien de filiation",
add_person: "Ajouter une personne",
create_link_help: "Pour créer un lien de filiation, cliquez d'abord sur un usager, puis sur un second ; précisez ensuite la nature du lien dans le formulaire d'édition.",
refresh: "Rafraîchir",
screenshot: "Prendre une photo",
choose_relation: "Choisissez le lien de parenté",
relationship_household: "Filiation du ménage",
},
item: {
type_person: "Usager",
type_user: "TMS",
type_thirdparty: "Tiers professionnel",
type_household: "Ménage"
},
person: {
firstname: "Prénom",
lastname: "Nom",
born: (ctx) => {
if (ctx.gender === 'man') {
return 'Né le';
} else if (ctx.gender === 'woman') {
return 'Née le';
} else {
return 'Né·e le';
}
},
center_id: "Identifiant du centre",
center_type: "Type de centre",
center_name: "Territoire", // vendée
phonenumber: "Téléphone",
mobilenumber: "Mobile",
altnames: "Autres noms",
email: "Courriel",
gender: {
title: "Genre",
placeholder: "Choisissez le genre de l'usager",
woman: "Féminin",
man: "Masculin",
neutral: "Neutre, non binaire",
undefined: "Non renseigné",
unknown: "Non renseigné"
}
},
error_only_one_person: "Une seule personne peut être sélectionnée !",
edit: 'Éditer',
del: 'Supprimer',
back: 'Revenir en arrière',
addNode: 'Ajouter un noeuds',
addEdge: 'Ajouter un lien de filiation',
editNode: 'Éditer le noeuds',
editEdge: 'Éditer le lien',
addDescription: 'Cliquez dans un espace vide pour créer un nouveau nœud.',
edgeDescription: 'Cliquez sur un usager et faites glisser le lien vers un autre usager pour les connecter.',
editEdgeDescription: 'Cliquez sur les points de contrôle et faites-les glisser vers un nœud pour les relier.',
createEdgeError: 'Il est impossible de relier des arêtes à un cluster.',
deleteClusterError: 'Les clusters ne peuvent pas être supprimés.',
editClusterError: 'Les clusters ne peuvent pas être modifiés.'
fr: {
add_persons: {
title: "Ajouter des usagers",
suggested_counter: "Pas de résultats | 1 résultat | {count} résultats",
selected_counter: " 1 sélectionné | {count} sélectionnés",
search_some_persons: "Rechercher des personnes..",
},
en: {
edit: 'Edit',
del: 'Delete selected',
back: 'Back',
addNode: 'Add Node',
addEdge: 'Add Link',
editNode: 'Edit Switch',
editEdge: 'Edit Link',
addDescription: 'Click in an empty space to place a new node.',
edgeDescription: 'Click on a node and drag the link to another node to connect them.',
editEdgeDescription: 'Click on the control points and drag them to a node to connect to it.',
createEdgeError: 'Cannot link edges to a cluster.',
deleteClusterError: 'Clusters cannot be deleted.',
editClusterError: 'Clusters cannot be edited.'
visgraph: {
Course: "Parcours",
Household: "Ménage",
Holder: "Titulaire",
Legend: "Calques",
concerned: "concerné",
years: "ans",
click_to_expand: "cliquez pour étendre",
add_relationship_link: "Créer un lien de filiation",
edit_relationship_link: "Modifier le lien de filiation",
delete_relationship_link: "Êtes-vous sûr ?",
delete_confirmation_text:
"Vous allez supprimer le lien entre ces 2 usagers.",
reverse_relation: "Inverser la relation",
relation_from_to_like: "{2} de {1}", // disable {0}
between: "entre",
and: "et",
add_link: "Créer un lien de filiation",
add_person: "Ajouter une personne",
create_link_help:
"Pour créer un lien de filiation, cliquez d'abord sur un usager, puis sur un second ; précisez ensuite la nature du lien dans le formulaire d'édition.",
refresh: "Rafraîchir",
screenshot: "Prendre une photo",
choose_relation: "Choisissez le lien de parenté",
relationship_household: "Filiation du ménage",
},
item: {
type_person: "Usager",
type_user: "TMS",
type_thirdparty: "Tiers professionnel",
type_household: "Ménage",
},
person: {
firstname: "Prénom",
lastname: "Nom",
born: (ctx) => {
if (ctx.gender === "man") {
return "Né le";
} else if (ctx.gender === "woman") {
return "Née le";
} else {
return "Né·e le";
}
},
center_id: "Identifiant du centre",
center_type: "Type de centre",
center_name: "Territoire", // vendée
phonenumber: "Téléphone",
mobilenumber: "Mobile",
altnames: "Autres noms",
email: "Courriel",
gender: {
title: "Genre",
placeholder: "Choisissez le genre de l'usager",
woman: "Féminin",
man: "Masculin",
neutral: "Neutre, non binaire",
undefined: "Non renseigné",
unknown: "Non renseigné",
},
},
error_only_one_person: "Une seule personne peut être sélectionnée !",
edit: "Éditer",
del: "Supprimer",
back: "Revenir en arrière",
addNode: "Ajouter un noeuds",
addEdge: "Ajouter un lien de filiation",
editNode: "Éditer le noeuds",
editEdge: "Éditer le lien",
addDescription: "Cliquez dans un espace vide pour créer un nouveau nœud.",
edgeDescription:
"Cliquez sur un usager et faites glisser le lien vers un autre usager pour les connecter.",
editEdgeDescription:
"Cliquez sur les points de contrôle et faites-les glisser vers un nœud pour les relier.",
createEdgeError: "Il est impossible de relier des arêtes à un cluster.",
deleteClusterError: "Les clusters ne peuvent pas être supprimés.",
editClusterError: "Les clusters ne peuvent pas être modifiés.",
},
en: {
edit: "Edit",
del: "Delete selected",
back: "Back",
addNode: "Add Node",
addEdge: "Add Link",
editNode: "Edit Switch",
editEdge: "Edit Link",
addDescription: "Click in an empty space to place a new node.",
edgeDescription:
"Click on a node and drag the link to another node to connect them.",
editEdgeDescription:
"Click on the control points and drag them to a node to connect to it.",
createEdgeError: "Cannot link edges to a cluster.",
deleteClusterError: "Clusters cannot be deleted.",
editClusterError: "Clusters cannot be edited.",
},
};
}
}
export {
visMessages
}
export { visMessages };

View File

@@ -1,37 +1,37 @@
import { createApp } from "vue"
import { store } from "./store.js"
import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n'
import { visMessages } from './i18n'
import App from './App.vue'
import 'vue-toast-notification/dist/theme-sugar.css';
import './vis-network';
import { createApp } from "vue";
import { store } from "./store.js";
import { _createI18n } from "ChillMainAssets/vuejs/_js/i18n";
import { visMessages } from "./i18n";
import App from "./App.vue";
import "vue-toast-notification/dist/theme-sugar.css";
import "./vis-network";
import ToastPlugin from "vue-toast-notification";
const i18n = _createI18n(visMessages)
const container = document.getElementById('relationship-graph')
const persons = JSON.parse(container.dataset.persons)
const i18n = _createI18n(visMessages);
const container = document.getElementById("relationship-graph");
const persons = JSON.parse(container.dataset.persons);
persons.forEach(person => {
store.dispatch('addPerson', person)
store.commit('markInWhitelist', person)
})
persons.forEach((person) => {
store.dispatch("addPerson", person);
store.commit("markInWhitelist", person);
});
/* exported app */
const app = createApp({
template: `<app :household_id="this.household_id"></app>`,
data() {
return {
household_id: JSON.parse(container.dataset.householdId)
}
}
template: `<app :household_id="this.household_id"></app>`,
data() {
return {
household_id: JSON.parse(container.dataset.householdId),
};
},
})
.use(store)
.use(i18n)
.use(ToastPlugin, {
.use(store)
.use(i18n)
.use(ToastPlugin, {
position: "bottom-right",
type: "error",
duration: 5000,
dismissible: true
})
.component('app', App)
.mount('#relationship-graph')
dismissible: true,
})
.component("app", App)
.mount("#relationship-graph");

View File

@@ -1,5 +1,5 @@
import { darkGreen, lightBlue, lightBrown, lightGreen } from './colors';
import { visMessages } from './i18n';
import { darkGreen, lightBlue, lightBrown, lightGreen } from "./colors";
import { visMessages } from "./i18n";
/**
* Vis-network initial data/configuration script
@@ -8,138 +8,138 @@ import { visMessages } from './i18n';
* cfr. https://github.com/almende/vis/issues/2524#issuecomment-307108271
*/
window.network = {}
window.network = {};
window.options = {
locale: 'fr',
locales: visMessages,
/*
*/
configure: {
enabled: false,
filter: 'physics',
showButton: true
locale: "fr",
locales: visMessages,
/*
*/
configure: {
enabled: false,
filter: "physics",
showButton: true,
},
physics: {
enabled: false,
barnesHut: {
theta: 0.5,
gravitationalConstant: -2000,
centralGravity: 0.08, //// 0.3
springLength: 220, //// 95
springConstant: 0.04,
damping: 0.09,
avoidOverlap: 0,
},
physics: {
enabled: false,
barnesHut: {
theta: 0.5,
gravitationalConstant: -2000,
centralGravity: 0.08, //// 0.3
springLength: 220, //// 95
springConstant: 0.04,
damping: 0.09,
avoidOverlap: 0
},
forceAtlas2Based: {
theta: 0.5,
gravitationalConstant: -50,
centralGravity: 0.01,
springLength: 100,
springConstant: 0.08,
damping: 0.75,
avoidOverlap: 0.00
},
repulsion: {
centralGravity: 0.2,
springLength: 200,
springConstant: 0.05,
nodeDistance: 100,
damping: 0.09
},
hierarchicalRepulsion: {
centralGravity: 0.0,
springLength: 100,
springConstant: 0.01,
nodeDistance: 120,
damping: 0.09,
avoidOverlap: 0
},
maxVelocity: 50,
minVelocity: 0.1,
solver: 'forceAtlas2Based', //'barnesHut', //
stabilization: {
enabled: true,
iterations: 1000,
updateInterval: 100,
onlyDynamicEdges: false,
fit: true
},
timestep: 0.5,
adaptiveTimestep: true,
wind: { x: 0, y: 0 }
forceAtlas2Based: {
theta: 0.5,
gravitationalConstant: -50,
centralGravity: 0.01,
springLength: 100,
springConstant: 0.08,
damping: 0.75,
avoidOverlap: 0.0,
},
interaction: {
hover: true,
multiselect: true,
navigationButtons: false,
repulsion: {
centralGravity: 0.2,
springLength: 200,
springConstant: 0.05,
nodeDistance: 100,
damping: 0.09,
},
manipulation: {
enabled: false,
initiallyActive: false,
addNode: false,
deleteNode: false
hierarchicalRepulsion: {
centralGravity: 0.0,
springLength: 100,
springConstant: 0.01,
nodeDistance: 120,
damping: 0.09,
avoidOverlap: 0,
},
nodes: {
borderWidth: 1,
borderWidthSelected: 3,
font: {
multi: 'md'
}
maxVelocity: 50,
minVelocity: 0.1,
solver: "forceAtlas2Based", //'barnesHut', //
stabilization: {
enabled: true,
iterations: 1000,
updateInterval: 100,
onlyDynamicEdges: false,
fit: true,
},
edges: {
font: {
color: '#b0b0b0',
size: 14,
face: 'arial',
background: 'none',
strokeWidth: 2, // px
strokeColor: '#ffffff',
align: 'middle',
multi: false,
vadjust: 0,
},
scaling:{
label: true,
},
smooth: true,
timestep: 0.5,
adaptiveTimestep: true,
wind: { x: 0, y: 0 },
},
interaction: {
hover: true,
multiselect: true,
navigationButtons: false,
},
manipulation: {
enabled: false,
initiallyActive: false,
addNode: false,
deleteNode: false,
},
nodes: {
borderWidth: 1,
borderWidthSelected: 3,
font: {
multi: "md",
},
groups: {
person: {
shape: 'box',
shapeProperties: {
borderDashes: false,
borderRadius: 3,
},
color: {
border: '#b0b0b0',
background: lightGreen,
highlight: {
border: '#216458',
background: darkGreen,
},
hover: {
border: '#216458',
background: darkGreen,
}
},
opacity: 0.9,
shadow:{
enabled: true,
color: 'rgba(0,0,0,0.5)',
size:10,
x:5,
y:5,
},
},
edges: {
font: {
color: "#b0b0b0",
size: 14,
face: "arial",
background: "none",
strokeWidth: 2, // px
strokeColor: "#ffffff",
align: "middle",
multi: false,
vadjust: 0,
},
scaling: {
label: true,
},
smooth: true,
},
groups: {
person: {
shape: "box",
shapeProperties: {
borderDashes: false,
borderRadius: 3,
},
color: {
border: "#b0b0b0",
background: lightGreen,
highlight: {
border: "#216458",
background: darkGreen,
},
household: {
color: lightBrown,
hover: {
border: "#216458",
background: darkGreen,
},
accompanying_period: {
color: lightBlue,
},
}
}
},
opacity: 0.9,
shadow: {
enabled: true,
color: "rgba(0,0,0,0.5)",
size: 10,
x: 5,
y: 5,
},
},
household: {
color: lightBrown,
},
accompanying_period: {
color: lightBlue,
},
},
};
/**
* TODO only one abstract function (-> getAge() is repeated in PersonRenderBox.vue)
@@ -147,11 +147,11 @@ window.options = {
* @returns {string|null}
*/
const getAge = (person) => {
if (person.age) {
return person.age + ' ' + visMessages.fr.visgraph.years;
}
return ''
}
if (person.age) {
return person.age + " " + visMessages.fr.visgraph.years;
}
return "";
};
/**
* Return member position in household
@@ -159,10 +159,10 @@ const getAge = (person) => {
* @returns string
*/
const getHouseholdLabel = (member) => {
let position = member.position.label.fr
let holder = member.holder ? ` ${visMessages.fr.visgraph.Holder}` : ''
return position + holder
}
let position = member.position.label.fr;
let holder = member.holder ? ` ${visMessages.fr.visgraph.Holder}` : "";
return position + holder;
};
/**
* Return edge width for member (depends of position in household)
@@ -170,14 +170,14 @@ const getHouseholdLabel = (member) => {
* @returns integer (width)
*/
const getHouseholdWidth = (member) => {
if (member.holder) {
return 5
}
if (member.shareHousehold) {
return 2
}
return 1
}
if (member.holder) {
return 5;
}
if (member.shareHousehold) {
return 2;
}
return 1;
};
/**
* Return direction edge
@@ -185,8 +185,8 @@ const getHouseholdWidth = (member) => {
* @returns string
*/
const getRelationshipDirection = (relationship) => {
return (!relationship.reverse) ? 'to' : 'from'
}
return !relationship.reverse ? "to" : "from";
};
/**
* Return label edge
@@ -195,8 +195,8 @@ const getRelationshipDirection = (relationship) => {
* @returns string
*/
const getRelationshipLabel = (relationship) => {
return relationship.relation.title.fr
}
return relationship.relation.title.fr;
};
/**
* Return title edge
@@ -204,10 +204,22 @@ const getRelationshipLabel = (relationship) => {
* @returns string
*/
const getRelationshipTitle = (relationship) => {
return (!relationship.reverse) ?
relationship.relation.title.fr + ': ' + relationship.fromPerson.text + '\n' + relationship.relation.reverseTitle.fr + ': ' + relationship.toPerson.text :
relationship.relation.title.fr + ': ' + relationship.toPerson.text + '\n' + relationship.relation.reverseTitle.fr + ': ' + relationship.fromPerson.text
}
return !relationship.reverse
? relationship.relation.title.fr +
": " +
relationship.fromPerson.text +
"\n" +
relationship.relation.reverseTitle.fr +
": " +
relationship.toPerson.text
: relationship.relation.title.fr +
": " +
relationship.toPerson.text +
"\n" +
relationship.relation.reverseTitle.fr +
": " +
relationship.fromPerson.text;
};
/**
* Split string id and return type|id substring
@@ -216,27 +228,25 @@ const getRelationshipTitle = (relationship) => {
* @returns string|integer
*/
const splitId = (id, position) => {
//console.log(id, position)
switch (position) {
case 'type': // return 'accompanying_period'
return /(.+)_/.exec(id)[1]
case 'id': // return 124
return parseInt(id.toString()
.split("_")
.pop())
case 'link':
return id.split("-")[0] // return first segment
default:
throw 'position undefined'
}
}
//console.log(id, position)
switch (position) {
case "type": // return 'accompanying_period'
return /(.+)_/.exec(id)[1];
case "id": // return 124
return parseInt(id.toString().split("_").pop());
case "link":
return id.split("-")[0]; // return first segment
default:
throw "position undefined";
}
};
export {
getAge,
getHouseholdLabel,
getHouseholdWidth,
getRelationshipDirection,
getRelationshipLabel,
getRelationshipTitle,
splitId
}
getAge,
getHouseholdLabel,
getHouseholdWidth,
getRelationshipDirection,
getRelationshipLabel,
getRelationshipTitle,
splitId,
};

View File

@@ -1,51 +1,51 @@
/*
* Endpoint chill_api_single_person_address
* method POST, post Person instance
*
* @id integer - id of Person
* @body Object - dictionary with changes to post
*/
* Endpoint chill_api_single_person_address
* method POST, post Person instance
*
* @id integer - id of Person
* @body Object - dictionary with changes to post
*/
const postAddressToPerson = (personId, addressId) => {
//console.log(personId);
//console.log(addressId);
const body = {
'id': addressId
};
const url = `/api/1.0/person/person/${personId}/address.json`
return fetch(url, {
method: 'POST',
headers: {'Content-Type': 'application/json;charset=utf-8'},
body: JSON.stringify(body)
})
.then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});
//console.log(personId);
//console.log(addressId);
const body = {
id: addressId,
};
const url = `/api/1.0/person/person/${personId}/address.json`;
return fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json;charset=utf-8" },
body: JSON.stringify(body),
}).then((response) => {
if (response.ok) {
return response.json();
}
throw Error("Error with request resource response");
});
};
/*
* Endpoint household
* method POST, post Household instance
*
* @id integer - id of household
* @body Object - dictionary with changes to post
*/
* Endpoint household
* method POST, post Household instance
*
* @id integer - id of household
* @body Object - dictionary with changes to post
*/
const postAddressToHousehold = (householdId, addressId) => {
const body = {
'id': addressId
};
const url = `/api/1.0/person/household/${householdId}/address.json`
return fetch(url, {
method: 'POST',
headers: {'Content-Type': 'application/json;charset=utf-8'},
body: JSON.stringify(body)
})
.then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});
const body = {
id: addressId,
};
const url = `/api/1.0/person/household/${householdId}/address.json`;
return fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json;charset=utf-8" },
body: JSON.stringify(body),
}).then((response) => {
if (response.ok) {
return response.json();
}
throw Error("Error with request resource response");
});
};
export { postAddressToPerson, postAddressToHousehold };

View File

@@ -1,56 +1,57 @@
/*
* Build query string with query and options
*/
* Build query string with query and options
*/
const parametersToString = ({ query, options }) => {
let types ='';
options.type.forEach(function(type) {
types += '&type[]=' + type;
});
return 'q=' + query + types;
let types = "";
options.type.forEach(function (type) {
types += "&type[]=" + type;
});
return "q=" + query + types;
};
/*
* Endpoint chill_person_search
* method GET, get a list of persons
*
* @query string - the query to search for
* @deprecated
*/
const searchPersons = ({ query, options }, signal) => {
console.err('deprecated');
let queryStr = parametersToString({ query, options });
let url = `/fr/search.json?name=person_regular&${queryStr}`;
let fetchOpts = {
method: 'GET',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
signal,
};
* Endpoint chill_person_search
* method GET, get a list of persons
*
* @query string - the query to search for
* @deprecated
*/
const searchPersons = ({ query, options }, signal) => {
console.err("deprecated");
let queryStr = parametersToString({ query, options });
let url = `/fr/search.json?name=person_regular&${queryStr}`;
let fetchOpts = {
method: "GET",
headers: {
"Content-Type": "application/json;charset=utf-8",
},
signal,
};
return fetch(url, fetchOpts)
.then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});
return fetch(url, fetchOpts).then((response) => {
if (response.ok) {
return response.json();
}
throw Error("Error with request resource response");
});
};
/*
* Endpoint v.2 chill_main_search_global
* method GET, get a list of persons and thirdparty
*
* @param query string - the query to search for
*
*/
const searchEntities = ({ query, options }, signal) => {
let queryStr = parametersToString({ query, options });
let url = `/api/1.0/search.json?${queryStr}`;
return fetch(url, { signal })
.then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});
* Endpoint v.2 chill_main_search_global
* method GET, get a list of persons and thirdparty
*
* @param query string - the query to search for
*
*/
const searchEntities = ({ query, options }, signal) => {
let queryStr = parametersToString({ query, options });
let url = `/api/1.0/search.json?${queryStr}`;
return fetch(url, { signal }).then((response) => {
if (response.ok) {
return response.json();
}
throw Error("Error with request resource response");
});
};
export { searchPersons, searchEntities };

View File

@@ -1,80 +1,88 @@
import {makeFetch} from 'ChillMainAssets/lib/api/apiMethods';
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
/*
* GET a person by id
*/
* GET a person by id
*/
const getPerson = (id) => {
const url = `/api/1.0/person/person/${id}.json`;
return fetch(url)
.then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});
const url = `/api/1.0/person/person/${id}.json`;
return fetch(url).then((response) => {
if (response.ok) {
return response.json();
}
throw Error("Error with request resource response");
});
};
const getPersonAltNames = () =>
fetch('/api/1.0/person/config/alt_names.json').then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});
fetch("/api/1.0/person/config/alt_names.json").then((response) => {
if (response.ok) {
return response.json();
}
throw Error("Error with request resource response");
});
const getCivilities = () =>
fetch('/api/1.0/main/civility.json').then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});
fetch("/api/1.0/main/civility.json").then((response) => {
if (response.ok) {
return response.json();
}
throw Error("Error with request resource response");
});
const getGenders = () => makeFetch("GET", '/api/1.0/main/gender.json')
// .then(response => {
// console.log(response)
// if (response.ok) { return response.json(); }
// throw Error('Error with request resource response');
// });
const getGenders = () => makeFetch("GET", "/api/1.0/main/gender.json");
// .then(response => {
// console.log(response)
// if (response.ok) { return response.json(); }
// throw Error('Error with request resource response');
// });
const getCentersForPersonCreation = () => makeFetch('GET', '/api/1.0/person/creation/authorized-centers', null);
const getCentersForPersonCreation = () =>
makeFetch("GET", "/api/1.0/person/creation/authorized-centers", null);
/*
* POST a new person
*/
* POST a new person
*/
const postPerson = (body) => {
const url = `/api/1.0/person/person.json`;
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify(body)
})
.then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});
const url = `/api/1.0/person/person.json`;
return fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8",
},
body: JSON.stringify(body),
}).then((response) => {
if (response.ok) {
return response.json();
}
throw Error("Error with request resource response");
});
};
/*
* PATCH an existing person
*/
* PATCH an existing person
*/
const patchPerson = (id, body) => {
const url = `/api/1.0/person/person/${id}.json`;
return fetch(url, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify(body)
})
.then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});
const url = `/api/1.0/person/person/${id}.json`;
return fetch(url, {
method: "PATCH",
headers: {
"Content-Type": "application/json;charset=utf-8",
},
body: JSON.stringify(body),
}).then((response) => {
if (response.ok) {
return response.json();
}
throw Error("Error with request resource response");
});
};
export {
getCentersForPersonCreation,
getPerson,
getPersonAltNames,
getCivilities,
getGenders,
postPerson,
patchPerson
getCentersForPersonCreation,
getPerson,
getPersonAltNames,
getCivilities,
getGenders,
postPerson,
patchPerson,
};

View File

@@ -1,21 +1,21 @@
const findSocialActionsBySocialIssue = (id) => {
const url = `/api/1.0/person/social/social-action/by-social-issue/${id}.json`;
return fetch(url)
.then(response => {
.then((response) => {
if (!response.ok) {
throw new Error("Error while retrieving social actions " + response.status
+ " " + response.statusText);
throw new Error(
"Error while retrieving social actions " +
response.status +
" " +
response.statusText,
);
}
return response.json();
})
.catch(err => {
throw err
})
;
.catch((err) => {
throw err;
});
};
export {
findSocialActionsBySocialIssue
};
export { findSocialActionsBySocialIssue };

View File

@@ -1,60 +1,53 @@
<template>
<ul
class="list-suggest add-items"
v-if="suggested.length > 0"
>
<li
v-for="(r, i) in suggested"
@click="setReferrer(r)"
:key="i"
>
<ul class="list-suggest add-items" v-if="suggested.length > 0">
<li v-for="(r, i) in suggested" @click="setReferrer(r)" :key="i">
<span>{{ r.text }}</span>
</li>
</ul>
</template>
<script>
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods.ts';
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods.ts";
export default {
name: "SetReferrer",
props: {
suggested: {
suggested: {
type: Array,
required: false,
//default: [],
},
periodId: {
type: Number,
required: true
}
required: true,
},
},
data() {
return {
/*suggested: [
{id: 5, text: 'Robert'}, {id: 8, text: 'Monique'},
]*/
}
};
},
emits: ['referrerSet'],
emits: ["referrerSet"],
methods: {
setReferrer: function(ref) {
setReferrer: function (ref) {
const url = `/api/1.0/person/accompanying-course/${this.periodId}.json`;
const body = { type: "accompanying_period", user: { id: ref.id, type: ref.type }};
const body = {
type: "accompanying_period",
user: { id: ref.id, type: ref.type },
};
return makeFetch('PATCH', url, body)
.then((response) => {
this.$emit('referrerSet', ref);
})
.catch((error) => {
throw error;
})
}
}
}
return makeFetch("PATCH", url, body)
.then((response) => {
this.$emit("referrerSet", ref);
})
.catch((error) => {
throw error;
});
},
},
};
</script>
<style scoped>
</style>
<style scoped></style>

View File

@@ -5,7 +5,7 @@
:title="$t(buttonTitle || '')"
@click="openModal"
>
<span v-if="displayTextButton">{{ $t(buttonTitle || '') }}</span>
<span v-if="displayTextButton">{{ $t(buttonTitle || "") }}</span>
</a>
<teleport to="body">
@@ -23,11 +23,8 @@
<template #body-head>
<div class="modal-body">
<div class="search">
<label
class="col-form-label"
style="float: right;"
>
{{ $tc('add_persons.suggested_counter', suggestedCounter) }}
<label class="col-form-label" style="float: right">
{{ $tc("add_persons.suggested_counter", suggestedCounter) }}
</label>
<input
@@ -36,7 +33,7 @@
v-model="query"
:placeholder="$t('add_persons.search_some_persons')"
ref="search"
>
/>
<i class="fa fa-search fa-lg" />
<i
class="fa fa-times"
@@ -45,28 +42,19 @@
/>
</div>
</div>
<div
class="modal-body"
v-if="checkUniq === 'checkbox'"
>
<div class="modal-body" v-if="checkUniq === 'checkbox'">
<div class="count">
<span>
<a
v-if="suggestedCounter > 2"
@click="selectAll"
>
{{ $t('action.check_all') }}
<a v-if="suggestedCounter > 2" @click="selectAll">
{{ $t("action.check_all") }}
</a>
<a
v-if="selectedCounter > 0"
@click="resetSelection"
>
<a v-if="selectedCounter > 0" @click="resetSelection">
<i v-if="suggestedCounter > 2"> </i>
{{ $t('action.reset') }}
{{ $t("action.reset") }}
</a>
</span>
<span v-if="selectedCounter > 0">
{{ $tc('add_persons.selected_counter', selectedCounter) }}
{{ $tc("add_persons.selected_counter", selectedCounter) }}
</span>
</div>
</div>
@@ -87,8 +75,12 @@
<div class="create-button">
<on-the-fly
v-if="queryLength >= 3 && (options.type.includes('person') || options.type.includes('thirdparty'))"
:button-text="$t('onthefly.create.button', {q: query})"
v-if="
queryLength >= 3 &&
(options.type.includes('person') ||
options.type.includes('thirdparty'))
"
:button-text="$t('onthefly.create.button', { q: query })"
:allowed-types="options.type"
:query="query"
action="create"
@@ -104,7 +96,7 @@
class="btn btn-create"
@click.prevent="$emit('addNewPersons', { selected, modal })"
>
{{ $t('action.add') }}
{{ $t("action.add") }}
</button>
</template>
</modal>
@@ -112,347 +104,372 @@
</template>
<script>
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
import OnTheFly from 'ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue';
import PersonSuggestion from './AddPersons/PersonSuggestion';
import { searchEntities } from 'ChillPersonAssets/vuejs/_api/AddPersons';
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods';
import Modal from "ChillMainAssets/vuejs/_components/Modal";
import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue";
import PersonSuggestion from "./AddPersons/PersonSuggestion";
import { searchEntities } from "ChillPersonAssets/vuejs/_api/AddPersons";
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
export default {
name: 'AddPersons',
components: {
Modal,
PersonSuggestion,
OnTheFly
},
props: [
'buttonTitle',
'modalTitle',
'options'
],
emits: ['addNewPersons'],
data() {
return {
modal: {
showModal: false,
modalDialogClass: "modal-dialog-scrollable modal-xl"
},
search: {
query: "",
previousQuery: "",
currentSearchQueryController: null,
suggested: [],
selected: [],
priorSuggestion: {}
},
name: "AddPersons",
components: {
Modal,
PersonSuggestion,
OnTheFly,
},
props: ["buttonTitle", "modalTitle", "options"],
emits: ["addNewPersons"],
data() {
return {
modal: {
showModal: false,
modalDialogClass: "modal-dialog-scrollable modal-xl",
},
search: {
query: "",
previousQuery: "",
currentSearchQueryController: null,
suggested: [],
selected: [],
priorSuggestion: {},
},
};
},
computed: {
query: {
set(query) {
return this.setQuery(query);
},
get() {
return this.search.query;
},
},
queryLength() {
return this.search.query.length;
},
suggested() {
return this.search.suggested;
},
suggestedCounter() {
return this.search.suggested.length;
},
selected() {
return this.search.selected;
},
selectedCounter() {
return this.search.selected.length;
},
selectedAndSuggested() {
this.addPriorSuggestion();
const uniqBy = (a, key) => [
...new Map(a.map((x) => [key(x), x])).values(),
];
let union = [
...new Set([
...this.suggested.slice().reverse(),
...this.selected.slice().reverse(),
]),
];
return uniqBy(union, (k) => k.key);
},
getClassButton() {
let size =
typeof this.options.button !== "undefined" &&
typeof this.options.button.size !== "undefined"
? this.options.button.size
: "";
let type =
typeof this.options.button !== "undefined" &&
typeof this.options.button.type !== "undefined"
? this.options.button.type
: "btn-create";
return size ? size + " " + type : type;
},
displayTextButton() {
return typeof this.options.button !== "undefined" &&
typeof this.options.button.display !== "undefined"
? this.options.button.display
: true;
},
checkUniq() {
if (this.options.uniq === true) {
return "radio";
}
},
computed: {
query: {
set(query) {
return this.setQuery(query);
},
get() {
return this.search.query;
}
},
queryLength() {
return this.search.query.length;
},
suggested() {
return this.search.suggested;
},
suggestedCounter() {
return this.search.suggested.length;
},
selected() {
return this.search.selected;
},
selectedCounter() {
return this.search.selected.length;
},
selectedAndSuggested() {
this.addPriorSuggestion();
const uniqBy = (a, key) => [
...new Map(
a.map(x => [key(x), x])
).values()
];
let union = [...new Set([
...this.suggested.slice().reverse(),
...this.selected.slice().reverse(),
])];
return uniqBy(union, k => k.key);
},
getClassButton() {
let size = (typeof this.options.button !== 'undefined' && typeof this.options.button.size !== 'undefined') ? this.options.button.size : '';
let type = (typeof this.options.button !== 'undefined' && typeof this.options.button.type !== 'undefined') ? this.options.button.type : 'btn-create';
return size ? size + ' ' + type : type;
},
displayTextButton() {
return (typeof this.options.button !== 'undefined' && typeof this.options.button.display !== 'undefined') ?
this.options.button.display : true;
},
checkUniq() {
if (this.options.uniq === true) {
return 'radio';
}
return 'checkbox';
},
priorSuggestion() {
return this.search.priorSuggestion;
},
hasPriorSuggestion() {
return this.search.priorSuggestion.key ? true : false;
},
},
methods: {
openModal() {
this.modal.showModal = true;
this.$nextTick(function() {
this.$refs.search.focus();
})
},
setQuery(query) {
this.search.query = query;
return "checkbox";
},
priorSuggestion() {
return this.search.priorSuggestion;
},
hasPriorSuggestion() {
return this.search.priorSuggestion.key ? true : false;
},
},
methods: {
openModal() {
this.modal.showModal = true;
this.$nextTick(function () {
this.$refs.search.focus();
});
},
setQuery(query) {
this.search.query = query;
setTimeout(function() {
if (query === "") {
this.loadSuggestions([]);
return;
setTimeout(
function () {
if (query === "") {
this.loadSuggestions([]);
return;
}
if (query === this.search.query) {
if (this.search.currentSearchQueryController !== null) {
this.search.currentSearchQueryController.abort();
}
if (query === this.search.query) {
if (this.search.currentSearchQueryController !== null) {
this.search.currentSearchQueryController.abort();
}
this.search.currentSearchQueryController = new AbortController();
searchEntities({ query, options: this.options }, this.search.currentSearchQueryController.signal)
.then(suggested => new Promise((resolve) => {
this.loadSuggestions(suggested.results);
resolve();
}))
.catch(error => {
if (error instanceof DOMException) {
if (error.name === 'AbortError') {
console.log('request aborted due to user continue typing');
return;
}
}
this.search.currentSearchQueryController = new AbortController();
searchEntities(
{ query, options: this.options },
this.search.currentSearchQueryController.signal,
)
.then(
(suggested) =>
new Promise((resolve) => {
this.loadSuggestions(suggested.results);
resolve();
}),
)
.catch((error) => {
if (error instanceof DOMException) {
if (error.name === "AbortError") {
console.log("request aborted due to user continue typing");
return;
}
}
throw error;
})
;
}
}.bind(this), query.length > 3 ? 300 : 700);
},
loadSuggestions(suggested) {
this.search.suggested = suggested;
this.search.suggested.forEach(function(item) {
item.key = this.itemKey(item);
}, this);
},
updateSelected(value) {
//console.log('value', value);
this.search.selected = value;
},
resetSearch() {
this.resetSelection();
this.resetSuggestion();
},
resetSuggestion() {
this.search.query = "";
this.search.suggested = [];
},
resetSelection() {
this.search.selected = [];
},
selectAll() {
this.search.suggested.forEach(function(item) {
this.search.selected.push(item);
}, this);
},
itemKey(item) {
return item.result.type + item.result.id;
},
addPriorSuggestion() {
// console.log('prior suggestion', this.priorSuggestion);
if (this.hasPriorSuggestion) {
// console.log('addPriorSuggestion',);
this.suggested.unshift(this.priorSuggestion);
this.selected.unshift(this.priorSuggestion);
throw error;
});
}
}.bind(this),
query.length > 3 ? 300 : 700,
);
},
loadSuggestions(suggested) {
this.search.suggested = suggested;
this.search.suggested.forEach(function (item) {
item.key = this.itemKey(item);
}, this);
},
updateSelected(value) {
//console.log('value', value);
this.search.selected = value;
},
resetSearch() {
this.resetSelection();
this.resetSuggestion();
},
resetSuggestion() {
this.search.query = "";
this.search.suggested = [];
},
resetSelection() {
this.search.selected = [];
},
selectAll() {
this.search.suggested.forEach(function (item) {
this.search.selected.push(item);
}, this);
},
itemKey(item) {
return item.result.type + item.result.id;
},
addPriorSuggestion() {
// console.log('prior suggestion', this.priorSuggestion);
if (this.hasPriorSuggestion) {
// console.log('addPriorSuggestion',);
this.suggested.unshift(this.priorSuggestion);
this.selected.unshift(this.priorSuggestion);
this.newPriorSuggestion(null);
}
},
newPriorSuggestion(entity) {
// console.log('newPriorSuggestion', entity);
if (entity !== null) {
let suggestion = {
key: entity.type + entity.id,
relevance: 0.5,
result: entity
}
this.search.priorSuggestion = suggestion;
// console.log('search priorSuggestion', this.search.priorSuggestion);
this.addPriorSuggestion(suggestion);
} else {
this.search.priorSuggestion = {};
}
},
saveFormOnTheFly({ type, data }) {
console.log('saveFormOnTheFly from addPersons, type', type, ', data', data);
if (type === 'person') {
this.newPriorSuggestion(null);
}
},
newPriorSuggestion(entity) {
// console.log('newPriorSuggestion', entity);
if (entity !== null) {
let suggestion = {
key: entity.type + entity.id,
relevance: 0.5,
result: entity,
};
this.search.priorSuggestion = suggestion;
// console.log('search priorSuggestion', this.search.priorSuggestion);
this.addPriorSuggestion(suggestion);
} else {
this.search.priorSuggestion = {};
}
},
saveFormOnTheFly({ type, data }) {
console.log(
"saveFormOnTheFly from addPersons, type",
type,
", data",
data,
);
if (type === "person") {
makeFetch("POST", "/api/1.0/person/person.json", data)
.then((responsePerson) => {
this.newPriorSuggestion(responsePerson);
this.$refs.onTheFly.closeModal();
makeFetch('POST', '/api/1.0/person/person.json', data)
.then(responsePerson => {
this.newPriorSuggestion(responsePerson);
this.$refs.onTheFly.closeModal();
if (null !== data.addressId) {
const household = {
'type': 'household'
};
const address = {
'id': data.addressId
};
makeFetch('POST', '/api/1.0/person/household.json', household)
.then(responseHousehold => {
const member = {
'concerned': [
{
'person': {
'type': 'person',
'id': responsePerson.id
},
'start_date': {
// TODO: use date.ts methods (low priority)
'datetime': `${new Date().toISOString().split('T')[0]}T00:00:00+02:00`
},
'holder': false,
'comment': null
}
],
'destination': {
'type': 'household',
'id': responseHousehold.id
},
'composition': null
};
return makeFetch('POST', '/api/1.0/person/household/members/move.json', member)
.then(_response => {
makeFetch('POST', `/api/1.0/person/household/${responseHousehold.id}/address.json`, address)
.then(_response => {console.log(_response)})
.catch((error) => {
if (error.name === 'ValidationException') {
for (let v of error.violations) {
this.$toast.open({message: v });
}
} else {
this.$toast.open({message: 'An error occurred'});
}
});
})
.catch((error) => {
if (error.name === 'ValidationException') {
for (let v of error.violations) {
this.$toast.open({message: v });
}
} else {
this.$toast.open({message: 'An error occurred'});
}
});
if (null !== data.addressId) {
const household = {
type: "household",
};
const address = {
id: data.addressId,
};
makeFetch("POST", "/api/1.0/person/household.json", household)
.then((responseHousehold) => {
const member = {
concerned: [
{
person: {
type: "person",
id: responsePerson.id,
},
start_date: {
// TODO: use date.ts methods (low priority)
datetime: `${new Date().toISOString().split("T")[0]}T00:00:00+02:00`,
},
holder: false,
comment: null,
},
],
destination: {
type: "household",
id: responseHousehold.id,
},
composition: null,
};
return makeFetch(
"POST",
"/api/1.0/person/household/members/move.json",
member,
)
.then((_response) => {
makeFetch(
"POST",
`/api/1.0/person/household/${responseHousehold.id}/address.json`,
address,
)
.then((_response) => {
console.log(_response);
})
.catch((error) => {
if (error.name === 'ValidationException') {
for (let v of error.violations) {
this.$toast.open({message: v });
}
} else {
this.$toast.open({message: 'An error occurred'});
}
if (error.name === "ValidationException") {
for (let v of error.violations) {
this.$toast.open({ message: v });
}
} else {
this.$toast.open({ message: "An error occurred" });
}
});
}
})
.catch((error) => {
if (error.name === 'ValidationException') {
for (let v of error.violations) {
this.$toast.open({message: v });
}
})
.catch((error) => {
if (error.name === "ValidationException") {
for (let v of error.violations) {
this.$toast.open({ message: v });
}
} else {
this.$toast.open({ message: "An error occurred" });
}
});
})
.catch((error) => {
if (error.name === "ValidationException") {
for (let v of error.violations) {
this.$toast.open({ message: v });
}
} else {
this.$toast.open({message: 'An error occurred'});
this.$toast.open({ message: "An error occurred" });
}
});
}
else if (type === 'thirdparty') {
makeFetch('POST', '/api/1.0/thirdparty/thirdparty.json', data)
.then(response => {
this.newPriorSuggestion(response);
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {
for (let v of error.violations) {
this.$toast.open({message: v });
}
} else {
this.$toast.open({message: 'An error occurred'});
}
})
}
});
}
})
.catch((error) => {
if (error.name === "ValidationException") {
for (let v of error.violations) {
this.$toast.open({ message: v });
}
} else {
this.$toast.open({ message: "An error occurred" });
}
});
} else if (type === "thirdparty") {
makeFetch("POST", "/api/1.0/thirdparty/thirdparty.json", data)
.then((response) => {
this.newPriorSuggestion(response);
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === "ValidationException") {
for (let v of error.violations) {
this.$toast.open({ message: v });
}
} else {
this.$toast.open({ message: "An error occurred" });
}
});
}
},
}
},
},
};
</script>
<style lang="scss">
li.add-persons {
a {
cursor: pointer;
li.add-persons {
a {
cursor: pointer;
}
}
div.body-head {
overflow-y: unset;
div.modal-body:first-child {
margin: auto 4em;
div.search {
position: relative;
input {
width: 100%;
padding: 1.2em 1.5em 1.2em 2.5em;
//margin: 1em 0;
}
}
div.body-head {
overflow-y: unset;
div.modal-body:first-child {
margin: auto 4em;
div.search {
position: relative;
input {
width: 100%;
padding: 1.2em 1.5em 1.2em 2.5em;
//margin: 1em 0;
}
i {
position: absolute;
opacity: 0.5;
padding: 0.65em 0;
top: 50%;
}
i.fa-search {
left: 0.5em;
}
i.fa-times {
right: 1em;
padding: 0.75em 0;
cursor: pointer;
}
}
i {
position: absolute;
opacity: 0.5;
padding: 0.65em 0;
top: 50%;
}
div.modal-body:last-child {
padding-bottom: 0;
i.fa-search {
left: 0.5em;
}
div.count {
margin: -0.5em 0 0.7em;
display: flex;
justify-content: space-between;
a {
cursor: pointer;
}
i.fa-times {
right: 1em;
padding: 0.75em 0;
cursor: pointer;
}
}
.create-button > a {
margin-top: 0.5em;
margin-left: 2.6em;
}
}
}
div.modal-body:last-child {
padding-bottom: 0;
}
div.count {
margin: -0.5em 0 0.7em;
display: flex;
justify-content: space-between;
a {
cursor: pointer;
}
}
}
.create-button > a {
margin-top: 0.5em;
margin-left: 2.6em;
}
</style>

View File

@@ -1,8 +1,5 @@
<template>
<div
class="list-item"
:class="{ checked: isChecked }"
>
<div class="list-item" :class="{ checked: isChecked }">
<label>
<div>
<input
@@ -11,13 +8,10 @@
name="item"
:id="item"
:value="setValueByType(item, type)"
>
/>
</div>
<suggestion-person
v-if="item.result.type === 'person'"
:item="item"
/>
<suggestion-person v-if="item.result.type === 'person'" :item="item" />
<suggestion-third-party
v-if="item.result.type === 'thirdparty'"
@@ -25,10 +19,7 @@
:item="item"
/>
<suggestion-user
v-if="item.result.type === 'user'"
:item="item"
/>
<suggestion-user v-if="item.result.type === 'user'" :item="item" />
<suggestion-household
v-if="item.result.type === 'household'"
@@ -39,90 +30,86 @@
</template>
<script>
import SuggestionPerson from './TypePerson';
import SuggestionThirdParty from './TypeThirdParty';
import SuggestionUser from './TypeUser';
import SuggestionHousehold from './TypeHousehold';
import SuggestionPerson from "./TypePerson";
import SuggestionThirdParty from "./TypeThirdParty";
import SuggestionUser from "./TypeUser";
import SuggestionHousehold from "./TypeHousehold";
export default {
name: 'PersonSuggestion',
components: {
SuggestionPerson,
SuggestionThirdParty,
SuggestionUser,
SuggestionHousehold,
},
props: [
'item',
'search',
'type'
],
emits: ['updateSelected', 'newPriorSuggestion'],
computed: {
selected: {
set(value) {
//console.log('value', value);
this.$emit('updateSelected', value);
},
get() {
return this.search.selected;
}
name: "PersonSuggestion",
components: {
SuggestionPerson,
SuggestionThirdParty,
SuggestionUser,
SuggestionHousehold,
},
props: ["item", "search", "type"],
emits: ["updateSelected", "newPriorSuggestion"],
computed: {
selected: {
set(value) {
//console.log('value', value);
this.$emit("updateSelected", value);
},
isChecked() {
return (this.search.selected.indexOf(this.item) === -1) ? false : true;
get() {
return this.search.selected;
},
},
methods: {
setValueByType(value, type) {
return (type === 'radio')? [value] : value;
},
newPriorSuggestion(response) {
this.$emit('newPriorSuggestion', response)
}
}
},
isChecked() {
return this.search.selected.indexOf(this.item) === -1 ? false : true;
},
},
methods: {
setValueByType(value, type) {
return type === "radio" ? [value] : value;
},
newPriorSuggestion(response) {
this.$emit("newPriorSuggestion", response);
},
},
};
</script>
<style lang="scss">
div.results {
div.list-item {
padding: 0.4em 0.8em;
display: flex;
flex-direction: row;
&.checked {
background-color: #ececec;
border-bottom: 1px dotted #8b8b8b;
}
label {
display: inline-flex;
width: 100%;
div.container:not(.household) {
& > input {
margin-right: 0.8em;
}
> span:not(.name) {
margin-left: 0.5em;
opacity: 0.5;
font-size: 90%;
font-style: italic;
}
}
div.right_actions {
margin: 0 0 0 auto;
display: flex;
align-items: flex-end;
& > * {
margin-left: 0.5em;
align-self: baseline;
}
a.btn {
border: 1px solid lightgrey;
font-size: 70%;
padding: 4px;
}
}
}
div.results {
div.list-item {
padding: 0.4em 0.8em;
display: flex;
flex-direction: row;
&.checked {
background-color: #ececec;
border-bottom: 1px dotted #8b8b8b;
}
label {
display: inline-flex;
width: 100%;
div.container:not(.household) {
& > input {
margin-right: 0.8em;
}
> span:not(.name) {
margin-left: 0.5em;
opacity: 0.5;
font-size: 90%;
font-style: italic;
}
}
}
div.right_actions {
margin: 0 0 0 auto;
display: flex;
align-items: flex-end;
& > * {
margin-left: 0.5em;
align-self: baseline;
}
a.btn {
border: 1px solid lightgrey;
font-size: 70%;
padding: 4px;
}
}
}
}
}
</style>

View File

@@ -7,24 +7,20 @@
</div>
<div class="right_actions">
<badge-entity
:entity="item.result"
:options="{ displayLong: true }"
/>
<badge-entity :entity="item.result" :options="{ displayLong: true }" />
</div>
</template>
<script>
import BadgeEntity from 'ChillMainAssets/vuejs/_components/BadgeEntity.vue';
import HouseholdRenderBox from 'ChillPersonAssets/vuejs/_components/Entity/HouseholdRenderBox.vue';
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
import HouseholdRenderBox from "ChillPersonAssets/vuejs/_components/Entity/HouseholdRenderBox.vue";
export default {
name: 'SuggestionHousehold',
components: {
BadgeEntity,
HouseholdRenderBox,
},
props: ['item'],
}
name: "SuggestionHousehold",
components: {
BadgeEntity,
HouseholdRenderBox,
},
props: ["item"],
};
</script>

View File

@@ -3,54 +3,41 @@
<span class="name">
<person-text :person="item.result" />
</span>
<span
class="birthday"
v-if="hasBirthdate"
>
{{ $d(item.result.birthdate.datetime, 'short') }}
<span class="birthday" v-if="hasBirthdate">
{{ $d(item.result.birthdate.datetime, "short") }}
</span>
<span
class="location"
v-if="hasAddress"
>
<span class="location" v-if="hasAddress">
{{ item.result.current_household_address.text }} -
{{ item.result.current_household_address.postcode.name }}
</span>
</div>
<div class="right_actions">
<badge-entity
:entity="item.result"
:options="{ displayLong: true }"
/>
<on-the-fly
type="person"
:id="item.result.id"
action="show"
/>
<badge-entity :entity="item.result" :options="{ displayLong: true }" />
<on-the-fly type="person" :id="item.result.id" action="show" />
</div>
</template>
<script>
import OnTheFly from 'ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue';
import BadgeEntity from 'ChillMainAssets/vuejs/_components/BadgeEntity.vue';
import PersonText from 'ChillPersonAssets/vuejs/_components/Entity/PersonText.vue';
import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue";
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
export default {
name: 'SuggestionPerson',
components: {
OnTheFly,
BadgeEntity,
PersonText,
},
props: ['item'],
computed: {
hasBirthdate() {
return this.item.result.birthdate !== null;
},
hasAddress() {
return this.item.result.current_household_address !== null;
}
}
}
name: "SuggestionPerson",
components: {
OnTheFly,
BadgeEntity,
PersonText,
},
props: ["item"],
computed: {
hasBirthdate() {
return this.item.result.birthdate !== null;
},
hasAddress() {
return this.item.result.current_household_address !== null;
},
},
};
</script>

View File

@@ -1,13 +1,10 @@
<template>
<div class="container tpartycontainer">
<div class="tparty-identification">
<span
v-if="item.result.profession"
class="profession"
>{{ item.result.profession }}</span>
<span class="name">
{{ item.result.text }}&nbsp;
</span>
<span v-if="item.result.profession" class="profession">{{
item.result.profession
}}</span>
<span class="name"> {{ item.result.text }}&nbsp; </span>
<span class="location">
<template v-if="hasAddress">
{{ getAddress.text }} -
@@ -15,21 +12,13 @@
</template>
</span>
</div>
<div
class="tpartyparent"
v-if="hasParent"
>
<span class="name">
> {{ item.result.parent.text }}
</span>
<div class="tpartyparent" v-if="hasParent">
<span class="name"> > {{ item.result.parent.text }} </span>
</div>
</div>
<div class="right_actions">
<badge-entity
:entity="item.result"
:options="{ displayLong: true }"
/>
<badge-entity :entity="item.result" :options="{ displayLong: true }" />
<on-the-fly
v-if="item.result.kind === 'company'"
:parent="item.result"
@@ -37,18 +26,14 @@
action="addContact"
ref="onTheFly"
/>
<on-the-fly
type="thirdparty"
:id="item.result.id"
action="show"
/>
<on-the-fly type="thirdparty" :id="item.result.id" action="show" />
</div>
</template>
<script>
import OnTheFly from 'ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue';
import BadgeEntity from 'ChillMainAssets/vuejs/_components/BadgeEntity.vue';
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods';
import OnTheFly from "ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue";
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
const i18n = {
messages: {
@@ -56,20 +41,20 @@ const i18n = {
thirdparty: {
contact: "Personne physique",
company: "Personne morale",
child: "Personne de contact"
}
}
}
child: "Personne de contact",
},
},
},
};
export default {
name: 'SuggestionThirdParty',
name: "SuggestionThirdParty",
components: {
OnTheFly,
BadgeEntity
BadgeEntity,
},
props: ['item'],
emits: ['newPriorSuggestion'],
props: ["item"],
emits: ["newPriorSuggestion"],
i18n,
computed: {
hasAddress() {
@@ -79,7 +64,7 @@ export default {
if (this.$props.item.result.parent !== null) {
return this.$props.item.result.parent.address !== null;
}
return false
return false;
},
hasParent() {
return this.$props.item.result.parent !== null;
@@ -93,37 +78,36 @@ export default {
}
return null;
}
},
},
methods: {
saveFormOnTheFly({data}) {
makeFetch('POST', '/api/1.0/thirdparty/thirdparty.json', data)
.then(response => {
this.$emit('newPriorSuggestion', response);
this.$refs.onTheFly.closeModal();
saveFormOnTheFly({ data }) {
makeFetch("POST", "/api/1.0/thirdparty/thirdparty.json", data)
.then((response) => {
this.$emit("newPriorSuggestion", response);
this.$refs.onTheFly.closeModal();
})
.catch((error) => {
if (error.name === 'ValidationException') {
for (let v of error.violations) {
this.$toast.open({message: v });
}
} else {
this.$toast.open({message: 'An error occurred'});
if (error.name === "ValidationException") {
for (let v of error.violations) {
this.$toast.open({ message: v });
}
})
}
}
}
} else {
this.$toast.open({ message: "An error occurred" });
}
});
},
},
};
</script>
<style lang="scss" scoped>
.tpartycontainer {
.tpartyparent {
.name {
font-weight: bold;
font-variant: all-small-caps;
}
.name {
font-weight: bold;
font-variant: all-small-caps;
}
}
.tparty-identification {
span:not(.name) {

View File

@@ -5,39 +5,36 @@
</div>
</div>
<div class="right_actions">
<badge-entity
:entity="item.result"
:options="{ displayLong: true }"
/>
<badge-entity :entity="item.result" :options="{ displayLong: true }" />
</div>
</template>
<script>
import BadgeEntity from 'ChillMainAssets/vuejs/_components/BadgeEntity.vue';
import UserRenderBoxBadge from 'ChillMainAssets/vuejs/_components/Entity/UserRenderBoxBadge.vue';
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
import UserRenderBoxBadge from "ChillMainAssets/vuejs/_components/Entity/UserRenderBoxBadge.vue";
export default {
name: 'SuggestionUser',
components: {
UserRenderBoxBadge,
BadgeEntity
},
props: ['item'],
computed: {
hasParent() {
return this.$props.item.result.parent !== null;
},
}
}
name: "SuggestionUser",
components: {
UserRenderBoxBadge,
BadgeEntity,
},
props: ["item"],
computed: {
hasParent() {
return this.$props.item.result.parent !== null;
},
},
};
</script>
<style lang="scss" scoped>
.usercontainer {
.userparent {
.userparent {
.name {
font-weight: bold;
font-variant: all-small-caps;
}
}
}
}
</style>

View File

@@ -3,19 +3,13 @@
<div class="item-row">
<div class="item-col">
<!-- identifier -->
<div
v-if="isHouseholdNew()"
class="h4"
>
<div v-if="isHouseholdNew()" class="h4">
<i class="fa fa-home" />
{{ $t('new_household') }}
{{ $t("new_household") }}
</div>
<div
v-else
class="h4"
>
<div v-else class="h4">
<i class="fa fa-home" />
{{ $t('household_number', { number: household.id } ) }}
{{ $t("household_number", { number: household.id }) }}
</div>
</div>
<div class="item-col">
@@ -30,32 +24,27 @@
v-for="m in currentMembers()"
:key="m.id"
class="m"
:class="{ is_new: m.is_new === true}"
:class="{ is_new: m.is_new === true }"
>
<person-render-box
render="badge"
:person="m.person"
:options="{
isHolder: m.holder,
addLink: true
addLink: true,
}"
>
<template
#post-badge
v-if="m.is_new === true"
>
<span class="post-badge is_new"><i class="fa fa-sign-in" /></span>
<template #post-badge v-if="m.is_new === true">
<span class="post-badge is_new"
><i class="fa fa-sign-in"
/></span>
</template>
</person-render-box>
</span>
</li>
<li
v-else
class="members"
:title="$t('current_members')"
>
<li v-else class="members" :title="$t('current_members')">
<p class="chill-no-data-statement">
{{ $t('no_members_yet') }}
{{ $t("no_members_yet") }}
</p>
</li>
@@ -67,7 +56,9 @@
/>
</li>
<li v-else>
<span class="chill-no-data-statement">{{ $t('no_current_address') }}</span>
<span class="chill-no-data-statement">{{
$t("no_current_address")
}}</span>
</li>
</ul>
</div>
@@ -76,43 +67,45 @@
</template>
<script>
import PersonRenderBox from 'ChillPersonAssets/vuejs/_components/Entity/PersonRenderBox.vue';
import AddressRenderBox from 'ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue';
import PersonRenderBox from "ChillPersonAssets/vuejs/_components/Entity/PersonRenderBox.vue";
import AddressRenderBox from "ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue";
const i18n = {
"messages": {
"fr": {
"household_number": "Ménage n°{number}",
"current_members": "Membres actuels",
"no_current_address": "Sans adresse actuellement",
"new_household": "Nouveau ménage",
"no_members_yet": "Aucun membre actuellement",
"holder": "titulaire",
}
}
messages: {
fr: {
household_number: "Ménage n°{number}",
current_members: "Membres actuels",
no_current_address: "Sans adresse actuellement",
new_household: "Nouveau ménage",
no_members_yet: "Aucun membre actuellement",
holder: "titulaire",
},
},
};
export default {
name: 'HouseholdRenderBox',
props: ['household', 'isAddressMultiline'],
name: "HouseholdRenderBox",
props: ["household", "isAddressMultiline"],
components: {
PersonRenderBox,
AddressRenderBox,
},
i18n,
computed: {
isMultiline() {
return (typeof this.isAddressMultiline !== 'undefined') ? this.isAddressMultiline : false;
}
},
computed: {
isMultiline() {
return typeof this.isAddressMultiline !== "undefined"
? this.isAddressMultiline
: false;
},
},
methods: {
hasCurrentMembers() {
return this.household.current_members_id.length > 0;
},
currentMembers() {
let members = this.household.members.filter(m => this.household.current_members_id.includes(m.id))
let members = this.household.members
.filter((m) => this.household.current_members_id.includes(m.id))
.sort((a, b) => {
const orderA = a.position ? a.position.ordering : 0;
const orderB = b.position ? b.position.ordering : 0;
@@ -132,12 +125,14 @@ export default {
});
if (this.household.new_members !== undefined) {
this.household.new_members.map(m => {
m.is_new = true;
return m;
}).forEach(m => {
members.push(m);
});
this.household.new_members
.map((m) => {
m.is_new = true;
return m;
})
.forEach((m) => {
members.push(m);
});
}
return members;
@@ -150,27 +145,24 @@ export default {
},
hasAddress() {
return this.household.current_address !== null;
}
}
},
},
};
</script>
<style lang="scss">
section.chill-entity {
&.entity-household {
&.entity-household {
ul.list-content li::marker {
content: "";
}
ul.list-content li::marker {
content: '';
.members {
.post-badge.is_new {
margin-left: 0.5rem;
color: var(--bs-chill-green);
}
.members {
.post-badge.is_new {
margin-left: 0.5rem;
color: var(--bs-chill-green);
}
}
}
}
}
}
</style>

View File

@@ -1,55 +1,49 @@
<template>
<div
v-if="render === 'bloc'"
class="item-bloc"
>
<div v-if="render === 'bloc'" class="item-bloc">
<section class="chill-entity entity-person">
<div class="item-row entity-bloc">
<div class="item-col">
<div class="entity-label">
<div :class="'denomination h' + options.hLevel">
<a
v-if="options.addLink === true"
:href="getUrl"
>
<a v-if="options.addLink === true" :href="getUrl">
<!-- use person-text here to avoid code duplication ? TODO -->
<span class="firstname">{{ person.firstName }}</span>
<span class="lastname">{{ person.lastName }}</span>
<span
v-if="person.suffixText"
class="suffixtext"
>&nbsp;{{ person.suffixText }}</span>
<span v-if="person.suffixText" class="suffixtext"
>&nbsp;{{ person.suffixText }}</span
>
<span
v-if="person.altNames && options.addAltNames == true"
class="altnames"
>
<span :class="'altname altname-' + altNameKey">{{ altNameLabel }}</span>
<span :class="'altname altname-' + altNameKey">{{
altNameLabel
}}</span>
</span>
</a>
<!-- use person-text here to avoid code duplication ? TODO -->
<span class="firstname">{{ person.firstName }}</span>
<span class="lastname">{{ person.lastName }}</span>
<span
v-if="person.suffixText"
class="suffixtext"
>&nbsp;{{ person.suffixText }}</span>
<span
v-if="person.deathdate"
class="deathdate"
> ()</span>
<span v-if="person.suffixText" class="suffixtext"
>&nbsp;{{ person.suffixText }}</span
>
<span v-if="person.deathdate" class="deathdate"> ()</span>
<span
v-if="person.altNames && options.addAltNames == true"
class="altnames"
>
<span :class="'altname altname-' + altNameKey">{{ altNameLabel }}</span>
<span :class="'altname altname-' + altNameKey">{{
altNameLabel
}}</span>
</span>
<span
v-if="options.addId == true"
class="id-number"
:title="'n° ' + person.id"
>{{ person.id }}</span>
>{{ person.id }}</span
>
<badge-entity
v-if="options.addEntity === true"
@@ -58,10 +52,7 @@
/>
</div>
<p
v-if="options.addInfo === true"
class="moreinfo"
>
<p v-if="options.addInfo === true" class="moreinfo">
<gender-icon-render-box
v-if="person.gender"
:gender="person.gender"
@@ -71,7 +62,15 @@
:datetime="person.birthdate"
:title="birthdate"
>
{{ $t(person.gender ? `renderbox.birthday.${person.gender.genderTranslation}` : 'renderbox.birthday.neutral') + ' ' + $d(birthdate, 'text') }}
{{
$t(
person.gender
? `renderbox.birthday.${person.gender.genderTranslation}`
: "renderbox.birthday.neutral",
) +
" " +
$d(birthdate, "text")
}}
</time>
<time
@@ -87,14 +86,11 @@
:datetime="person.deathdate"
:title="person.deathdate"
>
{{ $t('renderbox.deathdate') + ' ' + deathdate }}
{{ $t("renderbox.deathdate") + " " + deathdate }}
</time>
<span
v-if="options.addAge && person.birthdate"
class="age"
>{{
$tc('renderbox.years_old', person.age)
<span v-if="options.addAge && person.birthdate" class="age">{{
$tc("renderbox.years_old", person.age)
}}</span>
</p>
</div>
@@ -114,48 +110,56 @@
:address="person.current_household_address"
:is-multiline="isMultiline"
/>
<p
v-else
class="chill-no-data-statement"
>
{{ $t('renderbox.household_without_address') }}
<p v-else class="chill-no-data-statement">
{{ $t("renderbox.household_without_address") }}
</p>
<a
v-if="options.addHouseholdLink === true"
:href="getCurrentHouseholdUrl"
:title="$t('persons_associated.show_household_number', {id: person.current_household_id})"
:title="
$t('persons_associated.show_household_number', {
id: person.current_household_id,
})
"
>
<span class="badge rounded-pill bg-chill-beige">
<i class="fa fa-fw fa-home" /><!--{{ $t('persons_associated.show_household') }}-->
<i
class="fa fa-fw fa-home"
/><!--{{ $t('persons_associated.show_household') }}-->
</span>
</a>
</li>
<li v-else-if="options.addNoData">
<i class="fa fa-li fa-map-marker" /><p class="chill-no-data-statement">
{{ $t('renderbox.no_data') }}
<i class="fa fa-li fa-map-marker" />
<p class="chill-no-data-statement">
{{ $t("renderbox.no_data") }}
</p>
</li>
<template v-if="this.showResidentialAddresses && (person.current_residential_addresses || []).length > 0">
<template
v-if="
this.showResidentialAddresses &&
(person.current_residential_addresses || []).length > 0
"
>
<li
v-for="(addr, i) in person.current_residential_addresses"
:key="i"
>
<i class="fa fa-li fa-map-marker" />
<div v-if="addr.address">
<span class="item-key">{{ $t('renderbox.residential_address') }}:</span>
<div style="margin-top: -1em;">
<span class="item-key"
>{{ $t("renderbox.residential_address") }}:</span
>
<div style="margin-top: -1em">
<address-render-box
:address="addr.address"
:is-multiline="isMultiline"
/>
</div>
</div>
<div
v-else-if="addr.hostPerson"
class="mt-3"
>
<p>{{ $t('renderbox.located_at') }}:</p>
<div v-else-if="addr.hostPerson" class="mt-3">
<p>{{ $t("renderbox.located_at") }}:</p>
<span class="chill-entity entity-person badge-person">
<person-text
v-if="addr.hostPerson"
@@ -168,11 +172,8 @@
:is-multiline="isMultiline"
/>
</div>
<div
v-else-if="addr.hostThirdParty"
class="mt-3"
>
<p>{{ $t('renderbox.located_at') }}:</p>
<div v-else-if="addr.hostThirdParty" class="mt-3">
<p>{{ $t("renderbox.located_at") }}:</p>
<span class="chill-entity entity-person badge-thirdparty">
<third-party-text
v-if="addr.hostThirdParty"
@@ -195,32 +196,42 @@
<li v-else-if="options.addNoData">
<i class="fa fa-li fa-envelope-o" />
<p class="chill-no-data-statement">
{{ $t('renderbox.no_data') }}
{{ $t("renderbox.no_data") }}
</p>
</li>
<li v-if="person.mobilenumber">
<i class="fa fa-li fa-mobile" />
<a :href="'tel: ' + person.mobilenumber">{{ person.mobilenumber }}</a>
<a :href="'tel: ' + person.mobilenumber">{{
person.mobilenumber
}}</a>
</li>
<li v-else-if="options.addNoData">
<i class="fa fa-li fa-mobile" />
<p class="chill-no-data-statement">
{{ $t('renderbox.no_data') }}
{{ $t("renderbox.no_data") }}
</p>
</li>
<li v-if="person.phonenumber">
<i class="fa fa-li fa-phone" />
<a :href="'tel: ' + person.phonenumber">{{ person.phonenumber }}</a>
<a :href="'tel: ' + person.phonenumber">{{
person.phonenumber
}}</a>
</li>
<li v-else-if="options.addNoData">
<i class="fa fa-li fa-phone" />
<p class="chill-no-data-statement">
{{ $t('renderbox.no_data') }}
{{ $t("renderbox.no_data") }}
</p>
</li>
<li v-if="person.centers !== undefined && person.centers.length > 0 && options.addCenter">
<li
v-if="
person.centers !== undefined &&
person.centers.length > 0 &&
options.addCenter
"
>
<i class="fa fa-li fa-long-arrow-right" />
<template v-for="c in person.centers">
{{ c.name }}
@@ -229,7 +240,7 @@
<li v-else-if="options.addNoData">
<i class="fa fa-li fa-long-arrow-right" />
<p class="chill-no-data-statement">
{{ $t('renderbox.no_data') }}
{{ $t("renderbox.no_data") }}
</p>
</li>
<slot name="custom-zone" />
@@ -247,10 +258,7 @@
v-if="render === 'badge'"
class="chill-entity entity-person badge-person"
>
<a
v-if="options.addLink === true"
:href="getUrl"
>
<a v-if="options.addLink === true" :href="getUrl">
<span
v-if="options.isHolder"
class="fa-stack fa-holder"
@@ -278,12 +286,12 @@
</template>
<script>
import {ISOToDate} from 'ChillMainAssets/chill/js/date';
import AddressRenderBox from 'ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue';
import GenderIconRenderBox from 'ChillMainAssets/vuejs/_components/Entity/GenderIconRenderBox.vue'
import BadgeEntity from 'ChillMainAssets/vuejs/_components/BadgeEntity.vue';
import PersonText from 'ChillPersonAssets/vuejs/_components/Entity/PersonText.vue';
import ThirdPartyText from 'ChillThirdPartyAssets/vuejs/_components/Entity/ThirdPartyText.vue';
import { ISOToDate } from "ChillMainAssets/chill/js/date";
import AddressRenderBox from "ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue";
import GenderIconRenderBox from "ChillMainAssets/vuejs/_components/Entity/GenderIconRenderBox.vue";
import BadgeEntity from "ChillMainAssets/vuejs/_components/BadgeEntity.vue";
import PersonText from "ChillPersonAssets/vuejs/_components/Entity/PersonText.vue";
import ThirdPartyText from "ChillThirdPartyAssets/vuejs/_components/Entity/ThirdPartyText.vue";
export default {
name: "PersonRenderBox",
@@ -292,7 +300,7 @@ export default {
GenderIconRenderBox,
BadgeEntity,
PersonText,
ThirdPartyText
ThirdPartyText,
},
props: {
person: {
@@ -311,55 +319,62 @@ export default {
showResidentialAddresses: {
type: Boolean,
default: false,
}
},
},
computed: {
isMultiline: function () {
if (this.options.isMultiline) {
return this.options.isMultiline
return this.options.isMultiline;
} else {
return false
return false;
}
},
birthdate: function () {
if (this.person.birthdate !== null || this.person.birthdate === "undefined") {
if (
this.person.birthdate !== null ||
this.person.birthdate === "undefined"
) {
return ISOToDate(this.person.birthdate.datetime);
} else {
return "";
}
},
deathdate: function () {
if (this.person.deathdate !== null || this.person.birthdate === "undefined") {
if (
this.person.deathdate !== null ||
this.person.birthdate === "undefined"
) {
return new Date(this.person.deathdate.datetime);
} else {
return "";
}
},
altNameLabel: function () {
let altNameLabel = ''
this.person.altNames.forEach(altName => altNameLabel += altName.label)
return altNameLabel
let altNameLabel = "";
this.person.altNames.forEach(
(altName) => (altNameLabel += altName.label),
);
return altNameLabel;
},
altNameKey: function () {
let altNameKey = ''
this.person.altNames.forEach(altName => altNameKey += altName.key)
return altNameKey
let altNameKey = "";
this.person.altNames.forEach((altName) => (altNameKey += altName.key));
return altNameKey;
},
getUrl: function () {
return `/fr/person/${this.person.id}/general`;
},
getCurrentHouseholdUrl: function () {
let returnPath = this.returnPath ? `?returnPath=${this.returnPath}` : ``;
return `/fr/person/household/${this.person.current_household_id}/summary${returnPath}`
}
}
}
return `/fr/person/household/${this.person.current_household_id}/summary${returnPath}`;
},
},
};
</script>
<style lang='scss'>
<style lang="scss">
.lastname:before {
content: " "
content: " ";
}
div.flex-table {
@@ -371,7 +386,6 @@ div.flex-table {
div.item-col:last-child {
justify-content: flex-start;
}
}
}
@@ -381,13 +395,11 @@ div.flex-table {
margin-left: 0.5em;
&:before {
content: '(';
content: "(";
}
&:after {
content: ')';
content: ")";
}
}
</style>

View File

@@ -1,63 +1,62 @@
<template>
<span v-if="isCut">{{ cutText }}</span>
<span
v-else
class="person-text"
>
<span v-else class="person-text">
<span class="firstname">{{ person.firstName }}</span>
<span class="lastname">{{ person.lastName }}</span>
<span
v-if="person.altNames && person.altNames.length > 0"
class="altnames"
>
<span :class="'altname altname-' + altNameKey"> ({{ altNameLabel }})</span>
<span v-if="person.altNames && person.altNames.length > 0" class="altnames">
<span :class="'altname altname-' + altNameKey">
({{ altNameLabel }})</span
>
</span>
<span
v-if="person.suffixText"
class="suffixtext"
>&nbsp;{{ person.suffixText }}</span>
<span v-if="person.suffixText" class="suffixtext"
>&nbsp;{{ person.suffixText }}</span
>
<span
class="age"
v-if="this.addAge && person.birthdate !== null && person.deathdate === null"
>{{ $tc('renderbox.years_old', person.age) }}</span>
v-if="
this.addAge && person.birthdate !== null && person.deathdate === null
"
>{{ $tc("renderbox.years_old", person.age) }}</span
>
<span v-else-if="this.addAge && person.deathdate !== null">&nbsp;(‡)</span>
</span>
</template>
<script>
export default {
name: "PersonText",
props: {
person: {
required: true,
},
isCut: {
type: Boolean,
required: false,
default: false
},
addAge: {
type: Boolean,
required: false,
default: true,
}
name: "PersonText",
props: {
person: {
required: true,
},
computed: {
altNameLabel: function() {
let altNameLabel = ''
this.person.altNames.forEach(altName => altNameLabel += altName.label)
return altNameLabel
},
altNameKey: function() {
let altNameKey = ''
this.person.altNames.forEach(altName => altNameKey += altName.key)
return altNameKey
},
cutText: function() {
let more = (this.person.text.length > 15) ?'…' : '';
return this.person.text.slice(0,15) + more;
}
}
}
isCut: {
type: Boolean,
required: false,
default: false,
},
addAge: {
type: Boolean,
required: false,
default: true,
},
},
computed: {
altNameLabel: function () {
let altNameLabel = "";
this.person.altNames.forEach(
(altName) => (altNameLabel += altName.label),
);
return altNameLabel;
},
altNameKey: function () {
let altNameKey = "";
this.person.altNames.forEach((altName) => (altNameKey += altName.key));
return altNameKey;
},
cutText: function () {
let more = this.person.text.length > 15 ? "…" : "";
return this.person.text.slice(0, 15) + more;
},
},
};
</script>

View File

@@ -14,7 +14,7 @@
hLevel: 3,
addCenter: true,
addNoData: true,
isMultiline: true
isMultiline: true,
}"
:show-residential-addresses="true"
/>
@@ -29,8 +29,8 @@
v-model="lastName"
:placeholder="$t('person.lastname')"
@change="checkErrors"
>
<label for="lastname">{{ $t('person.lastname') }}</label>
/>
<label for="lastname">{{ $t("person.lastname") }}</label>
</div>
<div v-if="queryItems">
@@ -52,8 +52,8 @@
v-model="firstName"
:placeholder="$t('person.firstname')"
@change="checkErrors"
>
<label for="firstname">{{ $t('person.firstname') }}</label>
/>
<label for="firstname">{{ $t("person.firstname") }}</label>
</div>
<div v-if="queryItems">
@@ -78,59 +78,37 @@
:id="a.key"
:value="personAltNamesLabels[i]"
@input="onAltNameInput"
>
/>
<label :for="a.key">{{ a.labels.fr }}</label>
</div>
<!-- TODO fix placeholder if undefined
-->
<div class="form-floating mb-3">
<select
class="form-select form-select-lg"
id="gender"
v-model="gender"
>
<option
selected
disabled
>
{{ $t('person.gender.placeholder') }}
<select class="form-select form-select-lg" id="gender" v-model="gender">
<option selected disabled>
{{ $t("person.gender.placeholder") }}
</option>
<option
v-for="g in config.genders"
:value="g.id"
:key="g.id"
>
<option v-for="g in config.genders" :value="g.id" :key="g.id">
{{ g.label.fr }}
</option>
</select>
<label>{{ $t('person.gender.title') }}</label>
<label>{{ $t("person.gender.title") }}</label>
</div>
<div
class="form-floating mb-3"
v-if="showCenters && config.centers.length > 1"
>
<select
class="form-select form-select-lg"
id="center"
v-model="center"
>
<option
selected
disabled
>
{{ $t('person.center.placeholder') }}
<select class="form-select form-select-lg" id="center" v-model="center">
<option selected disabled>
{{ $t("person.center.placeholder") }}
</option>
<option
v-for="c in config.centers"
:value="c"
:key="c.id"
>
<option v-for="c in config.centers" :value="c" :key="c.id">
{{ c.name }}
</option>
</select>
<label>{{ $t('person.center.title') }}</label>
<label>{{ $t("person.center.title") }}</label>
</div>
<div class="form-floating mb-3">
@@ -139,28 +117,20 @@
id="civility"
v-model="civility"
>
<option
selected
disabled
>
{{ $t('person.civility.placeholder') }}
<option selected disabled>
{{ $t("person.civility.placeholder") }}
</option>
<option
v-for="c in config.civilities"
:value="c.id"
:key="c.id"
>
<option v-for="c in config.civilities" :value="c.id" :key="c.id">
{{ c.name.fr }}
</option>
</select>
<label>{{ $t('person.civility.title') }}</label>
<label>{{ $t("person.civility.title") }}</label>
</div>
<div class="input-group mb-3">
<span
class="input-group-text"
id="birthdate"
><i class="fa fa-fw fa-birthday-cake" /></span>
<span class="input-group-text" id="birthdate"
><i class="fa fa-fw fa-birthday-cake"
/></span>
<input
type="date"
class="form-control form-control-lg"
@@ -168,68 +138,64 @@
name="chill_personbundle_person[birthdate]"
v-model="birthDate"
aria-describedby="birthdate"
>
/>
</div>
<div class="input-group mb-3">
<span
class="input-group-text"
id="phonenumber"
><i class="fa fa-fw fa-phone" /></span>
<span class="input-group-text" id="phonenumber"
><i class="fa fa-fw fa-phone"
/></span>
<input
class="form-control form-control-lg"
v-model="phonenumber"
:placeholder="$t('person.phonenumber')"
:aria-label="$t('person.phonenumber')"
aria-describedby="phonenumber"
>
/>
</div>
<div class="input-group mb-3">
<span
class="input-group-text"
id="mobilenumber"
><i class="fa fa-fw fa-mobile" /></span>
<span class="input-group-text" id="mobilenumber"
><i class="fa fa-fw fa-mobile"
/></span>
<input
class="form-control form-control-lg"
v-model="mobilenumber"
:placeholder="$t('person.mobilenumber')"
:aria-label="$t('person.mobilenumber')"
aria-describedby="mobilenumber"
>
/>
</div>
<div class="input-group mb-3">
<span
class="input-group-text"
id="email"
><i class="fa fa-fw fa-at" /></span>
<span class="input-group-text" id="email"
><i class="fa fa-fw fa-at"
/></span>
<input
class="form-control form-control-lg"
v-model="email"
:placeholder="$t('person.email')"
:aria-label="$t('person.email')"
aria-describedby="email"
>
/>
</div>
<div
v-if="action === 'create'"
class="input-group mb-3 form-check"
>
<div v-if="action === 'create'" class="input-group mb-3 form-check">
<input
class="form-check-input"
type="checkbox"
v-model="showAddressForm"
name="showAddressForm"
>
<label class="form-check-label">{{ $t('person.address.show_address_form') }}</label>
/>
<label class="form-check-label">{{
$t("person.address.show_address_form")
}}</label>
</div>
<div
v-if="action === 'create' && showAddressFormValue"
class="form-floating mb-3"
>
<p>{{ $t('person.address.warning') }}</p>
<p>{{ $t("person.address.warning") }}</p>
<add-address
:context="addAddress.context"
:options="addAddress.options"
@@ -238,16 +204,9 @@
/>
</div>
<div
class="alert alert-warning"
v-if="errors.length"
>
<div class="alert alert-warning" v-if="errors.length">
<ul>
<li
v-for="(e, i) in errors"
:key="i"
>
<li v-for="(e, i) in errors" :key="i">
{{ e }}
</li>
</ul>
@@ -256,253 +215,293 @@
</template>
<script>
import { getCentersForPersonCreation, getCivilities, getGenders, getPerson, getPersonAltNames } from '../../_api/OnTheFly';
import PersonRenderBox from '../Entity/PersonRenderBox.vue';
import {
getCentersForPersonCreation,
getCivilities,
getGenders,
getPerson,
getPersonAltNames,
} from "../../_api/OnTheFly";
import PersonRenderBox from "../Entity/PersonRenderBox.vue";
import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue";
export default {
name: "OnTheFlyPerson",
props: ['id', 'type', 'action', 'query'],
//emits: ['createAction'],
components: {
PersonRenderBox,
AddAddress
},
data() {
return {
person: {
type: 'person',
lastName: '',
firstName: '',
altNames: [],
addressId: null,
center: null,
},
config: {
altNames: [],
civilities: [],
centers: [],
genders: []
},
showCenters: false, // NOTE: must remains false if the form is not in create mode
showAddressFormValue: false,
addAddress: {
options: {
button: {
text: { create: 'person.address.create_address' },
size: 'btn-sm'
},
title: { create: 'person.address.create_address' },
},
context: {
target: {}, // boilerplate for getting the address id
edit: false,
addressId: null,
defaults: window.addaddress
}
},
errors: []
}
},
computed: {
firstName: {
set(value) {
this.person.firstName = value;
},
get() { return this.person.firstName; }
name: "OnTheFlyPerson",
props: ["id", "type", "action", "query"],
//emits: ['createAction'],
components: {
PersonRenderBox,
AddAddress,
},
data() {
return {
person: {
type: "person",
lastName: "",
firstName: "",
altNames: [],
addressId: null,
center: null,
},
lastName: {
set(value) { this.person.lastName = value; },
get() { return this.person.lastName; }
config: {
altNames: [],
civilities: [],
centers: [],
genders: [],
},
gender: {
set(value) { this.person.gender = {id: value, type: 'chill_main_gender'}; },
get() { return this.person.gender ? this.person.gender.id : null; }
showCenters: false, // NOTE: must remains false if the form is not in create mode
showAddressFormValue: false,
addAddress: {
options: {
button: {
text: { create: "person.address.create_address" },
size: "btn-sm",
},
title: { create: "person.address.create_address" },
},
context: {
target: {}, // boilerplate for getting the address id
edit: false,
addressId: null,
defaults: window.addaddress,
},
},
civility: {
set(value) { this.person.civility = {id: value, type: 'chill_main_civility'}; },
get() { return this.person.civility ? this.person.civility.id : null; }
errors: [],
};
},
computed: {
firstName: {
set(value) {
this.person.firstName = value;
},
birthDate: {
set(value) {
if (this.person.birthdate) {
this.person.birthdate.datetime = value + "T00:00:00+0100";
} else {
this.person.birthdate = { datetime: value + "T00:00:00+0100"};
}
},
get() {
return (this.person.birthdate) ? this.person.birthdate.datetime.split('T')[0] : '';
}
get() {
return this.person.firstName;
},
phonenumber: {
set(value) { this.person.phonenumber = value; },
get() { return this.person.phonenumber; }
},
lastName: {
set(value) {
this.person.lastName = value;
},
mobilenumber: {
set(value) { this.person.mobilenumber = value; },
get() { return this.person.mobilenumber; }
get() {
return this.person.lastName;
},
email: {
set(value) { this.person.email = value; },
get() { return this.person.email; }
},
gender: {
set(value) {
this.person.gender = { id: value, type: "chill_main_gender" };
},
showAddressForm: {
set(value) { this.showAddressFormValue = value; },
get() { return this.showAddressFormValue; }
get() {
return this.person.gender ? this.person.gender.id : null;
},
center: {
set(value) {
console.log('will set center', value);
this.person.center = {id: value.id, type: value.type};
},
get() {
const center = this.config.centers.find(c => this.person.center !== null && this.person.center.id === c.id);
},
civility: {
set(value) {
this.person.civility = { id: value, type: "chill_main_civility" };
},
get() {
return this.person.civility ? this.person.civility.id : null;
},
},
birthDate: {
set(value) {
if (this.person.birthdate) {
this.person.birthdate.datetime = value + "T00:00:00+0100";
} else {
this.person.birthdate = { datetime: value + "T00:00:00+0100" };
}
},
get() {
return this.person.birthdate
? this.person.birthdate.datetime.split("T")[0]
: "";
},
},
phonenumber: {
set(value) {
this.person.phonenumber = value;
},
get() {
return this.person.phonenumber;
},
},
mobilenumber: {
set(value) {
this.person.mobilenumber = value;
},
get() {
return this.person.mobilenumber;
},
},
email: {
set(value) {
this.person.email = value;
},
get() {
return this.person.email;
},
},
showAddressForm: {
set(value) {
this.showAddressFormValue = value;
},
get() {
return this.showAddressFormValue;
},
},
center: {
set(value) {
console.log("will set center", value);
this.person.center = { id: value.id, type: value.type };
},
get() {
const center = this.config.centers.find(
(c) => this.person.center !== null && this.person.center.id === c.id,
);
console.log('center get', center);
console.log("center get", center);
return typeof center === 'undefined' ? null : center;
},
return typeof center === "undefined" ? null : center;
},
genderClass() {
switch (this.person.gender) {
case 'woman':
return 'fa-venus';
case 'man':
return 'fa-mars';
case 'both':
return 'fa-neuter';
case 'unknown':
return 'fa-genderless';
default:
return 'fa-genderless';
}
},
genderTranslation() {
switch (this.person.gender.genderTranslation) {
case 'woman':
return 'person.gender.woman';
case 'man':
return 'person.gender.man';
case 'neutral':
return 'person.gender.neutral';
case 'unknown':
return 'person.gender.unknown';
default:
return 'person.gender.unknown';
}
},
feminized() {
return (this.person.gender === 'woman')? 'e' : '';
},
personAltNamesLabels() {
return this.person.altNames.map(a => a ? a.label : '');
},
queryItems() {
return this.query ? this.query.split(' ') : null;
},
genderClass() {
switch (this.person.gender) {
case "woman":
return "fa-venus";
case "man":
return "fa-mars";
case "both":
return "fa-neuter";
case "unknown":
return "fa-genderless";
default:
return "fa-genderless";
}
},
mounted() {
getPersonAltNames()
.then(altNames => {
this.config.altNames = altNames;
});
getCivilities()
.then(civilities => {
if ('results' in civilities) {
this.config.civilities = civilities.results;
}
});
getGenders()
.then(genders => {
if ('results' in genders) {
this.config.genders = genders.results;
}
});
if (this.action !== 'create') {
this.loadData();
} else {
// console.log('show centers', this.showCenters);
getCentersForPersonCreation()
.then(params => {
this.config.centers = params.centers.filter(c => c.isActive);
this.showCenters = params.showCenters;
// console.log('centers', this.config.centers)
// console.log('show centers inside', this.showCenters);
if (this.showCenters && this.config.centers.length === 1) {
this.person.center = this.config.centers[0];
}
});
},
genderTranslation() {
switch (this.person.gender.genderTranslation) {
case "woman":
return "person.gender.woman";
case "man":
return "person.gender.man";
case "neutral":
return "person.gender.neutral";
case "unknown":
return "person.gender.unknown";
default:
return "person.gender.unknown";
}
},
methods: {
checkErrors() {
this.errors = [];
if (this.person.lastName === "") {
this.errors.push("Le nom ne doit pas être vide.");
}
if (this.person.firstName === "") {
this.errors.push("Le prénom ne doit pas être vide.");
}
if (!this.person.gender) {
this.errors.push("Le genre doit être renseigné");
}
if (this.showCenters && this.person.center === null) {
this.errors.push("Le centre doit être renseigné");
}
},
loadData() {
getPerson(this.id)
.then(person => new Promise((resolve) => {
this.person = person;
//console.log('get person', this.person);
resolve();
}));
},
onAltNameInput(event) {
const key = event.target.id;
const label = event.target.value;
let updateAltNames = this.person.altNames.filter((a) => a.key !== key);
updateAltNames.push(
{'key': key, 'label': label}
)
this.person.altNames = updateAltNames;
},
addQueryItem(field, queryItem) {
switch (field) {
case 'lastName':
this.person.lastName = this.person.lastName ? this.person.lastName += ` ${queryItem}` : queryItem;
break;
case 'firstName':
this.person.firstName = this.person.firstName ? this.person.firstName += ` ${queryItem}` : queryItem;
break;
}
},
submitNewAddress(payload) {
this.person.addressId = payload.addressId;
},
feminized() {
return this.person.gender === "woman" ? "e" : "";
},
personAltNamesLabels() {
return this.person.altNames.map((a) => (a ? a.label : ""));
},
queryItems() {
return this.query ? this.query.split(" ") : null;
},
},
mounted() {
getPersonAltNames().then((altNames) => {
this.config.altNames = altNames;
});
getCivilities().then((civilities) => {
if ("results" in civilities) {
this.config.civilities = civilities.results;
}
}
}
});
getGenders().then((genders) => {
if ("results" in genders) {
this.config.genders = genders.results;
}
});
if (this.action !== "create") {
this.loadData();
} else {
// console.log('show centers', this.showCenters);
getCentersForPersonCreation().then((params) => {
this.config.centers = params.centers.filter((c) => c.isActive);
this.showCenters = params.showCenters;
// console.log('centers', this.config.centers)
// console.log('show centers inside', this.showCenters);
if (this.showCenters && this.config.centers.length === 1) {
this.person.center = this.config.centers[0];
}
});
}
},
methods: {
checkErrors() {
this.errors = [];
if (this.person.lastName === "") {
this.errors.push("Le nom ne doit pas être vide.");
}
if (this.person.firstName === "") {
this.errors.push("Le prénom ne doit pas être vide.");
}
if (!this.person.gender) {
this.errors.push("Le genre doit être renseigné");
}
if (this.showCenters && this.person.center === null) {
this.errors.push("Le centre doit être renseigné");
}
},
loadData() {
getPerson(this.id).then(
(person) =>
new Promise((resolve) => {
this.person = person;
//console.log('get person', this.person);
resolve();
}),
);
},
onAltNameInput(event) {
const key = event.target.id;
const label = event.target.value;
let updateAltNames = this.person.altNames.filter((a) => a.key !== key);
updateAltNames.push({ key: key, label: label });
this.person.altNames = updateAltNames;
},
addQueryItem(field, queryItem) {
switch (field) {
case "lastName":
this.person.lastName = this.person.lastName
? (this.person.lastName += ` ${queryItem}`)
: queryItem;
break;
case "firstName":
this.person.firstName = this.person.firstName
? (this.person.firstName += ` ${queryItem}`)
: queryItem;
break;
}
},
submitNewAddress(payload) {
this.person.addressId = payload.addressId;
},
},
};
</script>
<style lang="scss" scoped>
div.flex-table {
div.item-bloc {
div.item-row {
div.item-col:last-child {
justify-content: flex-start;
}
div.item-bloc {
div.item-row {
div.item-col:last-child {
justify-content: flex-start;
}
}
}
}
}
dl {
dd {
margin-left: 1em;
}
dd {
margin-left: 1em;
}
}
div.form-check {
label {
margin-left: 0.5em!important;
}
label {
margin-left: 0.5em !important;
}
}
</style>

View File

@@ -1,63 +1,63 @@
const personMessages = {
fr: {
add_persons: {
title: "Ajouter des usagers",
suggested_counter: "Pas de résultats | 1 résultat | {count} résultats",
selected_counter: " 1 sélectionné | {count} sélectionnés",
search_some_persons: "Rechercher des personnes..",
fr: {
add_persons: {
title: "Ajouter des usagers",
suggested_counter: "Pas de résultats | 1 résultat | {count} résultats",
selected_counter: " 1 sélectionné | {count} sélectionnés",
search_some_persons: "Rechercher des personnes..",
},
item: {
type_person: "Usager",
type_user: "TMS",
type_thirdparty: "Tiers professionnel",
type_household: "Ménage",
},
person: {
firstname: "Prénom",
lastname: "Nom",
born: (ctx: { gender: "man" | "woman" | "neutral" }) => {
if (ctx.gender === "man") {
return "Né le";
} else if (ctx.gender === "woman") {
return "Née le";
} else {
return "Né·e le";
}
},
item: {
type_person: "Usager",
type_user: "TMS",
type_thirdparty: "Tiers professionnel",
type_household: "Ménage"
center_id: "Identifiant du centre",
center_type: "Type de centre",
center_name: "Territoire", // vendée
phonenumber: "Téléphone",
mobilenumber: "Mobile",
altnames: "Autres noms",
email: "Courriel",
gender: {
title: "Genre",
placeholder: "Choisissez le genre de l'usager",
woman: "Féminin",
man: "Masculin",
neutral: "Neutre, non binaire",
unknown: "Non renseigné",
undefined: "Non renseigné",
},
person: {
firstname: "Prénom",
lastname: "Nom",
born: (ctx: {gender: "man"|"woman"|"neutral"}) => {
if (ctx.gender === 'man') {
return 'Né le';
} else if (ctx.gender === 'woman') {
return 'Née le';
} else {
return 'Né·e le';
}
},
center_id: "Identifiant du centre",
center_type: "Type de centre",
center_name: "Territoire", // vendée
phonenumber: "Téléphone",
mobilenumber: "Mobile",
altnames: "Autres noms",
email: "Courriel",
gender: {
title: "Genre",
placeholder: "Choisissez le genre de l'usager",
woman: "Féminin",
man: "Masculin",
neutral: "Neutre, non binaire",
unknown: "Non renseigné",
undefined: "Non renseigné"
},
civility: {
title: "Civilité",
placeholder: "Choisissez la civilité",
},
address: {
create_address: "Ajouter une adresse",
show_address_form: "Ajouter une adresse pour un usager non suivi et seul dans un ménage",
warning: "Un nouveau ménage va être créé. L'usager sera membre de ce ménage."
},
center: {
placeholder: "Choisissez un centre",
title: "Centre",
}
civility: {
title: "Civilité",
placeholder: "Choisissez la civilité",
},
error_only_one_person: "Une seule personne peut être sélectionnée !"
}
address: {
create_address: "Ajouter une adresse",
show_address_form:
"Ajouter une adresse pour un usager non suivi et seul dans un ménage",
warning:
"Un nouveau ménage va être créé. L'usager sera membre de ce ménage.",
},
center: {
placeholder: "Choisissez un centre",
title: "Centre",
},
},
error_only_one_person: "Une seule personne peut être sélectionnée !",
},
};
export {
personMessages
};
export { personMessages };