Compare commits

..

64 Commits

Author SHA1 Message Date
57a9f52fa1 allow to close editor 2021-08-20 17:56:52 +02:00
bf0a24b38e various fixes accompanying period 2021-08-20 15:07:36 +02:00
Marc Ducobu
026ac91e69 Injection firstPerson in doc 2021-08-20 15:01:59 +02:00
176b68417a Merge remote-tracking branch 'origin/master' 2021-08-20 13:01:03 +02:00
1d2299e143 Merge branch 'integrate_wopi_bundle' into 'master'
Integration of wopi bundle with controller

See merge request Chill-Projet/chill-bundles!133
2021-08-20 10:49:43 +00:00
20ef04683d Merge remote-tracking branch 'origin/features/rdv' 2021-08-20 12:48:37 +02:00
b9674d7d28 Merge branch 'master' into integrate_wopi_bundle 2021-08-20 12:45:11 +02:00
ffec80c5fd Merge remote-tracking branch 'origin/master' 2021-08-20 12:44:57 +02:00
7f28effc1e Associate generate document with evaluation and update UX to go back to
documents
2021-08-20 12:44:15 +02:00
80672a038c Merge remote-tracking branch 'origin/master' into integrate_wopi_bundle 2021-08-20 11:05:42 +02:00
06abefd576 add redirection to wopi after doc generation 2021-08-19 23:30:45 +02:00
nobohan
3799627bf1 rdv: twig layout and field formatting 2021-08-19 21:50:52 +02:00
8295788d7f Merge branch 'feature/add-ChillWopiBundle' 2021-08-19 21:34:01 +02:00
nobohan
4ae9b29924 rdv: correct redirections 2021-08-19 19:01:01 +02:00
nobohan
1a025ead1b rdv: twig layout + teleport calendar controls 2021-08-19 18:45:59 +02:00
Pol Dellaiera
c9cc0dd2a9 Update status code. 2021-08-19 17:03:22 +02:00
Pol Dellaiera
10c9526b49 Fix property name. 2021-08-19 16:58:41 +02:00
Pol Dellaiera
53cad32910 Update checkFileInfo 2021-08-19 16:49:55 +02:00
Pol Dellaiera
2a40645604 Pass the filename, not the id. 2021-08-19 16:33:04 +02:00
Pol Dellaiera
da505ed106 Add missing favicon url 2021-08-19 16:30:12 +02:00
Pol Dellaiera
fe4b9647b9 fix path to twig template. 2021-08-19 16:29:14 +02:00
Pol Dellaiera
1d7ef9300c Add missing router service. 2021-08-19 16:28:36 +02:00
Pol Dellaiera
bb9e175849 Add missing psr17 service. 2021-08-19 16:27:41 +02:00
Pol Dellaiera
5a3fd2712c refactor: Add test controller. 2021-08-19 16:25:53 +02:00
Pol Dellaiera
0a183c8cfc Revert "fix: Fix services definitions."
This reverts commit 3599508a3b.
2021-08-19 16:11:33 +02:00
Pol Dellaiera
60328032d8 Revert "Remove obsolete controller."
This reverts commit 494573e5b4.
2021-08-19 16:11:32 +02:00
Pol Dellaiera
71900010f6 fix: Fix property name. 2021-08-19 16:06:05 +02:00
Pol Dellaiera
3599508a3b fix: Fix services definitions. 2021-08-19 16:04:43 +02:00
Pol Dellaiera
b1c15ec8ce fix: Update checkFileInfo, getFile and putFile. Remove obsolete code in unsupported methods. 2021-08-19 16:03:19 +02:00
Pol Dellaiera
4f39676e97 Remove obsolete OpenStack and Configuration stuff. 2021-08-19 14:24:40 +02:00
Pol Dellaiera
84a460c4e7 Remove obsolete file. 2021-08-19 14:18:24 +02:00
Pol Dellaiera
494573e5b4 Remove obsolete controller. 2021-08-19 14:18:24 +02:00
Pol Dellaiera
c16fc77d01 fix: Fix service naming, remove the suffix. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
282539ae6b fix: Add wiring for UserProviderInterface. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
50f1d3cd10 fix: Add UserProviderInterface dependency. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
4e04714a42 fix: Add wiring for UserProviderInterface. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
8992b99d56 fix: Add user data. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
62536ab2ff fix: Format date properly. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
b189726380 fix: Fix mimeType detection/discovery. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
a63c26482e fix: Fix mimeType detection/discovery. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
c208797daf fix: Update StoredObject entity. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
0366d0cb17 fix: Add exceptions. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
2b7fa630fc refactor: Add nyholm/psr7. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
a41b959fbd refactor: Fix TempUrlGeneratorInterface wiring. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
e4d9129af2 refactor: Add TempUrlGeneratorInterface wiring. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
72fc6e05cc refactor: Add WopiInterface wiring. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
47a2af6f19 Update composer.json. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
1bd01aefae refactor: Update ChillWopiBundle - Work in progress. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
c6b6fa5bf6 refactor: Update ChillDocStoreBundle - Add StoredObject repository. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
36d582c8ab Update configuration. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
df544bdfa4 update 2021-08-19 14:17:54 +02:00
Pol Dellaiera
12e17fac82 debug 2021-08-19 14:17:54 +02:00
Pol Dellaiera
b2d84a7677 Update. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
ebb679dbbb Update services.php. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
61bb595bba Update Test controller. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
c7aafc6730 Update services.php 2021-08-19 14:17:54 +02:00
Pol Dellaiera
24b675ce97 Fix path to services.php. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
3c888238c5 Fix services file. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
1bd00535ce Update services for controllers. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
d616e00660 Add test routes and controller. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
5d5ad9e4f7 Fix OpenStack service. 2021-08-19 14:17:54 +02:00
Pol Dellaiera
28af73db19 Fix typo. 2021-08-19 14:17:53 +02:00
Pol Dellaiera
364aff36a4 Add initial set of files. 2021-08-10 15:13:46 +02:00
Pol Dellaiera
3f1b5b2319 Add ChillWopiBundle. 2021-08-10 15:13:34 +02:00
32 changed files with 461 additions and 102 deletions

