Merge branch 'master' into person_renderbox_thirdparty_onthefly

This commit is contained in:
Mathieu Jaumotte 2021-09-13 12:18:01 +02:00
commit caca9ad71f
37 changed files with 885 additions and 597 deletions

View File

@ -47,68 +47,12 @@
</div>
<div class="item-col">
<ul class="list-content">
{% if activity.user and t.userVisible %}
<li>
<abbr class="referrer" title="{{ 'Referrer'|trans }}">ref:</abbr>
<b>{{ activity.user.usernameCanonical }}</b>
</li>
{% endif %}
<div class="float-button top">
<div class="box">
<li>
<b>{{ activity.type.name | localize_translatable_string }}</b>
{% if activity.attendee is not null and t.attendeeVisible %}
{% if activity.attendee %}
{{ '→ ' ~ 'present'|trans|capitalize }}
{% else %}
{{ '→ ' ~ 'not present'|trans|capitalize }}
{% endif %}
{% endif %}
</li>
<li>
<b>{{ 'location'|trans ~ ': ' }}</b>
Domicile de l'usager
{# TODO
{% if activity.location %}{{ activity.location }}{% endif %}
#}
</li>
{%- if t.reasonsVisible -%}
<li>
{%- if activity.reasons is not empty -%}
{% for r in activity.reasons %}
{{ r|chill_entity_render_box }}
{% endfor %}
{%- endif -%}
</li>
{% endif %}
{%- if t.socialIssuesVisible %}
<li class="social-issues">
{%- if activity.socialIssues is not empty -%}
{% for r in activity.socialIssues %}
{{ r|chill_entity_render_box }}
{% endfor %}
{%- endif -%}
</li>
{% endif %}
{%- if t.socialActionsVisible -%}
<li class="social-actions">
{%- if activity.socialActions is not empty -%}
{% for r in activity.socialActions %}
{{ r|chill_entity_render_box }}
{% endfor %}
{%- endif -%}
</li>
{% endif %}
</ul>
<ul class="record_actions">
<div class="action">
<ul class="record_actions">
<li>
<a href="{{ path('chill_activity_activity_show', { 'id': activity.id, 'person_id': person_id, 'accompanying_period_id': accompanying_course_id }) }}"
class="btn btn-sm btn-show "></a>
@ -134,6 +78,77 @@
#}
{% endif %}
</ul>
</div>
<ul class="list-content">
{% if activity.user and t.userVisible %}
<li>
<abbr class="referrer" title="{{ 'Referrer'|trans }}">ref:</abbr>
<b>{{ activity.user.usernameCanonical }}</b>
</li>
{% endif %}
<li>
<b>{{ activity.type.name | localize_translatable_string }}</b>
{% if activity.attendee is not null and t.attendeeVisible %}
{% if activity.attendee %}
{{ '→ ' ~ 'present'|trans|capitalize }}
{% else %}
{{ '→ ' ~ 'not present'|trans|capitalize }}
{% endif %}
{% endif %}
</li>
<li>
<b>{{ 'location'|trans ~ ': ' }}</b>
Domicile de l'usager
{# TODO {% if activity.location %}{{ activity.location }}{% endif %}
#}
</li>
{%- if t.reasonsVisible -%}
<li>
{%- if activity.reasons is not empty -%}
{% for r in activity.reasons %}
{{ r|chill_entity_render_box }}
{% endfor %}
{%- endif -%}
</li>
{% endif %}
{%- if t.socialIssuesVisible %}
<li class="social-issues">
{%- if activity.socialIssues is not empty -%}
{% for r in activity.socialIssues %}
{{ r|chill_entity_render_box }}
{% endfor %}
{%- endif -%}
</li>
{% endif %}
{%- if t.socialActionsVisible -%}
<li class="social-actions">
{%- if activity.socialActions is not empty -%}
{% for r in activity.socialActions %}
{{ r|chill_entity_render_box }}
{% endfor %}
{%- endif -%}
</li>
{% endif %}
</ul>
</div>
</div>
</div>
</div>

View File

@ -206,8 +206,8 @@ footer.footer {
/// titles
h1, h2,
.h1, .h2 {
font-weight: $headings-font-weight + 200;
.h1, .h2 {
font-weight: $headings-font-weight + 100;
}
/// typography
@ -276,6 +276,20 @@ div.metadata {
}
}
/// chill help tooltip
.chill-help-tooltip {
&::before {
content: '\f05a';
color: $chill-pink;
font-family: ForkAwesome;
font-style: normal;
font-size: 120%;
cursor: pointer;
margin: auto 0.3em;
}
}
/// display definition list
// with dt and dd on same line

View File

@ -19,7 +19,8 @@ $chill-theme-buttons: (
"view": $chill-blue,
"misc": $gray-300,
"cancel": $gray-300,
"choose": $gray-300
"choose": $gray-300,
"unlink": $chill-red,
);
@each $button, $color in $chill-theme-buttons {
@ -45,6 +46,7 @@ $chill-theme-buttons: (
&.btn-delete,
&.btn-danger,
&.btn-remove,
&.btn-unlink,
&.btn-action,
&.btn-edit,
&.btn-update {
@ -67,6 +69,7 @@ $chill-theme-buttons: (
// &.btn-submit::before,
// &.btn-reset::before,
// &.btn-action::before,
&.btn-unlink::before,
&.btn-delete::before,
&.btn-remove::before,
&.btn-choose::before,
@ -94,6 +97,7 @@ $chill-theme-buttons: (
&.btn-remove::before { content: "\f00d"; } // fa-times
&.btn-cancel::before { content: "\f060"; } // fa-arrow-left
&.btn-choose::before { content: "\f00c"; } // fa-check // f046 fa-check-square-o
&.btn-unlink::before { content: "\f127"; } // fa-chain-broken
}

View File

@ -1,3 +1,6 @@
// See Assets Album page:
// http://localhost:8001/_dev/assets
/*
* __FLEX-TABLE_________
* FLEX RESPONSIVE TABLE/BLOCK PRESENTATION
@ -175,13 +178,13 @@ div.wrap-list {
border: 1px solid $black;
div.wl-col.title {
background-color: $yellow;
background-color: yellow;
}
div.wl-col.list {
background-color: $green;
background-color: cyan;
p.wl-item {
background-color: $orange;
background-color: orange;
}
}
}
@ -256,3 +259,53 @@ div.wrap-header {
}
}
}
/*
* FLOATBUTTON
* p-ê pas convaincant: cet asset est toujours en observation
*/
div.float-button {
width: 100%;
div.box {
width: 100%;
div.action {
float: right;
}
}
&.top {
div.action {
padding: 0 0 1em 1em;
}
// avoid a position relative that make links unclickable
.fa-ul > li {
position: initial;
}
}
&.bottom {
display: flex;
overflow: hidden;
div.action {
height: calc(100% - 0em);
shape-outside: inset(calc(100% - 2em) 0 0);
display: flex;
align-items: flex-end;
padding: 0 0 0 1em;
* {
align-self: flex-end !important;
}
}
}
&.debug {
padding: 1em;
border: 1px solid black;
background-color: yellow;
div.action {
background-color: transparentize(#00ffff, 0.4);
}
}
}

View File

@ -479,7 +479,7 @@ $font-sizes: (
$headings-margin-bottom: $spacer / 2 !default;
$headings-font-family: null !default;
$headings-font-style: null !default;
$headings-font-weight: 500 !default;
$headings-font-weight: 600 !default;
$headings-line-height: 1.2 !default;
$headings-color: null !default;
// scss-docs-end headings-variables

View File

@ -1,9 +1,4 @@
<template>
<div v-for="error in displayErrors" class="alert alert-danger my-2">
{{ error }}
</div>
<add-address
v-bind:key="context.entity.type"
v-bind:context="context"
@ -23,6 +18,8 @@
*
* */
import AddAddress from './components/AddAddress.vue';
import { patchAddress } from "./api";
import { postAddressToHousehold, postAddressToPerson } from "ChillPersonAssets/vuejs/_api/AddAddress";
export default {
name: "App",
@ -39,6 +36,9 @@ export default {
},
addressId: window.addressId | null,
backUrl: window.backUrl,
valid: {
from: new Date()
},
},
addAddress: {
options: {
@ -75,12 +75,75 @@ export default {
},
submitAddress() {
console.log('@@@ click on Submit Address Button');
let payload = this.$refs.addAddress.submitNewAddress(); // Cast child method
this.addDateToAddressAndPostAddressTo(payload);
},
addDateToAddressAndPostAddressTo(payload)
{
payload.body = {
validFrom: {
datetime: `${this.context.valid.from.toISOString().split('T')[0]}T00:00:00+0100`
}
};
console.log('addDateToAddress', payload);
// Cast child method
this.$refs.addAddress.submitNewAddress();
// it fetch post request only for person and household
// else get returned payload then dispatch from here (parent)
}
this.$refs.addAddress.flag.loading = true;
return patchAddress(payload.addressId, payload.body)
.then(address => new Promise((resolve, reject) => {
this.context.valid.from = address.validFrom;
resolve();
})
.then(this.postAddressTo(payload))
)
.catch((error) => {
this.$refs.addAddress.errorMsg.push(error);
this.$refs.addAddress.flag.loading = false;
});
},
postAddressTo(payload)
{
console.log('postAddressTo', payload.entity);
if (!this.context.edit) {
switch (payload.entity) {
case 'household':
postAddressToHousehold(payload.entityId, payload.addressId)
.then(household => new Promise((resolve, reject) => {
console.log('..toHousehold', household);
this.$refs.addAddress.flag.loading = false;
this.$refs.addAddress.flag.success = true;
window.location.assign(this.context.backUrl);
resolve();
}))
.catch((error) => {
this.$refs.addAddress.errorMsg.push(error);
this.$refs.addAddress.flag.loading = false;
})
;
break;
case 'person':
postAddressToPerson(payload.entityId, payload.addressId)
.then(person => new Promise((resolve, reject) => {
console.log('..toPerson', person);
this.$refs.addAddress.flag.loading = false;
this.$refs.addAddress.flag.success = true;
window.location.assign(this.context.backUrl);
resolve();
}))
.catch((error) => {
this.$refs.addAddress.errorMsg.push(error);
this.$refs.addAddress.flag.loading = false;
})
;
break;
default:
this.$refs.addAddress.errorMsg.push('That entity is not managed by address !');
}
} else {
// address is already linked, just finish !
window.location.assign(this.context.backUrl);
}
},
}
}
</script>

View File

@ -29,7 +29,7 @@
v-bind:options="this.options"
v-bind:default="this.default"
v-bind:entity="this.entity"
v-bind:valid="this.valid"
v-bind:valid="this.context.valid"
v-bind:flag="this.flag"
ref="showAddress">
</show-address-pane>
@ -55,7 +55,7 @@
v-bind:options="this.options"
v-bind:default="this.default"
v-bind:entity="this.entity"
v-bind:valid="this.valid"
v-bind:valid="this.context.valid"
v-bind:flag="this.flag"
ref="showAddress"
v-bind:insideModal="false" @openEditPane="openEditPane"
@ -182,10 +182,6 @@ export default {
zoom: 12
},
},
valid: {
from: new Date(),
to: null
},
errorMsg: []
}
},
@ -248,7 +244,6 @@ export default {
* Opening and closing Panes when interacting with buttons
*/
openShowPane() {
console.log('open the Show Panel');
if (this.context.edit) {
this.getInitialAddress(this.context.addressId);
@ -263,17 +258,18 @@ export default {
} else {
this.flag.showPane = true;
console.log('step1: open the Show Panel');
}
},
openEditPane() {
console.log('open the Edit panel');
console.log('step2: open the Edit panel');
this.initForm();
this.getCountries();
},
closeEditPane() {
console.log('close the Edit Panel');
console.log('step2: close the Edit Panel');
this.applyChanges();
this.flag.showPane = true;
this.flag.editPane = false;
@ -413,7 +409,7 @@ export default {
newAddress: newAddress
});
} else {
this.addAddress(newAddress);
this.addNewAddress(newAddress);
}
},
@ -421,56 +417,52 @@ export default {
* Async POST transactions,
* creating new address, and receive backend datas when promise is resolved
*/
addAddress(payload)
addNewAddress(payload)
{
//console.log('addNewAddress', payload);
this.flag.loading = true;
if ('newPostcode' in payload) {
let postcodeBody = payload.newPostcode;
if (this.context.entity.type === 'person') {
postcodeBody = Object.assign(postcodeBody, {'origin': 3});
}
postPostalCode(postcodeBody)
.then(postalCode => {
let body = payload;
body.postcode = {'id': postalCode.id },
postAddress(body)
.then(address => new Promise((resolve, reject) => {
this.entity.address = address;
this.flag.loading = false;
this.flag.success = true;
resolve();
}))
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
});
})
.then(postalCode => {
payload.postcode = {'id': postalCode.id };
this.postNewAddress(payload);
});
} else {
postAddress(payload)
.then(address => new Promise((resolve, reject) => {
this.entity.address = address;
this.flag.loading = false;
this.flag.success = true;
resolve();
}))
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
});
this.postNewAddress(payload);
}
},
postNewAddress(payload) {
//console.log('postNewAddress', payload);
postAddress(payload)
.then(address => new Promise((resolve, reject) => {
this.entity.address = address;
this.flag.loading = false;
this.flag.success = true;
resolve();
}))
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
});
},
/*
* Async PATCH transactions,
* then update existing address with backend datas when promise is resolved
*/
updateAddress(payload)
{
// TODO change the condition because it writes new postal code in edit mode now: !writeNewPostalCode
this.flag.loading = true;
// TODO change the condition because it writes new postal code in edit mode now: !writeNewPostalCode
if ('newPostcode' in payload.newAddress) {
let postcodeBody = payload.newAddress.newPostcode;
@ -478,38 +470,32 @@ export default {
postPostalCode(postcodeBody)
.then(postalCode => {
let body = payload.newAddress;
body.postcode = {'id': postalCode.id },
patchAddress(payload.addressId, body)
.then(address => new Promise((resolve, reject) => {
this.entity.address = address;
this.flag.loading = false;
this.flag.success = true;
resolve();
}))
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
});
})
payload.newAddress.postcode = {'id': postalCode.id };
this.patchExistingAddress(payload);
});
} else {
patchAddress(payload.addressId, payload.newAddress)
.then(address => new Promise((resolve, reject) => {
this.entity.address = address;
this.flag.loading = false;
this.flag.success = true;
resolve();
}))
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
});
this.patchExistingAddress(payload);
}
},
patchExistingAddress(payload) {
console.log('patchExistingAddress', payload);
patchAddress(payload.addressId, payload.newAddress)
.then(address => new Promise((resolve, reject) => {
this.entity.address = address;
this.flag.loading = false;
this.flag.success = true;
resolve();
}))
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
});
},
/*
* When submit address
* Method called by parent when submitting address
* (get out step1 show pane, submit button)
*/
submitNewAddress()
@ -517,92 +503,16 @@ export default {
let payload = {
entity: this.context.entity.type,
entityId: this.context.entity.id,
addressId: this.entity.address.address_id,
body: {
validFrom: {
datetime: `${this.valid.from.toISOString().split('T')[0]}T00:00:00+0100`
}
},
backUrl: this.context.backUrl
}
addressId: this.entity.address.address_id
};
if ( payload.entity !== 'person' && payload.entity !== 'household' ) {
// just return payload to parent
// (changes will be patched in parent store)
this.initForm();
this.flag.showPane = false;
return payload;
}
console.log('submitNewAddress with', payload);
this.addDateToAddressAndAddressTo(payload);
console.log('submitNewAddress return', payload);
this.initForm();
this.flag.showPane = false;
},
addDateToAddressAndAddressTo(payload)
{
console.log('addDateToAddressAndAddressTo', payload.entity)
this.flag.loading = true;
return patchAddress(payload.addressId, payload.body)
.then(address => new Promise((resolve, reject) => {
this.valid.from = address.validFrom;
resolve();
})
.then(this.postAddressTo(payload))
)
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
});
},
postAddressTo(payload)
{
console.log('postAddressTo', payload.entity);
if (!this.context.edit) {
switch (payload.entity) {
case 'household':
postAddressToHousehold(payload.entityId, payload.addressId)
.then(household => new Promise((resolve, reject) => {
console.log('postAddressToHousehold', household);
this.flag.loading = false;
this.flag.success = true;
window.location.assign(payload.backUrl);
resolve();
}))
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
})
;
break;
case 'person':
postAddressToPerson(payload.entityId, payload.addressId)
.then(person => new Promise((resolve, reject) => {
console.log('postAddressToPerson', person);
this.flag.loading = false;
this.flag.success = true;
window.location.assign(payload.backUrl);
resolve();
}))
.catch((error) => {
this.errorMsg.push(error);
this.flag.loading = false;
})
;
break;
default:
this.errorMsg.push('That entity is not managed by address !');
}
} else {
// address is already linked, just finish !
window.location.assign(payload.backUrl);
}
},
return payload;
}
}
}
</script>

