mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-12 13:24:25 +00:00
first impl for household editor
This commit is contained in:
parent
cd52f7e6e8
commit
c6949490a4
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
namespace Chill\PersonBundle\Controller;
|
namespace Chill\PersonBundle\Controller;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Entity\Household\Position;
|
||||||
|
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||||
|
use Chill\PersonBundle\Entity\Person;
|
||||||
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
|
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
@ -15,7 +18,7 @@ class HouseholdMemberController extends ApiController
|
|||||||
/**
|
/**
|
||||||
* @Route(
|
* @Route(
|
||||||
* "/api/1.0/person/household/members/move.{_format}",
|
* "/api/1.0/person/household/members/move.{_format}",
|
||||||
* name="chill_person_household_members_move"
|
* name="chill_api_person_household_members_move"
|
||||||
* )
|
* )
|
||||||
*/
|
*/
|
||||||
public function move(Request $request, $_format): Response
|
public function move(Request $request, $_format): Response
|
||||||
@ -27,7 +30,6 @@ class HouseholdMemberController extends ApiController
|
|||||||
} catch (Exception\InvalidArgumentException | Exception\UnexpectedValueException $e) {
|
} catch (Exception\InvalidArgumentException | Exception\UnexpectedValueException $e) {
|
||||||
throw new BadRequestException("Deserialization error: {$e->getMessage()}", 45896, $e);
|
throw new BadRequestException("Deserialization error: {$e->getMessage()}", 45896, $e);
|
||||||
}
|
}
|
||||||
dump($editor);
|
|
||||||
// TODO ACL
|
// TODO ACL
|
||||||
//
|
//
|
||||||
// TODO validation
|
// TODO validation
|
||||||
@ -44,7 +46,52 @@ class HouseholdMemberController extends ApiController
|
|||||||
$em->flush();
|
$em->flush();
|
||||||
$em->commit();
|
$em->commit();
|
||||||
|
|
||||||
|
|
||||||
return $this->json($editor->getHousehold(), Response::HTTP_OK, ["groups" => ["read"]]);
|
return $this->json($editor->getHousehold(), Response::HTTP_OK, ["groups" => ["read"]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route(
|
||||||
|
* "/{_locale}/person/household/members/editor",
|
||||||
|
* name="chill_person_household_members_editor"
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function editor(Request $request)
|
||||||
|
{
|
||||||
|
if ($request->query->has('persons')) {
|
||||||
|
$ids = $request->query->get('persons', []);
|
||||||
|
|
||||||
|
if (0 === count($ids)) {
|
||||||
|
throw new BadRequestExceptions("parameters persons in query ".
|
||||||
|
"is not an array or empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
$persons = $this->getDoctrine()->getManager()
|
||||||
|
->getRepository(Person::class)
|
||||||
|
->findById($ids)
|
||||||
|
;
|
||||||
|
|
||||||
|
foreach ($persons as $person) {
|
||||||
|
$this->denyAccessUnlessGranted(PersonVoter::SEE, $person,
|
||||||
|
"You are not allowed to see person with id {$person->getId()}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$positions = $this->getDoctrine()->getManager()
|
||||||
|
->getRepository(Position::class)
|
||||||
|
->findAll()
|
||||||
|
;
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'persons' => $persons ?? false ?
|
||||||
|
$this->getSerializer()->normalize($persons, 'json', [ 'groups' => [ 'read' ]]): [],
|
||||||
|
'household' => null,
|
||||||
|
'positions' =>
|
||||||
|
$this->getSerializer()->normalize($positions, 'json', [ 'groups' => [ 'read' ]])
|
||||||
|
];
|
||||||
|
|
||||||
|
return $this->render('@ChillPerson/Household/members_editor.html.twig', [
|
||||||
|
'data' => $data
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use Doctrine\ORM\Mapping as ORM;
|
|||||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Entity(repositoryClass=PositionRepository::class)
|
* @ORM\Entity
|
||||||
* @ORM\Table(name="chill_person_household_position")
|
* @ORM\Table(name="chill_person_household_position")
|
||||||
* @Serializer\DiscriminatorMap(typeProperty="type", mapping={
|
* @Serializer\DiscriminatorMap(typeProperty="type", mapping={
|
||||||
* "household_position"=Position::class
|
* "household_position"=Position::class
|
||||||
@ -25,21 +25,25 @@ class Position
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="json")
|
* @ORM\Column(type="json")
|
||||||
|
* @Serializer\Groups({ "read" })
|
||||||
*/
|
*/
|
||||||
private $label = [];
|
private $label = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="boolean")
|
* @ORM\Column(type="boolean")
|
||||||
|
* @Serializer\Groups({ "read" })
|
||||||
*/
|
*/
|
||||||
private $shareHouseHold;
|
private $shareHouseHold;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="boolean")
|
* @ORM\Column(type="boolean")
|
||||||
|
* @Serializer\Groups({ "read" })
|
||||||
*/
|
*/
|
||||||
private $allowHolder;
|
private $allowHolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="float")
|
* @ORM\Column(type="float")
|
||||||
|
* @Serializer\Groups({ "read" })
|
||||||
*/
|
*/
|
||||||
private $ordering;
|
private $ordering;
|
||||||
|
|
||||||
|
@ -3,8 +3,10 @@
|
|||||||
namespace Chill\PersonBundle\Repository\Household;
|
namespace Chill\PersonBundle\Repository\Household;
|
||||||
|
|
||||||
use Chill\PersonBundle\Entity\Household\Position;
|
use Chill\PersonBundle\Entity\Household\Position;
|
||||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
//use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
use Doctrine\Persistence\ManagerRegistry;
|
//use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @method Position|null find($id, $lockMode = null, $lockVersion = null)
|
* @method Position|null find($id, $lockMode = null, $lockVersion = null)
|
||||||
@ -12,11 +14,20 @@ use Doctrine\Persistence\ManagerRegistry;
|
|||||||
* @method Position[] findAll()
|
* @method Position[] findAll()
|
||||||
* @method Position[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
* @method Position[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||||
*/
|
*/
|
||||||
class PositionRepository extends ServiceEntityRepository
|
final class PositionRepository
|
||||||
{
|
{
|
||||||
public function __construct(ManagerRegistry $registry)
|
private EntityRepository $repository;
|
||||||
|
|
||||||
|
public function __construct(EntityManagerInterface $entityManager)
|
||||||
{
|
{
|
||||||
parent::__construct($registry, Position::class);
|
$this->repository = $entityManager->getRepository(Position::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Position[]
|
||||||
|
*/
|
||||||
|
public function findAll(): array
|
||||||
|
{
|
||||||
|
return $this->repository->findAll();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
<template>
|
||||||
|
<concerned></concerned>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Concerned from './components/Concerned.vue';
|
||||||
|
import { mapState } from 'vuex';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'App',
|
||||||
|
components: {
|
||||||
|
Concerned,
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// for debugging purpose
|
||||||
|
// (not working)
|
||||||
|
//...mapState({
|
||||||
|
// 'concerned', 'household', 'positions'
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
@ -0,0 +1,118 @@
|
|||||||
|
<template>
|
||||||
|
<h1>{{ $t('household_members_editor.concerned.title') }}</h1>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div v-for="person in personsUnpositionned"
|
||||||
|
draggable="true"
|
||||||
|
@dragstart="onStartDragConcern($event, person.id)"
|
||||||
|
>
|
||||||
|
<span>{{ person.text }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<add-persons
|
||||||
|
buttonTitle="household_members_editor.concerned.add_persons"
|
||||||
|
modalTitle="household_members_editor.concerned.search"
|
||||||
|
v-bind:key="addPersons.key"
|
||||||
|
v-bind:options="addPersons.options"
|
||||||
|
@addNewPersons="addNewPersons"
|
||||||
|
ref="addPersons"> <!-- to cast child method -->
|
||||||
|
</add-persons>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="positions">
|
||||||
|
<div v-for="position in positions">
|
||||||
|
<h2>{{ position.label.fr }}</h2>
|
||||||
|
<ul>
|
||||||
|
<li
|
||||||
|
v-for="person in personByPosition(position.id)"
|
||||||
|
draggable="true"
|
||||||
|
@dragstart="onStartDragConcern($event, person.id)"
|
||||||
|
>
|
||||||
|
{{ person.text }}, {{ person.id }}
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
class="droppable"
|
||||||
|
@drop="onDropConcern($event, position.id)"
|
||||||
|
@dragover.prevent
|
||||||
|
@dragenter.prevent
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.concerned_box {
|
||||||
|
cursor: move;
|
||||||
|
padding: 1.5em;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
.concerned_box * {
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
.droppable_zone {
|
||||||
|
min-height: 50px;
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapGetters } from 'vuex';
|
||||||
|
import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Concerned',
|
||||||
|
components: {
|
||||||
|
AddPersons,
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters([
|
||||||
|
'personsUnpositionned',
|
||||||
|
'positions',
|
||||||
|
'personByPosition',
|
||||||
|
])
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
addPersons: {
|
||||||
|
key: 'household_members_editor_concerned',
|
||||||
|
options: {
|
||||||
|
type: ['person'],
|
||||||
|
priority: null,
|
||||||
|
uniq: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addNewPersons({ selected, modal }) {
|
||||||
|
console.log(selected);
|
||||||
|
selected.forEach(function(item) {
|
||||||
|
this.$store.dispatch('addConcerned', item.result);
|
||||||
|
}, this);
|
||||||
|
this.$refs.addPersons.resetSearch(); // to cast child method
|
||||||
|
modal.showModal = false;
|
||||||
|
},
|
||||||
|
onStartDragConcern(evt, person_id) {
|
||||||
|
console.log(evt);
|
||||||
|
console.log(person_id);
|
||||||
|
evt.dataTransfer.dropEffect = 'move'
|
||||||
|
evt.dataTransfer.effectAllowed = 'move'
|
||||||
|
evt.dataTransfer.setData('application/x.person', person_id)
|
||||||
|
},
|
||||||
|
onDropConcern(evt, position_id) {
|
||||||
|
console.log(evt);
|
||||||
|
console.log('position_id', position_id);
|
||||||
|
const person_id = Number(evt.dataTransfer.getData('application/x.person'));
|
||||||
|
this.$store.dispatch('markPosition', { person_id, position_id });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -0,0 +1,16 @@
|
|||||||
|
import { createApp } from 'vue';
|
||||||
|
import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n';
|
||||||
|
import { appMessages } from './js/i18n';
|
||||||
|
import { store } from './store';
|
||||||
|
|
||||||
|
import App from './App.vue';
|
||||||
|
|
||||||
|
const i18n = _createI18n(appMessages);
|
||||||
|
|
||||||
|
const app = createApp({
|
||||||
|
template: `<app></app>`,
|
||||||
|
})
|
||||||
|
.use(store)
|
||||||
|
.use(i18n)
|
||||||
|
.component('app', App)
|
||||||
|
.mount('#household_members_editor');
|
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n'
|
||||||
|
|
||||||
|
const appMessages = {
|
||||||
|
fr: {
|
||||||
|
household_members_editor: {
|
||||||
|
concerned: {
|
||||||
|
title: "Personnes concernées",
|
||||||
|
add_persons: "Ajouter d'autres usagers",
|
||||||
|
search: "Rechercher des usagers",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.assign(appMessages.fr, personMessages.fr);
|
||||||
|
|
||||||
|
export {
|
||||||
|
appMessages
|
||||||
|
};
|
@ -0,0 +1,74 @@
|
|||||||
|
import { createStore } from 'vuex';
|
||||||
|
|
||||||
|
const debug = process.env.NODE_ENV !== 'production';
|
||||||
|
|
||||||
|
const concerned = window.household_members_editor_data.persons.map(p => {
|
||||||
|
return {
|
||||||
|
person: p,
|
||||||
|
position: null,
|
||||||
|
start_date: null
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const store = createStore({
|
||||||
|
strict: debug,
|
||||||
|
state: {
|
||||||
|
concerned,
|
||||||
|
household: window.household_members_editor_data.household,
|
||||||
|
positions: window.household_members_editor_data.positions,
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
persons(state) {
|
||||||
|
return state.concerned.map(conc => conc.person);
|
||||||
|
},
|
||||||
|
personsUnpositionned(state) {
|
||||||
|
return state.concerned
|
||||||
|
.filter(conc => conc.position === null)
|
||||||
|
.map(conc => conc.person)
|
||||||
|
;
|
||||||
|
},
|
||||||
|
personByPosition: (state) => (position_id) => {
|
||||||
|
return state.concerned
|
||||||
|
.filter(conc =>
|
||||||
|
conc.position !== null ? conc.position.id === position_id : false
|
||||||
|
)
|
||||||
|
.map(conc => conc.person)
|
||||||
|
;
|
||||||
|
},
|
||||||
|
positions(state) {
|
||||||
|
return state.positions;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
addConcerned(state, person) {
|
||||||
|
console.log('from mutation addConcerned');
|
||||||
|
state.concerned.push({ person, position: null, start_date: null });
|
||||||
|
},
|
||||||
|
markPosition(state, { person_id, position_id}) {
|
||||||
|
console.log('from mutation markPosition');
|
||||||
|
console.log('person_id', person_id);
|
||||||
|
console.log('position_id', position_id);
|
||||||
|
console.log('state', state.concerned);
|
||||||
|
let
|
||||||
|
position = state.positions.find(pos => pos.id === position_id),
|
||||||
|
conc = state.concerned.find(c => c.person.id === person_id);
|
||||||
|
console.log(position);
|
||||||
|
console.log(conc);
|
||||||
|
conc.position = position;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
addConcerned({ commit }, person) {
|
||||||
|
console.log('from actions addConcerned');
|
||||||
|
commit('addConcerned', person);
|
||||||
|
},
|
||||||
|
markPosition({ commit, state }, { person_id, position_id }) {
|
||||||
|
console.log('from action markPosition');
|
||||||
|
console.log('person_id', person_id);
|
||||||
|
console.log('position_id', position_id);
|
||||||
|
commit('markPosition', { person_id, position_id });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export { store };
|
@ -0,0 +1,17 @@
|
|||||||
|
{% extends '@ChillMain/layout.html.twig' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>Editor</h1>
|
||||||
|
<div id="household_members_editor"></div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block js %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
window.household_members_editor_data = {{ data|json_encode|raw }};
|
||||||
|
</script>
|
||||||
|
{{ encore_entry_script_tags('household_members_editor') }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block css %}
|
||||||
|
{{ encore_entry_link_tags('household_members_editor') }}
|
||||||
|
{% endblock %}
|
@ -9,4 +9,5 @@ module.exports = function(encore, entries)
|
|||||||
});
|
});
|
||||||
|
|
||||||
encore.addEntry('accompanying_course', __dirname + '/Resources/public/vuejs/AccompanyingCourse/index.js');
|
encore.addEntry('accompanying_course', __dirname + '/Resources/public/vuejs/AccompanyingCourse/index.js');
|
||||||
|
encore.addEntry('household_members_editor', __dirname + '/Resources/public/vuejs/HouseholdMembersEditor/index.js');
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user