View File

@@ -139,10 +139,9 @@ class CalendarController extends AbstractController
$this->addFlash('success', $this->get('translator')->trans('Success : calendar item created!'));
$params = $this->buildParamsToUrl($user, $accompanyingPeriod); //TODO useful?
$params['id'] = $entity->getId();
$params = $this->buildParamsToUrl($user, $accompanyingPeriod);
return $this->redirectToRoute('chill_calendar_calendar_show', $params);
return $this->redirectToRoute('chill_calendar_calendar', $params);
} elseif ($form->isSubmitted() and !$form->isValid()) {
$this->addFlash('error', $this->get('translator')->trans('This form contains errors'));
}
@@ -241,8 +240,7 @@ class CalendarController extends AbstractController
$this->addFlash('success', $this->get('translator')->trans('Success : calendar item updated!'));
$params = $this->buildParamsToUrl($user, $accompanyingPeriod);
$params['id'] = $id;
return $this->redirectToRoute('chill_calendar_calendar_show', $params);
return $this->redirectToRoute('chill_calendar_calendar', $params);
} elseif ($form->isSubmitted() and !$form->isValid()) {
$this->addFlash('error', $this->get('translator')->trans('This form contains errors'));
}
@@ -304,7 +302,7 @@ class CalendarController extends AbstractController
$em->flush();
$this->addFlash('success', $this->get('translator')
->trans("The calendar has been successfully removed."));
->trans("The calendar item has been successfully removed."));
$params = $this->buildParamsToUrl($user, $accompanyingPeriod);
return $this->redirectToRoute('chill_calendar_calendar', $params);

View File