View File

@ -97,6 +97,7 @@ export default {
this.entity.selected.address = value;
this.entity.selected.address.street = value.street;
this.entity.selected.address.streetNumber = value.streetNumber;
this.entity.selected.writeNew.address = false;
this.updateMapCenter(value.point);
},
listenInputSearch(query) {
@ -107,6 +108,7 @@ export default {
let addr = this.splitAddress(this.$data.value.text);
this.entity.selected.address.street = addr.street;
this.entity.selected.address.streetNumber = addr.number;
this.entity.selected.writeNew.address = true;
}
},
splitAddress(address) {
@ -136,6 +138,7 @@ export default {
}
},
addAddress() {
console.log('addAddress: pass here ?? never, it seems');
this.entity.selected.writeNew.address = true;
}
}

View File

@ -95,11 +95,12 @@ export default {
this.entity.selected.city = value;
this.entity.selected.postcode.name = value.name;
this.entity.selected.postcode.code = value.code;
this.entity.selected.writeNew.postcode = false;
this.$emit('getReferenceAddresses', value);
this.focusOnAddress();
},
listenInputSearch(query) {
console.log('listenInputSearch', query, this.isCitySelectorOpen);
//console.log('listenInputSearch', query, this.isCitySelectorOpen);
if (this.isCitySelectorOpen) {
this.$data.value = { text: query };
} else if (this.isEnteredCustomCity) {
@ -108,6 +109,7 @@ export default {
this.entity.selected.city = city;
this.entity.selected.postcode.name = city.name;
this.entity.selected.postcode.code = city.code;
this.entity.selected.writeNew.postcode = true;
}
},
splitCity(city) {
@ -117,7 +119,7 @@ export default {
if (substr.length === 1) {
substr = city.split(' ');
}
console.log('substr', substr);
//console.log('substr', substr);
let decimal = [];
substr.forEach((s, i) => { decimal[i] = /^\d+$/.test(s) });
if (decimal[0] === true) {
@ -138,6 +140,7 @@ export default {
}
},
addPostcode() {
console.log('addPostcode: pass here ?? never, it seems');
this.entity.selected.writeNew.postcode = true;
}
}

View File

@ -79,6 +79,7 @@ const messages = {
},
deathdate: "Date de décès",
years_old: "ans",
household_without_address: "Le ménage de l'usager est sans adresse",
no_data: "Aucune information renseignée",
type: {
thirdparty: "Tiers",

View File

@ -192,3 +192,9 @@
{% endif %}
{% endfor %}
{% endblock %}
{% block comment_widget %}
{% for entry in form %}
{{ form_widget(entry) }}
{% endfor %}
{% endblock comment_widget %}

View File

@ -87,7 +87,6 @@ div.person-view {
}
}
/*
* ACCOMPANYING_COURSE CONTEXT
* Header custom for Accompanying Course
@ -125,7 +124,6 @@ abbr.referrer {
align-self: center; // in flex context
}
/*
* HOUSEHOLD CONTEXT
* Header custom for Household
@ -157,12 +155,19 @@ div.banner {
span.badge-member {
flex-shrink: 0; flex-grow: 0; flex-basis: auto;
color: $white;
border: 1px solid #ffffff3b;
border: 1px solid transparentize($white, 0.75);
border-bottom: 3px solid transparentize( shade-color( $chill-green, 20%), 0.3);
border-radius: 8px;
padding: 0.4em 0.8em;
padding: 0.2em 0.7em;
margin-bottom: 0.2em;
margin-right: 0.3em;
&.holder { order: -1; }
&.holder {
order: -1;
.fa-holder .text-success {
color: transparentize( shade-color( $chill-green, 20%), 0.3) !important;
}
}
&.child { order: 2; }
}
}
@ -179,3 +184,66 @@ div.banner {
}
}
}
div.household-resume {
display: flex;
flex-direction: row;
align-items: center;
div.col-address {
font-size: 120%;
padding-left: 1em;
}
div.col-comment {
//padding: 0;
margin-bottom: 1rem;
display: flex;
flex-direction: column;
> * > * {
& > .chill-user-quote {
margin: 1.5em -1.67em 0;
}
}
}
}
/*
* BADGES, MARKS, PINS
* for chill person theme
*/
// chill person badges
span.badge-person,
span.badge-thirdparty {
display: inline-block;
padding: 0 0.5em !important;
background-color: $white;
color: $dark;
border: 1px solid $chill-ll-gray;
border-bottom-width: 2px;
border-bottom-style: solid;
border-radius: 6px;
a {
text-decoration: none;
}
}
span.badge-person {
border-bottom-color: $chill-green;
}
// todo: move in thirdparty
span.badge-thirdparty {
border-bottom-color: shade-color($chill-pink, 10%);
}
// household holder mark
span.fa-holder {
width: 1em;
margin: -10px 0.3em -8px 0;
i:last-child {
font-weight: 900;
color: white;
font-size: 70%;
font-family: "Open Sans Extrabold";
}
}

View File

@ -26,26 +26,3 @@
}
}
}
// specific chill badges
span.badge-person,
span.badge-thirdparty {
display: inline-block;
padding: 0 0.5em !important;
background-color: $white;
color: $dark;
border: 1px solid $chill-ll-gray;
border-bottom-width: 2px;
border-bottom-style: solid;
border-radius: 6px;
a {
text-decoration: none;
}
}
span.badge-person {
border-bottom-color: $chill-green;
}
// todo: move in thirdparty
span.badge-thirdparty {
border-bottom-color: shade-color($chill-pink, 10%);
}

