From 3abfdbf6fd5c2134781bf1de4100480e7375d1cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Fri, 18 Jun 2021 19:41:58 +0200 Subject: [PATCH] first impl for create form --- .../CRUD/Routing/CRUDRoutesLoader.php | 4 +- .../DependencyInjection/Configuration.php | 2 +- .../Resources/public/js/date.js | 6 +- .../Normalizer/CollectionNormalizer.php | 1 - .../AccompanyingCourseWorkController.php | 52 +++++++++++ .../SocialWorkSocialActionApiController.php | 47 ++++++++++ .../ChillPersonExtension.php | 43 +++++++++ .../Entity/SocialWork/SocialAction.php | 1 + .../SocialWork/SocialIssueRepository.php | 43 ++++++++- .../AccompanyingCourseWorkCreate/App.vue | 89 +++++++++++++++++++ .../AccompanyingCourseWorkCreate/index.js | 15 ++++ .../AccompanyingCourseWorkCreate/store.js | 67 ++++++++++++++ .../vuejs/_api/SocialWorkSocialAction.js | 21 +++++ .../AccompanyingCourseWork/create.html.twig | 21 +++++ .../Normalizer/SocialActionNormalizer.php | 43 +++++++++ .../ChillPersonBundle/chill.webpack.config.js | 1 + 16 files changed, 448 insertions(+), 8 deletions(-) create mode 100644 src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php create mode 100644 src/Bundle/ChillPersonBundle/Controller/SocialWorkSocialActionApiController.php create mode 100644 src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/App.vue create mode 100644 src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/index.js create mode 100644 src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/store.js create mode 100644 src/Bundle/ChillPersonBundle/Resources/public/vuejs/_api/SocialWorkSocialAction.js create mode 100644 src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/create.html.twig create mode 100644 src/Bundle/ChillPersonBundle/Serializer/Normalizer/SocialActionNormalizer.php diff --git a/src/Bundle/ChillMainBundle/CRUD/Routing/CRUDRoutesLoader.php b/src/Bundle/ChillMainBundle/CRUD/Routing/CRUDRoutesLoader.php index 9d61d6233..d7e19ea9c 100644 --- a/src/Bundle/ChillMainBundle/CRUD/Routing/CRUDRoutesLoader.php +++ b/src/Bundle/ChillMainBundle/CRUD/Routing/CRUDRoutesLoader.php @@ -146,7 +146,7 @@ class CRUDRoutesLoader extends Loader foreach ($crudConfig['actions'] as $name => $action) { // filter only on single actions - $singleCollection = $action['single-collection'] ?? $name === '_entity' ? 'single' : NULL; + $singleCollection = $action['single_collection'] ?? $name === '_entity' ? 'single' : NULL; if ('collection' === $singleCollection) { // continue; } @@ -171,7 +171,7 @@ class CRUDRoutesLoader extends Loader // path are rewritten // if name === 'default', we rewrite it to nothing :-) $localName = \in_array($name, [ '_entity', '_index' ]) ? '' : '/'.$name; - if ('collection' === $action['single-collection'] || '_index' === $name) { + if ('collection' === $action['single_collection'] || '_index' === $name) { $localPath = $action['path'] ?? $localName.'.{_format}'; } else { $localPath = $action['path'] ?? '/{id}'.$localName.'.{_format}'; diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php index 4c90aaabb..c711f911f 100644 --- a/src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php +++ b/src/Bundle/ChillMainBundle/DependencyInjection/Configuration.php @@ -205,7 +205,7 @@ class Configuration implements ConfigurationInterface ->ignoreExtraKeys(false) ->info('the requirements for the route. Will be set to `[ \'id\' => \'\d+\' ]` if left empty.') ->end() - ->enumNode('single-collection') + ->enumNode('single_collection') ->values(['single', 'collection']) ->defaultValue('single') ->info('indicates if the returned object is a single element or a collection. '. diff --git a/src/Bundle/ChillMainBundle/Resources/public/js/date.js b/src/Bundle/ChillMainBundle/Resources/public/js/date.js index 7b9bf88a2..a11bc15bf 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/js/date.js +++ b/src/Bundle/ChillMainBundle/Resources/public/js/date.js @@ -15,9 +15,9 @@ */ const dateToISO = (date) => { return [ - this.$store.state.startDate.getFullYear(), - (this.$store.state.startDate.getMonth() + 1).toString().padStart(2, '0'), - this.$store.state.startDate.getDate().toString().padStart(2, '0') + date.getFullYear(), + (date.getMonth() + 1).toString().padStart(2, '0'), + date.getDate().toString().padStart(2, '0') ].join('-'); }; diff --git a/src/Bundle/ChillMainBundle/Serializer/Normalizer/CollectionNormalizer.php b/src/Bundle/ChillMainBundle/Serializer/Normalizer/CollectionNormalizer.php index 1ba95d924..d3f513c54 100644 --- a/src/Bundle/ChillMainBundle/Serializer/Normalizer/CollectionNormalizer.php +++ b/src/Bundle/ChillMainBundle/Serializer/Normalizer/CollectionNormalizer.php @@ -19,7 +19,6 @@ class CollectionNormalizer implements NormalizerInterface, NormalizerAwareInterf public function normalize($collection, string $format = null, array $context = []) { /** @var $collection Collection */ - /** @var $collection Chill\MainBundle\Pagination\PaginatorInterface */ $paginator = $collection->getPaginator(); $data['count'] = $paginator->getTotalItems(); diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php new file mode 100644 index 000000000..1a5ab3925 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php @@ -0,0 +1,52 @@ +trans = $trans; + $this->serializer = $serializer; + } + + /** + * @Route( + * "{_locale}/person/accompanying-period/{id}/work/new", + * methods={"GET", "POST"} + * ) + */ + public function createWork(AccompanyingPeriod $period) + { + // TODO ACL + + if ($period->getSocialIssues()->count() === 0) { + $this->addFlash('error', $this->trans->trans( + "accompanying_work.You must add at least ". + "one social issue on accompanying period") + ); + + return $this->redirectToRoute('chill_person_accompanying_course_index', [ + 'accompanying_period_id' => $period->getId() + ]); + } + + $json = $this->serializer->normalize($period, 'json', [ "groups" => [ "read" ]]); + + return $this->render('@ChillPerson/AccompanyingCourseWork/create.html.twig', [ + 'accompanyingCourse' => $period, + 'json' => $json + ]); + } +} diff --git a/src/Bundle/ChillPersonBundle/Controller/SocialWorkSocialActionApiController.php b/src/Bundle/ChillPersonBundle/Controller/SocialWorkSocialActionApiController.php new file mode 100644 index 000000000..de87b380a --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Controller/SocialWorkSocialActionApiController.php @@ -0,0 +1,47 @@ +socialIssueRepository = $socialIssueRepository; + $this->paginator = $paginator; + } + + public function listBySocialIssueApi($id, Request $request) + { + $socialIssue = $this->socialIssueRepository + ->find($id); + + if (NULL === $socialIssue) { + throw $this->createNotFoundException("socialIssue not found"); + } + + $socialActions = $socialIssue->getRecursiveSocialActions(); + $pagination = $this->paginator->create(count($socialActions)); + // max one page + $pagination->setItemsPerPage(count($socialActions)); + + $collection = new Collection($socialActions, $pagination); + + + return $this->json($collection, JsonResponse::HTTP_OK, [], [ "groups" => [ "read" ]]); + } + +} diff --git a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php index 1c62f361f..d810530ad 100644 --- a/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php +++ b/src/Bundle/ChillPersonBundle/DependencyInjection/ChillPersonExtension.php @@ -573,6 +573,49 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac ], ] ], + [ + 'class' => \Chill\PersonBundle\Entity\SocialWork\SocialAction::class, + 'name' => 'social_action', + 'base_path' => '/api/1.0/person/social/social-action', + 'controller' => \Chill\PersonBundle\Controller\SocialWorkSocialActionApiController::class, + // TODO: acl + 'base_role' => 'ROLE_USER', + 'actions' => [ + '_entity' => [ + 'methods' => [ + Request::METHOD_GET => true, + Request::METHOD_HEAD => true, + ], + 'roles' => [ + Request::METHOD_GET => 'ROLE_USER', + Request::METHOD_HEAD => 'ROLE_USER', + ] + ], + '_index' => [ + 'methods' => [ + Request::METHOD_GET => true, + Request::METHOD_HEAD => true, + ], + 'roles' => [ + Request::METHOD_GET => 'ROLE_USER', + Request::METHOD_HEAD => 'ROLE_USER', + ] + ], + 'listBySocialIssue' => [ + 'single-collection' => 'collection', + 'path' => '/by-social-issue/{id}.{_format}', + 'methods' => [ + Request::METHOD_GET => true, + Request::METHOD_HEAD => true, + ], + 'roles' => [ + Request::METHOD_GET => 'ROLE_USER', + Request::METHOD_HEAD => 'ROLE_USER', + ] + + ] + ] + ], ] ]); } diff --git a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php index 3f5eb14ed..6e104abcb 100644 --- a/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php +++ b/src/Bundle/ChillPersonBundle/Entity/SocialWork/SocialAction.php @@ -5,6 +5,7 @@ namespace Chill\PersonBundle\Entity\SocialWork; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Serializer\Annotation as Serializer; /** * @ORM\Entity diff --git a/src/Bundle/ChillPersonBundle/Repository/SocialWork/SocialIssueRepository.php b/src/Bundle/ChillPersonBundle/Repository/SocialWork/SocialIssueRepository.php index 1100d8136..4dc5ecc67 100644 --- a/src/Bundle/ChillPersonBundle/Repository/SocialWork/SocialIssueRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/SocialWork/SocialIssueRepository.php @@ -6,8 +6,9 @@ use Chill\PersonBundle\Entity\SocialWork\SocialIssue; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; +use Doctrine\Persistence\ObjectRepository; -final class SocialIssueRepository +final class SocialIssueRepository implements ObjectRepository { private EntityRepository $repository; @@ -15,4 +16,44 @@ final class SocialIssueRepository { $this->repository = $entityManager->getRepository(SocialIssue::class); } + + /** + * {@inheritDoc} + */ + public function find($id) + { + return $this->repository->find($id); + } + + /** + * {@inheritDoc} + */ + public function findAll() + { + return $this->repository->findAll(); + } + + /** + * {@inheritDoc} + */ + public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null) + { + return $this->repository->findBy($criteria, $orderBy, $limit, $offset); + } + + /** + * {@inheritDoc} + */ + public function findOneBy(array $criteria) + { + return $this->findOneBy($criteria); + } + + /** + * {@inheritDoc} + */ + public function getClassName() + { + return SocialIssue::class; + } } diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/App.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/App.vue new file mode 100644 index 000000000..1a8cf80e8 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/App.vue @@ -0,0 +1,89 @@ + + + + diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/index.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/index.js new file mode 100644 index 000000000..7e54e2b0b --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/index.js @@ -0,0 +1,15 @@ +import { createApp } from 'vue'; +import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n'; +import { store } from './store'; +import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n' +import App from './App.vue'; + +const i18n = _createI18n(personMessages); + +const app = createApp({ + template: ``, +}) +.use(store) +.use(i18n) +.component('app', App) +.mount('#accompanying_course_work_create'); diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/store.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/store.js new file mode 100644 index 000000000..a60074698 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkCreate/store.js @@ -0,0 +1,67 @@ + +import { createStore } from 'vuex'; +import { datetimeToISO } from 'ChillMainAssets/js/date.js'; +import { findSocialActionsBySocialIssue } from 'ChillPersonAssets/vuejs/_api/SocialWorkSocialAction.js'; + +const debug = process.env.NODE_ENV !== 'production'; + +const socialIssues = window.accompanyingCourse.socialIssues; + +const store = createStore({ + strict: debug, + state: { + socialIssues: socialIssues, + socialIssuePicked: null, + socialActionsReachables: [], + socialActionPicked: null, + startDate: new Date(), + endDate: null, + }, + getters: { + hasSocialActionPicked(state) { + console.log(state.socialActionPicked); + return null !== state.socialActionPicked; + }, + hasSocialIssuePicked(state) { + console.log(state.socialIssuePicked); + return null !== state.socialIssuePicked; + }, + }, + mutations: { + setSocialActionsReachables(state, actions) { + console.log('set social action reachables'); + console.log(actions); + + state.socialActionsReachables = actions; + }, + setSocialAction(state, socialAction) { + console.log('socialAction', socialAction); + state.socialActionPicked = socialAction; + }, + setSocialIssue(state, socialIssueId) { + console.log('socialAction', socialIssueId); + state.socialIssuePicked = state.socialIssues + .find(e => e.id === socialIssueId); + }, + }, + actions: { + pickSocialIssue({ commit }, payload) { + console.log('pick social issue'); + console.log(payload); + + + findSocialActionsBySocialIssue(payload).then( + (response) => { + console.log(response); + console.log(response.results); + commit('setSocialIssue', payload); + commit('setSocialActionsReachables', response.results); + }) + .catch(err => { + console.error(err); + }); + } + }, +}); + +export { store }; diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_api/SocialWorkSocialAction.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_api/SocialWorkSocialAction.js new file mode 100644 index 000000000..b419fe45a --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_api/SocialWorkSocialAction.js @@ -0,0 +1,21 @@ + +const findSocialActionsBySocialIssue = (id) => { + const url = `/api/1.0/person/social/social-action/by-social-issue/${id}.json`; + + return fetch(url) + .then(response => { + if (!response.ok) { + throw new Error("Error while retrieving social actions " + response.status + + " " + response.statusText) + } + return response.json(); + }) + .catch(err => { + throw err + }) + ; +}; + +export { + findSocialActionsBySocialIssue +}; diff --git a/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/create.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/create.html.twig new file mode 100644 index 000000000..da783ac70 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/views/AccompanyingCourseWork/create.html.twig @@ -0,0 +1,21 @@ +{% extends '@ChillPerson/AccompanyingCourse/layout.html.twig' %} + + +{% block content %} +

test

+ +
+ +{% endblock %} + +{% block js %} + + + {{ encore_entry_script_tags('accompanying_course_work_create') }} +{% endblock %} + +{% block stylesheets %} + {{ encore_entry_link_tags('accompanying_course_work_create') }} +{% endblock %} diff --git a/src/Bundle/ChillPersonBundle/Serializer/Normalizer/SocialActionNormalizer.php b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/SocialActionNormalizer.php new file mode 100644 index 000000000..9a045b207 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Serializer/Normalizer/SocialActionNormalizer.php @@ -0,0 +1,43 @@ +render = $render; + } + + /** + * {@inheritDoc} + */ + public function normalize($socialAction, string $format = null, array $context = []) + { + return [ + 'text' => $this->render->renderString($socialAction, []), + 'parent' => $this->normalizer->normalize($socialAction->getParent()), + 'desactivationDate' => $this->normalizer->normalize($socialAction->getDesactivationDate()), + 'title' => $socialAction->getTitle() + ]; + } + + /** + * {@inheritDoc} + */ + public function supportsNormalization($data, string $format = null) + { + return $data instanceof SocialAction; + } +} diff --git a/src/Bundle/ChillPersonBundle/chill.webpack.config.js b/src/Bundle/ChillPersonBundle/chill.webpack.config.js index d70796fe5..b20aa004e 100644 --- a/src/Bundle/ChillPersonBundle/chill.webpack.config.js +++ b/src/Bundle/ChillPersonBundle/chill.webpack.config.js @@ -13,4 +13,5 @@ module.exports = function(encore, entries) encore.addEntry('household_members_editor', __dirname + '/Resources/public/vuejs/HouseholdMembersEditor/index.js'); encore.addEntry('vue_accourse', __dirname + '/Resources/public/vuejs/AccompanyingCourse/index.js'); encore.addEntry('household_edit_metadata', __dirname + '/Resources/public/modules/household_edit_metadata/index.js'); + encore.addEntry('accompanying_course_work_create', __dirname + '/Resources/public/vuejs/AccompanyingCourseWorkCreate/index.js'); };