@@ -48,13 +48,13 @@ class CalendarType extends AbstractType
->add('comment', CommentType::class, [
'required' => false
])
->add('cancelReason', EntityType::class, [
'required' => false,
'class' => CancelReason::class,
'choice_label' => function (CancelReason $entity) {
return $entity->getCanceledBy();
},
])
// ->add('cancelReason', EntityType::class, [
// 'required' => false,
// 'class' => CancelReason::class,
// 'choice_label' => function (CancelReason $entity) {
// return $entity->getCanceledBy();
// },
// ])
->add('sendSMS', ChoiceType::class, [
'required' => false,
'choices' => [

View File

@@ -0,0 +1 @@
require('./scss/calendar.scss');

View File

@@ -0,0 +1,10 @@
div#calendarControls {
height: 50%;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
div#fullCalendar{
}

View File

@@ -1,18 +1,21 @@
<template>
<concerned-groups></concerned-groups>
<calendar-user-selector
v-bind:users="users"
v-bind:calendarEvents="calendarEvents"
v-bind:updateEventsSource="updateEventsSource"
v-bind:showMyCalendar="showMyCalendar"
v-bind:toggleMyCalendar="toggleMyCalendar" >
</calendar-user-selector>
<h2 class="chill-red">{{ $t('choose_your_date') }}</h2>
<FullCalendar ref="fullCalendar" :options="calendarOptions">
<template v-slot:eventContent='arg'>
<b>{{ arg.timeText }}</b>
</template>
</FullCalendar>
<teleport to="#calendarControls">
<calendar-user-selector
v-bind:users="users"
v-bind:calendarEvents="calendarEvents"
v-bind:updateEventsSource="updateEventsSource"
v-bind:showMyCalendar="showMyCalendar"
v-bind:toggleMyCalendar="toggleMyCalendar" >
</calendar-user-selector>
</teleport>
<teleport to="#fullCalendar">
<FullCalendar ref="fullCalendar" :options="calendarOptions">
<template v-slot:eventContent='arg'>
<b>{{ arg.timeText }}</b>
</template>
</FullCalendar>
</teleport>
</template>
<script>

View File

@@ -1,6 +1,6 @@
<template>
<h2 class="chill-red">{{ $t('choose_your_calendar_user') }}</h2>
<div>
<div class="calendar__controls">
<h2 class="chill-red">{{ $t('choose_your_calendar_user') }}</h2>
<VueMultiselect
name="field"
id="calendarUserSelector"
@@ -196,3 +196,12 @@ 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>

View File

@@ -2,7 +2,7 @@ const calendarUserSelectorMessages = {
fr: {
choose_your_calendar_user: "Afficher les plages de disponibilités",
select_user: "Sélectionnez des calendriers",
show_my_calendar: "Affichez mon calendrier"
show_my_calendar: "Afficher mon calendrier"
}
};

View File

@@ -40,10 +40,6 @@
.. location
{%- if form.cancelReason is defined -%}
{{ form_row(form.cancelReason) }}
{% endif %}
{%- if form.comment is defined -%}
{{ form_row(form.comment) }}
{% endif %}
@@ -52,8 +48,7 @@
{{ form_row(form.sendSMS) }}
{% endif %}
..calendarRange
<div id="fullCalendar"></div>
<ul class="record_actions sticky-form-buttons">
<li class="cancel">

View File

@@ -36,3 +36,7 @@
{{ parent() }}
{{ encore_entry_link_tags('vue_calendar') }}
{% endblock %}
{% block block_post_menu %}
<div id="calendarControls"></div>
{% endblock %}

View File

@@ -24,22 +24,25 @@
<div class="item-bloc">
<div class="item-row main">
<div class="item-col">
{% if calendar.startDate %}
<h3>{{ calendar.startDate|format_datetime('long') }} </h3>
{% endif %}
{% if calendar.endDate %}
<h3>{{ calendar.endDate|format_datetime('long') }}</h3>
{% endif %}
<div class="duration">
<p>
<i class="fa fa-fw fa-hourglass-end"></i>
{{ calendar.endDate.diff(calendar.startDate)|date("%H:%M")}}
</p>
</div>
{% 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 %}
{% endif %}
{% if context == 'user' and calendar.accompanyingPeriod is not empty %}
<div class="accompanyingPeriodLink" style="margin-top: 1rem">
@@ -66,7 +69,7 @@
{% if calendar.mainUser is not empty %}
<li>
<b>{{ 'main user concerned'|trans }}{{ calendar.mainUser.usernameCanonical }}</b>
<b>{{ 'main user concerned'|trans }}: {{ calendar.mainUser.usernameCanonical }}</b>
</li>
{% endif %}

View File

@@ -1,4 +1,4 @@
<h1>{{ "Calendar item creation"|trans ~ ' :' }}</h1>
<h1>{{ "Calendar item creation"|trans }}</h1>
{{ form_start(form) }}
{{ form_errors(form) }}
@@ -34,16 +34,8 @@
{{ form_row(form.endDate) }}
{% endif %}
{%- if form.calendarRange is defined -%}
{{ form_row(form.calendarRange) }}
{% endif %}
.. location
{%- if form.cancelReason is defined -%}
{{ form_row(form.cancelReason) }}
{% endif %}
{%- if form.comment is defined -%}
{{ form_row(form.comment) }}
{% endif %}
@@ -52,19 +44,16 @@
{{ form_row(form.sendSMS) }}
{% endif %}
..calendarRange
<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_activity_activity_list', { 'person_id': person.id } )}}"
href="{{ chill_return_path_or('chill_calendar_calendar', { 'person_id': person.id } )}}"
{%- else -%}
href="{{ chill_return_path_or('chill_activity_activity_list', { 'accompanying_period_id': accompanyingCourse.id } )}}"
href="{{ chill_return_path_or('chill_calendar_calendar', { 'accompanying_period_id': accompanyingCourse.id } )}}"
{%- endif -%}
>
{{ 'Cancel'|trans|chill_return_path_label }}

View File

@@ -34,4 +34,6 @@
<link rel="stylesheet" href="{{ asset('build/vue_calendar.css') }}"/>
{% endblock %}
{% block block_post_menu %}
<div id="calendarControls"></div>
{% endblock %}

View File

@@ -11,11 +11,18 @@
<h2 class="chill-red">{{ 'Calendar data'|trans }}</h2>
<dt class="inline">{{ 'start date'|trans }}</dt>
<dd>{{ entity.startDate|format_datetime('long') }}</dd>
<dt class="inline">{{ 'end date'|trans }}</dt>
<dd>{{ entity.endDate|format_datetime('long') }}</dd>
{% if entity.endDate.diff(entity.startDate).days >= 1 %}
<dt>{{ "From the day"|trans }} {{ entity.startDate|format_datetime('medium', 'short') }}
{{ "to the day"|trans }} {{ entity.endDate|format_datetime('medium', 'short') }}
</dt>
<dd></dd>
{% else %}
<dt>
{{ entity.startDate|format_date('full') }},
{{ entity.startDate|format_datetime('none', 'short', locale='fr') }} - {{ entity.endDate|format_datetime('none', 'short', locale='fr') }}
</dt>
<dd></dd>
{% endif %}
<dt class="inline">{{ 'cancel reason'|trans }}</dt>
<dd>

View File

@@ -1,10 +1,10 @@
// this file loads all assets from the Chill calendar bundle
module.exports = function(encore, entries) {
//entries.push(__dirname + '/Resources/public/index.js');
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');
};

View File

@@ -6,7 +6,7 @@ Are you sure you want to remove the calendar item?: Êtes-vous sûr de vouloir s
Concerned groups: Parties concernées
Calendar data: Données du rendez-vous
Update calendar: Modifier le rendez-vous
main user concerned: Utilisateur principal
main user concerned: Utilisateur concerné
Main user: Utilisateur principal
Calendar item creation: Création du rendez-vous
start date: début du rendez-vous
@@ -18,3 +18,7 @@ sendSMS: Envoi d'un SMS
Send s m s: Envoi d'un SMS ?
Cancel reason: Motif d'annulation
Add a new calendar: Ajouter un nouveau rendez-vous
"Success : calendar item updated!": "Rendez-vous mis à jour"
The calendar item has been successfully removed.: Le rendez-vous a été supprimé
From the day: Du
to the day: au

View File

@@ -54,9 +54,20 @@ class HouseholdMemberSelectionContext implements DocGeneratorContextInterface
*/
public function getData($entity): array {
$datas = array(
'setValue' => array(),
'setValues' => array(),
'cloneRowAndSetValues' => array()
); // TODO CREER UNE CLASSE POUR CA
);
$persons = $entity->getAccompanyingPeriodWork()->getPersons();
if(sizeof($persons) > 0) {
$firstPerson = $persons[0];
$datas['setValues'][] = array(
'firstPersonFirstName' => $firstPerson->getFirstName(),
'firstPersonLastName' => $firstPerson->getLastName(),);
}
if(get_class($entity) == AccompanyingPeriodWorkEvaluation::class) {
$values = array();

View File

@@ -4,8 +4,12 @@ namespace Chill\DocGeneratorBundle\Controller;
use Chill\DocGeneratorBundle\Repository\DocGeneratorTemplateRepository;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument;
use Chill\PersonBundle\Entity\SocialWork\Evaluation;
use GuzzleHttp\Exception\TransferException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\HeaderUtils;
@@ -57,8 +61,11 @@ class DocGeneratorTemplateController extends AbstractController
*/
public function generateDocFromTemplateAction(
\ChampsLibres\AsyncUploaderBundle\TempUrl\TempUrlGeneratorInterface $tempUrlGenerator,
DocGeneratorTemplate $template, string $entityClassName, int $entityId): Response
{
DocGeneratorTemplate $template,
string $entityClassName,
int $entityId,
Request $request
): Response {
$getUrlGen = $tempUrlGenerator->generate(
'GET',
$template->getFile());
@@ -77,7 +84,10 @@ class DocGeneratorTemplateController extends AbstractController
$templateProcessor = new TemplateProcessor($tmpfname);
// TODO foreach ($datas['setValue'] as $key => $value) {
foreach ($datas['setValues'] as $setValuesConf) {
$templateProcessor->setValues($setValuesConf);
}
foreach ($datas['cloneRowAndSetValues'] as $cloneRowAndSetValues) {
$templateProcessor->cloneRowAndSetValues($cloneRowAndSetValues[0], $cloneRowAndSetValues[1]);
}
@@ -105,18 +115,31 @@ class DocGeneratorTemplateController extends AbstractController
]);
if ($putResponse->getStatusCode() == 201) {
$em = $this->getDoctrine()->getManager();
$storedObject = new StoredObject();
$storedObject
// currently, only docx is supported
->setType('application/vnd.openxmlformats-officedocument.wordprocessingml.document')
->setFilename($genDocName);
$em = $this->getDoctrine()->getManager();
$em->persist($storedObject);
// Only for evaluation
if ($entity instanceof AccompanyingPeriodWorkEvaluation) {
$doc = new AccompanyingPeriodWorkEvaluationDocument();
$doc
->setStoredObject($storedObject)
->setTemplate($template)
;
$entity->addDocument($doc);
$em->persist($doc);
}
$em->flush();
return $this->redirectToRoute('chill_wopi_file_edit', [
'fileId' => $genDocName
'fileId' => $genDocName,
'returnPath' => $request->query->get('returnPath', "/")
]);
}
} catch (TransferException $e) {

View File

@@ -4,11 +4,11 @@ namespace Chill\DocGeneratorBundle\Entity;
use Chill\DocGeneratorBundle\Repository\DocGeneratorTemplateRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation as Serializer;
/**
* @ORM\Entity
* @ORM\Table(name="chill_docgen_template")
*/
class DocGeneratorTemplate
{
@@ -16,11 +16,13 @@ class DocGeneratorTemplate
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
* @Serializer\Groups({"read"})
*/
private int $id;
/**
* @ORM\Column(type="json_array")
* @Serializer\Groups({"read"})
*/
private array $name = [];

View File

@@ -8,12 +8,11 @@ use Doctrine\ORM\Mapping as ORM;
use ChampsLibres\AsyncUploaderBundle\Model\AsyncFileInterface;
use ChampsLibres\AsyncUploaderBundle\Validator\Constraints\AsyncFileExists;
use DateTimeInterface;
use Symfony\Component\Serializer\Annotation as Serializer;
/**
* Represent a document stored in an object store
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*
* @ORM\Entity()
* @ORM\Table("chill_doc.stored_object")
* @AsyncFileExists(
@@ -26,11 +25,13 @@ class StoredObject implements AsyncFileInterface
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
* @Serializer\Groups({"read"})
*/
private $id;
/**
* @ORM\Column(type="text")
* @Serializer\Groups({"read"})
*/
private $filename;
@@ -48,16 +49,19 @@ class StoredObject implements AsyncFileInterface
/**
* @ORM\Column(type="datetime", name="creation_date")
* @Serializer\Groups({"read"})
*/
private DateTimeInterface $creationDate;
/**
* @ORM\Column(type="text", name="type")
* @Serializer\Groups({"read"})
*/
private string $type = '';
/**
* @ORM\Column(type="json_array", name="datas")
* @Serializer\Groups({"read"})
*/
private array $datas = [];

View File

@@ -120,7 +120,8 @@ class AccompanyingPeriodWorkEvaluation implements TrackUpdateInterface, TrackCre
* @var Collection
* @ORM\OneToMany(
* targetEntity=AccompanyingPeriodWorkEvaluationDocument::class,
* mappedBy="accompanyingPeriodWorkEvaluation"
* mappedBy="accompanyingPeriodWorkEvaluation",
* cascade={"remove"}
* )
* @Serializer\Groups({"read"})
*/
@@ -135,6 +136,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackUpdateInterface, TrackCre
*
* @Serializer\Groups({"read"})
* @Serializer\Groups({"write"})
* @Serializer\Groups({"accompanying_period_work_evaluation:create"})
*
* @var mixed
*
@@ -382,6 +384,22 @@ class AccompanyingPeriodWorkEvaluation implements TrackUpdateInterface, TrackCre
return $this->documents;
}
public function addDocument(AccompanyingPeriodWorkEvaluationDocument $document): self
{
if (!$this->documents->contains($document)) {
$this->documents[] = $document;
$document->setAccompanyingPeriodWorkEvaluation($this);
}
return $this;
}
public function removeDocument(AccompanyingPeriodWorkEvaluationDocument $document): self
{
$this->documents->removeElement($document);
return $this;
}
/**
* Arbitrary data, used for client
*

View File

@@ -2,6 +2,7 @@
namespace Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
@@ -37,7 +38,7 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
* inversedBy="documents"
* )
*/
private ?AccompanyingPeriodWorkEvaluation $accompanyingPeriodWorkEvaluation;
private ?AccompanyingPeriodWorkEvaluation $accompanyingPeriodWorkEvaluation = null;
/**
* @ORM\ManyToOne(
@@ -45,13 +46,13 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
* )
* @Serializer\Groups({"read"})
*/
private ?User $createdBy;
private ?User $createdBy = null;
/**
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
* @Serializer\Groups({"read"})
*/
private ?\DateTimeImmutable $createdAt;
private ?\DateTimeImmutable $createdAt = null;
/**
* @ORM\ManyToOne(
@@ -59,18 +60,29 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
* )
* @Serializer\Groups({"read"})
*/
private ?User $updatedBy;
private ?User $updatedBy = null;
/**
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
* @Serializer\Groups({"read"})
*/
private ?DateTimeImmutable $updatedAt;
private ?\DateTimeImmutable $updatedAt = null;
// TODO: indiquer le document généré par le module "document"
private ?StoredObject $storedObject;
/**
* @ORM\ManyToOne(
* targetEntity=StoredObject::class
* )
* @Serializer\Groups({"read"})
*/
private ?StoredObject $storedObject = null;
// TODO: ajouter gabarit
/**
* @ORM\ManyToOne(
* targetEntity=DocGeneratorTemplate::class
* )
* @Serializer\Groups({"read"})
*/
private ?DocGeneratorTemplate $template = null;
/**
* @return AccompanyingPeriodWorkEvaluation|null
@@ -86,6 +98,14 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
*/
public function setAccompanyingPeriodWorkEvaluation(?AccompanyingPeriodWorkEvaluation $accompanyingPeriodWorkEvaluation): AccompanyingPeriodWorkEvaluationDocument
{
// if an evaluation is already associated, we cannot change the association (removing the association,
// by setting a null value, is allowed.
if ($this->accompanyingPeriodWorkEvaluation instanceof AccompanyingPeriodWorkEvaluation
&& $accompanyingPeriodWorkEvaluation instanceof AccompanyingPeriodWorkEvaluation) {
if ($this->accompanyingPeriodWorkEvaluation !== $accompanyingPeriodWorkEvaluation) {
throw new \RuntimeException("It is not allowed to change the evaluation for a document");
}
}
$this->accompanyingPeriodWorkEvaluation = $accompanyingPeriodWorkEvaluation;
return $this;
}
@@ -172,4 +192,22 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
return $this->updatedAt;
}
/**
* @return DocGeneratorTemplate|null
*/
public function getTemplate(): ?DocGeneratorTemplate
{
return $this->template;
}
/**
* @param DocGeneratorTemplate|null $template
* @return AccompanyingPeriodWorkEvaluationDocument
*/
public function setTemplate(?DocGeneratorTemplate $template): AccompanyingPeriodWorkEvaluationDocument
{
$this->template = $template;
return $this;
}
}

