mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Merge branch '37_modal_add-persons'
This commit is contained in:
commit
a63c38b6aa
@ -28,7 +28,7 @@
|
||||
// @import "bootstrap/scss/card";
|
||||
// @import "bootstrap/scss/breadcrumb";
|
||||
// @import "bootstrap/scss/pagination";
|
||||
// @import "bootstrap/scss/badge";
|
||||
@import "bootstrap/scss/badge";
|
||||
// @import "bootstrap/scss/jumbotron";
|
||||
// @import "bootstrap/scss/alert";
|
||||
// @import "bootstrap/scss/progress";
|
||||
@ -41,7 +41,7 @@
|
||||
// @import "bootstrap/scss/popover";
|
||||
// @import "bootstrap/scss/carousel";
|
||||
// @import "bootstrap/scss/spinners";
|
||||
// @import "bootstrap/scss/utilities";
|
||||
@import "bootstrap/scss/utilities";
|
||||
// @import "bootstrap/scss/print";
|
||||
|
||||
@import "custom";
|
||||
|
@ -5,7 +5,7 @@
|
||||
@include button($green, $white);
|
||||
}
|
||||
|
||||
&.bt-reset, &.bt-delete {
|
||||
&.bt-reset, &.bt-delete, &.bt-remove {
|
||||
@include button($red, $white);
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
&.bt-save::before,
|
||||
&.bt-new::before,
|
||||
&.bt-delete::before,
|
||||
&.bt-remove::before,
|
||||
&.bt-update::before,
|
||||
&.bt-edit::before,
|
||||
&.bt-cancel::before,
|
||||
@ -56,7 +57,12 @@
|
||||
// add a trash
|
||||
content: "";
|
||||
}
|
||||
|
||||
|
||||
&.bt-remove::before {
|
||||
// add a times
|
||||
content: "";
|
||||
}
|
||||
|
||||
&.bt-edit::before, &.bt-update::before {
|
||||
// add a pencil
|
||||
content: "";
|
||||
@ -94,6 +100,7 @@
|
||||
&.bt-save::before,
|
||||
&.bt-new::before,
|
||||
&.bt-delete::before,
|
||||
&.bt-remove::before,
|
||||
&.bt-update::before,
|
||||
&.bt-edit::before,
|
||||
&.bt-cancel::before,
|
||||
@ -123,6 +130,7 @@
|
||||
&.bt-save::before,
|
||||
&.bt-new::before,
|
||||
&.bt-delete::before,
|
||||
&.bt-remove::before,
|
||||
&.bt-update::before,
|
||||
&.bt-edit::before,
|
||||
&.bt-cancel::before,
|
||||
|
@ -39,6 +39,8 @@ div.subheader {
|
||||
height: 130px;
|
||||
}
|
||||
|
||||
//// VUEJS ////
|
||||
|
||||
div.vue-component {
|
||||
padding: 1.5em;
|
||||
margin: 2em 0;
|
||||
@ -55,3 +57,97 @@ div.vue-component {
|
||||
}
|
||||
dd { margin-left: 1em; }
|
||||
}
|
||||
|
||||
//// MODAL ////
|
||||
.modal-mask {
|
||||
position: fixed;
|
||||
z-index: 9998;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.75);
|
||||
display: table;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
.modal-header .close { // bootstrap classes, override sc-button 0 radius
|
||||
border-top-right-radius: 0.3rem;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following styles are auto-applied to elements with
|
||||
* transition="modal" when their visibility is toggled
|
||||
* by Vue.js.
|
||||
*
|
||||
* You can easily play with the modal transition by editing
|
||||
* these styles.
|
||||
*/
|
||||
.modal-enter {
|
||||
opacity: 0;
|
||||
}
|
||||
.modal-leave-active {
|
||||
opacity: 0;
|
||||
}
|
||||
.modal-enter .modal-container,
|
||||
.modal-leave-active .modal-container {
|
||||
-webkit-transform: scale(1.1);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
//// AddPersons modal
|
||||
div.modal-body.up {
|
||||
margin: auto 4em;
|
||||
div.search {
|
||||
position: relative;
|
||||
input {
|
||||
padding: 1.2em 1.5em 1.2em 2.5em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
i {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0.5em;
|
||||
padding: 0.65em 0;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
div.results {
|
||||
div.count {
|
||||
margin: -0.5em 0 0.7em;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
div.list-item {
|
||||
line-height: 26pt;
|
||||
padding: 0.3em 0.8em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
&.checked {
|
||||
background-color: #ececec;
|
||||
border-bottom: 1px dotted #8b8b8b;
|
||||
}
|
||||
div.container {
|
||||
& > input {
|
||||
margin-right: 0.8em;
|
||||
}
|
||||
}
|
||||
div.right_actions {
|
||||
margin: 0 0 0 auto;
|
||||
& > * {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
a.sc-button {
|
||||
border: 1px solid lightgrey;
|
||||
font-size: 70%;
|
||||
padding: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.discret {
|
||||
color: grey;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<transition name="modal">
|
||||
<div class="modal-mask">
|
||||
<!-- :: styles bootstrap :: -->
|
||||
<div class="modal-dialog" :class="modalDialogClass">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<slot name="header"></slot>
|
||||
<button class="close sc-button grey" @click="$emit('close')">
|
||||
<i class="fa fa-times" aria-hidden="true"></i></button>
|
||||
</div>
|
||||
<div class="modal-body up" style="overflow-y: unset;">
|
||||
<slot name="body-fixed"></slot>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<slot name="body"></slot>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="sc-button cancel" @click="$emit('close')">{{ $t('action.close') }}</button>
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- :: end styles bootstrap :: -->
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/*
|
||||
* This Modal component is a mix between :
|
||||
* - Vue3 modal implementation
|
||||
* => with 'v-if:showModal' directive:parameter, html scope is added/removed not just shown/hidden
|
||||
* => with slot we can pass content from parent component
|
||||
* => some classes are passed from parent component
|
||||
* - Bootstrap 4.6 _modal.scss module
|
||||
* => using bootstrap css classes, the modal have a responsive behaviour,
|
||||
* => modal design can be configured using css classes (size, scroll)
|
||||
*/
|
||||
export default {
|
||||
name: 'Modal',
|
||||
props: ['modalDialogClass'],
|
||||
emits: ['close']
|
||||
}
|
||||
</script>
|
@ -0,0 +1,55 @@
|
||||
import { createI18n } from 'vue-i18n'
|
||||
|
||||
const datetimeFormats = {
|
||||
fr: {
|
||||
short: {
|
||||
year: "numeric",
|
||||
month: "numeric",
|
||||
day: "numeric"
|
||||
},
|
||||
long: {
|
||||
year: "numeric",
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
weekday: "short",
|
||||
hour: "numeric",
|
||||
minute: "numeric",
|
||||
hour12: false
|
||||
}
|
||||
}
|
||||
};
|
||||
const messages = {
|
||||
fr: {
|
||||
action: {
|
||||
actions: "Actions",
|
||||
show: "Voir",
|
||||
edit: "Modifier",
|
||||
create: "Créer",
|
||||
remove: "Enlever",
|
||||
delete: "Supprimer",
|
||||
save: "Enregistrer",
|
||||
add: "Ajouter",
|
||||
show_modal: "Ouvrir une modale",
|
||||
ok: "OK",
|
||||
cancel: "Annuler",
|
||||
close: "Fermer",
|
||||
next: "Suivant",
|
||||
previous: "Précédent",
|
||||
back: "Retour",
|
||||
check_all: "cocher tout",
|
||||
reset: "réinitialiser"
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const _createI18n = (appMessages) => {
|
||||
Object.assign(messages.fr, appMessages.fr);
|
||||
return createI18n({
|
||||
locale: 'fr',
|
||||
fallbackLocale: 'fr',
|
||||
datetimeFormats,
|
||||
messages,
|
||||
})
|
||||
};
|
||||
|
||||
export { _createI18n }
|
@ -121,7 +121,7 @@ class AccompanyingCourseController extends Controller
|
||||
* @Route(
|
||||
* "/{_locale}/person/api/1.0/accompanying-course/{accompanying_period_id}/participation.{_format}",
|
||||
* name="chill_person_accompanying_course_api_add_participation",
|
||||
* methods={"POST"},
|
||||
* methods={"POST","DELETE"},
|
||||
* format="json",
|
||||
* requirements={
|
||||
* "_format": "json",
|
||||
@ -129,7 +129,7 @@ class AccompanyingCourseController extends Controller
|
||||
* )
|
||||
* @ParamConverter("accompanyingCourse", options={"id": "accompanying_period_id"})
|
||||
*/
|
||||
public function addParticipationAPI(Request $request, AccompanyingPeriod $accompanyingCourse, $_format): Response
|
||||
public function participationAPI(Request $request, AccompanyingPeriod $accompanyingCourse, $_format): Response
|
||||
{
|
||||
switch ($_format) {
|
||||
case 'json':
|
||||
@ -146,7 +146,9 @@ class AccompanyingCourseController extends Controller
|
||||
}
|
||||
|
||||
// TODO add acl
|
||||
$accompanyingCourse->addPerson($person);
|
||||
$participation = ($request->getMethod() === 'POST') ?
|
||||
$accompanyingCourse->addPerson($person) : $accompanyingCourse->removePerson($person);
|
||||
|
||||
$errors = $this->validator->validate($accompanyingCourse);
|
||||
|
||||
if ($errors->count() > 0) {
|
||||
@ -156,6 +158,6 @@ class AccompanyingCourseController extends Controller
|
||||
|
||||
$this->getDoctrine()->getManager()->flush();
|
||||
|
||||
return new JsonResponse();
|
||||
return $this->json($participation);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\DataFixtures\ORM;
|
||||
|
||||
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
|
||||
/**
|
||||
* Description of LoadAccompanyingPeriod
|
||||
*
|
||||
* @author Champs-Libres Coop
|
||||
*/
|
||||
class LoadAccompanyingPeriod extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface
|
||||
{
|
||||
use \Symfony\Component\DependencyInjection\ContainerAwareTrait;
|
||||
|
||||
|
||||
public const ACCOMPANYING_PERIOD = 'parcours 1';
|
||||
|
||||
public function getOrder()
|
||||
{
|
||||
return 10004;
|
||||
}
|
||||
|
||||
public static $references = array();
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
|
||||
$centerA = $this->getReference('centerA');
|
||||
$centerAId = $centerA->getId();
|
||||
|
||||
$personIds = $this->container->get('doctrine.orm.entity_manager')
|
||||
->createQueryBuilder()
|
||||
->select('p.id')
|
||||
->from('ChillPersonBundle:Person', 'p')
|
||||
->where('p.center = :centerAId')
|
||||
->orderBy('p.id', 'ASC')
|
||||
->setParameter('centerAId', $centerAId)
|
||||
->getQuery()
|
||||
->getScalarResult();
|
||||
|
||||
$openingDate = new \DateTime('2020-04-01');
|
||||
|
||||
$person1 = $manager->getRepository(Person::class)->find($personIds[0]);
|
||||
$person2 = $manager->getRepository(Person::class)->find($personIds[1]);
|
||||
|
||||
$socialScope = $this->getReference('scope_social');
|
||||
|
||||
$a = new AccompanyingPeriod($openingDate);
|
||||
$a->addPerson($person1);
|
||||
$a->addPerson($person2);
|
||||
$a->addScope($socialScope);
|
||||
$a->setStep(AccompanyingPeriod::STEP_CONFIRMED);
|
||||
|
||||
$manager->persist($a);
|
||||
|
||||
$this->addReference(self::ACCOMPANYING_PERIOD, $a);
|
||||
echo "Adding one AccompanyingPeriod\n";
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\DataFixtures\ORM;
|
||||
|
||||
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\Origin;
|
||||
|
||||
/**
|
||||
* Description of LoadAccompanyingPeriodOrigin
|
||||
*
|
||||
* @author Champs-Libres Coop
|
||||
*/
|
||||
class LoadAccompanyingPeriodOrigin extends AbstractFixture implements OrderedFixtureInterface
|
||||
{
|
||||
|
||||
public const ACCOMPANYING_PERIOD_ORIGIN = 'accompanying_period_origin';
|
||||
|
||||
public function getOrder()
|
||||
{
|
||||
return 10005;
|
||||
}
|
||||
|
||||
private $phoneCall = ['en' => 'phone call', 'fr' => 'appel téléphonique'];
|
||||
|
||||
public static $references = array();
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
$o = new Origin();
|
||||
$o->setLabel(json_encode($this->phoneCall));
|
||||
|
||||
$manager->persist($o);
|
||||
|
||||
$this->addReference(self::ACCOMPANYING_PERIOD_ORIGIN, $o);
|
||||
echo "Adding one AccompanyingPeriod Origin\n";
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
<template>
|
||||
<accompanying-course v-bind:accompanying_course="accompanying_course"/>
|
||||
<persons-associated v-bind:persons_associated="accompanying_course.persons"/>
|
||||
<requestor v-bind:accompanying_course="accompanying_course"/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AccompanyingCourse from './components/AccompanyingCourse.vue';
|
||||
import PersonsAssociated from './components/PersonsAssociated.vue';
|
||||
import Requestor from './components/Requestor.vue';
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
AccompanyingCourse,
|
||||
PersonsAssociated,
|
||||
Requestor
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
accompanying_course: {}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
accompanyingCourseId() {
|
||||
return window.accompanyingCourseId;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async getAccompanyingCourse() {
|
||||
let data_;
|
||||
return fetch(`/fr/api/parcours/${accompanyingCourseId}/show`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
this.$data.accompanying_course = data;
|
||||
});
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
await this.getAccompanyingCourse();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
@ -1,26 +0,0 @@
|
||||
<template>
|
||||
<div class="vue-component">
|
||||
<h3>Parcours</h3>
|
||||
<dl>
|
||||
<dt>id</dt>
|
||||
<dd>{{ accompanying_course.id }}</dd>
|
||||
<dt>opening_date</dt>
|
||||
<dd>{{ accompanying_course.opening_date }}</dd>
|
||||
<dt>closing_date</dt>
|
||||
<dd>{{ accompanying_course.closing_date }}</dd>
|
||||
<dt>remark</dt>
|
||||
<dd>{{ accompanying_course.remark }}</dd>
|
||||
<dt>closing_motive</dt>
|
||||
<dd>{{ accompanying_course.closing_motive }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AccompanyingCourse',
|
||||
props: {
|
||||
accompanying_course: Object
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,25 +0,0 @@
|
||||
<template>
|
||||
<tr>
|
||||
<td>{{ person.firstname }}</td>
|
||||
<td>{{ person.lastname }}</td>
|
||||
<td>{{ person.startdate }}</td>
|
||||
<td>{{ person.enddate }}</td>
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
<li><button class="sc-button bt-show"></button></li>
|
||||
<li><button class="sc-button bt-update"></button></li>
|
||||
<li><button class="sc-button bt-delete" @click.prevent="$emit('remove', person)"></button></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'PersonItem',
|
||||
props: {
|
||||
person: { type: Object, required: true }
|
||||
},
|
||||
emits: ['remove']
|
||||
}
|
||||
</script>
|
@ -1,69 +0,0 @@
|
||||
<template>
|
||||
<div class="vue-component">
|
||||
<h3>Usagers concernés</h3>
|
||||
|
||||
<label>{{ counter }} usagers</label>
|
||||
|
||||
<table class="rounded">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="chill-orange">firstname</th>
|
||||
<th class="chill-orange">lastname</th>
|
||||
<th class="chill-orange">startdate</th>
|
||||
<th class="chill-orange">enddate</th>
|
||||
<th class="chill-orange">actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<person-item
|
||||
v-for="person in persons_associated"
|
||||
v-bind:person="person"
|
||||
v-bind:key="person.id"
|
||||
@remove="removePerson" />
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<ul class="record_actions">
|
||||
<li><button class="sc-button bt-create" @click="addPerson">Ajouter un usager</button></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PersonItem from "./PersonItem.vue"
|
||||
|
||||
export default {
|
||||
name: 'PersonsAssociated',
|
||||
components: {
|
||||
PersonItem
|
||||
},
|
||||
props: {
|
||||
persons_associated: Array
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
persons: this.persons_associated
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
async counter() {
|
||||
// Pourquoi je peux pas compter un tableau avec length ???!!!
|
||||
return this.persons_associated.length // <= boum !
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
addPerson() {
|
||||
this.persons_associated.push({
|
||||
"firstname": "Lisa",
|
||||
"lastname": "Simpson",
|
||||
"startdate": "1975-09-15",
|
||||
"enddate": "2021-04-20"
|
||||
})
|
||||
},
|
||||
removePerson(item) {
|
||||
this.persons_associated = this.persons_associated.filter(person => person !== item)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,16 +0,0 @@
|
||||
<template>
|
||||
<div class="vue-component">
|
||||
<h3>Demandeur</h3>
|
||||
{{ accompanying_course.id }}
|
||||
{{ accompanying_course.remark }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Requestor',
|
||||
props: {
|
||||
accompanying_course: Object
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,8 +0,0 @@
|
||||
import App from './App.vue';
|
||||
import { createApp } from 'vue';
|
||||
|
||||
const app = createApp({
|
||||
template: `<app></app>`
|
||||
})
|
||||
.component('app', App)
|
||||
.mount('#accompanying-course');
|
@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<accompanying-course></accompanying-course>
|
||||
<persons-associated></persons-associated>
|
||||
<requestor></requestor>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
import AccompanyingCourse from './components/AccompanyingCourse.vue';
|
||||
import PersonsAssociated from './components/PersonsAssociated.vue';
|
||||
import Requestor from './components/Requestor.vue';
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
AccompanyingCourse,
|
||||
PersonsAssociated,
|
||||
Requestor
|
||||
},
|
||||
computed: mapState([
|
||||
'accompanyingCourse'
|
||||
])
|
||||
};
|
||||
</script>
|
@ -0,0 +1,49 @@
|
||||
const
|
||||
locale = 'fr',
|
||||
format = 'json'
|
||||
, accompanying_period_id = window.accompanyingCourseId //tmp
|
||||
;
|
||||
|
||||
/*
|
||||
* Endpoint chill_person_accompanying_course_api_show
|
||||
* method GET, get AccompanyingCourse Object
|
||||
*
|
||||
* @accompanying_period_id___ integer
|
||||
* @TODO var is not used but necessary in method signature
|
||||
*/
|
||||
let getAccompanyingCourse = (accompanying_period_id___) => { //tmp
|
||||
const url = `/${locale}/person/api/1.0/accompanying-course/${accompanying_period_id}/show.${format}`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoint chill_person_accompanying_course_api_add_participation,
|
||||
* method POST/DELETE, add/close a participation to the accompanyingCourse
|
||||
*
|
||||
* @accompanying_period_id integer - id of accompanyingCourse
|
||||
* @person_id integer - id of person
|
||||
* @method string - POST or DELETE
|
||||
*/
|
||||
let postParticipation = (accompanying_period_id, person_id, method) => {
|
||||
const url = `/${locale}/person/api/1.0/accompanying-course/${accompanying_period_id}/participation.${format}`
|
||||
return fetch(url, {
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
body: JSON.stringify({id: person_id})
|
||||
})
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
export {
|
||||
getAccompanyingCourse,
|
||||
postParticipation
|
||||
};
|
@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<div class="vue-component">
|
||||
<h3>{{ $t('course.title') }}</h3>
|
||||
<dl>
|
||||
<dt>{{ $t('course.id') }}</dt>
|
||||
<dd>{{ accompanyingCourse.id }}</dd>
|
||||
<dt>{{ $t('course.opening_date') }}</dt>
|
||||
<dd>{{ $d(accompanyingCourse.openingDate.datetime, 'short') }}</dd>
|
||||
<dt>{{ $t('course.closing_date') }}</dt>
|
||||
<dd>{{ $d(accompanyingCourse.closingDate.datetime, 'short') }}</dd>
|
||||
<dt>{{ $t('course.remark') }}</dt>
|
||||
<dd>{{ accompanyingCourse.remark }}</dd>
|
||||
<dt>{{ $t('course.closing_motive') }}</dt>
|
||||
<dd>{{ accompanyingCourse.closing_motive }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AccompanyingCourse',
|
||||
computed: {
|
||||
accompanyingCourse() {
|
||||
return this.$store.state.accompanyingCourse
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<tr>
|
||||
<td>{{ participation.person.firstName }}</td>
|
||||
<td>{{ participation.person.lastName }}</td>
|
||||
<td><span v-if="participation.startDate">
|
||||
{{ $d(participation.startDate.datetime, 'short') }}</span>
|
||||
</td>
|
||||
<td><span v-if="participation.endDate">
|
||||
{{ $d(participation.endDate.datetime, 'short') }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a class="sc-button bt-show" target="_blank"
|
||||
:href="url.show"
|
||||
:title="$t('action.show')">
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="sc-button bt-update" target="_blank"
|
||||
:href="url.edit"
|
||||
:title="$t('action.edit')">
|
||||
</a>
|
||||
</li>
|
||||
<!--li>
|
||||
<button class="sc-button bt-delete"
|
||||
:title="$t('action.delete')"
|
||||
@click.prevent="$emit('remove', participation)">
|
||||
</button>
|
||||
</li-->
|
||||
<li>
|
||||
<button class="sc-button bt-remove"
|
||||
:title="$t('action.remove')"
|
||||
@click.prevent="$emit('close', participation)">
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'PersonItem',
|
||||
props: ['participation'],
|
||||
data() {
|
||||
return {
|
||||
url: {
|
||||
show: '/fr/person/' + this.participation.person.id + '/general',
|
||||
edit: '/fr/person/' + this.participation.person.id + '/general/edit'
|
||||
}
|
||||
}
|
||||
},
|
||||
emits: ['remove', 'close']
|
||||
}
|
||||
</script>
|
@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<div class="vue-component">
|
||||
<h3>{{ $t('persons_associated.title')}}</h3>
|
||||
<label>{{ $tc('persons_associated.counter', counter) }}</label>
|
||||
<table class="rounded">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="chill-orange">{{ $t('persons_associated.firstname') }}</th>
|
||||
<th class="chill-orange">{{ $t('persons_associated.lastname') }}</th>
|
||||
<th class="chill-orange">{{ $t('persons_associated.startdate') }}</th>
|
||||
<th class="chill-orange">{{ $t('persons_associated.enddate') }}</th>
|
||||
<th class="chill-orange">{{ $t('action.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<person-item
|
||||
v-for="participation in participations"
|
||||
v-bind:participation="participation"
|
||||
v-bind:key="participation.id"
|
||||
@remove="removeParticipation"
|
||||
@close="closeParticipation">
|
||||
</person-item>
|
||||
</tbody>
|
||||
</table>
|
||||
<add-persons></add-persons>
|
||||
<ul class="record_actions">
|
||||
<!--li>
|
||||
<button class="sc-button orange" @click="savePersons">
|
||||
{{ $t('action.save') }}
|
||||
</button>
|
||||
</li-->
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import PersonItem from "./PersonItem.vue"
|
||||
import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue'
|
||||
|
||||
export default {
|
||||
name: 'PersonsAssociated',
|
||||
components: {
|
||||
PersonItem,
|
||||
AddPersons
|
||||
},
|
||||
computed: mapState({
|
||||
participations: state => state.accompanyingCourse.participations,
|
||||
counter: state => state.accompanyingCourse.participations.length
|
||||
}),
|
||||
methods: {
|
||||
removeParticipation(item) {
|
||||
this.$store.dispatch('removeParticipation', item)
|
||||
},
|
||||
closeParticipation(item) {
|
||||
console.log('@@ CLICK close participation: item', item);
|
||||
this.$store.dispatch('closeParticipation', item)
|
||||
},
|
||||
/*
|
||||
savePersons() {
|
||||
console.log('[wip] saving persons');
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
</script>
|
@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<div class="vue-component">
|
||||
<h3>{{ $t('requestor.title') }}</h3>
|
||||
{{ accompanyingCourse.id }}
|
||||
{{ accompanyingCourse.remark }}<br><br>
|
||||
|
||||
<!-- TESTS AREA -->
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<button class="sc-button bt-create" @click="modal1.showModal = true">
|
||||
{{ $t('action.show_modal') }}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button class="sc-button bt-create" @click="modal2.showModal = true">
|
||||
Ouvrir une seconde modale
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<teleport to="body">
|
||||
<modal v-if="modal1.showModal" :modalDialogClass="modal1.modalDialogClass" @close="modal1.showModal = false">
|
||||
<template v-slot:header>
|
||||
<h3 class="modal-title">Le titre de ma modale</h3>
|
||||
</template>
|
||||
<template v-slot: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>
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<button class="sc-button green" @click="modal1.showModal = false; modal2.showModal = true">
|
||||
{{ $t('action.next')}}</button>
|
||||
</template>
|
||||
</modal>
|
||||
</teleport>
|
||||
|
||||
<teleport to="body">
|
||||
<modal v-if="modal2.showModal" :modalDialogClass="modal2.modalDialogClass" @close="modal2.showModal = false">
|
||||
<template v-slot:header>
|
||||
<h3 class="modal-title">Une autre modale</h3>
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<p>modal 2</p>
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<button class="sc-button green" @click="modal2.showModal = false">
|
||||
{{ $t('action.save')}}</button>
|
||||
</template>
|
||||
</modal>
|
||||
</teleport>
|
||||
<!-- END TESTS -->
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from 'ChillMainAssets/vuejs/_components/Modal'
|
||||
|
||||
export default {
|
||||
name: 'Requestor',
|
||||
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: {
|
||||
accompanyingCourse() {
|
||||
return this.$store.state.accompanyingCourse
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -0,0 +1,23 @@
|
||||
import { createApp } from 'vue'
|
||||
import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n'
|
||||
import { appMessages } from './js/i18n'
|
||||
import { initPromise } from './store'
|
||||
|
||||
import App from './App.vue';
|
||||
|
||||
initPromise.then(store => {
|
||||
|
||||
//console.log('store in create_store', store);
|
||||
//console.log('store accompanyingCourse', store.state.accompanyingCourse);
|
||||
|
||||
const i18n = _createI18n(appMessages);
|
||||
|
||||
const app = createApp({
|
||||
template: `<app></app>`,
|
||||
})
|
||||
.use(store)
|
||||
.use(i18n)
|
||||
.component('app', App)
|
||||
.mount('#accompanying-course');
|
||||
|
||||
});
|
@ -0,0 +1,32 @@
|
||||
import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n'
|
||||
|
||||
const appMessages = {
|
||||
fr: {
|
||||
course: {
|
||||
id: "id",
|
||||
title: "Parcours",
|
||||
opening_date: "Date d'ouverture",
|
||||
closing_date: "Date de clôture",
|
||||
remark: "Commentaire",
|
||||
closing_motive: "Motif de clôture",
|
||||
},
|
||||
persons_associated: {
|
||||
title: "Usagers concernés",
|
||||
counter: "Pas d'usager | 1 usager | {count} usagers",
|
||||
firstname: "Prénom",
|
||||
lastname: "Nom",
|
||||
startdate: "Date d'entrée",
|
||||
enddate: "Date de sortie",
|
||||
addPerson: "Ajouter un usager",
|
||||
},
|
||||
requestor: {
|
||||
title: "Demandeur",
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
Object.assign(appMessages.fr, personMessages.fr);
|
||||
|
||||
export {
|
||||
appMessages
|
||||
};
|
@ -0,0 +1,76 @@
|
||||
import 'es6-promise/auto';
|
||||
import { createStore } from 'vuex';
|
||||
import addPersons from './modules/addPersons'
|
||||
import { getAccompanyingCourse, postParticipation } from '../api';
|
||||
|
||||
const debug = process.env.NODE_ENV !== 'production';
|
||||
|
||||
const id = window.accompanyingCourseId; //tmp
|
||||
|
||||
let initPromise = getAccompanyingCourse(id)
|
||||
.then(accompanying_course => new Promise((resolve, reject) => {
|
||||
|
||||
const store = createStore({
|
||||
strict: debug,
|
||||
modules: {
|
||||
addPersons
|
||||
},
|
||||
state: {
|
||||
accompanyingCourse: accompanying_course,
|
||||
errorMsg: []
|
||||
},
|
||||
getters: {
|
||||
},
|
||||
mutations: {
|
||||
removeParticipation(state, item) {
|
||||
//console.log('mutation: remove item', item.id);
|
||||
state.accompanyingCourse.participations = state.accompanyingCourse.participations.filter(participation => participation !== item);
|
||||
},
|
||||
closeParticipation(state, { participation, payload }) {
|
||||
console.log('### mutation: close item', { participation, payload });
|
||||
// trouve dans le state le payload et le supprime du state
|
||||
state.accompanyingCourse.participations = state.accompanyingCourse.participations.filter(participation => participation !== payload);
|
||||
// pousse la participation
|
||||
state.accompanyingCourse.participations.push(participation);
|
||||
},
|
||||
addParticipation(state, participation) {
|
||||
//console.log('### mutation: add participation', participation);
|
||||
state.accompanyingCourse.participations.push(participation);
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
removeParticipation({ commit }, payload) {
|
||||
commit('removeParticipation', payload);
|
||||
},
|
||||
closeParticipation({ commit }, payload) {
|
||||
//console.log('## action: fetch delete participation: payload', payload.person.id);
|
||||
postParticipation(id, payload.person.id, 'DELETE')
|
||||
.then(participation => new Promise((resolve, reject) => {
|
||||
//console.log('payload', payload);
|
||||
commit('closeParticipation', { participation, payload });
|
||||
resolve();
|
||||
}))
|
||||
.catch((error) => {
|
||||
state.errorMsg.push(error.message);
|
||||
});
|
||||
},
|
||||
addParticipation(addPersons, payload) {
|
||||
//console.log('## action: fetch post participation: payload', payload.id);
|
||||
postParticipation(id, payload.id, 'POST')
|
||||
.then(participation => new Promise((resolve, reject) => {
|
||||
//console.log(participation, payload);
|
||||
addPersons.commit('addParticipation', participation);
|
||||
addPersons.commit('resetState', payload);
|
||||
resolve();
|
||||
}))
|
||||
.catch((error) => {
|
||||
state.errorMsg.push(error.message);
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
//console.log('store object', store.state.accompanyingCourse.id);
|
||||
resolve(store);
|
||||
}));
|
||||
|
||||
export { initPromise };
|
@ -0,0 +1,76 @@
|
||||
import { searchPersons } from 'ChillPersonAssets/vuejs/_api/AddPersons'
|
||||
import { postParticipation } from '../../api';
|
||||
|
||||
|
||||
// initial state
|
||||
const state = {
|
||||
query: "",
|
||||
suggested: [],
|
||||
selected: []
|
||||
}
|
||||
|
||||
// getters
|
||||
const getters = {
|
||||
selectedAndSuggested: state => {
|
||||
const uniqBy = (a, key) => [
|
||||
...new Map(
|
||||
a.map(x => [key(x), x])
|
||||
).values()
|
||||
];
|
||||
let union = [...new Set([
|
||||
...state.suggested.slice().reverse(),
|
||||
...state.selected.slice().reverse(),
|
||||
])];
|
||||
return uniqBy(union, k => k.id);
|
||||
}
|
||||
}
|
||||
|
||||
// mutations
|
||||
const mutations = {
|
||||
setQuery(state, query) {
|
||||
//console.log('q=', query);
|
||||
state.query = query;
|
||||
},
|
||||
loadSuggestions(state, suggested) {
|
||||
state.suggested = suggested;
|
||||
},
|
||||
updateSelected(state, value) {
|
||||
state.selected = value;
|
||||
},
|
||||
resetState(state, selected) {
|
||||
//console.log('avant', state.selected);
|
||||
state.selected = state.selected.filter(value => value !== selected);
|
||||
//console.log('après', state.selected);
|
||||
state.query = "";
|
||||
state.suggested = [];
|
||||
}
|
||||
}
|
||||
|
||||
// actions
|
||||
const actions = {
|
||||
setQuery({ commit }, payload) {
|
||||
//console.log('## action: setquery: payload', payload);
|
||||
commit('setQuery', payload.query);
|
||||
if (payload.query.length >= 3) {
|
||||
searchPersons(payload.query)
|
||||
.then(suggested => new Promise((resolve, reject) => {
|
||||
commit('loadSuggestions', suggested.results);
|
||||
resolve();
|
||||
}));
|
||||
} else {
|
||||
commit('loadSuggestions', []);
|
||||
}
|
||||
},
|
||||
updateSelected({ commit }, payload) {
|
||||
//console.log('## action: update selected values: payload', payload);
|
||||
commit('updateSelected', payload);
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
//namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
const
|
||||
locale = 'fr',
|
||||
format = 'json'
|
||||
;
|
||||
|
||||
/*
|
||||
* Endpoint chill_person_search, method GET, get a list of persons
|
||||
*
|
||||
* @query string - the query to search for
|
||||
*/
|
||||
let searchPersons = (query) => {
|
||||
let url = `/${locale}/search.${format}?name=person_regular&q=${query}`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
export { searchPersons };
|
@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<button class="sc-button bt-create centered mt-4" @click="openModal">
|
||||
{{ $t('add_persons.search_add_others_persons') }}
|
||||
</button>
|
||||
|
||||
<teleport to="body">
|
||||
<modal v-if="modal.showModal"
|
||||
:modalDialogClass="modal.modalDialogClass"
|
||||
@close="modal.showModal = false">
|
||||
|
||||
<template v-slot:header>
|
||||
<h3 class="modal-title">{{ $t('add_persons.title') }}</h3>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-fixed>
|
||||
<div class="search">
|
||||
<label style="float: right;">
|
||||
{{ $tc('add_persons.suggested_counter', suggestedCounter) }}
|
||||
</label>
|
||||
|
||||
<input id="search-persons"
|
||||
name="query"
|
||||
v-model="query"
|
||||
:placeholder="$t('add_persons.search_some_persons')"
|
||||
ref="search" />
|
||||
<i class="fa fa-search fa-lg"></i>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-slot:body>
|
||||
<!--span class="discret">Selection: {{ selected }}</span-->
|
||||
<div class="results">
|
||||
<div class="count">
|
||||
<span>
|
||||
<a v-if="suggestedCounter > 0" href="#">
|
||||
{{ $t('action.check_all')}}</a>
|
||||
<a v-if="selectedCounter > 0" href="#">
|
||||
{{ $t('action.reset')}}</a>
|
||||
</span>
|
||||
<span v-if="selectedCounter > 0">
|
||||
{{ $tc('add_persons.selected_counter', selectedCounter) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<person-suggestion
|
||||
v-for="item in this.selectedAndSuggested.slice().reverse()"
|
||||
v-bind:item="item"
|
||||
v-bind:key="item.id">
|
||||
</person-suggestion>
|
||||
|
||||
<button v-if="query.length >= 3" class="sc-button bt-create ml-5 mt-2" name="createPerson">
|
||||
{{ $t('action.create') }} "{{ query }}"
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-slot:footer>
|
||||
<button class="sc-button green" @click="addNewPersons">
|
||||
<i class="fa fa-plus fa-fw"></i>{{ $t('action.add')}}
|
||||
</button>
|
||||
</template>
|
||||
|
||||
</modal>
|
||||
</teleport>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
|
||||
import PersonSuggestion from 'ChillPersonAssets/vuejs/_components/PersonSuggestion';
|
||||
|
||||
export default {
|
||||
name: 'AddPersons',
|
||||
components: {
|
||||
Modal,
|
||||
PersonSuggestion,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
modal: {
|
||||
showModal: false,
|
||||
modalDialogClass: "modal-dialog-scrollable modal-xl"
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
addPersons: state => state.addPersons
|
||||
}),
|
||||
query: {
|
||||
set(query) {
|
||||
this.$store.dispatch('setQuery', { query });
|
||||
},
|
||||
get() {
|
||||
return this.addPersons.query;
|
||||
}
|
||||
},
|
||||
suggested() {
|
||||
return this.addPersons.suggested;
|
||||
},
|
||||
suggestedCounter() {
|
||||
return this.addPersons.suggested.length;
|
||||
},
|
||||
selected() {
|
||||
return this.addPersons.selected;
|
||||
},
|
||||
selectedCounter() {
|
||||
return this.addPersons.selected.length;
|
||||
},
|
||||
selectedAndSuggested() {
|
||||
return this.$store.getters.selectedAndSuggested;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
openModal() {
|
||||
this.modal.showModal = true;
|
||||
this.$nextTick(function() {
|
||||
this.$refs.search.focus();
|
||||
})
|
||||
},
|
||||
addNewPersons() {
|
||||
console.log('@@@ CLICK button addPersons')
|
||||
this.selected.forEach(function(item) {
|
||||
//console.log('# dispatch action for each item', item);
|
||||
this.$store.dispatch('addParticipation', item);
|
||||
}, this
|
||||
);
|
||||
this.modal.showModal = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<div class="list-item" :class="{ checked: isChecked }">
|
||||
<div class="container">
|
||||
|
||||
<!--a class="discret" target="_blank" :href="url.show">{{ item.id }}</a-->
|
||||
<input class=""
|
||||
type="checkbox"
|
||||
v-model="selected"
|
||||
:value="item" />
|
||||
|
||||
{{ item.text }}
|
||||
|
||||
</div>
|
||||
<div class="right_actions">
|
||||
|
||||
<span class="badge badge-pill badge-secondary" :title="item.id">
|
||||
{{ $t('item.type_person') }}
|
||||
</span>
|
||||
<a class="sc-button bt-show" target="_blank" :title="item.id" :href="url.show"></a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'PersonSuggestion',
|
||||
props: ['item'],
|
||||
data() {
|
||||
return {
|
||||
url: {
|
||||
show: '/fr/person/' + this.item.id + '/general',
|
||||
edit: '/fr/person/' + this.item.id + '/general/edit'
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
selected: {
|
||||
set(value) {
|
||||
this.$store.dispatch('updateSelected', value);
|
||||
},
|
||||
get() {
|
||||
return this.$store.state.addPersons.selected;
|
||||
}
|
||||
},
|
||||
isChecked() {
|
||||
return (this.selected.indexOf(this.item) === -1) ? false : true;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -0,0 +1,21 @@
|
||||
const personMessages = {
|
||||
fr: {
|
||||
add_persons: {
|
||||
search_add_others_persons: "Rechercher et ajouter d'autres usagers",
|
||||
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_tms: "TMS",
|
||||
type_3rdparty: "Tiers",
|
||||
type_menage: "Ménage"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
personMessages
|
||||
};
|
@ -5,15 +5,13 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{{ block('title') }}</h1>
|
||||
|
||||
<div id="accompanying-course"></div>
|
||||
{% endblock %}
|
||||
|
||||
{{ encore_entry_script_tags('accompanying_course') }}
|
||||
|
||||
{% block js %}
|
||||
<script type="text/javascript">
|
||||
window.accompanyingCourseId = {{ accompanyingCourse.id|e('js') }};
|
||||
</script>
|
||||
|
||||
{{ encore_entry_script_tags('accompanying_course') }}
|
||||
{% endblock %}
|
||||
|
@ -7,6 +7,6 @@ module.exports = function(encore, entries)
|
||||
encore.addAliases({
|
||||
ChillPersonAssets: __dirname + '/Resources/public'
|
||||
});
|
||||
|
||||
encore.addEntry('accompanying_course', __dirname + '/Resources/public/js/AccompanyingCourse/index.js');
|
||||
|
||||
encore.addEntry('accompanying_course', __dirname + '/Resources/public/vuejs/AccompanyingCourse/index.js');
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user