View File

@ -33,7 +33,7 @@ import AddressRenderBox from "ChillMainAssets/vuejs/_components/Entity/AddressRe
export default {
name: "ButtonLocation",
components: {
import AddressRenderBox from,
AddressRenderBox,
Modal,
},
props: ['person'],

View File

@ -2,16 +2,44 @@
<div class="vue-component">
<h2><a name="section-10"></a>{{ $t('persons_associated.title')}}</h2>
<div v-if="participations.length > 0">
<div v-if="currentParticipations.length > 0">
<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>
</div>
<div v-if="participationWithoutHousehold.length > 0" class="alert alert-warning no-household">
<i class="fa fa-warning fa-2x"></i>
<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>
</div>
<p class="mb-3">{{ $t('persons_associated.person_without_household_warning') }}</p>
<div class="form-check" v-for="p in participationWithoutHousehold">
<input type="checkbox"
class="form-check-input"
v-model="hasNoHousehold"
name="persons[]"
checked="checked"
:id="p.person.id"
:value="p.person.id"
/>
<label class="form-check-label" for="hasNoHousehold">
{{ p.person.text }}
</label>
</div>
<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>
</div>
<div class="flex-table mb-3">
<participation-item
v-for="participation in participations"
v-for="participation in currentParticipations"
v-bind:participation="participation"
v-bind:key="participation.id"
@remove="removeParticipation"
@ -56,10 +84,24 @@ export default {
}
}
},
computed: mapState({
participations: state => state.accompanyingCourse.participations,
counter: state => state.accompanyingCourse.participations.length
}),
computed: {
...mapState({
courseId: state => state.accompanyingCourse.id,
participations: state => state.accompanyingCourse.participations
}),
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) {
//console.log('@@ CLICK remove participation: item', item);
@ -81,3 +123,30 @@ export default {
}
}
</script>
<style lang="scss" scoped>
div#accompanying-course {
div.vue-component {
& > div.alert {
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;
}
& > form {
flex-basis: auto;
div.action {
button.btn-update {
margin-right: 2em;
}
}
}
}
}
}
</style>