View File

@@ -68,12 +68,15 @@
</li>
</ul>
</div>
<ul class="record_actions">
<ul class="record_actions" v-if="availableForCheckGoal.length > 0">
<li>
<button :title="$t('add_an_objective')" class="btn btn-create"
@click="toggleAddObjective"></button>
</li>
</ul>
<div v-else>
<span class="chill-no-data-statement">{{ $t('no_goals_available') }}</span>
</div>
</div>
<div><!-- empty for results --></div>
</div>
@@ -102,11 +105,14 @@
</li>
</ul>
</div>
<ul class="record_actions">
<ul class="record_actions" v-if="evaluationsForAction.length > 0">
<li>
<button :title="$t('add_an_evaluation')" class="btn btn-create" @click="toggleAddEvaluation"></button>
</li>
</ul>
<div v-else>
<span class="chill-no-data-statement">{{ $t('no_evaluations_available') }}</span>
</div>
</div>
</div>
@@ -255,6 +261,8 @@ const i18n = {
choose_thirdparties: "Choisir des tiers",
fix_these_errors: "Veuillez corriger les erreurs suivantes :",
available_evaluations_text: "Évaluations disponibles pour ajout :",
no_evaluations_available: "Aucune évaluation disponible",
no_goals_available: "Aucun objectif disponible",
}
}
};

