mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Merge branch 'rdv'
This commit is contained in:
commit
6a21bcc520
@ -69,7 +69,7 @@ class CalendarController extends AbstractController
|
||||
|
||||
/**
|
||||
* Lists all Calendar entities.
|
||||
* @Route("/{_locale}/calendar/", name="chill_calendar_calendar")
|
||||
* @Route("/{_locale}/calendar/calendar/", name="chill_calendar_calendar_list")
|
||||
*/
|
||||
public function listAction(Request $request): Response
|
||||
{
|
||||
@ -80,18 +80,17 @@ class CalendarController extends AbstractController
|
||||
|
||||
if ($user instanceof User) {
|
||||
|
||||
// $calendar = $em->getRepository(Calendar::class)
|
||||
// ->findByUser($user)
|
||||
// ;
|
||||
|
||||
// $view = 'ChillCalendarBundle:Calendar:listByUser.html.twig';
|
||||
$calendarItems = $em->getRepository(Calendar::class)
|
||||
->findByUser($user)
|
||||
;
|
||||
$view = '@ChillCalendar/Calendar/listByUser.html.twig';
|
||||
} elseif ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$calendarItems = $em->getRepository(Calendar::class)->findBy(
|
||||
['accompanyingPeriod' => $accompanyingPeriod],
|
||||
['startDate' => 'DESC']
|
||||
);
|
||||
|
||||
$view = 'ChillCalendarBundle:Calendar:listByAccompanyingCourse.html.twig';
|
||||
$view = '@ChillCalendar/Calendar/listByAccompanyingCourse.html.twig';
|
||||
}
|
||||
|
||||
return $this->render($view, [
|
||||
@ -103,7 +102,7 @@ class CalendarController extends AbstractController
|
||||
|
||||
/**
|
||||
* Create a new calendar item
|
||||
* @Route("/{_locale}/calendar/new", name="chill_calendar_calendar_new")
|
||||
* @Route("/{_locale}/calendar/calendar/new", name="chill_calendar_calendar_new")
|
||||
*/
|
||||
public function newAction(Request $request): Response
|
||||
{
|
||||
@ -112,10 +111,10 @@ class CalendarController extends AbstractController
|
||||
[$user, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$view = 'ChillCalendarBundle:Calendar:newAccompanyingCourse.html.twig';
|
||||
$view = '@ChillCalendar/Calendar/newAccompanyingCourse.html.twig';
|
||||
}
|
||||
// elseif ($user instanceof User) {
|
||||
// $view = 'ChillCalendarBundle:Calendar:newUser.html.twig';
|
||||
// $view = '@ChillCalendar/Calendar/newUser.html.twig';
|
||||
// }
|
||||
|
||||
$entity = new Calendar();
|
||||
@ -142,7 +141,7 @@ class CalendarController extends AbstractController
|
||||
|
||||
$params = $this->buildParamsToUrl($user, $accompanyingPeriod);
|
||||
|
||||
return $this->redirectToRoute('chill_calendar_calendar', $params);
|
||||
return $this->redirectToRoute('chill_calendar_calendar_list', $params);
|
||||
} elseif ($form->isSubmitted() and !$form->isValid()) {
|
||||
$this->addFlash('error', $this->get('translator')->trans('This form contains errors'));
|
||||
}
|
||||
@ -165,7 +164,7 @@ class CalendarController extends AbstractController
|
||||
|
||||
/**
|
||||
* Show a calendar item
|
||||
* @Route("/{_locale}/calendar/{id}/show", name="chill_calendar_calendar_show")
|
||||
* @Route("/{_locale}/calendar/calendar/{id}/show", name="chill_calendar_calendar_show")
|
||||
*/
|
||||
public function showAction(Request $request, $id): Response
|
||||
{
|
||||
@ -174,11 +173,11 @@ class CalendarController extends AbstractController
|
||||
[$user, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$view = 'ChillCalendarBundle:Calendar:showAccompanyingCourse.html.twig';
|
||||
$view = '@ChillCalendar/Calendar/showByAccompanyingCourse.html.twig';
|
||||
}
|
||||
// elseif ($person instanceof Person) {
|
||||
// $view = 'ChillCalendarBundle:Calendar:showPerson.html.twig';
|
||||
// }
|
||||
elseif ($user instanceof User) {
|
||||
$view = '@ChillCalendar/Calendar/showByUser.html.twig';
|
||||
}
|
||||
|
||||
$entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id);
|
||||
|
||||
@ -198,9 +197,9 @@ class CalendarController extends AbstractController
|
||||
}
|
||||
|
||||
return $this->render($view, [
|
||||
//'person' => $person,
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
'entity' => $entity,
|
||||
'user' => $user
|
||||
//'delete_form' => $deleteForm->createView(),
|
||||
]);
|
||||
}
|
||||
@ -209,7 +208,7 @@ class CalendarController extends AbstractController
|
||||
|
||||
/**
|
||||
* Edit a calendar item
|
||||
* @Route("/{_locale}/calendar/{id}/edit", name="chill_calendar_calendar_edit")
|
||||
* @Route("/{_locale}/calendar/calendar/{id}/edit", name="chill_calendar_calendar_edit")
|
||||
*/
|
||||
public function editAction($id, Request $request): Response
|
||||
{
|
||||
@ -218,11 +217,11 @@ class CalendarController extends AbstractController
|
||||
[$user, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$view = 'ChillCalendarBundle:Calendar:editAccompanyingCourse.html.twig';
|
||||
$view = '@ChillCalendar/Calendar/editByAccompanyingCourse.html.twig';
|
||||
}
|
||||
elseif ($user instanceof User) {
|
||||
$view = '@ChillCalendar/Calendar/editByUser.html.twig';
|
||||
}
|
||||
// elseif ($person instanceof Person) {
|
||||
// $view = 'ChillCalendarBundle:Calendar:editPerson.html.twig';
|
||||
// }
|
||||
|
||||
$entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id);
|
||||
|
||||
@ -241,7 +240,7 @@ class CalendarController extends AbstractController
|
||||
$this->addFlash('success', $this->get('translator')->trans('Success : calendar item updated!'));
|
||||
|
||||
$params = $this->buildParamsToUrl($user, $accompanyingPeriod);
|
||||
return $this->redirectToRoute('chill_calendar_calendar', $params);
|
||||
return $this->redirectToRoute('chill_calendar_calendar_list', $params);
|
||||
} elseif ($form->isSubmitted() and !$form->isValid()) {
|
||||
$this->addFlash('error', $this->get('translator')->trans('This form contains errors'));
|
||||
}
|
||||
@ -259,6 +258,7 @@ class CalendarController extends AbstractController
|
||||
'form' => $form->createView(),
|
||||
'delete_form' => $deleteForm->createView(),
|
||||
'accompanyingCourse' => $accompanyingPeriod,
|
||||
'user' => $user,
|
||||
'entity_json' => $entity_array
|
||||
]);
|
||||
}
|
||||
@ -274,11 +274,11 @@ class CalendarController extends AbstractController
|
||||
[$user, $accompanyingPeriod] = $this->getEntity($request);
|
||||
|
||||
if ($accompanyingPeriod instanceof AccompanyingPeriod) {
|
||||
$view = 'ChillCalendarBundle:Calendar:confirm_deleteAccompanyingCourse.html.twig';
|
||||
$view = '@ChillCalendar/Calendar/confirm_deleteByAccompanyingCourse.html.twig';
|
||||
}
|
||||
// elseif ($person instanceof Person) {
|
||||
// $view = 'ChillCalendarBundle:Calendar:confirm_deletePerson.html.twig';
|
||||
// }
|
||||
elseif ($user instanceof User) {
|
||||
$view = '@ChillCalendar/Calendar/confirm_deleteByUser.html.twig';
|
||||
}
|
||||
|
||||
/* @var $entity Calendar */
|
||||
$entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id);
|
||||
@ -306,7 +306,7 @@ class CalendarController extends AbstractController
|
||||
->trans("The calendar item has been successfully removed."));
|
||||
|
||||
$params = $this->buildParamsToUrl($user, $accompanyingPeriod);
|
||||
return $this->redirectToRoute('chill_calendar_calendar', $params);
|
||||
return $this->redirectToRoute('chill_calendar_calendar_list', $params);
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,9 +324,9 @@ class CalendarController extends AbstractController
|
||||
/**
|
||||
* Creates a form to delete a Calendar entity by id.
|
||||
*/
|
||||
private function createDeleteForm(int $id, ?Person $person, ?AccompanyingPeriod $accompanyingPeriod): Form
|
||||
private function createDeleteForm(int $id, ?User $user, ?AccompanyingPeriod $accompanyingPeriod): Form
|
||||
{
|
||||
$params = $this->buildParamsToUrl($person, $accompanyingPeriod);
|
||||
$params = $this->buildParamsToUrl($user, $accompanyingPeriod);
|
||||
$params['id'] = $id;
|
||||
|
||||
return $this->createFormBuilder()
|
||||
@ -350,7 +350,8 @@ class CalendarController extends AbstractController
|
||||
throw $this->createNotFoundException('User not found');
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $user);
|
||||
// TODO Add permission
|
||||
// $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $user);
|
||||
} elseif ($request->query->has('accompanying_period_id')) {
|
||||
$accompanying_period_id = $request->get('accompanying_period_id');
|
||||
$accompanyingPeriod = $em->getRepository(AccompanyingPeriod::class)->find($accompanying_period_id);
|
||||
|
@ -18,16 +18,19 @@ class CalendarRangeAPIController extends ApiController
|
||||
*/
|
||||
public function availableRanges(Request $request, string $_format): JsonResponse
|
||||
{
|
||||
if ($request->query->has('user')) {
|
||||
$user = $request->query->get('user');
|
||||
}
|
||||
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$query = $em->createQuery(
|
||||
'SELECT c FROM ChillCalendarBundle:CalendarRange c
|
||||
WHERE NOT EXISTS (SELECT cal.id FROM ChillCalendarBundle:Calendar cal WHERE cal.calendarRange = c.id)')
|
||||
;
|
||||
$sql = 'SELECT c FROM ChillCalendarBundle:CalendarRange c
|
||||
WHERE NOT EXISTS (SELECT cal.id FROM ChillCalendarBundle:Calendar cal WHERE cal.calendarRange = c.id)';
|
||||
|
||||
if ($request->query->has('user')) {
|
||||
$user = $request->query->get('user');
|
||||
$sql = $sql . ' AND c.user = :user';
|
||||
$query = $em->createQuery($sql)
|
||||
->setParameter('user', $user);
|
||||
} else {
|
||||
$query = $em->createQuery($sql);
|
||||
}
|
||||
|
||||
$results = $query->getResult();
|
||||
|
||||
|
@ -66,13 +66,16 @@ class ChillCalendarExtension extends Extension implements PrependExtensionInterf
|
||||
'_index' => [
|
||||
'methods' => [
|
||||
Request::METHOD_GET => true,
|
||||
Request::METHOD_HEAD => true
|
||||
Request::METHOD_HEAD => true,
|
||||
],
|
||||
],
|
||||
'_entity' => [
|
||||
'methods' => [
|
||||
Request::METHOD_GET => true,
|
||||
Request::METHOD_HEAD => true
|
||||
Request::METHOD_HEAD => true,
|
||||
Request::METHOD_POST => true,
|
||||
Request::METHOD_PATCH => true,
|
||||
Request::METHOD_DELETE => true,
|
||||
]
|
||||
],
|
||||
]
|
||||
|
@ -37,14 +37,16 @@ class Calendar
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
* @Serializer\Groups({"calendar:read"})
|
||||
*/
|
||||
private ?int $id;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
|
||||
* @Groups({"read"})
|
||||
* @Serializer\Groups({"calendar:read"})
|
||||
*/
|
||||
private User $user;
|
||||
private ?User $user = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod")
|
||||
@ -64,6 +66,7 @@ class Calendar
|
||||
* cascade={"persist", "remove", "merge", "detach"})
|
||||
* @ORM\JoinTable(name="chill_calendar.calendar_to_persons")
|
||||
* @Groups({"read"})
|
||||
* @Serializer\Groups({"calendar:read"})
|
||||
*/
|
||||
private Collection $persons;
|
||||
|
||||
@ -74,6 +77,7 @@ class Calendar
|
||||
* cascade={"persist", "remove", "merge", "detach"})
|
||||
* @ORM\JoinTable(name="chill_calendar.calendar_to_thirdparties")
|
||||
* @Groups({"read"})
|
||||
* @Serializer\Groups({"calendar:read"})
|
||||
*/
|
||||
private Collection $professionals;
|
||||
|
||||
@ -89,6 +93,7 @@ class Calendar
|
||||
|
||||
/**
|
||||
* @ORM\Embedded(class=CommentEmbeddable::class, columnPrefix="comment_")
|
||||
* @Serializer\Groups({"calendar:read"})
|
||||
*/
|
||||
private CommentEmbeddable $comment;
|
||||
|
||||
@ -96,20 +101,20 @@ class Calendar
|
||||
* @ORM\Column(type="datetimetz_immutable")
|
||||
* @Serializer\Groups({"calendar:read"})
|
||||
*/
|
||||
private \DateTimeImmutable $startDate;
|
||||
private ?\DateTimeImmutable $startDate = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetimetz_immutable")
|
||||
* @Serializer\Groups({"calendar:read"})
|
||||
*/
|
||||
private \DateTimeImmutable $endDate;
|
||||
private ?\DateTimeImmutable $endDate = null;
|
||||
|
||||
//TODO Lieu
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255)
|
||||
*/
|
||||
private string $status;
|
||||
private ?string $status = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="CancelReason")
|
||||
@ -124,7 +129,7 @@ class Calendar
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\Activity")
|
||||
*/
|
||||
private Activity $activity;
|
||||
private ?Activity $activity = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="boolean", nullable=true)
|
||||
|
@ -25,21 +25,21 @@ class CalendarRange
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
|
||||
* @Groups({"read"})
|
||||
* @groups({"read", "write"})
|
||||
*/
|
||||
private User $user;
|
||||
private ?User $user = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetimetz_immutable")
|
||||
* @groups({"read"})
|
||||
* @groups({"read", "write"})
|
||||
*/
|
||||
private \DateTimeImmutable $startDate;
|
||||
private ?\DateTimeImmutable $startDate = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetimetz_immutable")
|
||||
* @groups({"read"})
|
||||
* @groups({"read", "write"})
|
||||
*/
|
||||
private \DateTimeImmutable $endDate;
|
||||
private ?\DateTimeImmutable $endDate = null;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity=Calendar::class,
|
||||
|
@ -37,7 +37,7 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
|
||||
|
||||
if (AccompanyingPeriod::STEP_DRAFT !== $period->getStep()) {
|
||||
$menu->addChild($this->translator->trans('Calendar'), [
|
||||
'route' => 'chill_calendar_calendar',
|
||||
'route' => 'chill_calendar_calendar_list',
|
||||
'routeParameters' => [
|
||||
'accompanying_period_id' => $period->getId(),
|
||||
]])
|
||||
|
@ -7,4 +7,14 @@ div#calendarControls {
|
||||
|
||||
div#fullCalendar{
|
||||
|
||||
}
|
||||
|
||||
span.calendarRangeItems {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
a {
|
||||
text-decoration: none;
|
||||
padding: 3px;
|
||||
}
|
||||
}
|
@ -0,0 +1,468 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2 class="chill-red">{{ $t('edit_your_calendar_range') }}</h2>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="checkbox" id="myCalendar" class="form-check-input" v-model="showMyCalendarWidget" />
|
||||
<label class="form-check-label" for="myCalendar">{{ $t('show_my_calendar') }}</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" id="weekends" class="form-check-input" @click="toggleWeekends" />
|
||||
<label class="form-check-label" for="weekends">{{ $t('show_weekends') }}</label>
|
||||
</div>
|
||||
|
||||
<FullCalendar ref="fullCalendar" :options="calendarOptions">
|
||||
<template v-slot:eventContent='arg' >
|
||||
<span class='calendarRangeItems'>
|
||||
<b v-if="arg.event.extendedProps.myCalendar" style="text-decoration: underline" >{{ arg.timeText }}</b>
|
||||
<b v-else-if="!arg.event.extendedProps.myCalendar && arg.event.extendedProps.toDelete" style="text-decoration: line-through red" >{{ arg.timeText }}</b>
|
||||
<b v-else >{{ arg.timeText }}</b>
|
||||
<i> {{ arg.event.title }}</i>
|
||||
<a v-if=!arg.event.extendedProps.myCalendar class="fa fa-fw fa-times"
|
||||
@click.prevent="onClickDelete(arg.event)">
|
||||
</a>
|
||||
</span>
|
||||
</template>
|
||||
</FullCalendar>
|
||||
<div>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<button class="btn btn-save" :disabled="!dirty"
|
||||
@click.prevent="onClickSave">
|
||||
{{ $t('action.save')}}
|
||||
</button>
|
||||
<span v-if="flag.loading" class="loading">
|
||||
<i class="fa fa-circle-o-notch fa-spin fa-fw"></i>
|
||||
<span class="sr-only">{{ $t('loading') }}</span>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<button v-if="disableCopyDayButton" class="btn btn-action" disabled>
|
||||
{{ $t('copy_range_to_next_day')}}
|
||||
</button>
|
||||
<button v-else class="btn btn-action"
|
||||
@click.prevent="copyDay">
|
||||
{{ $t('copy_range_from_day')}} {{this.lastNewDate.toLocaleDateString()}} {{ $t('to_the_next_day')}}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<div v-if="newCalendarRanges.length > 0">
|
||||
<h4>{{ $t('new_range_to_save') }}</h4>
|
||||
<ul>
|
||||
<li v-for="i in newCalendarRanges" :key="i.start">
|
||||
{{ i.start.toLocaleString() }} - {{ i.end.toLocaleString() }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-if="updateCalendarRanges.length > 0">
|
||||
<h4>{{ $t('update_range_to_save') }}</h4>
|
||||
<ul>
|
||||
<li v-for="i in updateCalendarRanges" :key="i.start">
|
||||
{{ i.start.toLocaleString() }} - {{ i.end.toLocaleString() }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-if="deleteCalendarRanges.length > 0">
|
||||
<h4>{{ $t('delete_range_to_save') }}</h4>
|
||||
<ul>
|
||||
<li v-for="i in deleteCalendarRanges" :key="i.start">
|
||||
{{ i.start.toLocaleString() }} - {{ i.end.toLocaleString() }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<teleport to="body">
|
||||
<modal v-if="modal.showModal"
|
||||
:modalDialogClass="modal.modalDialogClass"
|
||||
@close="modal.showModal = false">
|
||||
|
||||
<template v-slot:header>
|
||||
<h2 class="modal-title">{{ this.renderEventDate() }}</h2>
|
||||
</template>
|
||||
|
||||
<template v-slot:body>
|
||||
<p>{{ $t('by')}} {{this.myCalendarClickedEvent.user.username }}</p>
|
||||
<p>{{ $t('main_user_concerned') }} : {{ this.myCalendarClickedEvent.mainUser.username }}</p>
|
||||
<p v-if="myCalendarClickedEvent.comment.length > 0" >{{ this.myCalendarClickedEvent.comment }}</p>
|
||||
</template>
|
||||
|
||||
<template v-slot:footer>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a
|
||||
class="btn btn-show"
|
||||
:href=myCalendarEventShowLink() >
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="btn btn-update"
|
||||
:href=myCalendarEventUpdateLink() >
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="btn btn-delete"
|
||||
:href=myCalendarEventDeleteLink() >
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
</modal>
|
||||
</teleport>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import '@fullcalendar/core/vdom'; // solves problem with Vite
|
||||
import frLocale from '@fullcalendar/core/locales/fr';
|
||||
import FullCalendar from '@fullcalendar/vue3';
|
||||
import dayGridPlugin from '@fullcalendar/daygrid';
|
||||
import interactionPlugin from '@fullcalendar/interaction';
|
||||
import timeGridPlugin from '@fullcalendar/timegrid';
|
||||
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
|
||||
import { deleteCalendarRange, fetchCalendar, fetchCalendarRangesByUser, patchCalendarRange, postCalendarRange } from '../_api/api';
|
||||
import { mapState } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: "App",
|
||||
components: {
|
||||
FullCalendar,
|
||||
Modal
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
errorMsg: [],
|
||||
modal: {
|
||||
showModal: false,
|
||||
modalDialogClass: "modal-dialog-scrollable modal-m"
|
||||
},
|
||||
flag: {
|
||||
loading: false
|
||||
},
|
||||
userId: window.userId,
|
||||
showMyCalendar: true,
|
||||
myCalendarClickedEvent: null,
|
||||
calendarEvents: {
|
||||
userCalendar: null,
|
||||
userCalendarRange: null,
|
||||
new: {
|
||||
events: [],
|
||||
color: "#3788d8"
|
||||
}
|
||||
},
|
||||
lastNewDate: null,
|
||||
disableCopyDayButton: true,
|
||||
calendarOptions: {
|
||||
locale: frLocale,
|
||||
plugins: [ dayGridPlugin, interactionPlugin, timeGridPlugin ],
|
||||
initialView: 'timeGridWeek',
|
||||
initialDate: window.startDate !== undefined ? window.startDate : new Date(),
|
||||
eventSource: [],
|
||||
selectable: true,
|
||||
select: this.onDateSelect,
|
||||
eventChange: this.onEventChange,
|
||||
eventDrop: this.onEventDropOrResize,
|
||||
eventResize: this.onEventDropOrResize,
|
||||
eventClick: this.onEventClick,
|
||||
selectMirror: false,
|
||||
editable: true,
|
||||
weekends: false,
|
||||
headerToolbar: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'dayGridMonth,timeGridWeek,timeGridDay'
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
newCalendarRanges: state => state.newCalendarRanges,
|
||||
updateCalendarRanges: state => state.updateCalendarRanges,
|
||||
deleteCalendarRanges: state => state.deleteCalendarRanges,
|
||||
dirty: state => state.newCalendarRanges.length > 0 || state.updateCalendarRanges.length > 0 || state.deleteCalendarRanges.length > 0
|
||||
}),
|
||||
showMyCalendarWidget: {
|
||||
set(value) {
|
||||
this.toggleMyCalendar(value);
|
||||
this.updateEventsSource();
|
||||
},
|
||||
get() {
|
||||
return this.showMyCalendar;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.fetchData();
|
||||
},
|
||||
openModal() {
|
||||
this.modal.showModal = true;
|
||||
},
|
||||
myCalendarEventShowLink() {
|
||||
return `/fr/calendar/calendar/${this.myCalendarClickedEvent.id}/show?user_id=${ this.userId }`
|
||||
},
|
||||
myCalendarEventUpdateLink() {
|
||||
return `/fr/calendar/calendar/${this.myCalendarClickedEvent.id}/edit?user_id=${ this.userId }`
|
||||
},
|
||||
myCalendarEventDeleteLink() {
|
||||
return `/fr/calendar/calendar/${this.myCalendarClickedEvent.id}/delete?user_id=${ this.userId }`
|
||||
},
|
||||
resetCalendar() {
|
||||
this.fetchData();
|
||||
this.calendarEvents.new = {
|
||||
events: [],
|
||||
color: "#3788d8"
|
||||
};
|
||||
this.updateEventsSource();
|
||||
},
|
||||
fetchData() {
|
||||
this.flag.loading = true;
|
||||
fetchCalendarRangesByUser(this.userId).then(calendarRanges => new Promise((resolve, reject) => {
|
||||
let events = calendarRanges.results.map(i =>
|
||||
({
|
||||
start: i.startDate.datetime,
|
||||
end: i.endDate.datetime,
|
||||
calendarRangeId: i.id,
|
||||
toDelete: false
|
||||
})
|
||||
);
|
||||
let calendarRangeEvents = {
|
||||
events: events,
|
||||
borderColor: "#3788d8",
|
||||
backgroundColor: '#ffffff',
|
||||
textColor: '#444444',
|
||||
};
|
||||
this.calendarEvents.userCalendarRange = calendarRangeEvents;
|
||||
|
||||
fetchCalendar(this.userId).then(calendar => new Promise((resolve, reject) => {
|
||||
let events = calendar.results.map(i =>
|
||||
({
|
||||
myCalendar: true,
|
||||
calendarId: i.id,
|
||||
start: i.startDate.datetime,
|
||||
end: i.endDate.datetime,
|
||||
user: i.user,
|
||||
mainUser: i.mainUser,
|
||||
persons: i.persons,
|
||||
professionals: i.professionals,
|
||||
comment: i.comment
|
||||
})
|
||||
);
|
||||
let calendarEventsCurrentUser = {
|
||||
events: events,
|
||||
color: 'darkblue',
|
||||
id: 1000,
|
||||
editable: false
|
||||
};
|
||||
this.calendarEvents.userCalendar = calendarEventsCurrentUser;
|
||||
this.updateEventsSource();
|
||||
this.flag.loading = false;
|
||||
resolve();
|
||||
}));
|
||||
|
||||
resolve();
|
||||
}));
|
||||
},
|
||||
updateEventsSource() {
|
||||
this.calendarOptions.eventSources = [];
|
||||
this.calendarOptions.eventSources.push(this.calendarEvents.new);
|
||||
this.calendarOptions.eventSources.push(this.calendarEvents.userCalendarRange);
|
||||
if (this.showMyCalendar) {
|
||||
this.calendarOptions.eventSources.push(this.calendarEvents.userCalendar);
|
||||
}
|
||||
console.log(this.calendarOptions.eventSources);
|
||||
},
|
||||
toggleMyCalendar(value) {
|
||||
this.showMyCalendar = value;
|
||||
},
|
||||
toggleWeekends: function() {
|
||||
this.calendarOptions.weekends = !this.calendarOptions.weekends;
|
||||
},
|
||||
onDateSelect(payload) {
|
||||
let events = this.calendarEvents.new.events;
|
||||
events.push({
|
||||
start: payload.startStr,
|
||||
end: payload.endStr
|
||||
});
|
||||
this.calendarEvents.new = {
|
||||
events: events,
|
||||
borderColor: "#3788d8",
|
||||
backgroundColor: '#fffadf ',
|
||||
textColor: '#444444',
|
||||
};
|
||||
this.disableCopyDayButton = false;
|
||||
this.lastNewDate = new Date(payload.startStr);
|
||||
this.updateEventsSource();
|
||||
this.$store.dispatch('createRange', payload);
|
||||
},
|
||||
onEventChange(payload) {
|
||||
},
|
||||
onEventDropOrResize(payload) {
|
||||
payload.event.setProp('borderColor', '#3788d8');
|
||||
payload.event.setProp('backgroundColor', '#fffadf');
|
||||
payload.event.setProp('textColor', '#444444');
|
||||
this.$store.dispatch('updateRange', payload);
|
||||
},
|
||||
onEventClick(payload) {
|
||||
if (payload.event.extendedProps.myCalendar) {
|
||||
this.myCalendarClickedEvent = {
|
||||
id: payload.event.extendedProps.calendarId,
|
||||
start: payload.event.start,
|
||||
end: payload.event.end,
|
||||
user: payload.event.extendedProps.user,
|
||||
mainUser: payload.event.extendedProps.mainUser,
|
||||
persons: payload.event.extendedProps.persons,
|
||||
professionals: payload.event.extendedProps.professionals,
|
||||
comment: payload.event.extendedProps.comment
|
||||
};
|
||||
console.log(this.myCalendarClickedEvent)
|
||||
this.openModal();
|
||||
}
|
||||
},
|
||||
onClickSave(payload) {
|
||||
this.flag.loading = true;
|
||||
if (this.$store.state.newCalendarRanges.length > 0){
|
||||
Promise.all(this.$store.state.newCalendarRanges.map(cr => {
|
||||
postCalendarRange({
|
||||
user: {
|
||||
type: 'user',
|
||||
id: window.userId,
|
||||
},
|
||||
startDate: {
|
||||
datetime: `${cr.start.toISOString().split('.')[0]}+0000`, //should be like "2021-08-20T15:00:00+0200",
|
||||
},
|
||||
endDate: {
|
||||
datetime: `${cr.end.toISOString().split('.')[0]}+0000`, // TODO check if OK with time zone
|
||||
},
|
||||
})
|
||||
})
|
||||
).then((_r) => this.resetCalendar());
|
||||
|
||||
this.$store.dispatch('clearNewCalendarRanges', payload);
|
||||
}
|
||||
if (this.$store.state.updateCalendarRanges.length > 0){
|
||||
Promise.all(this.$store.state.updateCalendarRanges.map(cr => {
|
||||
patchCalendarRange(cr.id,
|
||||
{
|
||||
startDate: {
|
||||
datetime: `${cr.start.toISOString().split('.')[0]}+0000`, //should be like "2021-08-20T15:00:00+0200",
|
||||
},
|
||||
endDate: {
|
||||
datetime: `${cr.end.toISOString().split('.')[0]}+0000`, // TODO check if OK with time zone
|
||||
},
|
||||
})
|
||||
})
|
||||
).then((_r) => this.resetCalendar());
|
||||
this.$store.dispatch('clearUpdateCalendarRanges', payload);
|
||||
}
|
||||
if (this.$store.state.deleteCalendarRanges.length > 0){
|
||||
Promise.all(this.$store.state.deleteCalendarRanges.map(cr => {
|
||||
deleteCalendarRange(cr.id)
|
||||
})
|
||||
).then((_r) => this.resetCalendar());
|
||||
this.$store.dispatch('clearDeleteCalendarRanges', payload);
|
||||
}
|
||||
|
||||
},
|
||||
onClickDelete(payload) {
|
||||
if (payload.extendedProps.hasOwnProperty("calendarRangeId")) {
|
||||
if (payload.extendedProps.toDelete) {
|
||||
payload.setExtendedProp('toDelete', false)
|
||||
payload.setProp('borderColor', '#79bafc');
|
||||
this.$store.dispatch('removeFromDeleteRange', payload);
|
||||
} else {
|
||||
payload.setExtendedProp('toDelete', true)
|
||||
payload.setProp('borderColor', '#dddddd');
|
||||
this.$store.dispatch('deleteRange', payload);
|
||||
}
|
||||
} else {
|
||||
let newEvents = this.calendarEvents.new.events;
|
||||
let filterEvents = newEvents.filter((e) =>
|
||||
e.start !== payload.startStr && e.end !== payload.endStr
|
||||
);
|
||||
this.calendarEvents.new = {
|
||||
events: filterEvents,
|
||||
color: "#3788d8"
|
||||
};
|
||||
|
||||
this.$store.dispatch('removeNewCalendarRanges', payload);
|
||||
|
||||
this.updateEventsSource();
|
||||
}
|
||||
|
||||
},
|
||||
isSameDay(date1, date2) {
|
||||
return date1.getFullYear() === date2.getFullYear() &&
|
||||
date1.getMonth() === date2.getMonth() &&
|
||||
date1.getDate() === date2.getDate();
|
||||
},
|
||||
isFriday(date) {
|
||||
return date.getDay() === 5
|
||||
},
|
||||
copyDay(_payload) {
|
||||
console.log(this.calendarEvents.new);
|
||||
if (this.calendarEvents.new.events.length > 0) {
|
||||
// Create the copied events
|
||||
let increment = !this.calendarOptions.weekends && this.isFriday(this.lastNewDate) ? 24*60*60*1000*3 : 24*60*60*1000;
|
||||
let events = this.calendarEvents.new.events.filter(
|
||||
i => this.isSameDay(new Date(i.start), this.lastNewDate)).map(
|
||||
i => {
|
||||
let startDate = new Date(new Date(i.start).getTime() + increment);
|
||||
let endDate = new Date(new Date(i.end).getTime() + increment);
|
||||
return ({
|
||||
start: startDate.toISOString(),
|
||||
end: endDate.toISOString()
|
||||
})
|
||||
}
|
||||
);
|
||||
let copiedEvents = {
|
||||
events: events,
|
||||
color: "#3788d8"
|
||||
};
|
||||
console.log(copiedEvents);
|
||||
|
||||
// Add to the calendar
|
||||
let newEvents = this.calendarEvents.new.events;
|
||||
newEvents.push(...copiedEvents.events);
|
||||
this.calendarEvents.new = {
|
||||
events: newEvents,
|
||||
color: "#3788d8"
|
||||
};
|
||||
this.updateEventsSource();
|
||||
|
||||
// Set the last new date
|
||||
this.lastNewDate = new Date(copiedEvents.events[copiedEvents.events.length - 1].start);
|
||||
|
||||
// Dispatch in store for saving
|
||||
for (let i = 0; i < copiedEvents.events.length; i++) {
|
||||
let eventObj = {
|
||||
start: new Date(copiedEvents.events[i].start),
|
||||
end: new Date(copiedEvents.events[i].end)
|
||||
}
|
||||
this.$store.dispatch('createRange', eventObj);
|
||||
}
|
||||
|
||||
} else {
|
||||
console.log('no new events to copy-paste!')
|
||||
}
|
||||
},
|
||||
renderEventDate() {
|
||||
let start = this.myCalendarClickedEvent.start;
|
||||
let end = this.myCalendarClickedEvent.end;
|
||||
return start.getDate() === end.getDate() ?
|
||||
`${start.toLocaleDateString()}, ${start.toLocaleTimeString()} - ${end.toLocaleTimeString()}` :
|
||||
`${start.toLocaleString()} - ${end.toLocaleString()}`;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
</script>
|
@ -0,0 +1,21 @@
|
||||
const appMessages = {
|
||||
fr: {
|
||||
edit_your_calendar_range: "Planifiez vos plages de disponibilités",
|
||||
show_my_calendar: "Afficher mon calendrier",
|
||||
show_weekends: "Afficher les week-ends",
|
||||
copy_range_to_next_day: "Copier les plages du jour au jour suivant",
|
||||
copy_range_from_day: "Copier les plages du ",
|
||||
to_the_next_day: " au jour suivant",
|
||||
copy_range_to_next_week: "Copier les plages de la semaine à la semaine suivante",
|
||||
copy_range_how_to: "Créez les plages de disponibilités durant une journée et copiez-les facilement au jour suivant avec ce bouton. Si les week-ends sont cachés, le jour suivant un vendredi sera le lundi.",
|
||||
new_range_to_save: "Nouvelles plages à enregistrer",
|
||||
update_range_to_save: "Plages à modifier",
|
||||
delete_range_to_save: "Plages à supprimer",
|
||||
by: "Par",
|
||||
main_user_concerned: "Utilisateur concerné"
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
appMessages
|
||||
};
|
@ -0,0 +1,16 @@
|
||||
import { createApp } from 'vue';
|
||||
import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n'
|
||||
import { appMessages } from './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('#myCalendar');
|
@ -0,0 +1,89 @@
|
||||
import 'es6-promise/auto';
|
||||
import { createStore } from 'vuex';
|
||||
import { postCalendarRange, patchCalendarRange, deleteCalendarRange } from '../_api/api';
|
||||
|
||||
const debug = process.env.NODE_ENV !== 'production';
|
||||
|
||||
const store = createStore({
|
||||
strict: debug,
|
||||
state: {
|
||||
newCalendarRanges: [],
|
||||
updateCalendarRanges: [],
|
||||
deleteCalendarRanges: []
|
||||
},
|
||||
mutations: {
|
||||
updateRange(state, payload) {
|
||||
state.updateCalendarRanges.push({
|
||||
id: payload.event.extendedProps.calendarRangeId,
|
||||
start: payload.event.start,
|
||||
end: payload.event.end
|
||||
});
|
||||
},
|
||||
addRange(state, payload) {
|
||||
state.newCalendarRanges.push({
|
||||
start: payload.start,
|
||||
end: payload.end
|
||||
});
|
||||
},
|
||||
deleteRange(state, payload) {
|
||||
state.deleteCalendarRanges.push({
|
||||
id: payload.extendedProps.calendarRangeId,
|
||||
start: payload.start,
|
||||
end: payload.end
|
||||
});
|
||||
},
|
||||
clearNewCalendarRanges(state) {
|
||||
state.newCalendarRanges = [];
|
||||
},
|
||||
clearUpdateCalendarRanges(state) {
|
||||
state.updateCalendarRanges = [];
|
||||
},
|
||||
clearDeleteCalendarRanges(state) {
|
||||
state.deleteCalendarRanges = [];
|
||||
},
|
||||
removeNewCalendarRanges(state, payload) {
|
||||
let filteredCollection = state.newCalendarRanges.filter(
|
||||
(e) => e.start.toString() !== payload.start.toString() && e.end.toString() !== payload.end.toString()
|
||||
)
|
||||
state.newCalendarRanges = filteredCollection;
|
||||
},
|
||||
removeFromDeleteRange(state, payload) {
|
||||
let filteredCollection = state.deleteCalendarRanges.filter(
|
||||
(e) => e.start.toString() !== payload.start.toString() && e.end.toString() !== payload.end.toString()
|
||||
)
|
||||
state.deleteCalendarRanges = filteredCollection;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
createRange({ commit }, payload) {
|
||||
console.log('### action createRange', payload);
|
||||
commit('addRange', payload);
|
||||
},
|
||||
updateRange({ commit }, payload) {
|
||||
console.log('### action updateRange', payload);
|
||||
commit('updateRange', payload);
|
||||
},
|
||||
deleteRange({ commit }, payload) {
|
||||
console.log('### action deleteRange', payload);
|
||||
commit('deleteRange', payload);
|
||||
},
|
||||
clearNewCalendarRanges({ commit }, payload) {
|
||||
commit('clearNewCalendarRanges', payload);
|
||||
},
|
||||
clearUpdateCalendarRanges({ commit }, payload) {
|
||||
commit('clearUpdateCalendarRanges', payload);
|
||||
},
|
||||
clearDeleteCalendarRanges({ commit }, payload) {
|
||||
commit('clearDeleteCalendarRanges', payload);
|
||||
},
|
||||
removeNewCalendarRanges({ commit }, payload) {
|
||||
commit('removeNewCalendarRanges', payload);
|
||||
},
|
||||
removeFromDeleteRange({ commit }, payload) {
|
||||
commit('removeFromDeleteRange', payload);
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export default store;
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Endpoint chill_api_single_calendar_range
|
||||
* method GET, get Calendar ranges
|
||||
* @returns {Promise} a promise containing all Calendar ranges objects
|
||||
*/
|
||||
const fetchCalendarRanges = () => {
|
||||
const url = `/api/1.0/calendar/calendar-range-available.json`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
const fetchCalendarRangesByUser = (userId) => {
|
||||
const url = `/api/1.0/calendar/calendar-range-available.json?user=${userId}`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoint chill_api_single_calendar
|
||||
* method GET, get Calendar events, can be filtered by mainUser
|
||||
* @returns {Promise} a promise containing all Calendar objects
|
||||
*/
|
||||
const fetchCalendar = (mainUserId) => {
|
||||
const url = `/api/1.0/calendar/calendar.json?main_user=${mainUserId}&item_per_page=1000`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Endpoint chill_api_single_calendar_range__entity_create
|
||||
* method POST, post CalendarRange entity
|
||||
*/
|
||||
const postCalendarRange = (body) => {
|
||||
const url = `/api/1.0/calendar/calendar-range.json?`;
|
||||
return fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
}).then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoint chill_api_single_calendar_range__entity
|
||||
* method PATCH, patch CalendarRange entity
|
||||
*/
|
||||
const patchCalendarRange = (id, body) => {
|
||||
console.log(body)
|
||||
const url = `/api/1.0/calendar/calendar-range/${id}.json`;
|
||||
return fetch(url, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
body: JSON.stringify(body)
|
||||
}).then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoint chill_api_single_calendar_range__entity
|
||||
* method DELETE, delete CalendarRange entity
|
||||
*/
|
||||
const deleteCalendarRange = (id) => {
|
||||
const url = `/api/1.0/calendar/calendar-range/${id}.json`;
|
||||
return fetch(url, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
}).then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
export {
|
||||
fetchCalendarRanges,
|
||||
fetchCalendar,
|
||||
fetchCalendarRangesByUser,
|
||||
postCalendarRange,
|
||||
patchCalendarRange,
|
||||
deleteCalendarRange
|
||||
};
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="calendar__controls">
|
||||
<div>
|
||||
<h2 class="chill-red">{{ $t('choose_your_calendar_user') }}</h2>
|
||||
<VueMultiselect
|
||||
name="field"
|
||||
@ -31,7 +31,7 @@
|
||||
</template>
|
||||
<script>
|
||||
|
||||
import { fetchCalendarRanges, fetchCalendar } from './js/api'
|
||||
import { fetchCalendarRanges, fetchCalendar } from '../../_api/api'
|
||||
import VueMultiselect from 'vue-multiselect';
|
||||
import { whoami } from 'ChillPersonAssets/vuejs/AccompanyingCourse/api';
|
||||
|
||||
@ -201,12 +201,3 @@ export default {
|
||||
|
||||
<style src="vue-multiselect/dist/vue-multiselect.css"></style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
div.calendar__controls {
|
||||
background-color: 'black';
|
||||
height: 50%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Endpoint chill_api_single_calendar_range
|
||||
* method GET, get Calendar ranges
|
||||
* @returns {Promise} a promise containing all Calendar ranges objects
|
||||
*/
|
||||
const fetchCalendarRanges = () => {
|
||||
const url = `/api/1.0/calendar/calendar-range-available.json`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Endpoint chill_api_single_calendar
|
||||
* method GET, get Calendar events, can be filtered by mainUser
|
||||
* @returns {Promise} a promise containing all Calendar objects
|
||||
*/
|
||||
const fetchCalendar = (mainUserId) => {
|
||||
const url = `/api/1.0/calendar/calendar.json?main_user=${mainUserId}&item_per_page=1000`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
if (response.ok) { return response.json(); }
|
||||
throw Error('Error with request resource response');
|
||||
});
|
||||
};
|
||||
|
||||
export {
|
||||
fetchCalendarRanges,
|
||||
fetchCalendar
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
{% extends "@ChillPerson/AccompanyingCourse/layout.html.twig" %}
|
||||
|
||||
{% set activeRouteKey = 'chill_calendar_calendar' %}
|
||||
{% set activeRouteKey = 'chill_calendar_calendar_list' %}
|
||||
|
||||
{% block title 'Remove calendar item'|trans %}
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
{
|
||||
'title' : 'Remove calendar item'|trans,
|
||||
'confirm_question' : 'Are you sure you want to remove the calendar item?'|trans,
|
||||
'cancel_route' : 'chill_calendar_calendar',
|
||||
'cancel_parameters' : { 'accompanying_course_id' : accompanyingCourse.id, 'id' : calendar.id },
|
||||
'cancel_route' : 'chill_calendar_calendar_list',
|
||||
'cancel_parameters' : { 'accompanying_period_id' : accompanyingCourse.id, 'id' : calendar.id },
|
||||
'form' : delete_form
|
||||
} ) }}
|
||||
{% endblock %}
|
@ -0,0 +1,18 @@
|
||||
{% extends "@ChillMain/layout.html.twig" %}
|
||||
|
||||
{% set user = calendar.user %}
|
||||
|
||||
{% set activeRouteKey = 'chill_calendar_calendar_list' %}
|
||||
|
||||
{% block title 'Remove activity'|trans %}
|
||||
|
||||
{% block content %}
|
||||
{{ include('@ChillMain/Util/confirmation_template.html.twig',
|
||||
{
|
||||
'title' : 'Remove calendar item'|trans,
|
||||
'confirm_question' : 'Are you sure you want to remove the calendar item?'|trans,
|
||||
'cancel_route' : 'chill_calendar_calendar_list',
|
||||
'cancel_parameters' : { 'user_id' : calendar.user.id, 'id' : calendar.id },
|
||||
'form' : delete_form
|
||||
} ) }}
|
||||
{% endblock %}
|
@ -1,17 +0,0 @@
|
||||
{% extends "@ChillPerson/Person/layout.html.twig" %}
|
||||
|
||||
{% set activeRouteKey = 'chill_activity_activity_list' %}
|
||||
{% set person = activity.person %}
|
||||
|
||||
{% block title 'Remove activity'|trans %}
|
||||
|
||||
{% block personcontent %}
|
||||
{{ include('@ChillMain/Util/confirmation_template.html.twig',
|
||||
{
|
||||
'title' : 'Remove activity'|trans,
|
||||
'confirm_question' : 'Are you sure you want to remove the activity about "%name%" ?'|trans({ '%name%' : person.firstname ~ ' ' ~ person.lastname } ),
|
||||
'cancel_route' : 'chill_activity_activity_list',
|
||||
'cancel_parameters' : { 'person_id' : activity.person.id, 'id' : activity.id },
|
||||
'form' : delete_form
|
||||
} ) }}
|
||||
{% endblock %}
|
@ -48,16 +48,20 @@
|
||||
{{ form_row(form.sendSMS) }}
|
||||
{% endif %}
|
||||
|
||||
{% if context == 'user' %}
|
||||
<div id="calendarControls"></div>
|
||||
{% endif %}
|
||||
|
||||
<div id="fullCalendar"></div>
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li class="cancel">
|
||||
<a
|
||||
class="btn btn-cancel"
|
||||
{%- if context == 'person' -%}
|
||||
href="{{ chill_return_path_or('chill_calendar_calendar', { 'person_id': person.id } )}}"
|
||||
{%- else -%}
|
||||
href="{{ chill_return_path_or('chill_calendar_calendar', { 'accompanying_period_id': accompanyingCourse.id } )}}"
|
||||
{%- if context == 'user' -%}
|
||||
href="{{ chill_return_path_or('chill_calendar_calendar_list', { 'user_id': user.id } )}}"
|
||||
{%- elseif context == 'accompanyingCourse' -%}
|
||||
href="{{ chill_return_path_or('chill_calendar_calendar_list', { 'accompanying_period_id': accompanyingCourse.id } )}}"
|
||||
{%- endif -%}
|
||||
>
|
||||
{{ 'Cancel'|trans|chill_return_path_label }}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
{% set activeRouteKey = 'chill_calendar_calendar_list' %}
|
||||
|
||||
{% block title 'Update calendar'|trans %}
|
||||
{% block title 'Update calendar'|trans %}
|
||||
|
||||
{% block content %}
|
||||
<div class="calendar-edit">
|
||||
@ -35,6 +35,7 @@
|
||||
{% block css %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_link_tags('vue_calendar') }}
|
||||
{{ encore_entry_link_tags('page_calendar') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block block_post_menu %}
|
@ -0,0 +1,36 @@
|
||||
{% extends "@ChillMain/layout.html.twig" %}
|
||||
|
||||
{% block title 'Update calendar'|trans %}
|
||||
|
||||
{% block content %}
|
||||
<div class="calendar-edit">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-10 col-xxl">
|
||||
|
||||
<div id="calendar"></div> {# <=== vue component #}
|
||||
{% include 'ChillCalendarBundle:Calendar:edit.html.twig' with {'context': 'user'} %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ parent() }}
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('DOMContentLoaded', function (e) {
|
||||
chill.displayAlertWhenLeavingModifiedForm('form[name="{{ form.vars.form.vars.name }}"]',
|
||||
'{{ "You are going to leave a page with unsubmitted data. Are you sure you want to leave ?"|trans }}');
|
||||
});
|
||||
window.entity = {{ entity_json|json_encode|raw }};
|
||||
window.startDate = {{ entity.startDate|date('Y-m-d H:i:s')|json_encode|raw }};
|
||||
window.endDate = {{ entity.endDate|date('Y-m-d H:i:s')|json_encode|raw }};
|
||||
window.mainUser = {{ entity.mainUser.id }};
|
||||
</script>
|
||||
{{ encore_entry_script_tags('vue_calendar') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_link_tags('vue_calendar') }}
|
||||
{% endblock %}
|
@ -8,134 +8,128 @@
|
||||
{% set accompanying_course_id = accompanyingCourse.id %}
|
||||
{% endif %}
|
||||
|
||||
<h2>{{ 'Calendar list' |trans }}</h2>
|
||||
{% if context == 'user' %}
|
||||
<h2>{{ 'My calendar list' |trans }}</h2>
|
||||
{% else %}
|
||||
<h2>{{ 'Calendar list' |trans }}</h2>
|
||||
{% endif %}
|
||||
|
||||
{% if calendarItems|length == 0 %}
|
||||
<p class="chill-no-data-statement">
|
||||
{{ "There is no calendar items."|trans }}
|
||||
<a href="{{ path('chill_calendar_calendar_new', {'user_id': user_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-create button-small"></a>
|
||||
</p>
|
||||
{% if context == 'user' %}
|
||||
<div id="myCalendar"></div>
|
||||
{% else %}
|
||||
|
||||
<div class="flex-table list-records context-{{ context }}">
|
||||
{% if calendarItems|length == 0 %}
|
||||
<p class="chill-no-data-statement">
|
||||
{{ "There is no calendar items."|trans }}
|
||||
<a href="{{ path('chill_calendar_calendar_new', {'user_id': user_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-create button-small"></a>
|
||||
</p>
|
||||
{% else %}
|
||||
|
||||
{% for calendar in calendarItems %}
|
||||
<div class="flex-table list-records context-{{ context }}">
|
||||
|
||||
<div class="item-bloc">
|
||||
<div class="item-row main">
|
||||
<div class="item-col">
|
||||
{% for calendar in calendarItems %}
|
||||
|
||||
<div class="item-bloc">
|
||||
<div class="item-row main">
|
||||
<div class="item-col">
|
||||
|
||||
|
||||
{% if calendar.startDate and calendar.endDate %}
|
||||
{% if calendar.endDate.diff(calendar.startDate).days >= 1 %}
|
||||
<h3>{{ "From the day"|trans }} {{ calendar.startDate|format_datetime('medium', 'short') }} </h3>
|
||||
<h3>{{ "to the day"|trans }} {{ calendar.endDate|format_datetime('medium', 'short') }}</h3>
|
||||
{% else %}
|
||||
<h3>{{ calendar.startDate|format_date('full') }} </h3>
|
||||
<h3>{{ calendar.startDate|format_datetime('none', 'short', locale='fr') }} - {{ calendar.endDate|format_datetime('none', 'short', locale='fr') }}</h3>
|
||||
{% if calendar.startDate and calendar.endDate %}
|
||||
{% if calendar.endDate.diff(calendar.startDate).days >= 1 %}
|
||||
<h3>{{ "From the day"|trans }} {{ calendar.startDate|format_datetime('medium', 'short') }} </h3>
|
||||
<h3>{{ "to the day"|trans }} {{ calendar.endDate|format_datetime('medium', 'short') }}</h3>
|
||||
{% else %}
|
||||
<h3>{{ calendar.startDate|format_date('full') }} </h3>
|
||||
<h3>{{ calendar.startDate|format_datetime('none', 'short', locale='fr') }} - {{ calendar.endDate|format_datetime('none', 'short', locale='fr') }}</h3>
|
||||
|
||||
<div class="duration">
|
||||
<p>
|
||||
<i class="fa fa-fw fa-hourglass-end"></i>
|
||||
{{ calendar.endDate.diff(calendar.startDate)|date("%H:%M")}}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="duration">
|
||||
<p>
|
||||
<i class="fa fa-fw fa-hourglass-end"></i>
|
||||
{{ calendar.endDate.diff(calendar.startDate)|date("%H:%M")}}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</div>
|
||||
<div class="item-col">
|
||||
<ul class="list-content">
|
||||
{% if calendar.user %}
|
||||
<li>
|
||||
<b>{{ 'by'|trans }}{{ calendar.user.usernameCanonical }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if calendar.mainUser is not empty %}
|
||||
<li>
|
||||
<b>{{ 'main user concerned'|trans }}: {{ calendar.mainUser.usernameCanonical }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
</ul>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_show', { 'id': calendar.id, 'user_id': user_id, 'accompanying_period_id': accompanying_course_id }) }}" class="btn btn-show "></a>
|
||||
</li>
|
||||
{# TOOD
|
||||
{% if is_granted('CHILL_ACTIVITY_UPDATE', calendar) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_edit', { 'id': calendar.id, 'user_id': user_id, 'accompanying_period_id': accompanying_course_id }) }}" class="btn btn-update "></a>
|
||||
</li>
|
||||
{# TOOD
|
||||
{% endif %}
|
||||
{% if is_granted('CHILL_ACTIVITY_DELETE', calendar) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_delete', { 'id': calendar.id, 'user_id' : user_id, 'accompanying_period_id': accompanying_course_id } ) }}" class="btn btn-delete "></a>
|
||||
</li>
|
||||
{#
|
||||
{% endif %}
|
||||
#}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{%
|
||||
if calendar.comment.comment is not empty
|
||||
or calendar.users|length > 0
|
||||
or calendar.thirdParties|length > 0
|
||||
or calendar.users|length > 0
|
||||
%}
|
||||
<div class="item-row details">
|
||||
<div class="item-col">
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {'context': context, 'with_display': 'row', 'entity': calendar } %}
|
||||
</div>
|
||||
|
||||
{% if calendar.comment.comment is not empty %}
|
||||
<div class="item-col comment">
|
||||
{{ calendar.comment|chill_entity_render_box( { 'limit_lines': 3, 'metadata': false } ) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if context == 'user' and calendar.accompanyingPeriod is not empty %}
|
||||
<a class="btn btn-sm btn-outline-primary"
|
||||
title="{{ 'Period number %number%'|trans({'%number%': calendar.accompanyingPeriod.id}) }}"
|
||||
href="{{ chill_path_add_return_path(
|
||||
"chill_user_accompanying_course_index",
|
||||
{ 'accompanying_period_id': calendar.accompanyingPeriod.id }
|
||||
) }}"><i class="fa fa-random"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<div class="item-col">
|
||||
<ul class="list-content">
|
||||
{% if calendar.user %}
|
||||
<li>
|
||||
<b>{{ 'by'|trans }}{{ calendar.user.usernameCanonical }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if calendar.mainUser is not empty %}
|
||||
<li>
|
||||
<b>{{ 'main user concerned'|trans }}: {{ calendar.mainUser.usernameCanonical }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<li>
|
||||
{%- if calendar.comment.isEmpty -%}
|
||||
<span class="chill-no-data-statement">{{ 'No comments'|trans }}</span>
|
||||
{%- else -%}
|
||||
{{ calendar.comment|chill_entity_render_box }}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_show', { 'id': calendar.id, 'user_id': user_id, 'accompanying_period_id': accompanying_course_id }) }}" class="btn btn-show "></a>
|
||||
</li>
|
||||
{# TOOD
|
||||
{% if is_granted('CHILL_ACTIVITY_UPDATE', calendar) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_edit', { 'id': calendar.id, 'user_id': user_id, 'accompanying_period_id': accompanying_course_id }) }}" class="btn btn-update "></a>
|
||||
</li>
|
||||
{# TOOD
|
||||
{% endif %}
|
||||
{% if is_granted('CHILL_ACTIVITY_DELETE', calendar) %}
|
||||
#}
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_delete', { 'id': calendar.id, 'user_id' : user_id, 'accompanying_period_id': accompanying_course_id } ) }}" class="btn btn-delete "></a>
|
||||
</li>
|
||||
{#
|
||||
{% endif %}
|
||||
#}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{%
|
||||
if calendar.comment.comment is not empty
|
||||
or calendar.users|length > 0
|
||||
or calendar.thirdParties|length > 0
|
||||
or calendar.users|length > 0
|
||||
%}
|
||||
<div class="item-row details">
|
||||
<div class="item-col">
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {'context': context, 'with_display': 'row', 'entity': calendar } %}
|
||||
</div>
|
||||
|
||||
{% if calendar.comment.comment is not empty %}
|
||||
<div class="item-col comment">
|
||||
{{ calendar.comment|chill_entity_render_box( { 'limit_lines': 3, 'metadata': false } ) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if context != 'user' %}
|
||||
{# TODO set this condition in configuration #}
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_new', {'user_id': user_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-create">
|
||||
{{ 'Add a new calendar' | trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if context != 'user' %}
|
||||
{# TODO set this condition in configuration #}
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_new', {'user_id': user_id, 'accompanying_period_id': accompanying_course_id}) }}" class="btn btn-create">
|
||||
{{ 'Add a new calendar' | trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
@ -0,0 +1,23 @@
|
||||
{% extends "@ChillMain/layout.html.twig" %}
|
||||
|
||||
{% set activeRouteKey = 'chill_calendar_calendar_list' %}
|
||||
|
||||
{% block title %}{{ 'My calendar list' |trans }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
{% include 'ChillCalendarBundle:Calendar:list.html.twig' with {'context': 'user'} %}
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ parent() }}
|
||||
<script type="text/javascript">
|
||||
window.userId = {{ user.id }};
|
||||
</script>
|
||||
{{ encore_entry_script_tags('vue_mycalendarrange') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_link_tags('vue_calendar') }}
|
||||
{{ encore_entry_link_tags('page_calendar') }}
|
||||
{% endblock %}
|
@ -51,9 +51,9 @@
|
||||
<a
|
||||
class="btn btn-cancel"
|
||||
{%- if context == 'person' -%}
|
||||
href="{{ chill_return_path_or('chill_calendar_calendar', { 'person_id': person.id } )}}"
|
||||
href="{{ chill_return_path_or('chill_calendar_calendar_list', { 'person_id': person.id } )}}"
|
||||
{%- else -%}
|
||||
href="{{ chill_return_path_or('chill_calendar_calendar', { 'accompanying_period_id': accompanyingCourse.id } )}}"
|
||||
href="{{ chill_return_path_or('chill_calendar_calendar_list', { 'accompanying_period_id': accompanyingCourse.id } )}}"
|
||||
{%- endif -%}
|
||||
>
|
||||
{{ 'Cancel'|trans|chill_return_path_label }}
|
||||
|
@ -58,24 +58,37 @@
|
||||
{% set accompanying_course_id = accompanyingCourse.id %}
|
||||
{% endif %}
|
||||
|
||||
{% set user_id = null %}
|
||||
{% if user %}
|
||||
{% set user_id = user.id %}
|
||||
{% endif %}
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li class="cancel">
|
||||
<a class="btn btn-cancel" href="{{ path('chill_calendar_calendar', { 'accompanying_period_id': accompanying_course_id } ) }}">
|
||||
<a class="btn btn-cancel" href="{{ path('chill_calendar_calendar_list', { 'accompanying_period_id': accompanying_course_id, 'user_id': user_id } ) }}">
|
||||
{{ 'Back to the list'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
{% if accompanyingCourse %}
|
||||
<li>
|
||||
<a class="btn btn-update" href="{{ path('chill_calendar_calendar_edit', { 'id': entity.id, 'accompanying_period_id': accompanying_course_id }) }}">
|
||||
{{ 'Edit'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
{% endif %}
|
||||
{% if user %}
|
||||
<li>
|
||||
<a class="btn btn-update" href="{{ path('chill_calendar_calendar_edit', { 'id': entity.id, 'user_id': user_id }) }}">
|
||||
{{ 'Edit'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{# TODO
|
||||
{% if is_granted('CHILL_ACTIVITY_DELETE', entity) %}
|
||||
#}
|
||||
|
||||
<li>
|
||||
<a href="{{ path('chill_calendar_calendar_delete', { 'id': entity.id, 'accompanying_period_id': accompanying_course_id } ) }}" class="btn btn-delete">
|
||||
<a href="{{ path('chill_calendar_calendar_delete', { 'id': entity.id, 'accompanying_period_id': accompanying_course_id, 'user_id': user_id } ) }}" class="btn btn-delete">
|
||||
{{ 'Delete'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
@ -0,0 +1,13 @@
|
||||
{% extends "@ChillMain/layout.html.twig" %}
|
||||
|
||||
{% block title 'Calendar'|trans %}
|
||||
|
||||
{% block content -%}
|
||||
<div class="calendar-show">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-10 col-xxl">
|
||||
{% include 'ChillCalendarBundle:Calendar:show.html.twig' with {'context': 'user'} %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CalendarBundle\Tests\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
|
||||
class CalendarControllerTest extends WebTestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* Setup before the first test of this class (see phpunit doc)
|
||||
*/
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
static::bootKernel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup before each test method (see phpunit doc)
|
||||
*/
|
||||
public function setUp()
|
||||
{
|
||||
$this->client = static::createClient(array(), array(
|
||||
'PHP_AUTH_USER' => 'center a_social',
|
||||
'PHP_AUTH_PW' => 'password',
|
||||
));
|
||||
}
|
||||
|
||||
private function getAccompanyingPeriodFromFixtures(): AccompanyingPeriod
|
||||
{
|
||||
$em = static::$kernel->getContainer()
|
||||
->get('doctrine.orm.entity_manager');
|
||||
|
||||
$accompanying_period = $em->getRepository('ChillPersonBundle:AccompanyingPeriod')->find(1);
|
||||
|
||||
if ($accompanying_period === NULL) {
|
||||
throw new \RuntimeException("We need an accompanying course with id = 1. Did you add fixtures ?");
|
||||
}
|
||||
|
||||
return $accompanying_period;
|
||||
}
|
||||
|
||||
public function testList()
|
||||
{
|
||||
$this->client->request(
|
||||
Request::METHOD_GET,
|
||||
sprintf('/fr/calendar/?accompanying_period_id=%d', $this->getAccompanyingPeriodFromFixtures()->getId())
|
||||
);
|
||||
|
||||
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
|
||||
public function testNew()
|
||||
{
|
||||
$this->client->request(
|
||||
Request::METHOD_GET,
|
||||
sprintf('/fr/calendar/new?accompanying_period_id=%d', $this->getAccompanyingPeriodFromFixtures()->getId())
|
||||
);
|
||||
|
||||
$this->assertEquals(200, $this->client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
}
|
@ -8,6 +8,28 @@ servers:
|
||||
- url: "/api"
|
||||
description: "Your current dev server"
|
||||
|
||||
components:
|
||||
schemas:
|
||||
Date:
|
||||
type: object
|
||||
properties:
|
||||
datetime:
|
||||
type: string
|
||||
format: date-time
|
||||
User:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- user
|
||||
username:
|
||||
type: string
|
||||
text:
|
||||
type: string
|
||||
|
||||
paths:
|
||||
/1.0/calendar/calendar.json:
|
||||
get:
|
||||
@ -48,6 +70,34 @@ paths:
|
||||
responses:
|
||||
200:
|
||||
description: "ok"
|
||||
post:
|
||||
tags:
|
||||
- calendar
|
||||
summary: create a new calendar range
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
user:
|
||||
$ref: '#/components/schemas/User'
|
||||
startDate:
|
||||
$ref: '#/components/schemas/Date'
|
||||
endDate:
|
||||
$ref: '#/components/schemas/Date'
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
422:
|
||||
description: "Unprocessable entity (validation errors)"
|
||||
400:
|
||||
description: "transition cannot be applyed"
|
||||
|
||||
/1.0/calendar/calendar-range/{id}.json:
|
||||
get:
|
||||
@ -70,6 +120,56 @@ paths:
|
||||
description: "not found"
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
patch:
|
||||
tags:
|
||||
- calendar
|
||||
summary: update a calendar range
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
user:
|
||||
$ref: '#/components/schemas/User'
|
||||
startDate:
|
||||
$ref: '#/components/schemas/Date'
|
||||
endDate:
|
||||
$ref: '#/components/schemas/Date'
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
422:
|
||||
description: "Unprocessable entity (validation errors)"
|
||||
400:
|
||||
description: "transition cannot be applyed"
|
||||
delete:
|
||||
tags:
|
||||
- calendar
|
||||
summary: "Remove a calendar range"
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The calendar range id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
responses:
|
||||
401:
|
||||
description: "Unauthorized"
|
||||
404:
|
||||
description: "Not found"
|
||||
200:
|
||||
description: "OK"
|
||||
422:
|
||||
description: "object with validation errors"
|
||||
|
||||
/1.0/calendar/calendar-range-available.json:
|
||||
get:
|
||||
|
@ -1,10 +1,11 @@
|
||||
// this file loads all assets from the Chill calendar bundle
|
||||
module.exports = function(encore, entries) {
|
||||
entries.push(__dirname + '/Resources/public/chill/index.js');
|
||||
|
||||
|
||||
encore.addAliases({
|
||||
ChillCalendarAssets: __dirname + '/Resources/public'
|
||||
});
|
||||
|
||||
encore.addEntry('vue_calendar', __dirname + '/Resources/public/vuejs/Calendar/index.js');
|
||||
encore.addEntry('vue_mycalendarrange', __dirname + '/Resources/public/vuejs/MyCalendarRange/index.js');
|
||||
encore.addEntry('page_calendar', __dirname + '/Resources/public/chill/index.js');
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
Calendar: Rendez-vous
|
||||
Calendar list: Liste des rendez-vous
|
||||
My calendar list: Mes rendez-vous
|
||||
There is no calendar items.: Il n'y a pas de rendez-vous
|
||||
Remove calendar item: Supprimer le rendez-vous
|
||||
Are you sure you want to remove the calendar item?: Êtes-vous sûr de vouloir supprimer le rendez-vous?
|
||||
|
@ -87,6 +87,8 @@ class ApiController extends AbstractCRUDController
|
||||
return $this->entityPut('_entity', $request, $id, $_format);
|
||||
case Request::METHOD_POST:
|
||||
return $this->entityPostAction('_entity', $request, $id, $_format);
|
||||
case Request::METHOD_DELETE:
|
||||
return $this->entityDelete('_entity', $request, $id, $_format);
|
||||
default:
|
||||
throw new \Symfony\Component\HttpFoundation\Exception\BadRequestException("This method is not implemented");
|
||||
}
|
||||
@ -217,6 +219,54 @@ class ApiController extends AbstractCRUDController
|
||||
$this->getContextForSerializationPostAlter($action, $request, $_format, $entity)
|
||||
);
|
||||
}
|
||||
public function entityDelete($action, Request $request, $id, string $_format): Response
|
||||
{
|
||||
$entity = $this->getEntity($action, $id, $request, $_format);
|
||||
|
||||
if (NULL === $entity) {
|
||||
throw $this->createNotFoundException(sprintf("The %s with id %s "
|
||||
. "is not found", $this->getCrudName(), $id));
|
||||
}
|
||||
|
||||
$response = $this->checkACL($action, $request, $_format, $entity);
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$response = $this->onPostCheckACL($action, $request, $_format, $entity);
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$response = $this->onBeforeSerialize($action, $request, $_format, $entity);
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$errors = $this->validate($action, $request, $_format, $entity);
|
||||
|
||||
$response = $this->onAfterValidation($action, $request, $_format, $entity, $errors);
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
if ($errors->count() > 0) {
|
||||
$response = $this->json($errors);
|
||||
$response->setStatusCode(Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
$this->getDoctrine()->getManager()->remove($entity);
|
||||
$this->getDoctrine()->getManager()->flush();
|
||||
|
||||
$response = $this->onAfterFlush($action, $request, $_format, $entity, $errors);
|
||||
if ($response instanceof Response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return $this->json(Response::HTTP_OK);
|
||||
}
|
||||
|
||||
protected function onAfterValidation(string $action, Request $request, string $_format, $entity, ConstraintViolationListInterface $errors, array $more = []): ?Response
|
||||
{
|
||||
|
@ -78,6 +78,7 @@ export default {
|
||||
@import 'ChillMainAssets/module/bootstrap/shared';
|
||||
@import 'ChillPersonAssets/chill/scss/mixins';
|
||||
|
||||
div#accompanying-course {
|
||||
span.multiselect__tag {
|
||||
@include badge_social_issue;
|
||||
background: $chill-l-gray;
|
||||
@ -93,6 +94,7 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
@ -115,6 +115,17 @@ class UserMenuBuilder implements LocalMenuBuilderInterface
|
||||
'icon' => 'tasks'
|
||||
]);
|
||||
|
||||
$menu->addChild("My calendar list", [
|
||||
'route' => 'chill_calendar_calendar_list',
|
||||
'routeParameters' => [
|
||||
'user_id' => $user->getId(),
|
||||
]
|
||||
])
|
||||
->setExtras([
|
||||
'order' => -9,
|
||||
'icon' => 'tasks'
|
||||
]);
|
||||
|
||||
/*
|
||||
$menu->addChild("My aside activities", [
|
||||
'route' => 'chill_crud_aside_activity_index'
|
||||
|
Loading…
x
Reference in New Issue
Block a user