View File

@ -5,11 +5,13 @@
addId : false,
addEntity: false,
addLink: false,
addHouseholdLink: true,
addAltNames: true,
addAge : true,
hLevel : 3,
}"
:person="participation.person">
:person="participation.person"
:returnPath="getAccompanyingCourseReturnPath">
<template v-slot:record-actions>
<ul class="record_actions">
@ -40,34 +42,54 @@
<li>
<button v-if="!participation.endDate"
class="btn btn-sm btn-remove"
v-bind:title="$t('action.remove')"
@click.prevent="$emit('close', participation)">
v-bind:title="$t('persons_associated.leave_course')"
@click="modal.showModal = true">
</button>
<button v-else
class="btn btn-sm btn-remove disabled"></button>
</li>
</ul>
</template>
</person-render-box>
<teleport to="body">
<modal v-if="modal.showModal" :modalDialogClass="modal.modalDialogClass" @close="modal.showModal = false">
<template v-slot:header>
<h2 class="modal-title">{{ $t('persons_associated.sure') }}</h2>
</template>
<template v-slot:body>
<p>{{ $t('persons_associated.sure_description') }}</p>
</template>
<template v-slot:footer>
<button class="btn btn-danger" @click.prevent="$emit('close', participation)">
{{ $t('persons_associated.ok') }}
</button>
</template>
</modal>
</teleport>
</template>
<script>
import OnTheFly from 'ChillMainAssets/vuejs/_components/OnTheFly.vue';
import ButtonLocation from '../ButtonLocation.vue';
import PersonRenderBox from 'ChillPersonAssets/vuejs/_components/Entity/PersonRenderBox.vue';
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
export default {
name: 'ParticipationItem',
components: {
OnTheFly,
ButtonLocation,
PersonRenderBox
PersonRenderBox,
Modal
},
props: ['participation'],
emits: ['remove', 'close'],
data() {
return {
modal: {
showModal: false,
modalDialogClass: "modal-dialog-centered modal-md"
},
PersonRenderBox: {
participation: 'participation',
options: {
@ -86,6 +108,9 @@ export default {
return true;
}
return false;
},
getAccompanyingCourseReturnPath() {
return `fr/parcours/${this.$store.state.accompanyingCourse.id}/edit#section-10`;
}
}
}
@ -93,10 +118,7 @@ export default {
/*
* dates of participation
*
* :title="$t('persons_associated.date_start_to_end', {
* start: $d(participation.startDate.datetime, 'short'),
* end: $d(participation.endDate.datetime, 'short')
* })"
*
*
* <tr>
* <td><span v-if="participation.startDate">

View File

@ -42,6 +42,14 @@ const appMessages = {
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 personnes n'appartiennent à aucun ménage actuellement. Renseignez leur appartenance à un ménage dès que possible.",
update_household: "Modifier l'appartenance",
},
requestor: {
title: "Demandeur",

View File

@ -35,7 +35,7 @@
<ul>
<li v-for="p in personsReachables" :key="p.id">
<input type="checkbox" :value="p.id" v-model="personsPicked">
<person-render-box render="badge" :person="p"></person-render-box>
<person-render-box render="badge" :options="{}" :person="p"></person-render-box>
</li>
</ul>
</div>

View File

@ -122,7 +122,7 @@
<ul>
<li v-for="p in personsReachables" :key="p.id">
<input v-model="personsPicked" :value="p.id" type="checkbox">
<person-render-box render="badge" :person="p"></person-render-box>
<person-render-box render="badge" :options="{}" :person="p"></person-render-box>
</li>
</ul>
</div>

View File

@ -25,7 +25,7 @@
<div class="item-row">
<div class="item-col">
<div>
<person-render-box render="badge" :person="conc.person"></person-render-box>
<person-render-box render="badge" :options="{}" :person="conc.person"></person-render-box>
</div>
<div v-if="conc.person.birthdate !== null">
{{ $t('person.born', {'gender': conc.person.gender} ) }}

View File

@ -3,7 +3,7 @@
<div class="item-row">
<div class="item-col">
<div>
<person-render-box render="badge" :person="conc.person"></person-render-box>
<person-render-box render="badge" :options="{}" :person="conc.person"></person-render-box>
<span v-if="isHolder" class="badge bg-primary holder">
{{ $t('household_members_editor.holder') }}
</span>

View File

@ -1,48 +0,0 @@
// CURRENTLY NOT IN USE
<template>
<li v-if="address" class="chill-entity entity-address">
<i v-if="options.with_picto == true" class="fa fa-fw fa-map-marker"></i>
<span v-if="options.render == 'list' || options.render == 'list'" :class="'address ' + {'multiline' : options.multiline === true}">
<!-- if address.street is not empty -->
<p v-if="address.street" class="street">{{ address.street }}
<!-- if address.streetNumber is not empty -->
<span v-if="address.streetNumber" class="streetnumber">{{ address.streetNumber }}</span>
</p>
<!-- if options['extended_infos'] -->
<div v-if="options.extended_infos == true">
<span v-if="address.floor" class="floor">{{ address.floor }}</span>
<span v-if="address.corridor" class="corridor">{{ address.corridor }}</span>
<span v-if="address.steps" class="steps">{{ address.steps }}</span>
<span v-if="address.buildingName" class="buildingName">{{ address.buildingName }}</span>
<span v-if="address.flat" class="flat">{{ address.flat }}</span>
<span v-if="address.distribution" class="distribution">{{ address.distribution }}</span>
<span v-if="address.extra" class="extra">{{ address.extra }}</span>
</div>
<!-- if address.postCode is not empty -->
<div v-if="address.postCode">
<p class="postcode">
<span class="code">{{ address.postCode.code }}</span>
<span class="name">{{ address.postCode.name }}</span>
</p>
<p class="country">{{ address.postCode.country.name }}</p>
</div>
</span>
</li>
</template>
<script>
export default{
name: "AddressRenderBox",
props: ['address', 'options']
}
</script>

View File

@ -44,47 +44,67 @@
</div>
<div class="item-col">
<ul class="list-content fa-ul">
<div class="float-button bottom">
<div class="box">
<div class="action">
<slot name="record-actions"></slot>
</div>
<ul class="list-content fa-ul">
<li v-if="person.current_household_address">
<i class="fa fa-li fa-map-marker"></i>
<address-render-box :address="person.current_household_address" :isMultiline="isMultiline"></address-render-box>
</li>
<li v-else-if="options.addNoData">
<i class="fa fa-li fa-map-marker"></i>
<p class="chill-no-data-statement">{{ $t('renderbox.no_data') }}</p>
</li>
<li v-if="person.current_household_id">
<i class="fa fa-li fa-map-marker"></i>
<address-render-box v-if="person.current_household_address"
:address="person.current_household_address"
:isMultiline="isMultiline">
</address-render-box>
<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})">
<span class="badge rounded-pill bg-chill-beige">
<i class="fa fa-fw fa-home"></i><!--{{ $t('persons_associated.show_household') }}-->
</span>
</a>
</li>
<li v-else-if="options.addNoData">
<i class="fa fa-li fa-map-marker"></i>
<p class="chill-no-data-statement">
{{ $t('renderbox.no_data') }}
</p>
</li>
<li v-if="person.mobilenumber">
<i class="fa fa-li fa-mobile"></i>
<a :href="'tel: ' + person.mobilenumber">{{ person.mobilenumber }}</a>
</li>
<li v-else-if="options.addNoData">
<i class="fa fa-li fa-mobile"></i>
<p class="chill-no-data-statement">{{ $t('renderbox.no_data') }}</p>
</li>
<li v-if="person.phonenumber">
<i class="fa fa-li fa-phone"></i>
<a :href="'tel: ' + person.phonenumber">{{ person.phonenumber }}</a>
</li>
<li v-else-if="options.addNoData">
<i class="fa fa-li fa-phone"></i>
<p class="chill-no-data-statement">{{ $t('renderbox.no_data') }}</p>
</li>
<li v-if="person.mobilenumber">
<i class="fa fa-li fa-mobile"></i>
<a :href="'tel: ' + person.mobilenumber">{{ person.mobilenumber }}</a>
</li>
<li v-else-if="options.addNoData">
<i class="fa fa-li fa-mobile"></i>
<p class="chill-no-data-statement">{{ $t('renderbox.no_data') }}</p>
</li>
<li v-if="person.phonenumber">
<i class="fa fa-li fa-phone"></i>
<a :href="'tel: ' + person.phonenumber">{{ person.phonenumber }}</a>
</li>
<li v-else-if="options.addNoData">
<i class="fa fa-li fa-phone"></i>
<p class="chill-no-data-statement">{{ $t('renderbox.no_data') }}</p>
</li>
<li v-if="person.center && options.addCenter">
<i class="fa fa-li fa-long-arrow-right"></i>
{{ person.center.name }}
</li>
<li v-else-if="options.addNoData">
<i class="fa fa-li fa-long-arrow-right"></i>
<p class="chill-no-data-statement">{{ $t('renderbox.no_data') }}</p>
</li>
<slot name="custom-zone"></slot>
<li v-if="person.center && options.addCenter">
<i class="fa fa-li fa-long-arrow-right"></i>
{{ person.center.name }}
</li>
<li v-else-if="options.addNoData">
<i class="fa fa-li fa-long-arrow-right"></i>
<p class="chill-no-data-statement">{{ $t('renderbox.no_data') }}</p>
</li>
<slot name="custom-zone"></slot>
</ul>
<slot name="record-actions"></slot>
</ul>
</div>
</div>
</div>
</div>
@ -119,7 +139,7 @@ export default {
components: {
AddressRenderBox
},
props: ['person', 'options', 'render'],
props: ['person', 'options', 'render', 'returnPath'],
computed: {
getGenderTranslation: function() {
return this.person.gender == 'woman' ? 'renderbox.birthday.woman' : 'renderbox.birthday.man';
@ -155,12 +175,12 @@ export default {
return "";
}
},
altNameLabel: function(){
altNameLabel: function() {
for(let i = 0; i < this.person.altNames.length; i++){
return this.person.altNames[i].label
}
},
altNameKey: function(){
altNameKey: function() {
for(let i = 0; i < this.person.altNames.length; i++){
return this.person.altNames[i].key
}
@ -168,7 +188,7 @@ export default {
getUrl: function() {
return `/fr/person/${this.person.id}/general`;
},
getAge: function(){
getAge: function() {
if(this.person.birthdate && !this.person.deathdate){
const birthday = new Date(this.person.birthdate.datetime)
const now = new Date()
@ -184,6 +204,10 @@ export default {
// todo: change this
return "Age unknown"
}
},
getCurrentHouseholdUrl: function() {
let returnPath = this.returnPath ? `?returnPath=${this.returnPath}` : ``;
return `/fr/person/household/${this.person.current_household_id}/summary${returnPath}`
}
}
}
@ -191,17 +215,6 @@ export default {
<style lang='scss'>
span.fa-holder {
width: 1em;
margin: -10px 0.3em -8px 0;
i:last-child {
font-weight: 900;
color: white;
font-size: 70%;
font-family: "Open Sans Extrabold";
}
}
.lastname:before{
content: " "
}

View File

@ -9,6 +9,9 @@
* modalTitle twig translated chain
* buttonText twig translated chain
* buttonSize bootstrap class like 'btn-sm'
* buttonDisplayText bool
* binModalStep1 bool
* binModalStep2 bool
#}
<div id="address"></div>

View File

@ -16,6 +16,10 @@
'replace' Twig\Markup,
'after' Twig\Markup
]
* customArea [
'beforeLabel' Twig\Markup,
'afterLabel' Twig\Markup,
]
#}
{% macro raw(person, options) %}
@ -37,11 +41,22 @@
<div class="denomination {{ 'h' ~ options['hLevel'] }}">
{%- if options['addLink'] and is_granted('CHILL_PERSON_SEE', person) -%}
<a href="{{ chill_path_add_return_path('chill_person_view', { 'person_id': person.id }) }}">
{{ _self.raw(person, options) }}
</a>
{%- else -%}
{{ _self.raw(person, options) }}
{%- endif -%}
{% if options['customArea']['beforeLabel'] is defined %}
{{ options['customArea']['beforeLabel'] }}
{% endif %}
{{ _self.raw(person, options) }}
{% if options['customArea']['afterLabel'] is defined %}
{{ options['customArea']['afterLabel'] }}
{% endif %}
{%- if options['addLink'] and is_granted('CHILL_PERSON_SEE', person) -%}
</a>
{%- endif -%}
{%- if options['addEntity'] -%}
<span class="badge rounded-pill bg-secondary">{{ 'Person'|trans }}</span>
{%- endif -%}

View File

@ -4,7 +4,8 @@
{% block content %}
<h1>{{ block('title') }}</h1>
<h1>{{ member.person|chill_entity_render_string }}</h1>
<h2 class="mb-5">{{ 'household.Edit his household'|trans }}</h2>
{{ form_start(form) }}
{{ form_widget(form) }}

View File

@ -0,0 +1,65 @@
{% macro addHolder(holder) %}
{% if holder %}
<span class="fa-stack fa-holder" title="{{ 'household.holder'|trans }}">
<i class="fa fa-circle fa-stack-1x text-success"></i>
<i class="fa fa-stack-1x">T</i>
</span>
{% endif %}
{% endmacro %}
<div class="item-bloc">
<div class="item-row">
<div class="item-col" style="flex-basis: 30%;">
{{ member.person|chill_entity_render_box({
'render': 'label',
'addLink': true,
'addInfo': true,
'customArea': {
'afterLabel': _self.addHolder(member.holder)
}
}) }}
</div>
<div class="item-col">
<div class="float-button top"><div class="box">
<div class="action">
<ul class="record_actions">
{% if customButtons['before'] is defined %}
{{ customButtons['before'] }}
{% endif %}
<li>
<a class="btn btn-sm btn-edit"
title="{{ 'household.Edit member household'|trans }}"
href="{{ chill_path_add_return_path('chill_person_household_member_edit', { 'id': member.id }) }}"></a>
</li>
{% if customButtons['after'] is defined %}
{{ customButtons['after'] }}
{% endif %}
</ul>
</div>
<ul class="list-content fa-ul small ms-0">
{% if member.startDate is not empty %}
<li><i class="fa fa-long-arrow-right"></i>
{{ 'Since %date%'|trans({'%date%': member.startDate|format_date('short') }) }}</li>
{% endif %}
{% if member.endDate is not empty %}
<li><i class="fa fa-long-arrow-right"></i>
{{ 'Until %date%'|trans({'%date%': member.endDate|format_date('short') }) }}</li>
{% endif %}
</ul>
{% if member.comment is not empty %}
<blockquote class="chill-user-quote ms-0 mb-0" style="clear: right">
{{ member.comment|chill_markdown_to_html }}
</blockquote>
{% endif %}
</div></div>
</div>
</div>
</div>

View File

@ -24,12 +24,15 @@
<span
class="badge-member{%- if m.holder %} holder{% endif -%}{%- if m.position.ordering >= 2 %} child{% endif -%}"
title="{{ m.position.label.fr }}">
{%- if m.holder %}
<span class="badge bg-chill-light-gray text-chill-gray">
{{ 'household.holder'|trans }}
</span>
{% endif -%}
{{- m.person|chill_entity_render_box({'addLink': false}) -}}
<a href="{{ path('chill_person_view', { person_id: m.person.id}) }}">
{%- if m.holder %}
<span class="fa-stack fa-holder" title="{{ 'household.holder'|trans }}">
<i class="fa fa-circle fa-stack-1x text-success"></i>
<i class="fa fa-stack-1x">T</i>
</span>
{% endif -%}
{{- m.person|chill_entity_render_box() -}}
</a>
</span>
{%- endfor -%}

View File

@ -17,4 +17,8 @@
'layout': '@ChillPerson/menu.html.twig',
'args' : { 'household': household }
}) }}
{% block block_post_menu %}
{% endblock %}
{% endblock %}

View File

@ -22,5 +22,6 @@
{% endblock %}
{% block css %}
{{ encore_entry_link_tags('vue_household_members_editor') }}
{{ parent() }}
{{ encore_entry_link_tags('vue_household_members_editor') }}
{% endblock %}

View File

@ -2,213 +2,195 @@
{% block title 'household.Household summary'|trans %}
{% block block_post_menu %}
<div class="block-post-menu"></div>
{% endblock %}
{% block content %}
<div class="household-summary">
<h1>{{ block('title') }}</h1>
{#
<h1>{{ block('title') }}</h1>
<h2>{{ 'household.Current address'|trans }}</h2>
#}
<h2>{{ 'household.Current address'|trans }}</h2>
{% set address = household.currentAddress %}
{% set address = household.currentAddress %}
{% if address is empty %}
<p class="chill-no-data-statement">{{ 'household.Household does not have any address currently'|trans }}</p>
{% else %}
<div>
{{ address|chill_entity_render_box({'multiline': true}) }}
</div>
{% endif %}
<h2>{{ 'household.Household members'|trans }}</h2>
{% if form is not null %}
{{ form_start(form) }}
{{ form_row(form.commentMembers) }}
<div id="waitingForBirthContainer">
{{ form_row(form.waitingForBirth) }}
</div>
<div id="waitingForBirthDateContainer">
{{ form_row(form.waitingForBirthDate) }}
</div>
<ul class="record_actions">
<li>
<button type="submit" class="btn btn-save">
{{ 'Save'|trans }}
</button>
</li>
</ul>
{{ form_end(form) }}
{% else %}
{% if not household.commentMembers.isEmpty() %}
{{ household.commentMembers|chill_entity_render_box }}
{% endif %}
{% if household.waitingForBirth %}
{% if household.waitingForBirthDate is not null %}
{{ 'household.Expecting for birth on date'|trans({ 'date': household.waitingForBirthDate|format_date('long') }) }}
{% if address is empty %}
<p class="chill-no-data-statement">{{ 'household.Household does not have any address currently'|trans }}</p>
{% else %}
{{ 'household.Expecting for birth'|trans }}
{% endif %}
{% else %}
<p class="chill-no-data-statement">
{{ 'household.Any expecting birth'|trans }}
</p>
{% endif %}
<div class="row household-resume">
<ul class="record_actions">
<li>
<a href="{{ chill_path_add_return_path('chill_person_household_summary', { 'household_id': household.id, 'edit': 1 }) }}"
class="btn btn-edit">
{{ 'household.Comment and expecting birth'|trans }}
</a>
</li>
</ul>
<div class="item-bloc col-5 col-address">
{% endif %}
<h2>{{ 'Address'|trans }}</h2>
{{ address|chill_entity_render_box({'multiline': true}) }}
{% for p in positions %}
<h3>{{ p.label|localize_translatable_string }}</h3>
<ul class="list-inline text-right mt-2">
<li class="list-inline-item">
{# include vue_address component #}
{% include '@ChillPerson/Address/_insert_vue_address.html.twig' with {
mode: 'create',
buttonSize: 'btn-sm',
buttonText: 'Move household',
modalTitle: 'Move household',
buttonDisplayText: false
} %}
</li>
<li class="list-inline-item">
<a class="btn btn-secondary btn-sm" title="{{ "Addresses history"|trans }}"
href="{{ path('chill_person_household_addresses', { 'household_id': household.id } ) }}">
<i class="fa fa-list fa-fw"></i>
</a>
</li>
</ul>
{% if false == p.shareHousehold %}
<p>{{ 'household.Those members does not share address'|trans }}</p>
{% endif %}
{%- set members = household.currentMembersByPosition(p) %}
{% if members|length > 0 %}
<div class="flex-table list-household-members">
{% for m in members %}
<div class="item-bloc">
<div class="item-row">
<div class="item-col">
<div>
{{ m.person|chill_entity_render_box({'addLink': true}) }}
{% if m.holder %}
<span class="badge bg-primary">{{ 'household.holder'|trans }}</span>
{% endif %}
</div>
<div>
{{ 'Born the date'|trans({ 'gender': m.person.gender, 'birthdate': m.person.birthdate|format_date('long') }) }}
</div>
</div>
<div class="item-col">
<ul class="list-content fa-ul">
{% if m.startDate is not empty %}
<li>{{ 'Since %date%'|trans({'%date%': m.startDate|format_date('long') }) }}</li>
<div class="item-bloc col-7 col-comment">
{% if form is null %}
{% if household.waitingForBirth or not household.commentMembers.isEmpty() %}
<div class="p-4 bg-light">
{% if household.waitingForBirth %}
<i class="fa fa-check-square-o pe-2"></i>
{% if household.waitingForBirthDate is not null %}
{{ 'household.Expecting for birth on date'|trans({ 'date': household.waitingForBirthDate|format_date('long') }) }}
{% else %}
{{ 'household.Expecting for birth'|trans }}
{% endif %}
{% endif %}
{% if not household.commentMembers.isEmpty() %}
{{ household.commentMembers|chill_entity_render_box }}
{% endif %}
</div>
{% endif %}
{% if not household.commentMembers.isEmpty() %}
<a href="{{ chill_path_add_return_path('chill_person_household_summary', { 'household_id': household.id, 'edit': 1 }) }}"
class="btn btn-edit btn-block">
{{ 'household.Edit comment and expecting birth'|trans }}
</a>
{% else %}
<a href="{{ chill_path_add_return_path('chill_person_household_summary', { 'household_id': household.id, 'edit': 1 }) }}"
class="btn btn-create btn-block">
{{ 'household.New comment and expecting birth'|trans }}
</a>
{% endif %}
{% else %}
{{ form_start(form) }}
<div id="waitingForBirthContainer">
{{ form_widget(form.waitingForBirth) }}
</div>
<div id="waitingForBirthDateContainer">
{{ form_widget(form.waitingForBirthDate) }}
</div>
<div class="mt-3">
{{ form_widget(form.commentMembers) }}
</div>
<ul class="record_actions">
<li>
<button type="submit" class="btn btn-save">
{{ 'Save'|trans }}
</button>
</li>
</ul>
{{ form_end(form) }}
{% endif %}
{% if m.endDate is not empty %}
<li>{{ 'Until %date%'|trans({'%date%': m.endDate|format_date('long') }) }}</li>
{% endif %}
</ul>
<ul class="record_actions">
<li>
<a href="{{ chill_path_add_return_path('chill_person_household_member_edit', { 'id': m.id }) }}"
class="btn btn-edit" />
{{ 'household.Update membership'|trans }}
</a>
</li>
<li>
<a href="{{ chill_path_add_return_path('chill_person_household_members_editor', {'persons': [ m.person.id ], 'household': household.id} ) }}"
class="btn btn-misc" />
<i class="fa fa-arrows-h"></i>
{{ 'household.Change position'|trans }}
</a>
</li>
<li>
<a href="{{ chill_path_add_return_path('chill_person_household_members_editor', {'persons': [ m.person.id ], 'allow_leave_without_household': true } ) }}"
class="btn btn-misc" />
<i class="fa fa-sign-out"></i>
{{ 'household.Leave'|trans }}
</a>
</li>
</ul>
</div>
</div>
{% if m.comment is not empty %}
<div class="item-row comment">
<blockquote class="chill-user-quote">
{{ m.comment|chill_markdown_to_html }}
</blockquote>
</div>
{% endif %}
</div>
{% endfor %}
</div>
{% else %}
<p class="chill-no-data-statement">{{ 'household.Any persons into this position'|trans }}</p>
{% endif %}
{% endif %}
{% set members = household.nonCurrentMembersByPosition(p) %}
{% if members|length > 0 %}
<p><!-- force a space after table --></p>
<button class="btn btn-green" type="button" data-bs-toggle="collapse" data-bs-target="#nonCurrent_{{ p.id }}" aria-expanded="false" aria-controls="collapse non current members">
{{ 'household.Show future or past memberships'|trans({'length': members|length}) }}
</button>
<h2 class="my-5">{{ 'household.Household members'|trans }}</h2>
<div id="nonCurrent_{{ p.id }}" class="collapse">
<div class="flex-table list-household-members">
{% for m in members %}
<div class="item-bloc">
<div class="item-row">
<div class="item-col">
<div>
{{ m.person|chill_entity_render_box({'addLink': true}) }}
{% if m.holder %}
<span class="badge bg-primary">{{ 'household.holder'|trans }}</span>
{% endif %}
{% for p in positions %}
<div class="mb-5">
<h3>{{ p.label|localize_translatable_string }}
{% if false == p.shareHousehold %}
<i class="chill-help-tooltip" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-html="true"
title="{{ 'household.Those members does not share address'|trans }}"></i>
{% endif %}
</h3>
{%- set members = household.currentMembersByPosition(p) %}
{% macro customButtons(member, household) %}
<li>
<a href="{{ chill_path_add_return_path('chill_person_household_members_editor', {'persons': [ member.person.id ], 'allow_leave_without_household': true } ) }}"
class="btn btn-sm btn-unlink" title="{{ 'household.person.leave'|trans }}"></a>
</li>
<li>
<a href="{{ chill_path_add_return_path('chill_person_household_members_editor', {'persons': [ member.person.id ], 'household': household.id} ) }}"
class="btn btn-sm btn-misc" title="{{ 'household.Change position'|trans }}"><i class="fa fa-arrows-h"></i></a>
</li>
{% endmacro %}
{% if members|length > 0 %}
<div class="flex-table list-household-members">
{% for m in members %}
{% include '@ChillPerson/Household/_render_member.html.twig' with {
'member': m,
'customButtons': { 'after': _self.customButtons(m, household) }
} %}
{% endfor %}
</div>
{% else %}
<p class="chill-no-data-statement">{{ 'household.Any persons into this position'|trans }}</p>
{% endif %}
{% set members = household.nonCurrentMembersByPosition(p) %}
{% if members|length > 0 %}
<style>
button[aria-expanded="true"] > span.folded,
button[aria-expanded="false"] > span.unfolded { display: none; }
button[aria-expanded="false"] > span.folded,
button[aria-expanded="true"] > span.unfolded { display: inline; }
</style>
<div class="accordion" id="nonCurrent">
<div class="accordion-item">
<h2 class="accordion-header" id="heading_{{ p.id }}">
<button
class="accordion-button collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target="#collapse_{{ p.id }}"
aria-expanded="false"
aria-controls="collapse_{{ p.id }}">
<span class="folded">{{ 'household.Show future or past memberships'|trans({'length': members|length}) }}</span>
<span class="unfolded text-secondary">{{ 'household.Hide memberships'|trans }}</span>
</button>
</h2>
<div id="collapse_{{ p.id }}"
class="accordion-collapse collapse"
aria-labelledby="heading_{{ p.id }}"
data-bs-parent="#nonCurrent">
<div class="flex-table my-0 list-household-members">
{% for m in members %}
{% include '@ChillPerson/Household/_render_member.html.twig' with { 'member': m } %}
{% endfor %}
</div>
</div>
<div>
{{ 'Born the date'|trans({ 'gender': m.person.gender, 'birthdate': m.person.birthdate|format_date('long') }) }}
</div>
</div>
<div class="item-col">
<ul class="list-content fa-ul">
{% if m.startDate is not empty %}
<li>{{ 'Since %date%'|trans({'%date%': m.startDate|format_date('long') }) }}</li>
{% endif %}
{% if m.endDate is not empty %}
<li>{{ 'Until %date%'|trans({'%date%': m.endDate|format_date('long') }) }}</li>
{% endif %}
</ul>
<ul class="record_actions">
<li>
<a href="{{ chill_path_add_return_path('chill_person_household_member_edit', { 'id': m.id }) }}"
class="btn btn-edit">
{{ 'household.Update membership'|trans }}
</a>
</li>
</ul>
</div>
</div>
{% if m.comment is not empty %}
<div class="item-row comment">
<blockquote class="chill-user-quote">
{{ m.comment|chill_markdown_to_html }}
</blockquote>
</div>
{% endif %}
</div>
{% endfor %}
</div>
</div>
{% endif %}
</div>
{% endfor %}
{% endif %}
{% endfor %}
<ul class="record_actions">
<li>
<a href="{{ chill_path_add_return_path('chill_person_household_members_editor', {'household': household.id }) }}"
class="btn btn-create">
{{ 'household.Add a member'|trans }}
</a>
</li>
</ul>
<ul class="record_actions">
<li>
<a href="{{ chill_path_add_return_path('chill_person_household_members_editor', {'household': household.id }) }}"
class="btn btn-create">
{{ 'household.Add a member'|trans }}
</a>
</li>
</ul>
</div>
{% endblock %}

View File

@ -19,6 +19,7 @@
namespace Chill\PersonBundle\Serializer\Normalizer;
use Chill\MainBundle\Entity\Center;
use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Entity\Person;
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
@ -61,6 +62,9 @@ class PersonNormalizer implements
public function normalize($person, string $format = null, array $context = array())
{
/** @var Household $household */
$household = $person->getCurrentHousehold();
/** @var Person $person */
return [
'type' => 'person',
@ -77,6 +81,7 @@ class PersonNormalizer implements
'gender' => $person->getGender(),
'gender_numeric' => $person->getGenderNumeric(),
'current_household_address' => $this->normalizer->normalize($person->getCurrentHouseholdAddress()),
'current_household_id' => $household ? $this->normalizer->normalize($household->getId()) : null,
];
}
@ -90,7 +95,7 @@ class PersonNormalizer implements
return $r;
}
public function supportsNormalization($data, string $format = null): bool
{

View File

@ -62,6 +62,7 @@ class PersonRender extends AbstractChillEntityRender
'address_multiline' => $options['address_multiline'] ?? false,
'hLevel' => $options['hLevel'] ?? 3,
'customButtons' => $options['customButtons'] ?? [],
'customArea' => $options['customArea'] ?? [],
];
return

View File

@ -19,10 +19,13 @@ household:
many {Montrer # anciennes ou futures appartenances}
other {Montrer # anciennes ou futures appartenances}
}
Hide memberships: Masquer
Those members does not share address: Ces usagers ne partagent pas l'adresse du ménage.
Any persons into this position: Aucune personne n'appartient au ménage à cette position.
Leave household: Quitter le ménage
Leave: Quitter
Leave: Détacher
person:
leave: L'usager quitte le ménage
Join: Rejoindre un ménage
Change position: Repositionner
Household file: Dossier ménage
@ -36,10 +39,11 @@ household:
is not holder: N'est pas titulaire
holder: Titulaire
Edit member household: Modifier l'appartenance au ménage
Edit his household: Modifier son appartenance au ménage
Current household members: Membres actuels
Household summary: Résumé du ménage
Accompanying period: Parcours d'accompagnement
Addresses: Adresses
Addresses: Historique adresse
Current address: Adresse actuelle
Household does not have any address currently: Le ménage n'a pas d'adresse renseignée actuellement
Edit household members: Modifier l'appartenance au ménage
@ -52,7 +56,8 @@ household:
Expecting for birth on date: Naissance attendue pour le {date}
Expecting for birth: Naissance attendue (date inconnue)
Any expecting birth: Aucune naissance proche n'a été renseignée.
Comment and expecting birth: Commentaire et naissance attendue
New comment and expecting birth: Écrire un commentaire
Edit comment and expecting birth: Mettre à jour le commentaire
Edit member metadata: Données supplémentaires
comment_membership: Commentaire général sur les membres
expecting_birth: Naissance attendue ?

View File

@ -32,24 +32,29 @@
</div>
<div class="item-col">
<ul class="list-content fa-ul">
<li v-if="thirdparty.address">
<i class="fa fa-li fa-map-marker"></i>
<address-render-box :address="thirdparty.address" :isMultiline="isMultiline"></address-render-box>
</li>
<li v-if="thirdparty.phonenumber">
<i class="fa fa-li fa-mobile"></i>
<a :href="'tel: ' + thirdparty.phonenumber">{{ thirdparty.phonenumber }}</a>
</li>
<li v-if="thirdparty.email">
<i class="fa fa-li fa-envelope-o"></i>
<a :href="'mailto: ' + thirdparty.email">{{ thirdparty.email }}</a>
</li>
</ul>
<slot name="record-actions"></slot>
<div class="float-button bottom">
<div class="box">
<div class="action">
<slot name="record-actions"></slot>
</div>
<ul class="list-content fa-ul">
<li v-if="thirdparty.address">
<i class="fa fa-li fa-map-marker"></i>
<address-render-box :address="thirdparty.address" :isMultiline="isMultiline"></address-render-box>
</li>
<li v-if="thirdparty.telephone">
<i class="fa fa-li fa-mobile"></i>
<a :href="'tel: ' + thirdparty.telephone">{{ thirdparty.telephone }}</a>
</li>
<li v-if="thirdparty.email">
<i class="fa fa-li fa-envelope-o"></i>
<a :href="'mailto: ' + thirdparty.email">{{ thirdparty.email }}</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</section>
</div>

View File

@ -13,6 +13,10 @@
'replace' Twig\Markup,
'after' Twig\Markup
]
* customArea [
'beforeLabel' Twig\Markup,
'afterLabel' Twig\Markup,
]
#}
{% macro raw(thirdparty, options) %}
@ -23,13 +27,25 @@
<div class="entity-label">
<div class="denomination {{ 'h' ~ options['hLevel'] }}">
{%- if options['addLink'] and is_granted('CHILL_3PARTY_3PARTY_SHOW', thirdparty) -%}
<a href="{{ chill_path_add_return_path('chill_3party_3party_show', { 'thirdparty_id': thirdparty.id }) }}">
{{ _self.raw(thirdparty, options) }}
</a>
{%- else -%}
{{ _self.raw(thirdparty, options) }}
{%- endif -%}
{% if options['customArea']['beforeLabel'] is defined %}
{{ options['customArea']['beforeLabel'] }}
{% endif %}
{{ _self.raw(thirdparty, options) }}
{% if options['customArea']['afterLabel'] is defined %}
{{ options['customArea']['afterLabel'] }}
{% endif %}
{%- if options['addLink'] and is_granted('CHILL_3PARTY_3PARTY_SHOW', thirdparty) -%}
</a>
{%- endif -%}
{%- if options['addEntity'] -%}
<span class="badge rounded-pill bg-secondary">{{ 'Third party'|trans }}</span>
{%- endif -%}

View File

@ -54,6 +54,7 @@ class ThirdPartyRender extends AbstractChillEntityRender
'addInfo' => $options['addInfo'] ?? false,
'hLevel' => $options['hLevel'] ?? 3,
'customButtons' => $options['customButtons'] ?? [],
'customArea' => $options['customArea'] ?? [],
];
return