View File

@@ -19,8 +19,20 @@
<dt v-if="evaluation.warningInterval">{{ $t('warningInterval') }} :</dt>
<dd v-if="evaluation.warningInterval">{{ evaluation.warningInterval }}</dd>
<dt v-if="evaluation.documents && evaluation.documents.length > 0">{{ $t('documents') }} :</dt>
<dd v-if="evaluation.documents && evaluation.documents.length > 0">{{ evaluation.documents.length }}</dd>
<template v-if="evaluation.documents.length > 0">
<dt>{{ $t('documents') }} :</dt>
<dd>
<ul>
<li v-for="d in evaluation.documents">
{{ d.template.name.fr }}
<a :href="buildEditLink(d.storedObject)" class="btn btn-action btn-sm">
<i class="fa fa-edit"></i>
</a>
</li>
</ul>
</dd>
</template>
</dl>
<dl class="item-details">
@@ -82,7 +94,7 @@ export default {
computed: {
pickedEvaluations() {
return this.$store.state.evaluationsPicked;
}
},
},
methods: {
removeEvaluation(e) {
@@ -95,7 +107,11 @@ export default {
},
submitForm() {
this.toggleEditEvaluation();
}
},
buildEditLink(storedObject) {
return `/fr/chill_wopi/edit/${storedObject.filename}?returnPath=` + encodeURIComponent(
window.location.pathname + window.location.search + window.location.hash);
},
}
}
</script>

