first layout for form edit

This commit is contained in:
Julien Fastré 2021-06-09 16:13:39 +02:00
parent 18217f53e8
commit e14205ae1d
16 changed files with 386 additions and 83 deletions

View File

@ -0,0 +1,121 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg34"
version="1.1"
viewBox="0 0 32 32">
<metadata
id="metadata40">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs38" />
<rect
id="rect2"
x="0"
y="4"
width="4"
height="4" />
<rect
id="rect4"
x="0"
y="12"
width="4"
height="4" />
<rect
id="rect6"
x="0"
y="20"
width="4"
height="4" />
<rect
id="rect8"
x="0"
y="28"
width="4"
height="4" />
<rect
id="rect10"
x="8"
y="4"
width="4"
height="4" />
<rect
id="rect12"
x="8"
y="12"
width="4"
height="4" />
<rect
id="rect14"
x="8"
y="20"
width="4"
height="4" />
<rect
id="rect16"
x="8"
y="28"
width="4"
height="4" />
<rect
id="rect18"
x="16"
y="4"
width="4"
height="4" />
<rect
id="rect20"
x="16"
y="12"
width="4"
height="4" />
<rect
id="rect22"
x="16"
y="20"
width="4"
height="4" />
<rect
id="rect24"
x="16"
y="28"
width="4"
height="4" />
<rect
id="rect26"
x="24"
y="4"
width="4"
height="4" />
<rect
id="rect28"
x="24"
y="12"
width="4"
height="4" />
<rect
id="rect30"
x="24"
y="20"
width="4"
height="4" />
<rect
id="rect32"
x="24"
y="28"
width="4"
height="4" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,5 +1,7 @@
/**
* Some utils for manipulating dates
*
* **WARNING** experimental
*/
/**
@ -8,6 +10,8 @@
* The date is valid for the same timezone as the date's locale
*
* Do not take time into account
*
* **Experimental**
*/
const dateToISO = (date) => {
return [
@ -19,16 +23,36 @@ const dateToISO = (date) => {
/**
* Return a date object from iso string formatted as YYYY-mm-dd
*
* **Experimental**
*/
const ISOToDate = (str) => {
let
let
[year, month, day] = str.split('-');
return new Date(year, month-1, day);
}
/**
* Return a date object from iso string formatted as YYYY-mm-dd:HH:MM:ss+01:00
*
* **Experimental**
*/
const ISOToDatetime = (str) => {
console.log(str);
let
[cal, times] = str.split('T'),
[year, month, date] = cal.split('-'),
[time, timezone] = cal.split(times.charAt(9)),
[hours, minutes, seconds] = cal.split(':')
;
return new Date(year, month-1, date, hours, minutes, seconds);
}
/**
* Convert a date to ISO8601, valid for usage in api
*
*/
const datetimeToISO = (date) => {
let cal, time, offset;
@ -52,7 +76,6 @@ const datetimeToISO = (date) => {
].join('');
let x = cal + 'T' + time + offset;
console.log('return date', x);
return x;
};
@ -60,5 +83,6 @@ const datetimeToISO = (date) => {
export {
dateToISO,
ISOToDate,
ISOToDatetime,
datetimeToISO
};

View File

@ -17,7 +17,7 @@
// @import "bootstrap/scss/grid";
// @import "bootstrap/scss/tables";
// @import "bootstrap/scss/forms";
// @import "bootstrap/scss/buttons";
@import "bootstrap/scss/buttons";
@import "bootstrap/scss/transitions";
// @import "bootstrap/scss/dropdown";
// @import "bootstrap/scss/button-group";
@ -30,7 +30,7 @@
// @import "bootstrap/scss/pagination";
@import "bootstrap/scss/badge";
// @import "bootstrap/scss/jumbotron";
// @import "bootstrap/scss/alert";
@import "bootstrap/scss/alert";
// @import "bootstrap/scss/progress";
// @import "bootstrap/scss/media";
// @import "bootstrap/scss/list-group";

View File

@ -112,7 +112,7 @@ div.flex-bloc {
display: flex;
flex-direction: column;
div.item-row {
& > div.item-row {
flex-grow: 1; flex-shrink: 1; flex-basis: auto;
display: flex;
flex-direction: column;

View File

@ -62,7 +62,7 @@ const messages = {
person: "un nouvel usager",
thirdparty: "un nouveau tiers"
},
}
},
}
};

View File

@ -47,7 +47,9 @@ div.list-household-members--summary {
.chill-entity__person {
.chill-entity__person__first-name,
.chill-entity__person__last-name {
.chill-entity__person__last-name,
// text is used in vue component 'Person'
.chill-entity__person__text {
font-size: 1.3em;
font-weight: 700;
}

View File

@ -1,25 +1,56 @@
<template>
<h2>{{ $t('household_members_editor.concerned.title') }}</h2>
<div>
<div v-for="conc in concUnpositionned"
<h3>{{ $t('household_members_editor.concerned.persons_to_positionnate') }}</h3>
<div class="flex-table list-household-members">
<div v-for="conc in concUnpositionned"
class="item-bloc"
v-bind:key="conc.person.id"
draggable="true"
@dragstart="onStartDragConcern($event, conc.person.id)"
>
<span>{{ conc.person.text }}</span>
<span>
{{ $t('household_members_editor.concerned.move_to') }}:
</span>
<span
v-for="position in positions"
@click="moveToPosition(conc.person.id, position.id)"
>
{{ position.label.fr }}
</span>
<button v-if="conc.allowRemove" @click="removeConcerned(conc)">
{{ $t('household_members_editor.remove_concerned') }}
</button>
<div class="item-row person">
<div class="item-col box-person">
<div>
<img src="~ChillMainAssets/img/draggable.svg" class="drag-icon" />
<person :person="conc.person"></person>
</div>
<div>
{{ $t('person.born', {'gender': conc.person.gender} ) }}
{{ $d(conc.person.birthdate.datetime, 'short') }}
</div>
</div>
<div class="item-col box-where">
<ul class="list-content fa-ul">
<li>
<i class="fa fa-li fa-map-marker"></i>
<span class="chill-no-data-statement">Sans adresse</span>
</li>
</ul>
</div>
</div>
<div class="item-row move_to">
<div class="item-col">
<template
v-for="position in positions"
>
<button
class="btn btn-outline-primary"
@click="moveToPosition(conc.person.id, position.id)"
>
{{ position.label.fr }}
</button>&nbsp;
</template>
<button v-if="conc.allowRemove" @click="removeConcerned(conc)" class="btn bt-primary">
{{ $t('household_members_editor.remove_concerned') }}
</button>
</div>
</div>
</div>
</div>
@ -39,8 +70,8 @@
<div
v-for="position in positions"
>
<h2>{{ position.label.fr }}</h2>
<ul>
<h3>{{ position.label.fr }}</h3>
<div class="flex-table list-household-members">
<member-details
v-for="conc in concByPosition(position.id)"
v-bind:key="conc.person.id"
@ -49,14 +80,15 @@
@dragstart="onStartDragConcern($event, conc.person.id)"
>
</member-details>
<li
class="droppable"
<div
class="droppable_zone"
@drop="onDropConcern($event, position.id)"
@dragover.prevent
@dragenter.prevent
>
</li>
</ul>
{{ $t('household_members_editor.drop_persons_here', {'position': position.label.fr }) }}
</div>
</div>
</div>
</div>
@ -64,33 +96,53 @@
</template>
<style scoped>
.concerned_box {
div.person {
cursor: move;
padding: 1.5em;
border: 1px solid black;
* {
cursor: move
}
}
.concerned_box * {
cursor: move;
.drag-icon {
height: 1.1em;
margin-right: 0.5em;
}
.droppable_zone {
min-height: 50px;
width: 100%;
border: 1px solid black;
background-color: var(--chill-llight-gray);
color: white;
font-size: large;
text-align: center;
display: table-cell;
vertical-align: middle;
padding: 1em;
background: linear-gradient(to top, var(--chill-light-gray), 30%, var(--chill-llight-gray));
}
</style>
<script>
import { mapGetters } from 'vuex';
import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue';
import Person from 'ChillPersonAssets/vuejs/_components/Person/Person.vue';
import MemberDetails from './MemberDetails.vue';
import { ISOToDatetime } from 'ChillMainAssets/js/date.js';
export default {
name: 'Concerned',
components: {
AddPersons,
MemberDetails,
Person,
},
computed: {
as_date: (state) => (d) => {
console.log(d);
let k = ISOToDatetime(d);
console.log(k);
return k;
},
...mapGetters([
'concUnpositionned',
'positions',

View File

@ -1,16 +1,31 @@
<template>
<div v-if="hasWarnings" class="alert alert-warning">
{{ $t('household_members_editor.confirmation.there_are_warnings') }}
</div>
<p v-if="hasWarnings">
{{ $t('household_members_editor.confirmation.check_those_items') }}
</p>
<ul>
<li v-for="(msg, index) in warnings">
{{ $t(msg.m, msg.a) }}
</li>
</ul>
<div v-if="hasNoWarnings">
<button class="sc-button bt-green" @click="confirm">{{ $t('household_member_editor.confirmation') }}</button>
</div>
<ul class="record_actions sticky-form-buttons">
<li>
<button class="sc-button bt-save" :disabled="hasWarnings" @click="confirm">
{{ $t('household_members_editor.confirmation.save') }}
</button>
</li>
</ul>
</template>
<style scoped lang="scss">
</style>
<script>
import { mapState } from 'vuex';
@ -20,6 +35,7 @@ export default {
...mapState({
warnings: (state) => state.warnings,
hasNoWarnings: (state) => state.warnings.length === 0,
hasWarnings: (state) => state.warnings.length > 0,
}),
},
methods: {

View File

@ -1,9 +1,9 @@
<template>
<h2>{{ $t('household_member_editor.dates_title') }}</h2>
<h2>{{ $t('household_members_editor.dates_title') }}</h2>
<p>
<label for="start_date">
{{ $t('household_member_editor.dates.start_date') }}
{{ $t('household_members_editor.dates.start_date') }}
</label>
<input type="date" v-model="startDate" />
</p>

View File

@ -1,29 +1,29 @@
<template>
<h2>{{ $t('household_member_editor.household_part') }}</h2>
<h2>{{ $t('household_members_editor.household_part') }}</h2>
<div v-if="hasHousehold">
<span v-if="isHouseholdNew">
{{ $t('household_member_editor.new_household') }}
{{ $t('household_members_editor.new_household') }}
</span>
<div v-else>
Ménage existant
</div>
</div>
<div v-else-if="isForceLeaveWithoutHousehold">
{{ $t('household_member_editor.will_leave_any_household') }}
{{ $t('household_members_editor.will_leave_any_household') }}
</div>
<div v-else>
Aucun ménage
</div>
<button v-if="allowHouseholdCreate" class="sc-button bt-create" @click="createHousehold">
{{ $t('household_member_editor.create_household') }}
{{ $t('household_members_editor.create_household') }}
</button>
<button v-if="allowHouseholdSearch">
{{ $t('household_member_editor.search_household') }}
{{ $t('household_members_editor.search_household') }}
</button>
<button v-if="allowLeaveWithoutHousehold" @click="forceLeaveWithoutHousehold">
{{ $t('household_member_editor.leave_without_household') }}
{{ $t('household_members_editor.leave_without_household') }}
</button>
</template>

View File

@ -1,29 +1,82 @@
<template>
<li>
<div>
<span>{{ conc.person.text }}</span>
<span v-if="conc.position.allowHolder">
<button class="badge badge-pill" :class="{ 'badge-primary': isHolder, 'badge-secondary': !isHolder}" @click="toggleHolder">
{{ $t('household_members_editor.holder') }}
</button>
<div class="item-bloc">
<div class="item-row person">
<div class="item-col box-person">
<div>
<img src="~ChillMainAssets/img/draggable.svg" class="drag-icon" />
<person :person="conc.person"></person>
<span v-if="isHolder" class="badge badge-primary holder">
{{ $t('household_members_editor.holder') }}
</span>
</div>
<div>{{ $t('person.born', {'gender': conc.person.gender} ) }}</div>
</div>
<div class="item-col box-where">
<ul class="list-content fa-ul">
<li>
<i class="fa fa-li fa-map-marker"></i>
<span class="chill-no-data-statement">Sans adresse</span>
</li>
</ul>
</div>
</div>
</span>
<button @click="removePosition">
{{ $t('household_members_editor.remove_position', {position: conc.position.label.fr}) }}
</button>
<button @click="removeConcerned">
{{ $t('household_members_editor.remove_concerned') }}
</button>
<div class="item-row participation-details">
<div v-if="conc.position.allowHolder" class="action">
<button class="btn" :class="{ 'btn-primary': isHolder, 'btn-secondary': !isHolder}" @click="toggleHolder">
{{ $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>
</div>
<div>
<button v-if="conc.allowRemove" @click="removeConcerned" class="btn btn-primary">
{{ $t('household_members_editor.remove_concerned') }}
</button>
</div>
</div>
</div>
</li>
</template>
<style scoped lang="scss">
.drag-icon {
height: 1.1em;
margin-right: 0.5em;
}
div.participation-details {
display: flex;
flex-direction: row !important;
justify-content: flex-end;
.action {
align-self: flex-start;
margin-right: auto;
}
}
.holder {
display: inline;
vertical-align: super;
font-size: 0.6em;
}
</style>
<script>
import { mapGetters } from 'vuex';
import Person from 'ChillPersonAssets/vuejs/_components/Person/Person.vue';
export default {
name: 'MemberDetails',
components: {
Person,
},
props: [
'conc'
],

View File

@ -9,15 +9,31 @@ const appMessages = {
add_persons: "Ajouter d'autres usagers",
search: "Rechercher des usagers",
move_to: "Déplacer vers",
persons_to_positionnate: 'Usagers à positionner',
},
holder: "Titulaire du ménage",
drop_persons_here: "Glissez-déposez ici les usagers pour la position \"{position}\"",
holder: "Titulaire",
is_holder: "Sera titulaire",
is_not_holder: "Ne sera pas titulaire",
remove_position: "Retirer des {position}",
remove_concerned: "Enlever du ménage",
remove_concerned: "Ne plus transférer",
household_part: "Ménage de destination",
new_household: "Nouveau ménage",
create_household: "Créer un ménage",
search_household: "Chercher un ménage",
}
dates_title: "Période de validité",
dates: {
start_date: "Début de validité",
end_date: "Fin de validité",
},
confirmation: {
save: "Enregistrer",
there_are_warnings: "Impossible de valider actuellement",
check_those_items: "Veuillez corriger les éléments suivants",
},
give_a_position_to_every_person: "Indiquer une position pour chaque usager concerné",
}
}
};

View File

@ -194,30 +194,19 @@ const store = createStore({
payload;
if (!getters.hasHousehold && !state.forceLeaveWithoutHousehold) {
warnings.push({ m: 'household_member_editor.add_destination', a: {} });
warnings.push({ m: 'household_members_editor.add_destination', a: {} });
}
if (state.concerned.length === 0) {
warnings.push({ m: 'household_member_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_member_editor.give_a_position_to_every_person', a: {} })
warnings.push({ m: 'household_members_editor.give_a_position_to_every_person', a: {} })
}
if (warnings.length === 0) {
payload = getters.buildPayload;
householdMoveTest(payload).then(errors => {
for (let i in errors.violations) {
console.log('error from server', errors.violations[i]);
warnings.push({ m: errors.violations[i].title, a: {} });
}
commit('setWarnings', warnings);
});
} else {
commit('setWarnings', warnings);
}
commit('setWarnings', warnings);
},
confirm({ getters }) {
let payload = getters.buildPayload;

View File

@ -0,0 +1,16 @@
<template>
<span class="chill-entity chill-entity__person">
<span class="chill-entity__person__text">
{{ person.text }}
</span>
</span>
</template>
<script>
export default {
name: 'Person',
props: ['person']
}
</script>

View File

@ -15,7 +15,15 @@ const personMessages = {
person: {
firstname: "Prénom",
lastname: "Nom",
born: "né{e} le ",
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

View File

@ -1,8 +1,14 @@
{% extends '@ChillMain/layout.html.twig' %}
{% block title 'household.Edit household members'|trans %}
{% block content %}
<h1>Editor</h1>
<div id="household_members_editor"></div>
<div class="grid-12 parent">
<div class="grid-10 push-1 parent">
<h1>{{ block('title') }}</h1>
<div id="household_members_editor"></div>
</div>
</div>
{% endblock %}
{% block js %}