View File

@@ -17,6 +17,10 @@
'layout': '@ChillPerson/menu.html.twig',
'args' : { 'accompanyingCourse': accompanyingCourse }
}) }}
{% block block_post_menu %}
{% endblock %}
{% endblock %}
{% block css %}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Add a link between evaluation document, stored object, and document template
*/
final class Version20210820093927 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add a link between evaluation document, stored object, and document template';
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document ADD template_id INT DEFAULT NULL');
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document ADD storedObject_id INT DEFAULT NULL');
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document ADD CONSTRAINT FK_33EC92296C99C13A FOREIGN KEY (storedObject_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document ADD CONSTRAINT FK_33EC92295DA0FB8 FOREIGN KEY (template_id) REFERENCES chill_docgen_template (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('CREATE INDEX IDX_33EC92296C99C13A ON chill_person_accompanying_period_work_evaluation_document (storedObject_id)');
$this->addSql('CREATE INDEX IDX_33EC92295DA0FB8 ON chill_person_accompanying_period_work_evaluation_document (template_id)');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document DROP CONSTRAINT FK_33EC92296C99C13A');
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document DROP CONSTRAINT FK_33EC92295DA0FB8');
$this->addSql('DROP INDEX IDX_33EC92296C99C13A');
$this->addSql('DROP INDEX IDX_33EC92295DA0FB8');
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document DROP template_id');
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document DROP storedObject_id');
}
}

View File

@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Add missing sequence for evaluation documents
*/
final class Version20210820100407 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add missing sequence for evaluation documents';
}
public function up(Schema $schema): void
{
$this->addSql('CREATE SEQUENCE chill_person_social_work_eval_doc_id_seq INCREMENT BY 1 MINVALUE 1000 START 1000');
}
public function down(Schema $schema): void
{
$this->addSql('DROP SEQUENCE chill_person_social_work_eval_doc_id_seq');
}
}

View File

@@ -0,0 +1,6 @@
// this file loads all assets from the Chill person bundle
module.exports = function(encore, entries)
{
encore.addEntry('page_wopi_editor', __dirname + '/src/Resources/public/page/editor/index.js');
//home/julien/dev/département-vendee/chill/vendor/chill-project/chill-bundles/src/Bundle/ChillWopiBundle/src/Resources/public/page/editor/index.js
};

View File

@@ -16,6 +16,7 @@ use Chill\WopiBundle\Service\Controller\ResponderInterface;
use Exception;
use loophp\psr17\Psr17Interface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Security;
@@ -61,7 +62,7 @@ final class Test
$storedObject = $this->storedObjectRepository->findOneBy(['filename' => $fileId]);
if (null === $storedObject) {
throw new Exception(sprintf('Unable to find object named %s', $fileId));
throw new NotFoundHttpException(sprintf('Unable to find object named %s', $fileId));
}
if ([] === $discoverExtension = $this->wopiDiscovery->discoverMimeType($storedObject->getType())) {
@@ -86,6 +87,7 @@ final class Test
],
UrlGeneratorInterface::ABSOLUTE_URL
),
'closebutton' => 1
]
)
);
@@ -93,7 +95,7 @@ final class Test
return $this
->responder
->render(
'@Wopi/Editor/page.html.twig',
'@ChillWopi/Editor/page.html.twig',
$configuration
);

View File

@@ -0,0 +1,46 @@
require('./index.scss');
window.addEventListener('DOMContentLoaded', function(e) {
let frameholder = document.getElementById('frameholder');
let office_frame = document.createElement('iframe');
office_frame.name = 'office_frame';
office_frame.id = 'office_frame';
// The title should be set for accessibility
office_frame.title = 'Office Frame';
// This attribute allows true fullscreen mode in slideshow view
// when using PowerPoint's 'view' action.
office_frame.setAttribute('allowfullscreen', 'true');
// The sandbox attribute is needed to allow automatic redirection to the O365 sign-in page in the business user flow
office_frame.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-popups allow-top-navigation allow-popups-to-escape-sandbox');
frameholder.appendChild(office_frame);
document.getElementById('office_form').submit();
console.log(office_frame);
const url = new URL(editor_url);
const editor_domain = url.origin;
window.addEventListener("message", function(message) {
if (message.origin !== editor_domain) {
return;
}
let data = JSON.parse(message.data);
if ('UI_Close' === data.MessageId) {
closeEditor();
}
});
});
function closeEditor() {
let
params = new URLSearchParams(window.location.search),
returnPath = params.get('returnPath');
window.location.assign(returnPath);
}

View File

@@ -0,0 +1,19 @@
body {
margin: 0;
padding: 0;
overflow: hidden;
-ms-content-zooming: none;
}
#office_frame {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: 0;
border: none;
display: block;
}

View File

@@ -0,0 +1,36 @@
<style type="text/css">
#office_frame {
width: 100%;
height: 800px;
margin: 0;
border: none;
display: block;
}
</style>
<form id="office_form" name="office_form" target="office_frame" action="{{ server }}" method="post">
<input name="access_token" value="{{ access_token }}" type="hidden" />
<input name="access_token_ttl" value="{{ access_token_ttl }}" type="hidden" />
</form>
<span id="frameholder"></span>
<script type="text/javascript">
var frameholder = document.getElementById('frameholder');
var office_frame = document.createElement('iframe');
office_frame.name = 'office_frame';
office_frame.id = 'office_frame';
// The title should be set for accessibility
office_frame.title = 'Office Frame';
// This attribute allows true fullscreen mode in slideshow view
// when using PowerPoint's 'view' action.
office_frame.setAttribute('allowfullscreen', 'true');
// The sandbox attribute is needed to allow automatic redirection to the O365 sign-in page in the business user flow
office_frame.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-popups allow-top-navigation allow-popups-to-escape-sandbox');
frameholder.appendChild(office_frame);
document.getElementById('office_form').submit();
</script>

View File

@@ -0,0 +1,33 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<!-- Enable IE Standards mode -->
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<link rel="shortcut icon" href="{{ favIconUrl }}" />
<script type="text/javascript">
const editor_url = "{{ server|escape('js') }}";
</script>
{{ encore_entry_link_tags('page_wopi_editor') }}
{{ encore_entry_script_tags('page_wopi_editor') }}
</head>
<body>
<form id="office_form" name="office_form" target="office_frame" action="{{ server }}" method="post">
<input name="access_token" value="{{ access_token }}" type="hidden" />
<input name="access_token_ttl" value="{{ access_token_ttl }}" type="hidden" />
</form>
<span id="frameholder"></span>
</body>
</html>