mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Merge remote-tracking branch 'origin/master' into issue511_document_evaluations
This commit is contained in:
commit
ae5940eb48
15
CHANGELOG.md
15
CHANGELOG.md
@ -11,11 +11,14 @@ and this project adheres to
|
||||
## Unreleased
|
||||
|
||||
<!-- write down unreleased development here -->
|
||||
|
||||
* [person] AccompanyingCourseWorkEdit: fix deleting evaluation documents (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/546)
|
||||
* [person] AccompanyingCourseWorkEdit: download existing documents (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/512)
|
||||
* [person] AccompanyingCourseWorkEdit: replace document by a new one (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/511)
|
||||
|
||||
* [person] AccompanyingPeriodWork: add referrers to work, add doctrine event listener to add logged user to referrers collection and display a referrers list in work list (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/502)
|
||||
* [person] AccompanyingPeriodWorkEvaluation: fix circular reference when serialising (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/495)
|
||||
* [person] order accompanying period by opening date in search persons, person and household period lists (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/493)
|
||||
* [parcours] autosave of the pinned comment for draft accompanying course (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/477)
|
||||
* [main] filter user job in undispatch acc period to assign (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/472)
|
||||
* [main] filter user job in undispatch acc period to assign (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/472)
|
||||
* [person] Add url in accompanying period work evaluations entity and form (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/476)
|
||||
* [person] Add document generation in admin and in person/{id}/document (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/464)
|
||||
@ -35,13 +38,21 @@ and this project adheres to
|
||||
* [confidential] Fix position of toggle button so it does not cover text nor fall outside of box (no issue)
|
||||
* [parcours] Fix edit of both thirdparty and contact name (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/474)
|
||||
* [template] do not list inactive templates (for doc generator)
|
||||
* [household] bugfix if position of member is null, renderbox no longer throws an error (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/480)
|
||||
* [parcours] location cannot be removed if linked to a user (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/478)
|
||||
* [person] email added to twig personRenderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/490)
|
||||
* [person] Add link to current household in person banner (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/484)
|
||||
* [address] person badge in address history changed to open OnTheFly with all person info (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/489)
|
||||
* [person] Change 'personne' with 'usager' and '&' with 'ET' (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/499)
|
||||
* [thirdparty] Add parameter condition to display centers or not (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/500)
|
||||
* [phonenumber] Remove placeholder in phonenumber field (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/496)
|
||||
* [person_resource] separate create page created to avoid confusion (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/504)
|
||||
* [contact] add contact button color changed plus the pipe at the side removed (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/506)
|
||||
* [household] create-edit household composition placed in separate page to avoid confusion (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/505)
|
||||
* [blur] Improved positioning of toggle icon (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/486)
|
||||
* [parcours] List of parcours for a specific user so they can be reassigned in case of absence (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/509)
|
||||
* [thirdparty] Thirdparty view page, english text translated (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/534)
|
||||
* [social_action] Translation changed in evaluation section (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/512)
|
||||
|
||||
## Test releases
|
||||
|
||||
|
@ -46,7 +46,7 @@
|
||||
|
||||
{% include 'ChillActivityBundle:Activity:list.html.twig' with {'context': 'person'} %}
|
||||
|
||||
{% if is_granted('CHILL_ACTIVITY_CREATE', person) %}
|
||||
{% if is_granted('CHILL_ACTIVITY_CREATE_PERSON', person) %}
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li>
|
||||
<a href="{{ path('chill_activity_activity_new', {'person_id': person_id, 'accompanying_period_id': accompanying_course_id}) }}"
|
||||
|
@ -26,6 +26,7 @@ use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
use function count;
|
||||
use function strlen;
|
||||
|
||||
class LoadPostalCodesCommand extends Command
|
||||
{
|
||||
@ -118,6 +119,13 @@ class LoadPostalCodesCommand extends Command
|
||||
|
||||
private function addPostalCode($row, OutputInterface $output)
|
||||
{
|
||||
if ('FR' === $row[2] && strlen($row[0]) === 4) {
|
||||
// CP in FRANCE are on 5 digit
|
||||
// For CP starting with a zero, the starting zero can be remove if stored as number in a csv
|
||||
// add a zero if CP from FR and on 4 digit
|
||||
$row[0] = '0' . $row[0];
|
||||
}
|
||||
|
||||
if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
|
||||
$output->writeln('handling row: ' . $row[0] . ' | ' . $row[1] . ' | ' . $row[2]);
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ class UserJob
|
||||
* @var array|string[]A
|
||||
* @ORM\Column(name="label", type="json")
|
||||
* @Serializer\Groups({"read", "docgen:read"})
|
||||
* @Serializer\Context({"is-translatable": true}, groups={"docgen:read"})
|
||||
*/
|
||||
protected array $label = [];
|
||||
|
||||
|
@ -1,17 +1,22 @@
|
||||
/**
|
||||
* Generic api method that can be adapted to any fetch request
|
||||
*/
|
||||
const makeFetch = (method, url, body) => {
|
||||
return fetch(url, {
|
||||
const makeFetch = (method, url, body, options) => {
|
||||
let opts = {
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=utf-8'
|
||||
},
|
||||
body: (body !== null) ? JSON.stringify(body) : null
|
||||
})
|
||||
};
|
||||
|
||||
if (typeof options !== 'undefined') {
|
||||
opts = Object.assign(opts, options);
|
||||
}
|
||||
|
||||
return fetch(url, opts)
|
||||
.then(response => {
|
||||
if (response.ok) {
|
||||
console.log('200 error')
|
||||
return response.json();
|
||||
}
|
||||
|
||||
|
@ -1,37 +1,26 @@
|
||||
.confidential {
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
.toggle-far-twig {
|
||||
i {
|
||||
bottom: 0px;
|
||||
right: -30px;
|
||||
}
|
||||
margin-right: 20px
|
||||
}
|
||||
|
||||
.toggle-close-twig {
|
||||
i {
|
||||
bottom: 0px;
|
||||
right: -5px;
|
||||
}
|
||||
.toggle-container {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
cursor: pointer;
|
||||
z-index: 5;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
.toggle{
|
||||
margin-left: 30px;
|
||||
margin-top: 5px;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
right: -30px
|
||||
}
|
||||
|
||||
.toggle-far {
|
||||
bottom: 0px;
|
||||
right: 20px !important;
|
||||
}
|
||||
|
||||
.toggle-close {
|
||||
bottom: 125px;
|
||||
right: 15px !important;
|
||||
right: 4px;
|
||||
&-twig {
|
||||
position: absolute;
|
||||
right: -25px;
|
||||
bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.blur {
|
||||
|
@ -2,18 +2,19 @@ require('./blur.scss');
|
||||
|
||||
document.querySelectorAll('.confidential').forEach(function (el) {
|
||||
let i = document.createElement('i');
|
||||
const classes = ['fa', 'fa-eye', 'toggle'];
|
||||
const classes = ['fa', 'fa-eye-slash', 'toggle-twig'];
|
||||
i.classList.add(...classes);
|
||||
el.appendChild(i);
|
||||
|
||||
const toggleBlur = function(e) {
|
||||
for (let child of el.children) {
|
||||
if (!child.classList.contains('toggle')) {
|
||||
if (!child.classList.contains('toggle-twig')) {
|
||||
child.classList.toggle('blur');
|
||||
}
|
||||
}
|
||||
i.classList.toggle('fa-eye');
|
||||
i.classList.toggle('fa-eye-slash');
|
||||
i.classList.toggle('fa-eye');
|
||||
}
|
||||
i.addEventListener('click', toggleBlur);
|
||||
toggleBlur();
|
||||
});
|
||||
});
|
@ -22,6 +22,7 @@ const fetchCountries = () => {
|
||||
*/
|
||||
const fetchCities = (country) => {
|
||||
//console.log('<<< fetching cities for', country);
|
||||
// warning: do not use fetchResults (in apiMethods): we need only a **part** of the results in the db
|
||||
const url = `/api/1.0/main/postal-code.json?item_per_page=1000&country=${country.id}`;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
|
@ -42,9 +42,6 @@
|
||||
<a class="btn btn-sm btn-show" :href="getUrl(e)">
|
||||
{{ $t('show_entity', { entity: $t('the_evaluation') }) }}
|
||||
</a>
|
||||
<a class="btn btn-sm btn-update" :href="getUrl(e.accompanyingPeriodWork)">
|
||||
{{ $t('show_entity', { entity: $t('the_action') }) }}
|
||||
</a>
|
||||
<a class="btn btn-sm btn-show" :href="getUrl(e.accompanyingPeriodWork.accompanyingPeriod)">
|
||||
{{ $t('show_entity', { entity: $t('the_course') }) }}
|
||||
</a>
|
||||
@ -102,4 +99,4 @@ export default {
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
@ -3,8 +3,8 @@
|
||||
<div :class="{ 'blur': isBlurred }">
|
||||
<slot name="confidential-content"></slot>
|
||||
</div>
|
||||
<div>
|
||||
<i class="fa fa-eye toggle" :class="positionBtn" aria-hidden="true" @click="toggleBlur"></i>
|
||||
<div class="toggle-container">
|
||||
<i class="fa toggle" :class="toggleIcon" aria-hidden="true" @click="toggleBlur"></i>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -12,28 +12,24 @@
|
||||
<script>
|
||||
export default {
|
||||
name: "Confidential",
|
||||
props: ['positionBtnFar'],
|
||||
data() {
|
||||
return {
|
||||
isBlurred: true,
|
||||
toggleIcon: 'fa-eye',
|
||||
};
|
||||
},
|
||||
methods : {
|
||||
toggleBlur() {
|
||||
console.log(this.positionBtnFar);
|
||||
this.isBlurred = !this.isBlurred;
|
||||
this.toggleIcon = this.isBlurred ? 'fa-eye' : 'fa-eye-slash';
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
positionBtn() {
|
||||
return this.positionBtnFar ? 'toggle-far' : 'toggle-close'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang='scss'>
|
||||
.confidential{
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
}
|
||||
</style>
|
||||
|
@ -59,7 +59,7 @@
|
||||
must be shown in such list
|
||||
#}
|
||||
{%- if render == 'list' -%}
|
||||
<li class="chill-entity entity-address {% if address.confidential %} confidential toggle-far-twig {% endif %}">
|
||||
<li class="chill-entity entity-address {% if address.confidential %} confidential {% endif %}">
|
||||
{% if options['with_picto'] %}
|
||||
<i class="fa fa-li fa-map-marker"></i>
|
||||
{% endif %}
|
||||
@ -68,7 +68,7 @@
|
||||
{%- endif -%}
|
||||
|
||||
{%- if render == 'inline' -%}
|
||||
<span class="chill-entity entity-address {% if address.confidential %} confidential toggle-far-twig {% endif %}">
|
||||
<span class="chill-entity entity-address {% if address.confidential %} confidential {% endif %}">
|
||||
{% if options['with_picto'] %}
|
||||
<i class="fa fa-fw fa-map-marker"></i>
|
||||
{% endif %}
|
||||
@ -77,7 +77,7 @@
|
||||
{%- endif -%}
|
||||
|
||||
{%- if render == 'bloc' -%}
|
||||
<div class="chill-entity entity-address {% if address.confidential %} confidential toggle-close-twig {% endif %}">
|
||||
<div class="chill-entity entity-address {% if address.confidential %} confidential {% endif %}">
|
||||
{% if options['has_no_address'] == true and address.isNoAddress == true %}
|
||||
{% if address.postCode is not empty %}
|
||||
<div class="address{% if options['multiline'] %} multiline{% endif %}{% if options['with_delimiter'] %} delimiter{% endif %}">
|
||||
|
@ -27,7 +27,7 @@
|
||||
</a>
|
||||
{% for menu in menus %}
|
||||
<a class="list-group-item list-group-item-action" href="{{ menu.uri }}">
|
||||
{{ menu.label|upper }}
|
||||
{{ menu.label|trans|upper }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
@ -1,60 +1,62 @@
|
||||
{% extends '@ChillMain/Admin/Permission/layout_crud_permission_index.html.twig' %}
|
||||
|
||||
{% block admin_content -%}
|
||||
{% embed '@ChillMain/CRUD/_index.html.twig' %}
|
||||
{% block table_entities_thead_tr %}
|
||||
<th>{{ 'crud.admin_user.index.is_active'|trans }}</th>
|
||||
<th>{{ 'crud.admin_user.index.usernames'|trans }}</th>
|
||||
<th>{{ 'crud.admin_user.index.mains'|trans }}</th>
|
||||
<th> </th>
|
||||
{% endblock %}
|
||||
{% block table_entities_tbody %}
|
||||
{% for entity in entities %}
|
||||
<tr data-username="{{ entity.username|e('html_attr') }}">
|
||||
<td>
|
||||
|
||||
<h1>{{"Users"|trans}}</h1>
|
||||
{% for entity in entities %}
|
||||
<div class="flex-table">
|
||||
<div class="item-bloc">
|
||||
<div class="item-row">
|
||||
<div class="item-col">
|
||||
{{ entity.label }}
|
||||
{% if entity.isEnabled %}
|
||||
<i class="fa fa-check chill-green"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-times chill-red"></i>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ entity.username }}
|
||||
<br/>
|
||||
{{ entity.label }}
|
||||
<br/>
|
||||
{{ entity.email }}
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
<div class="item-col"><i>{{ entity.email }}</i></div>
|
||||
</div>
|
||||
<div class="item-row">
|
||||
<div class="item-col">
|
||||
login: {{ entity.username|e('html_attr') }}
|
||||
</div>
|
||||
<div class="item-col">
|
||||
{% if entity.userJob %}
|
||||
{{ entity.userJob.label|localize_translatable_string }}
|
||||
<br/>
|
||||
{{ entity.userJob.label|localize_translatable_string }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-row">
|
||||
<div class="item-col">
|
||||
{% if entity.mainScope %}
|
||||
{{ entity.mainScope.name|localize_translatable_string }}
|
||||
<br/>
|
||||
{{ entity.mainScope.name|localize_translatable_string }}
|
||||
{% endif %}
|
||||
{% if entity.mainCenter %}
|
||||
{{ entity.mainCenter.name }}
|
||||
, {{ entity.mainCenter.name }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-row">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a class="btn btn-edit" href="{{ path('chill_crud_admin_user_edit', { 'id': entity.id }) }}"></a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="btn btn-chill-red" href="{{ path('admin_user_edit_password', { 'id' : entity.id }) }}" title="{{ 'Edit password'|trans|e('html_attr') }}"><i class="fa fa-ellipsis-h"></i></a>
|
||||
</li>
|
||||
{% if is_granted('ROLE_ALLOWED_TO_SWITCH') %}
|
||||
<li>
|
||||
<a class="btn btn-edit" href="{{ path('chill_crud_admin_user_edit', { 'id': entity.id }) }}"></a>
|
||||
<a class="btn btn-chill-blue" href="{{ path('chill_main_homepage', {'_switch_user': entity.username }) }}" title="{{ "Impersonate"|trans|e('html_attr') }}"><i class="fa fa-user-secret"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="btn btn-chill-red" href="{{ path('admin_user_edit_password', { 'id' : entity.id }) }}" title="{{ 'Edit password'|trans|e('html_attr') }}"><i class="fa fa-ellipsis-h"></i></a>
|
||||
</li>
|
||||
{% if is_granted('ROLE_ALLOWED_TO_SWITCH') %}
|
||||
<li>
|
||||
<a class="btn btn-chill-blue" href="{{ path('chill_main_homepage', {'_switch_user': entity.username }) }}" title="{{ "Impersonate"|trans|e('html_attr') }}"><i class="fa fa-user-secret"></i></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{{ chill_pagination(paginator) }}
|
||||
|
||||
{% endblock %}
|
@ -16,10 +16,10 @@ use libphonenumber\PhoneNumber;
|
||||
use libphonenumber\PhoneNumberUtil;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
|
||||
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
class PhonenumberNormalizer implements NormalizerInterface, DenormalizerInterface
|
||||
class PhonenumberNormalizer implements ContextAwareNormalizerInterface, DenormalizerInterface
|
||||
{
|
||||
private string $defaultCarrierCode;
|
||||
|
||||
@ -53,6 +53,10 @@ class PhonenumberNormalizer implements NormalizerInterface, DenormalizerInterfac
|
||||
|
||||
public function normalize($object, ?string $format = null, array $context = []): string
|
||||
{
|
||||
if ('docgen' === $format && null === $object) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->phoneNumberUtil->formatOutOfCountryCallingNumber($object, $this->defaultCarrierCode);
|
||||
}
|
||||
|
||||
@ -61,8 +65,18 @@ class PhonenumberNormalizer implements NormalizerInterface, DenormalizerInterfac
|
||||
return 'libphonenumber\PhoneNumber' === $type;
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, ?string $format = null)
|
||||
public function supportsNormalization($data, ?string $format = null, array $context = []): bool
|
||||
{
|
||||
return $data instanceof PhoneNumber;
|
||||
if ($data instanceof PhoneNumber && 'json' === $format) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ('docgen' === $format && (
|
||||
$data instanceof PhoneNumber || PhoneNumber::class === ($context['docgen:expects'] ?? null)
|
||||
)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -222,6 +222,10 @@ class AccompanyingPeriodController extends AbstractController
|
||||
$accompanyingPeriodsRaw = $this->accompanyingPeriodACLAwareRepository
|
||||
->findByPerson($person, AccompanyingPeriodVoter::SEE);
|
||||
|
||||
usort($accompanyingPeriodsRaw, static function ($a, $b) {
|
||||
return $b->getOpeningDate() > $a->getOpeningDate();
|
||||
});
|
||||
|
||||
// filter visible or not visible
|
||||
$accompanyingPeriods = array_filter($accompanyingPeriodsRaw, function (AccompanyingPeriod $ap) {
|
||||
return $this->isGranted(AccompanyingPeriodVoter::SEE, $ap);
|
||||
|
@ -134,7 +134,7 @@ class HouseholdCompositionController extends AbstractController
|
||||
public function index(Household $household, Request $request): Response
|
||||
{
|
||||
if (!$this->security->isGranted(HouseholdVoter::SEE, $household)) {
|
||||
throw new AccessDeniedException('not allowed to edit an household');
|
||||
throw new AccessDeniedException('not allowed to edit a household');
|
||||
}
|
||||
|
||||
$count = $this->householdCompositionRepository->countByHousehold($household);
|
||||
@ -146,6 +146,20 @@ class HouseholdCompositionController extends AbstractController
|
||||
$paginator->getCurrentPageFirstItemNumber()
|
||||
);
|
||||
|
||||
return new Response($this->engine->render(
|
||||
'@ChillPerson/HouseholdComposition/index.html.twig',
|
||||
[
|
||||
'household' => $household,
|
||||
'compositions' => $compositions,
|
||||
]
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/{_locale}/person/household/{id}/composition/new", name="chill_person_household_composition_new")
|
||||
*/
|
||||
public function newAction(Household $household, Request $request): Response
|
||||
{
|
||||
if ($this->security->isGranted(HouseholdVoter::EDIT, $household)) {
|
||||
$isEdit = $request->query->has('edit');
|
||||
|
||||
@ -195,10 +209,9 @@ class HouseholdCompositionController extends AbstractController
|
||||
}
|
||||
|
||||
return new Response($this->engine->render(
|
||||
'@ChillPerson/HouseholdComposition/index.html.twig',
|
||||
'@ChillPerson/HouseholdComposition/create.html.twig',
|
||||
[
|
||||
'household' => $household,
|
||||
'compositions' => $compositions,
|
||||
'form' => isset($form) ? $form->createView() : null,
|
||||
'isPosted' => isset($form) ? $form->isSubmitted() : false,
|
||||
'editId' => $request->query->getInt('edit', -1),
|
||||
|
@ -78,6 +78,10 @@ class HouseholdController extends AbstractController
|
||||
}
|
||||
}
|
||||
|
||||
usort($accompanyingPeriods, static function ($a, $b) {
|
||||
return $b->getOpeningDate() > $a->getOpeningDate();
|
||||
});
|
||||
|
||||
$oldMembers = $household->getNonCurrentMembers();
|
||||
$accompanyingPeriodsOld = [];
|
||||
|
||||
|
@ -133,6 +133,19 @@ final class PersonResourceController extends AbstractController
|
||||
$personResources = [];
|
||||
$personResources = $this->personResourceRepository->findBy(['personOwner' => $personOwner->getId()]);
|
||||
|
||||
return $this->render(
|
||||
'ChillPersonBundle:PersonResource:list.html.twig',
|
||||
[
|
||||
'person' => $personOwner,
|
||||
'personResources' => $personResources,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function newAction(Request $request, $person_id)
|
||||
{
|
||||
$personOwner = $this->personRepository->find($person_id);
|
||||
|
||||
$form = $this->createForm(PersonResourceType::class);
|
||||
|
||||
$form->handleRequest($request);
|
||||
@ -165,11 +178,10 @@ final class PersonResourceController extends AbstractController
|
||||
}
|
||||
|
||||
return $this->render(
|
||||
'ChillPersonBundle:PersonResource:list.html.twig',
|
||||
'ChillPersonBundle:PersonResource:create.html.twig',
|
||||
[
|
||||
'person' => $personOwner,
|
||||
'personResources' => $personResources,
|
||||
'form' => $form->createView(),
|
||||
'person' => $personOwner,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\Controller;
|
||||
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||
use Chill\MainBundle\Repository\UserRepository;
|
||||
use Chill\MainBundle\Templating\Entity\UserRender;
|
||||
use Chill\PersonBundle\Repository\AccompanyingPeriodACLAwareRepository;
|
||||
use Chill\PersonBundle\Repository\AccompanyingPeriodACLAwareRepositoryInterface;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Templating\EngineInterface;
|
||||
|
||||
class ReassignAccompanyingPeriodController extends AbstractController
|
||||
{
|
||||
private AccompanyingPeriodACLAwareRepositoryInterface $accompanyingPeriodACLAwareRepository;
|
||||
|
||||
private EngineInterface $engine;
|
||||
|
||||
private FormFactoryInterface $formFactory;
|
||||
|
||||
private PaginatorFactory $paginatorFactory;
|
||||
|
||||
private Security $security;
|
||||
|
||||
private UserRender $userRender;
|
||||
|
||||
private UserRepository $userRepository;
|
||||
|
||||
public function __construct(AccompanyingPeriodACLAwareRepositoryInterface $accompanyingPeriodACLAwareRepository, UserRepository $userRepository, EngineInterface $engine, FormFactoryInterface $formFactory, PaginatorFactory $paginatorFactory, Security $security, UserRender $userRender)
|
||||
{
|
||||
$this->accompanyingPeriodACLAwareRepository = $accompanyingPeriodACLAwareRepository;
|
||||
$this->engine = $engine;
|
||||
$this->formFactory = $formFactory;
|
||||
$this->paginatorFactory = $paginatorFactory;
|
||||
$this->security = $security;
|
||||
$this->userRepository = $userRepository;
|
||||
$this->userRender = $userRender;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/{_locale}/person/accompanying-periods/reassign", name="chill_course_list_reassign")
|
||||
*/
|
||||
public function listAction(Request $request): Response
|
||||
{
|
||||
if (!$this->security->isGranted('ROLE_USER') || !$this->security->getUser() instanceof User) {
|
||||
throw new AccessDeniedException();
|
||||
}
|
||||
|
||||
$form = $this->buildFilterForm();
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
$total = $this->accompanyingPeriodACLAwareRepository->countByUserOpenedAccompanyingPeriod(
|
||||
$form['user']->getData()
|
||||
);
|
||||
$paginator = $this->paginatorFactory->create($total);
|
||||
$periods = $this->accompanyingPeriodACLAwareRepository
|
||||
->findByUserOpenedAccompanyingPeriod(
|
||||
$form['user']->getData(),
|
||||
['openingDate' => 'ASC'],
|
||||
$paginator->getItemsPerPage(),
|
||||
$paginator->getCurrentPageFirstItemNumber()
|
||||
);
|
||||
|
||||
return new Response(
|
||||
$this->engine->render('@ChillPerson/AccompanyingPeriod/reassign_list.html.twig', [
|
||||
'paginator' => $paginator,
|
||||
'periods' => $periods,
|
||||
'form' => $form->createView(),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
private function buildFilterForm(): FormInterface
|
||||
{
|
||||
$data = [
|
||||
'user' => null,
|
||||
];
|
||||
$builder = $this->formFactory->createBuilder(FormType::class, $data, [
|
||||
'method' => 'get', 'csrf_protection' => false, ]);
|
||||
|
||||
$builder
|
||||
->add('user', EntityType::class, [
|
||||
'class' => User::class,
|
||||
'choices' => $this->userRepository->findByActive(['username' => 'ASC']),
|
||||
'choice_label' => function (User $u) {
|
||||
return $this->userRender->renderString($u, []);
|
||||
},
|
||||
'multiple' => false,
|
||||
'label' => 'User',
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
return $builder->getForm();
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ use Chill\MainBundle\DependencyInjection\MissingBundleException;
|
||||
use Chill\MainBundle\Security\Authorization\ChillExportVoter;
|
||||
use Chill\PersonBundle\Controller\HouseholdCompositionTypeApiController;
|
||||
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodCommentVoter;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodResourceVoter;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
@ -415,6 +416,25 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'class' => \Chill\PersonBundle\Entity\AccompanyingPeriod\Comment::class,
|
||||
'name' => 'accompanying_period_comment',
|
||||
'base_path' => '/api/1.0/person/accompanying-period/comment',
|
||||
'base_role' => 'ROLE_USER',
|
||||
'actions' => [
|
||||
'_entity' => [
|
||||
'methods' => [
|
||||
Request::METHOD_GET => false,
|
||||
Request::METHOD_PATCH => true,
|
||||
Request::METHOD_HEAD => false,
|
||||
Request::METHOD_DELETE => false,
|
||||
],
|
||||
'roles' => [
|
||||
Request::METHOD_PATCH => AccompanyingPeriodCommentVoter::EDIT,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'class' => \Chill\PersonBundle\Entity\AccompanyingPeriod\Resource::class,
|
||||
'name' => 'accompanying_period_resource',
|
||||
|
@ -257,9 +257,11 @@ class AccompanyingPeriod implements
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity=Comment::class
|
||||
* targetEntity=Comment::class,
|
||||
* cascade={"persist"},
|
||||
* )
|
||||
* @Groups({"read"})
|
||||
* @ORM\JoinColumn(onDelete="SET NULL")
|
||||
*/
|
||||
private ?Comment $pinnedComment = null;
|
||||
|
||||
|
@ -142,6 +142,15 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
|
||||
*/
|
||||
private Collection $persons;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity=User::class)
|
||||
* @ORM\JoinTable(name="chill_person_accompanying_period_work_referrer")
|
||||
* @Serializer\Groups({"read", "docgen:read", "read:accompanyingPeriodWork:light"})
|
||||
* @Serializer\Groups({"accompanying_period_work:edit"})
|
||||
* @Serializer\Groups({"accompanying_period_work:create"})
|
||||
*/
|
||||
private Collection $referrers;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity=Result::class, inversedBy="accompanyingPeriodWorks")
|
||||
* @ORM\JoinTable(name="chill_person_accompanying_period_work_result")
|
||||
@ -196,6 +205,7 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
|
||||
$this->thirdParties = new ArrayCollection();
|
||||
$this->persons = new ArrayCollection();
|
||||
$this->accompanyingPeriodWorkEvaluations = new ArrayCollection();
|
||||
$this->referrers = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function addAccompanyingPeriodWorkEvaluation(AccompanyingPeriodWorkEvaluation $evaluation): self
|
||||
@ -227,6 +237,15 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addReferrer(User $referrer): self
|
||||
{
|
||||
if (!$this->referrers->contains($referrer)) {
|
||||
$this->referrers[] = $referrer;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addResult(Result $result): self
|
||||
{
|
||||
if (!$this->results->contains($result)) {
|
||||
@ -308,6 +327,14 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
|
||||
return $this->persons;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|User[]
|
||||
*/
|
||||
public function getReferrers(): Collection
|
||||
{
|
||||
return $this->referrers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|Result[]
|
||||
*/
|
||||
@ -382,6 +409,13 @@ class AccompanyingPeriodWork implements AccompanyingPeriodLinkedWithSocialIssues
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeReferrer(User $referrer): self
|
||||
{
|
||||
$this->referrers->removeElement($referrer);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeResult(Result $result): self
|
||||
{
|
||||
$this->results->removeElement($result);
|
||||
|
@ -124,6 +124,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU
|
||||
/**
|
||||
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
|
||||
* @Serializer\Groups({"read", "docgen:read"})
|
||||
* @Serializer\Groups({"write"})
|
||||
* @Serializer\Groups({"accompanying_period_work_evaluation:create"})
|
||||
*/
|
||||
private ?DateTimeImmutable $maxDate = null;
|
||||
|
@ -109,6 +109,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
* @ORM\OneToMany(targetEntity=AccompanyingPeriodParticipation::class,
|
||||
* mappedBy="person",
|
||||
* cascade={"persist", "remove", "merge", "detach"})
|
||||
* @ORM\OrderBy({"startDate": "DESC"})
|
||||
*/
|
||||
private $accompanyingPeriodParticipations;
|
||||
|
||||
|
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\EventListener;
|
||||
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
class AccompanyingPeriodWorkEventListener
|
||||
{
|
||||
private Security $security;
|
||||
|
||||
public function __construct(Security $security)
|
||||
{
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
public function prePersistAccompanyingPeriodWork(AccompanyingPeriodWork $work): void
|
||||
{
|
||||
$work->addReferrer($this->security->getUser());
|
||||
}
|
||||
}
|
@ -68,12 +68,14 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface
|
||||
}
|
||||
|
||||
if ($this->security->isGranted(AccompanyingPeriodVoter::SEE_DETAILS, $period)) {
|
||||
$menu->addChild($this->translator->trans('Accompanying Course History'), [
|
||||
'route' => 'chill_person_accompanying_course_history',
|
||||
'routeParameters' => [
|
||||
'accompanying_period_id' => $period->getId(),
|
||||
], ])
|
||||
->setExtras(['order' => 30]);
|
||||
/*
|
||||
$menu->addChild($this->translator->trans('Accompanying Course History'), [
|
||||
'route' => 'chill_person_accompanying_course_history',
|
||||
'routeParameters' => [
|
||||
'accompanying_period_id' => $period->getId(),
|
||||
], ])
|
||||
->setExtras(['order' => 30]);
|
||||
*/
|
||||
|
||||
$menu->addChild($this->translator->trans('Accompanying Course Comment'), [
|
||||
'route' => 'chill_person_accompanying_period_comment_list',
|
||||
|
@ -22,15 +22,9 @@ use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
*/
|
||||
class SectionMenuBuilder implements LocalMenuBuilderInterface
|
||||
{
|
||||
/**
|
||||
* @var AuthorizationCheckerInterface
|
||||
*/
|
||||
protected $authorizationChecker;
|
||||
protected AuthorizationCheckerInterface $authorizationChecker;
|
||||
|
||||
/**
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
protected TranslatorInterface $translator;
|
||||
|
||||
/**
|
||||
* SectionMenuBuilder constructor.
|
||||
@ -63,6 +57,14 @@ class SectionMenuBuilder implements LocalMenuBuilderInterface
|
||||
'order' => 11,
|
||||
'icons' => ['plus'],
|
||||
]);
|
||||
|
||||
$menu->addChild($this->translator->trans('Accompanying courses of users'), [
|
||||
'route' => 'chill_course_list_reassign',
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 12,
|
||||
'icons' => ['task'],
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getMenuIds(): array
|
||||
|
@ -87,9 +87,12 @@ class AccompanyingPeriodWorkEvaluationRepository implements ObjectRepository
|
||||
->join('work.accompanyingPeriod', 'period')
|
||||
->where(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->eq('period.user', ':user'),
|
||||
$qb->expr()->isNull('e.endDate'),
|
||||
$qb->expr()->gte(':now', $qb->expr()->diff('e.maxDate', 'e.warningInterval'))
|
||||
$qb->expr()->gte(':now', $qb->expr()->diff('e.maxDate', 'e.warningInterval')),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->eq('period.user', ':user'),
|
||||
$qb->expr()->isMemberOf(':user', 'work.referrers')
|
||||
)
|
||||
)
|
||||
)
|
||||
->setParameters([
|
||||
|
@ -159,9 +159,12 @@ final class AccompanyingPeriodWorkRepository implements ObjectRepository
|
||||
->join('w.accompanyingPeriod', 'period')
|
||||
->where(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->eq('period.user', ':user'),
|
||||
$qb->expr()->gte('w.endDate', ':since'),
|
||||
$qb->expr()->lte('w.startDate', ':until')
|
||||
$qb->expr()->lte('w.startDate', ':until'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->eq('period.user', ':user'),
|
||||
$qb->expr()->isMemberOf(':user', 'w.referrers')
|
||||
)
|
||||
)
|
||||
)
|
||||
->setParameters([
|
||||
|
@ -11,6 +11,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\Repository;
|
||||
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
@ -41,6 +42,37 @@ final class AccompanyingPeriodACLAwareRepository implements AccompanyingPeriodAC
|
||||
$this->centerResolverDispatcher = $centerResolverDispatcher;
|
||||
}
|
||||
|
||||
public function buildQueryOpenedAccompanyingCourseByUser(?User $user)
|
||||
{
|
||||
$qb = $this->accompanyingPeriodRepository->createQueryBuilder('ap');
|
||||
|
||||
$qb->where($qb->expr()->eq('ap.user', ':user'))
|
||||
->andWhere(
|
||||
$qb->expr()->neq('ap.step', ':draft'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull('ap.closingDate'),
|
||||
$qb->expr()->gt('ap.closingDate', ':now')
|
||||
)
|
||||
)
|
||||
->setParameter('user', $user)
|
||||
->setParameter('now', new \DateTime('now'))
|
||||
->setParameter('draft', AccompanyingPeriod::STEP_DRAFT);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function countByUserOpenedAccompanyingPeriod(?User $user): int
|
||||
{
|
||||
if (null === $user) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $this->buildQueryOpenedAccompanyingCourseByUser($user)
|
||||
->select('COUNT(ap)')
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
}
|
||||
|
||||
public function findByPerson(
|
||||
Person $person,
|
||||
string $role,
|
||||
@ -92,4 +124,25 @@ final class AccompanyingPeriodACLAwareRepository implements AccompanyingPeriodAC
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|AccompanyingPeriod[]
|
||||
*/
|
||||
public function findByUserOpenedAccompanyingPeriod(?User $user, array $orderBy = [], int $limit = 0, int $offset = 50): array
|
||||
{
|
||||
if (null === $user) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$qb = $this->buildQueryOpenedAccompanyingCourseByUser($user);
|
||||
|
||||
$qb->setFirstResult($offset)
|
||||
->setMaxResults($limit);
|
||||
|
||||
foreach ($orderBy as $field => $direction) {
|
||||
$qb->addOrderBy('ap.'.$field, $direction);
|
||||
}
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\Repository;
|
||||
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
|
||||
interface AccompanyingPeriodACLAwareRepositoryInterface
|
||||
@ -22,4 +23,8 @@ interface AccompanyingPeriodACLAwareRepositoryInterface
|
||||
?int $limit = null,
|
||||
?int $offset = null
|
||||
): array;
|
||||
|
||||
public function findByUserOpenedAccompanyingPeriod(?User $user, array $orderBy = [], int $limit = 0, int $offset = 50): array;
|
||||
|
||||
public function countByUserOpenedAccompanyingPeriod(?User $user): int;
|
||||
}
|
||||
|
@ -78,6 +78,16 @@ final class AccompanyingPeriodRepository implements ObjectRepository
|
||||
->getResult();
|
||||
}
|
||||
|
||||
public function findConfirmedByUser(User $user)
|
||||
{
|
||||
$qb = $this->createQueryBuilder('ap');
|
||||
$qb->where($qb->expr()->eq('ap.user', ':user'))
|
||||
->andWhere('ap.step', 'CONFIRMED')
|
||||
->setParameter('user', $user);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function findOneBy(array $criteria): ?AccompanyingPeriod
|
||||
{
|
||||
return $this->findOneBy($criteria);
|
||||
|
@ -33,6 +33,8 @@ div.banner {
|
||||
padding-top: 1em;
|
||||
padding-bottom: 1em;
|
||||
div.contact {
|
||||
display: flex;
|
||||
align-content: center;
|
||||
& > * {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
@ -14,24 +14,27 @@
|
||||
|
||||
<ckeditor
|
||||
name="content"
|
||||
v-bind:placeholder="$t('comment.content')"
|
||||
:placeholder="$t('comment.content')"
|
||||
:editor="editor"
|
||||
v-model="content"
|
||||
tag-name="textarea">
|
||||
</ckeditor>
|
||||
|
||||
<div v-if="pinnedComment" class="metadata">
|
||||
{{ $t('comment.created_by', [
|
||||
pinnedComment.creator.text,
|
||||
$d(pinnedComment.createdAt.datetime, 'long')
|
||||
]) }}
|
||||
<div class="sub-comment">
|
||||
<div v-if="pinnedComment !== null && typeof pinnedComment.creator !== 'undefined'" class="metadata">
|
||||
{{ $t('comment.created_by', [
|
||||
pinnedComment.creator.text,
|
||||
$d(pinnedComment.updatedAt.datetime, 'long')
|
||||
])
|
||||
}}
|
||||
</div>
|
||||
<div class="loading">
|
||||
<i v-if="loading" class="fa fa-circle-o-notch fa-spin" :title="$t('loading')"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<button type="submit" class="btn btn-save">{{ $t('action.save') }}</button>
|
||||
</li>
|
||||
<li v-if="pinnedComment !== null">
|
||||
<a class="btn btn-delete"
|
||||
@click="removeComment">
|
||||
@ -50,6 +53,7 @@
|
||||
<script>
|
||||
import CKEditor from '@ckeditor/ckeditor5-vue';
|
||||
import ClassicEditor from "ChillMainAssets/module/ckeditor5";
|
||||
import { mapState } from "vuex";
|
||||
|
||||
export default {
|
||||
name: "Comment",
|
||||
@ -59,22 +63,58 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
editor: ClassicEditor,
|
||||
formdata: {
|
||||
type: "accompanying_period_comment",
|
||||
content: ''
|
||||
}
|
||||
loading: false,
|
||||
lastRecordedContent: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
pinnedComment() {
|
||||
return this.$store.state.accompanyingCourse.pinnedComment;
|
||||
},
|
||||
...mapState({
|
||||
pinnedComment: state => state.accompanyingCourse.pinnedComment,
|
||||
}),
|
||||
content: {
|
||||
set(value) {
|
||||
this.formdata.content = value;
|
||||
console.log('new comment value', value);
|
||||
console.log('previous value', this.lastRecordedContent);
|
||||
this.lastRecordedContent = value;
|
||||
|
||||
setTimeout(() => {
|
||||
console.log('performing test on ', value);
|
||||
if (this.lastRecordedContent === value) {
|
||||
this.loading = true;
|
||||
if (value !== '') {
|
||||
this.$store.dispatch('updatePinnedComment', value)
|
||||
.then(() => {
|
||||
this.loading = false;
|
||||
})
|
||||
.catch(({name, violations}) => {
|
||||
if (name === 'ValidationException' || name === 'AccessException') {
|
||||
violations.forEach((violation) => this.$toast.open({message: violation}));
|
||||
} else {
|
||||
this.$toast.open({message: 'An error occurred'})
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (this.$store.state.accompanyingCourse.pinnedComment !== null) {
|
||||
this.$store.dispatch('removePinnedComment', {id: this.pinnedComment.id})
|
||||
.then(() => {
|
||||
this.loading = false;
|
||||
this.lastRecoredContent = null;
|
||||
})
|
||||
.catch(({name, violations}) => {
|
||||
if (name === 'ValidationException' || name === 'AccessException') {
|
||||
violations.forEach((violation) => this.$toast.open({message: violation}));
|
||||
} else {
|
||||
this.$toast.open({message: 'An error occurred'})
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 3000);
|
||||
|
||||
},
|
||||
get() {
|
||||
return (this.pinnedComment)? this.pinnedComment.content : {};
|
||||
get() {
|
||||
return this.pinnedComment ? this.pinnedComment.content : '';
|
||||
}
|
||||
},
|
||||
errors() {
|
||||
@ -82,18 +122,11 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submitform() {
|
||||
this.$store.dispatch('postFirstComment', this.formdata)
|
||||
.catch(({name, violations}) => {
|
||||
if (name === 'ValidationException' || name === 'AccessException') {
|
||||
violations.forEach((violation) => this.$toast.open({message: violation}));
|
||||
} else {
|
||||
this.$toast.open({message: 'An error occurred'})
|
||||
}
|
||||
});
|
||||
onContentChange() {
|
||||
let lastRecordedContent = this.formData.content;
|
||||
},
|
||||
removeComment() {
|
||||
this.$store.dispatch('postFirstComment', {})
|
||||
this.$store.dispatch('removePinnedComment', {id: this.pinnedComment.id})
|
||||
.catch(({name, violations}) => {
|
||||
if (name === 'ValidationException' || name === 'AccessException') {
|
||||
violations.forEach((violation) => this.$toast.open({message: violation}));
|
||||
@ -104,15 +137,18 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* TODO
|
||||
* - [x] delete button in ul record_actions, but not in form
|
||||
* - [ ] display updatedAt => pinnedComment fetch PATCH content changes MUST NOT change object id !!
|
||||
*/
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
div.ck-editor.ck-reset {
|
||||
margin: 0.6em 0;
|
||||
}
|
||||
div.sub-comment {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
div.loading {
|
||||
margin-right: 6px;
|
||||
margin-left: 6px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<input type="checkbox" v-model="requestorIsAnonymous" class="me-2" />
|
||||
{{ $t('requestor.is_anonymous') }}
|
||||
</label>
|
||||
<confidential :positionBtn="false" v-if="accompanyingCourse.requestor.type === 'thirdparty'">
|
||||
<confidential v-if="accompanyingCourse.requestor.type === 'thirdparty'">
|
||||
<template v-slot:confidential-content>
|
||||
<third-party-render-box
|
||||
:thirdparty="accompanyingCourse.requestor"
|
||||
@ -33,7 +33,7 @@
|
||||
</template>
|
||||
</confidential>
|
||||
|
||||
<confidential :positionBtnFar="false" v-else-if="accompanyingCourse.requestor.type === 'person'">
|
||||
<confidential v-else-if="accompanyingCourse.requestor.type === 'person'">
|
||||
<template v-slot:confidential-content>
|
||||
<person-render-box render="bloc"
|
||||
:person="accompanyingCourse.requestor"
|
||||
@ -339,5 +339,6 @@ div.flex-table {
|
||||
|
||||
.confidential {
|
||||
display: block;
|
||||
margin-right: 0px !important;
|
||||
}
|
||||
</style>
|
||||
|
@ -122,7 +122,7 @@ const appMessages = {
|
||||
title: "Observations",
|
||||
label: "Ajout d'une note",
|
||||
content: "Rédigez une première note…",
|
||||
created_by: "créé par {0}, le {1}"
|
||||
created_by: "créé par {0}, mis à jour le {1}"
|
||||
},
|
||||
confirm: {
|
||||
title: "Confirmation",
|
||||
|
@ -42,7 +42,11 @@ let initPromise = (root) => Promise.all([getScopesPromise(root), accompanyingCou
|
||||
referrersSuggested: [],
|
||||
// all the users available
|
||||
users: [],
|
||||
permissions: {}
|
||||
permissions: {},
|
||||
// controller for updating comment
|
||||
updateCommentAbortController: null,
|
||||
// waiting response for inserting first comment
|
||||
postFirstPinnedCommentResponse: null,
|
||||
},
|
||||
getters: {
|
||||
isParticipationValid(state) {
|
||||
@ -203,9 +207,35 @@ let initPromise = (root) => Promise.all([getScopesPromise(root), accompanyingCou
|
||||
//console.log('### mutation: toggleConfidential');
|
||||
state.accompanyingCourse.confidential = value;
|
||||
},
|
||||
postFirstComment(state, comment) {
|
||||
//console.log('### mutation: postFirstComment', comment);
|
||||
state.accompanyingCourse.pinnedComment = comment;
|
||||
setPinnedComment(state, content) {
|
||||
if (null === state.accompanyingCourse.pinnedComment) {
|
||||
state.accompanyingCourse.pinnedComment = {
|
||||
id: -1,
|
||||
content,
|
||||
type: "accompanying_period_comment",
|
||||
};
|
||||
} else {
|
||||
state.accompanyingCourse.pinnedComment.content = content;
|
||||
}
|
||||
},
|
||||
setPinnedCommentDetails(state, value) {
|
||||
state.accompanyingCourse.pinnedComment.id = value.id;
|
||||
if (typeof value.creator !== 'undefined') {
|
||||
state.accompanyingCourse.pinnedComment.creator = value.creator;
|
||||
state.accompanyingCourse.pinnedComment.updatedBy = value.updatedBy;
|
||||
state.accompanyingCourse.pinnedComment.updatedAt = value.updatedAt;
|
||||
state.accompanyingCourse.pinnedComment.createdAt = value.createdAt;
|
||||
|
||||
}
|
||||
},
|
||||
removePinnedComment(state, value) {
|
||||
state.accompanyingCourse.pinnedComment = null;
|
||||
},
|
||||
setPinCommentAbortController(state, value) {
|
||||
state.updateCommentAbortController = value;
|
||||
},
|
||||
setPostFirstPinnedCommentResponse(state, value) {
|
||||
state.postFirstPinnedCommentResponse = value;
|
||||
},
|
||||
updateSocialIssues(state, value) {
|
||||
console.log('updateSocialIssues', value);
|
||||
@ -337,6 +367,87 @@ let initPromise = (root) => Promise.all([getScopesPromise(root), accompanyingCou
|
||||
throw error;
|
||||
})
|
||||
},
|
||||
/**
|
||||
* Add/remove pinnedComment
|
||||
*/
|
||||
removePinnedComment({ commit }, payload) {
|
||||
const body = {type: "accompanying_period_comment", id: payload.id};
|
||||
const url = `/api/1.0/person/accompanying-course/${id}/comment.json`;
|
||||
|
||||
return makeFetch('DELETE', url, body)
|
||||
.then((response) => {
|
||||
commit('removePinnedComment');
|
||||
})
|
||||
.catch((error) => {
|
||||
commit('catchError', error);
|
||||
throw error;
|
||||
})
|
||||
},
|
||||
/**
|
||||
* internal method to insert a new comment
|
||||
*
|
||||
* @param commit
|
||||
* @param dispatch
|
||||
* @param content
|
||||
* @returns {*}
|
||||
*/
|
||||
addPinnedComment({ commit, dispatch }, content) {
|
||||
const url = `/api/1.0/person/accompanying-course/${id}/comment.json`;
|
||||
|
||||
return makeFetch('POST', url, {type: "accompanying_period_comment", content})
|
||||
.then((response) => {
|
||||
commit('setPinnedCommentDetails', response);
|
||||
return dispatch('patchFirstComment', response);
|
||||
})
|
||||
.catch((error) => {
|
||||
commit('catchError', error);
|
||||
throw error;
|
||||
})
|
||||
},
|
||||
updatePinnedComment({ commit, state, dispatch }, content) {
|
||||
commit('setPinnedComment', content);
|
||||
if (state.accompanyingCourse.pinnedComment.id === -1 && state.postFirstPinnedCommentResponse === null) {
|
||||
let r = dispatch('addPinnedComment', content).then(() => {
|
||||
commit('setPostFirstPinnedCommentResponse', null);
|
||||
});
|
||||
commit('setPostFirstPinnedCommentResponse', r);
|
||||
} else {
|
||||
(state.postFirstPinnedCommentResponse === null ? Promise.resolve() : state.postFirstPinnedCommentResponse).then(() => {
|
||||
dispatch('updateExistingPinnedComment', content);
|
||||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
* internal method to patch an existing comment
|
||||
*
|
||||
* @param commit
|
||||
* @param state
|
||||
* @param comment
|
||||
* @returns {*}
|
||||
*/
|
||||
updateExistingPinnedComment({ commit, state }, content) {
|
||||
const payload = {type: "accompanying_period_comment", content, id: state.accompanyingCourse.pinnedComment.id};
|
||||
const url = `/api/1.0/person/accompanying-period/comment/${payload.id}.json`;
|
||||
|
||||
if (state.updateCommentAbortController !== null) {
|
||||
state.updateCommentAbortController.abort();
|
||||
commit('setPinCommentAbortController', null);
|
||||
}
|
||||
|
||||
let controller = new AbortController();
|
||||
commit('setPinCommentAbortController', controller);
|
||||
|
||||
return makeFetch('PATCH', url, payload, { signal: controller.signal })
|
||||
.then((response) => {
|
||||
commit('setPinCommentAbortController', null);
|
||||
commit('setPinnedCommentDetails', response);
|
||||
})
|
||||
.catch((error) => {
|
||||
commit('catchError', error);
|
||||
commit('setPinCommentAbortController', null);
|
||||
throw error;
|
||||
})
|
||||
},
|
||||
/**
|
||||
* Add/remove/display anonymous requestor
|
||||
*/
|
||||
@ -606,18 +717,20 @@ let initPromise = (root) => Promise.all([getScopesPromise(root), accompanyingCou
|
||||
|
||||
return Promise.all(promises);
|
||||
},
|
||||
postFirstComment({ commit }, payload) {
|
||||
const url = `/api/1.0/person/accompanying-course/${id}.json`
|
||||
const body = { type: "accompanying_period", pinnedComment: payload }
|
||||
|
||||
patchFirstComment({ commit }, payload) {
|
||||
const url = `/api/1.0/person/accompanying-course/${id}.json`;
|
||||
const body = {
|
||||
type: "accompanying_period",
|
||||
pinnedComment: {
|
||||
type: "accompanying_period_comment",
|
||||
id: payload.id
|
||||
}
|
||||
};
|
||||
return makeFetch('PATCH', url, body)
|
||||
.then((response) => {
|
||||
commit('postFirstComment', response.pinnedComment);
|
||||
})
|
||||
.catch((error) => {
|
||||
commit('catchError', error);
|
||||
throw error;
|
||||
})
|
||||
});
|
||||
},
|
||||
updateSocialIssues({ state, commit, dispatch }, { payload, body, method }) {
|
||||
const url = `/api/1.0/person/accompanying-course/${id}/socialissue.json`;
|
||||
|
@ -151,6 +151,37 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="referrers" class="action-row">
|
||||
<h3>{{ $t('referrers') }}</h3>
|
||||
|
||||
<div v-if="!hasReferrers">
|
||||
<p class="chill-no-data-statement">{{ $t('no_referrers') }}</p>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<ul class="list-suggest remove-items inline">
|
||||
<li v-for="u in referrers" :key="u.id" :title="$t('remove_referrer')" @click="removeReferrer(u)">
|
||||
<span>
|
||||
{{ u.text }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<ul class="record_actions">
|
||||
<li class="add-persons">
|
||||
<add-persons
|
||||
ref="referrerPicker"
|
||||
:key="referrerPicker.key"
|
||||
:buttonTitle="$t('add_referrers')"
|
||||
:modalTitle="$t('choose_referrers')"
|
||||
:options="referrerPicker.options"
|
||||
@addNewPersons="addReferrers">
|
||||
</add-persons>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="handlingThirdParty" class="action-row">
|
||||
<h3>{{ $t('handling_thirdparty') }}</h3>
|
||||
|
||||
@ -289,7 +320,6 @@ import PersonText from 'ChillPersonAssets/vuejs/_components/Entity/PersonText.vu
|
||||
import {buildLinkCreate} from 'ChillMainAssets/lib/entity-workflow/api.js';
|
||||
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods';
|
||||
|
||||
|
||||
const i18n = {
|
||||
messages: {
|
||||
fr: {
|
||||
@ -319,9 +349,13 @@ const i18n = {
|
||||
add_thirdparties: "Ajouter des tiers",
|
||||
choose_thirdparties: "Choisir des tiers",
|
||||
fix_these_errors: "Veuillez corriger les erreurs suivantes :",
|
||||
available_evaluations_text: "Évaluations disponibles pour ajout :",
|
||||
available_evaluations_text: "Documents disponibles pour ajout :",
|
||||
no_evaluations_available: "Aucune évaluation disponible",
|
||||
no_goals_available: "Aucun objectif disponible",
|
||||
referrers: "Agents traitants",
|
||||
no_referrers: "Aucun agent traitant",
|
||||
choose_referrers: "Choisir des agents traitants",
|
||||
remove_referrer: "Enlever l'agent"
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -370,6 +404,17 @@ export default {
|
||||
}
|
||||
},
|
||||
},
|
||||
referrerPicker: {
|
||||
key: 'referrer',
|
||||
options: {
|
||||
type: ['user'],
|
||||
priority: null,
|
||||
uniq: false,
|
||||
button: {
|
||||
display: false
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -381,6 +426,7 @@ export default {
|
||||
'personsReachables',
|
||||
'handlingThirdParty',
|
||||
'thirdParties',
|
||||
'referrers',
|
||||
'isPosting',
|
||||
'errors',
|
||||
'templatesAvailablesForAction',
|
||||
@ -389,6 +435,7 @@ export default {
|
||||
'hasResultsForAction',
|
||||
'hasHandlingThirdParty',
|
||||
'hasThirdParties',
|
||||
'hasReferrers'
|
||||
]),
|
||||
startDate: {
|
||||
get() {
|
||||
@ -465,6 +512,14 @@ export default {
|
||||
removeThirdParty(t) {
|
||||
this.$store.commit('removeThirdParty', t);
|
||||
},
|
||||
addReferrers({selected, modal}) {
|
||||
this.$store.commit('addReferrers', selected.map(r => r.result));
|
||||
this.$refs.referrerPicker.resetSearch();
|
||||
modal.showModal = false;
|
||||
},
|
||||
removeReferrer(u) {
|
||||
this.$store.commit('removeReferrer', u);
|
||||
},
|
||||
goToGenerateWorkflow({link}) {
|
||||
console.log('save before leave to generate workflow')
|
||||
const callback = (data) => {
|
||||
@ -521,6 +576,7 @@ div#workEditor {
|
||||
"objectives objectives"
|
||||
"evaluations evaluations"
|
||||
"persons persons"
|
||||
"referrers referrers"
|
||||
"handling handling"
|
||||
"tparties tparties"
|
||||
"errors errors";
|
||||
@ -543,6 +599,8 @@ div#workEditor {
|
||||
grid-area: handling; }
|
||||
#thirdParties {
|
||||
grid-area: tparties; }
|
||||
#referrers {
|
||||
grid-area: referrers; }
|
||||
#errors {
|
||||
grid-area: errors; }
|
||||
|
||||
@ -657,5 +715,4 @@ div#workEditor {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
@ -70,7 +70,7 @@
|
||||
<div class="input-group input-group-lg mb-3">
|
||||
<div>
|
||||
<input
|
||||
class="form-control form-control-lg"
|
||||
class="form-control"
|
||||
style="font-weight: bold;"
|
||||
type="text"
|
||||
:value="d.title"
|
||||
|
@ -31,6 +31,7 @@ const store = createStore({
|
||||
.map(p => p.person),
|
||||
handlingThirdParty: window.accompanyingCourseWork.handlingThierParty,
|
||||
thirdParties: window.accompanyingCourseWork.thirdParties,
|
||||
referrers: window.accompanyingCourseWork.referrers,
|
||||
isPosting: false,
|
||||
errors: [],
|
||||
},
|
||||
@ -54,6 +55,9 @@ const store = createStore({
|
||||
hasHandlingThirdParty(state) {
|
||||
return state.handlingThirdParty !== null;
|
||||
},
|
||||
hasReferrers(state) {
|
||||
return state.referrers.length > 0;
|
||||
},
|
||||
hasThirdParties(state) {
|
||||
return state.thirdParties.length > 0;
|
||||
},
|
||||
@ -82,6 +86,7 @@ const store = createStore({
|
||||
},
|
||||
results: state.resultsPicked.map(r => ({id: r.id, type: r.type})),
|
||||
thirdParties: state.thirdParties.map(t => ({id: t.id, type: t.type})),
|
||||
referrers: state.referrers.map(t => ({id: t.id, type: t.type})),
|
||||
goals: state.goalsPicked.map(g => {
|
||||
let o = {
|
||||
type: g.type,
|
||||
@ -315,6 +320,18 @@ const store = createStore({
|
||||
state.thirdParties = state.thirdParties
|
||||
.filter(t => t.id !== thirdParty.id);
|
||||
},
|
||||
addReferrers(state, referrers) {
|
||||
let ids = state.referrers.map(t => t.id);
|
||||
let unexistings = referrers.filter(t => !ids.includes(t.id));
|
||||
|
||||
for (let i in unexistings) {
|
||||
state.referrers.push(unexistings[i]);
|
||||
}
|
||||
},
|
||||
removeReferrer(state, user) {
|
||||
state.referrers = state.referrers
|
||||
.filter(u => u.id !== user.id);
|
||||
},
|
||||
setErrors(state, errors) {
|
||||
state.errors = errors;
|
||||
},
|
||||
@ -333,7 +350,6 @@ const store = createStore({
|
||||
},
|
||||
actions: {
|
||||
updateThirdParty({ commit }, payload) {
|
||||
console.log(payload);
|
||||
commit('updateThirdParty', payload);
|
||||
},
|
||||
getReachablesGoalsForAction({ getters, commit, dispatch }) {
|
||||
|
@ -87,10 +87,14 @@ export default {
|
||||
currentMembers() {
|
||||
let members = this.household.members.filter(m => this.household.current_members_id.includes(m.id))
|
||||
.sort((a, b) => {
|
||||
if (a.position.ordering < b.position.ordering) {
|
||||
|
||||
const orderA = a.position ? a.position.ordering : 0;
|
||||
const orderB = b.position ? b.position.ordering : 0;
|
||||
|
||||
if (orderA < orderB) {
|
||||
return -1;
|
||||
}
|
||||
if (a.position.ordering > b.position.ordering) {
|
||||
if (orderA > orderB) {
|
||||
return 1;
|
||||
}
|
||||
if (a.holder && !b.holder) {
|
||||
|
@ -28,11 +28,14 @@
|
||||
{% if w.createdBy %}
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<h3>{{ 'Referrer'|trans }}</h3>
|
||||
<h3>{{ 'Referrers'|trans }}</h3>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
<p class="wl-item">
|
||||
{{ w.createdBy|chill_entity_render_box }}
|
||||
{% for u in w.referrers %}
|
||||
{{ u|chill_entity_render_box }}
|
||||
{% if not loop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -0,0 +1,82 @@
|
||||
{% extends 'ChillMainBundle::layout.html.twig' %}
|
||||
|
||||
{% block title 'period_by_user_list.Period by user'|trans %}
|
||||
|
||||
{% block js %}
|
||||
{{ encore_entry_script_tags('mod_set_referrer') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ encore_entry_link_tags('mod_set_referrer') }}
|
||||
{% endblock %}
|
||||
|
||||
{% macro period_meta(period) %}
|
||||
{% if is_granted('CHILL_PERSON_ACCOMPANYING_PERIOD_UPDATE', period) %}
|
||||
<div class="item-col item-meta">
|
||||
{% set job_id = null %}
|
||||
{% if period.job is defined %}
|
||||
{% set job_id = period.job.id %}
|
||||
{% endif %}
|
||||
<span
|
||||
data-set-referrer-app="data-set-referrer-app"
|
||||
data-set-referrer-accompanying-period-id="{{ period.id }}"
|
||||
data-set-referrer-job-id="{{ job_id }}"
|
||||
></span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
{% macro period_actions(period) %}
|
||||
{% if is_granted('CHILL_PERSON_ACCOMPANYING_PERIOD_SEE', period) %}
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_person_accompanying_course_index', {'accompanying_period_id': period.id}) }}" class="btn btn-show"></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% import _self as m %}
|
||||
|
||||
{% block content %}
|
||||
<div class="col-10">
|
||||
<h1>{{ block('title') }}</h1>
|
||||
|
||||
{{ form_start(form) }}
|
||||
<div class="row filter-box">
|
||||
<div class="col-md-6">
|
||||
{{ form_label(form.user ) }}
|
||||
{{ form_widget(form.user, {'attr': {'class': 'select2'}}) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<button type="submit" class="btn btn-save change-icon">
|
||||
<i class="fa fa-filter"></i> Filtrer
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{{ form_end(form) }}
|
||||
|
||||
{% if form.user.vars.value is empty %}
|
||||
<p class="chill-no-data-statement">{{ 'period_by_user_list.Pick a user'|trans }}</p>
|
||||
{% elseif periods|length == 0 and form.user.vars.value is not empty %}
|
||||
<p class="chill-no-data-statement">{{ 'period_by_user_list.Any course or no authorization to see them'|trans }}</p>
|
||||
|
||||
{% else %}
|
||||
<p><span class="badge rounded-pill bg-primary">{{ paginator.totalItems }}</span> parcours à réassigner (calculé ce jour à {{ null|format_time('medium') }})</p>
|
||||
|
||||
<div class="flex-table">
|
||||
{% for period in periods %}
|
||||
{% include '@ChillPerson/AccompanyingPeriod/_list_item.html.twig' with {'period': period,
|
||||
'recordAction': m.period_actions(period), 'itemMeta': m.period_meta(period) } %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{{ chill_pagination(paginator) }}
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -0,0 +1,26 @@
|
||||
{% extends '@ChillPerson/Household/layout.html.twig' %}
|
||||
|
||||
{% block title 'household_composition.create'|trans %}
|
||||
|
||||
{% block block_post_menu %}
|
||||
<div class="post-menu"></div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{{ 'household_composition.Create'|trans }}</h1>
|
||||
|
||||
<div>
|
||||
{{ form_start(form) }}
|
||||
|
||||
{{ form_widget(form) }}
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<button type="submit" class="btn btn-create">{{ 'Save'|trans }}</button>
|
||||
</li>
|
||||
</ul>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -15,7 +15,7 @@
|
||||
{% else %}
|
||||
<div class="flex-table">
|
||||
{% for c in compositions %}
|
||||
{% if c.id != editId %}
|
||||
{# {% if c.id != editId %} #}
|
||||
<div class="item-bloc">
|
||||
<div class="item-row">
|
||||
<div class="item-col">
|
||||
@ -42,7 +42,7 @@
|
||||
<div class="item-row">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_person_household_composition_index', {'id': c.household.id, 'edit': c.id}) }}" class="btn btn-edit"></a>
|
||||
<a href="{{ path('chill_person_household_composition_new', {'id': c.household.id, 'edit': c.id}) }}" class="btn btn-edit"></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_person_household_composition_delete', {'composition_id': c.id,
|
||||
@ -54,45 +54,17 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ form_start(form) }}
|
||||
|
||||
{{ form_widget(form) }}
|
||||
|
||||
<ul class="record_actions">
|
||||
<li class="cancel" style="margin-right: auto;">
|
||||
<a class="btn btn-cancel" href="{{ path('chill_person_household_composition_index', {'id': c.household.id}) }}">{{ 'Cancel'|trans }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<button type="submit" class="btn btn-create">{{ 'Save'|trans }}</button>
|
||||
</li>
|
||||
</ul>
|
||||
{{ form_end(form) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="collapseForm" class="{% if not isPosted %}collapse{% endif %}">
|
||||
{{ form_start(form) }}
|
||||
|
||||
{{ form_widget(form) }}
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<button type="submit" class="btn btn-create">{{ 'Save'|trans }}</button>
|
||||
</li>
|
||||
</ul>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
|
||||
{% if editId == -1 %}
|
||||
{% if is_granted('CHILL_PERSON_HOUSEHOLD_EDIT', household) %}
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li>
|
||||
<button class="btn btn-primary btn-create change-icon" type="button" data-bs-toggle="collapse" data-bs-target="#collapseForm" aria-expanded="false" aria-controls="collapseForm">
|
||||
{{ 'Create'|trans }}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_person_household_composition_new', {'id': household.id,}) }}"
|
||||
class="btn btn-new"
|
||||
title="{{ 'Create'|trans }}">{{ 'Create'|trans }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
@ -1,15 +1,25 @@
|
||||
{% extends "@ChillPerson/Person/layout.html.twig" %}
|
||||
|
||||
{% set activeRouteKey = 'chill_person_resource_list' %}
|
||||
|
||||
{% block title %}{{ 'Person resources'|trans|capitalize ~ ' ' ~ person|chill_entity_render_string }}{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ encore_entry_script_tags('page_person_resource_showhide_input') }}
|
||||
{{ encore_entry_script_tags('mod_pickentity_type') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ encore_entry_link_tags('page_person_resource_showhide_input') }}
|
||||
{{ encore_entry_link_tags('mod_pickentity_type') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block personcontent %}
|
||||
|
||||
<h1 style="margin-bottom: 2rem;">{{ 'Add a person resource'|trans }}</h1>
|
||||
|
||||
<div class="col-md col-xxl">
|
||||
<div id="collapseForm" class="{% if not form.vars.submitted %}collapse{% endif %}">
|
||||
<h3 style="margin-bottom: 2rem;">{{ 'Add a person resource'|trans }}</h3>
|
||||
{% include "@ChillPerson/PersonResource/form.html.twig" %}
|
||||
</div>
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li>
|
||||
<button class="btn btn-primary btn-create change-icon" type="button" data-bs-toggle="collapse" data-bs-target="#collapseForm" aria-expanded="false" aria-controls="collapseForm">
|
||||
{{ 'Add a person resource'|trans }}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
@ -85,8 +85,14 @@
|
||||
<p class="chill-no-data-statement">{{ 'There are no available resources'|trans }}</p>
|
||||
{% endif %}
|
||||
|
||||
<h1 style="margin-bottom: 2rem;">{{ 'Add a person resource'|trans }}</h1>
|
||||
|
||||
{% include "@ChillPerson/PersonResource/create.html.twig" %}
|
||||
{% if is_granted('CHILL_PERSON_UPDATE', person) %}
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_person_resource_new', {'person_id': person.id,}) }}"
|
||||
class="btn btn-new"
|
||||
title="{{ 'Create'|trans }}">{{ 'Create'|trans }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
@ -49,7 +49,12 @@
|
||||
<li>
|
||||
<i class="fa fa-li fa-home"></i>
|
||||
<span class="item-key">{{ "Address of"|trans}} </span>
|
||||
<span class="chill-entity entity-person badge-person">{{ a.hostPerson|chill_entity_render_box }}</span>
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
action: 'show', displayBadge: true,
|
||||
targetEntity: { name: 'person', id: a.hostPerson.id },
|
||||
buttonText: a.hostPerson|chill_entity_render_string,
|
||||
isDead: a.hostPerson.deathdate is not null
|
||||
} %}
|
||||
</li>
|
||||
<li>
|
||||
{% set address_date = date(a.startDate|date("m/d/Y")) %}
|
||||
@ -62,7 +67,12 @@
|
||||
<li>
|
||||
<i class="fa fa-li fa-home"></i>
|
||||
<span class="item-key">{{ "Address of"|trans}}</span>
|
||||
<span class="chill-entity entity-person badge-thirdparty">{{ a.hostThirdParty|chill_entity_render_box }}</span>
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
action: 'show', displayBadge: true,
|
||||
targetEntity: { name: 'thirdparty', id: a.hostThirdParty.id },
|
||||
buttonText: a.hostThirdParty|chill_entity_render_string,
|
||||
isDead: false,
|
||||
} %}
|
||||
</li>
|
||||
<li>
|
||||
{% if a.hostThirdParty.address is not null %}
|
||||
|
@ -1,5 +1,10 @@
|
||||
{%- import "@ChillDocStore/Macro/macro.html.twig" as m -%}
|
||||
|
||||
<div class="flex-table accompanying_course_work-list">
|
||||
<div class="item-bloc evaluation-item bg-chill-llight-gray">
|
||||
<div class="item-row mb-2">
|
||||
<h1>{{ doc.title }}</h1>
|
||||
</div>
|
||||
<div class="item-row mb-2">
|
||||
<h2 class="badge-title">
|
||||
<span class="title_label"></span>
|
||||
@ -20,6 +25,24 @@
|
||||
</span>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="item-row mb-2">
|
||||
<div class="item-col" style="width: 17%;">
|
||||
<h4 class="title_label">
|
||||
{{ 'Participants'|trans }}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="item-col list">
|
||||
{% for p in evaluation.accompanyingPeriodWork.persons %}
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
targetEntity: { name: 'person', id: p.id },
|
||||
action: 'show',
|
||||
displayBadge: true,
|
||||
buttonText: p|chill_entity_render_string,
|
||||
isDead: p.deathdate is not null
|
||||
} %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-row column">
|
||||
<table class="obj-res-eval my-3" style="font-size: 110% !important;">
|
||||
<thead>
|
||||
@ -92,12 +115,19 @@
|
||||
</div>
|
||||
|
||||
{% if display_action is defined and display_action == true %}
|
||||
{# TODO add acl #}
|
||||
{% if is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_UPDATE', evaluation.accompanyingPeriodWork) %}
|
||||
<ul class="record_actions">
|
||||
<li>{{ m.download_button(doc.storedObject, doc.title) }}</li>
|
||||
{% if chill_document_is_editable(doc.storedObject) %}
|
||||
<li>
|
||||
{{ doc.storedObject|chill_document_edit_button }}
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a class="btn btn-show" href="{{ path('chill_person_accompanying_period_work_edit', {'id': evaluation.accompanyingPeriodWork.id}) }}">
|
||||
{{ 'Show'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
@ -14,6 +14,7 @@ namespace Chill\PersonBundle\Serializer\Normalizer;
|
||||
use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
|
||||
use Chill\MainBundle\Workflow\Helper\MetadataExtractor;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
|
||||
@ -46,7 +47,10 @@ class AccompanyingPeriodWorkEvaluationNormalizer implements ContextAwareNormaliz
|
||||
{
|
||||
$initial = $this->normalizer->normalize($object, $format, array_merge(
|
||||
$context,
|
||||
[self::IGNORE_EVALUATION => spl_object_hash($object)]
|
||||
[self::IGNORE_EVALUATION => spl_object_hash($object)],
|
||||
[AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => static function ($object, $format, $context) {
|
||||
return $object->getId();
|
||||
}]
|
||||
));
|
||||
|
||||
// due to bug: https://api-platform.com/docs/core/serialization/#collection-relation
|
||||
|
@ -16,6 +16,7 @@ use Chill\PersonBundle\Entity\Household\HouseholdMember;
|
||||
use Chill\PersonBundle\Entity\Household\Position;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
@ -25,17 +26,24 @@ use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
*/
|
||||
final class HouseholdNormalizerTest extends KernelTestCase
|
||||
{
|
||||
private EntityManagerInterface $entityManager;
|
||||
|
||||
private ?NormalizerInterface $normalizer;
|
||||
|
||||
private array $toDelete;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
self::bootKernel();
|
||||
$this->normalizer = self::$container->get(NormalizerInterface::class);
|
||||
$this->entityManager = self::$container->get(EntityManagerInterface::class);
|
||||
}
|
||||
|
||||
public function testNormalizationRecursive()
|
||||
{
|
||||
$person = new Person();
|
||||
$person->setFirstName('ok')->setLastName('ok');
|
||||
$this->entityManager->persist($person);
|
||||
$member = new HouseholdMember();
|
||||
$household = new Household();
|
||||
$position = (new Position())
|
||||
@ -44,7 +52,8 @@ final class HouseholdNormalizerTest extends KernelTestCase
|
||||
|
||||
$member->setPerson($person)
|
||||
->setStartDate(new DateTimeImmutable('1 year ago'))
|
||||
->setEndDate(new DateTimeImmutable('1 month ago'));
|
||||
->setEndDate(new DateTimeImmutable('1 month ago'))
|
||||
->setPosition($position);
|
||||
|
||||
$household->addMember($member);
|
||||
|
||||
|
@ -61,8 +61,8 @@ class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityW
|
||||
return $this->translator->trans(
|
||||
'workflow.Doc for evaluation (n°%eval%)',
|
||||
['%eval%' => $entityWorkflow->getRelatedEntityId()]
|
||||
) . ' - ' . $this->translatableStringHelper->localize($doc->getAccompanyingPeriodWorkEvaluation()
|
||||
->getEvaluation()->getTitle());
|
||||
) . ' (' . $this->translatableStringHelper->localize($doc->getAccompanyingPeriodWorkEvaluation()
|
||||
->getEvaluation()->getTitle()) . ') ' . $doc->getTitle();
|
||||
}
|
||||
|
||||
public function getRelatedEntity(EntityWorkflow $entityWorkflow): ?AccompanyingPeriodWorkEvaluationDocument
|
||||
|
@ -59,6 +59,10 @@ chill_person_resource_list:
|
||||
path: /{_locale}/person/{person_id}/resources/list
|
||||
controller: Chill\PersonBundle\Controller\PersonResourceController::listAction
|
||||
|
||||
chill_person_resource_new:
|
||||
path: /{_locale}/person/{person_id}/resources/new
|
||||
controller: Chill\PersonBundle\Controller\PersonResourceController::newAction
|
||||
|
||||
chill_person_resource_edit:
|
||||
path: /{_locale}/person/{person_id}/resources/{resource_id}/edit
|
||||
controller: Chill\PersonBundle\Controller\PersonResourceController::editAction
|
||||
@ -91,11 +95,6 @@ chill_person_address_update:
|
||||
chill_person_timeline:
|
||||
path: /{_locale}/person/{person_id}/timeline
|
||||
controller: Chill\PersonBundle\Controller\TimelinePersonController::personAction
|
||||
options:
|
||||
menus:
|
||||
person:
|
||||
order: 60
|
||||
label: Timeline
|
||||
|
||||
chill_person_admin:
|
||||
path: "/{_locale}/admin/person"
|
||||
|
@ -41,6 +41,11 @@ services:
|
||||
autowire: true
|
||||
tags: ['controller.service_arguments']
|
||||
|
||||
Chill\PersonBundle\Controller\ReassignAccompanyingPeriodController:
|
||||
autoconfigure: true
|
||||
autowire: true
|
||||
tags: ['controller.service_arguments']
|
||||
|
||||
Chill\PersonBundle\Controller\PersonApiController:
|
||||
arguments:
|
||||
$authorizationHelper: '@Chill\MainBundle\Security\Authorization\AuthorizationHelper'
|
||||
|
@ -12,3 +12,13 @@ services:
|
||||
event: 'prePersist'
|
||||
entity: 'Chill\PersonBundle\Entity\PersonAltName'
|
||||
method: 'prePersistAltName'
|
||||
|
||||
Chill\PersonBundle\EventListener\AccompanyingPeriodWorkEventListener:
|
||||
autoconfigure: true
|
||||
autowire: true
|
||||
tags:
|
||||
-
|
||||
name: 'doctrine.orm.entity_listener'
|
||||
event: 'prePersist'
|
||||
entity: 'Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork'
|
||||
method: 'prePersistAccompanyingPeriodWork'
|
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Person;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Add referrers to AccompanyingPeriodWork.
|
||||
*/
|
||||
final class Version20220310063629 extends AbstractMigration
|
||||
{
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('DROP TABLE chill_person_accompanying_period_work_referrer');
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add referrers to AccompanyingPeriodWork';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('CREATE TABLE chill_person_accompanying_period_work_referrer (accompanyingperiodwork_id INT NOT NULL, user_id INT NOT NULL, PRIMARY KEY(accompanyingperiodwork_id, user_id))');
|
||||
$this->addSql('CREATE INDEX IDX_3619F5EBB99F6060 ON chill_person_accompanying_period_work_referrer (accompanyingperiodwork_id)');
|
||||
$this->addSql('CREATE INDEX IDX_3619F5EBA76ED395 ON chill_person_accompanying_period_work_referrer (user_id)');
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD CONSTRAINT FK_3619F5EBB99F6060 FOREIGN KEY (accompanyingperiodwork_id) REFERENCES chill_person_accompanying_period_work (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_referrer ADD CONSTRAINT FK_3619F5EBA76ED395 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('INSERT INTO chill_person_accompanying_period_work_referrer (accompanyingperiodwork_id, user_id)
|
||||
SELECT id, createdby_id FROM postgres.public.chill_person_accompanying_period_work');
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Person;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Change constraint on pinnedComment in Accompanying period.
|
||||
*/
|
||||
final class Version20220310124318 extends AbstractMigration
|
||||
{
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period DROP CONSTRAINT fk_e260a868b0804e90');
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period ADD CONSTRAINT fk_e260a868b0804e90 FOREIGN KEY (pinnedcomment_id) REFERENCES chill_person_accompanying_period_comment (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Change constraint on pinnedComment in Accompanying period';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period DROP CONSTRAINT FK_E260A868B0804E90');
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period ADD CONSTRAINT FK_E260A868B0804E90 FOREIGN KEY (pinnedComment_id) REFERENCES chill_person_accompanying_period_comment (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
}
|
||||
}
|
@ -194,6 +194,7 @@ No accompanying user: Aucun accompagnant
|
||||
No data given: Pas d'information
|
||||
Participants: Personnes impliquées
|
||||
Create an accompanying course: Créer un parcours
|
||||
Accompanying courses of users: Parcours des utilisateurs
|
||||
This accompanying course is still a draft: Ce parcours est encore à l'état brouillon.
|
||||
Associated peoples: Usagers concernés
|
||||
Resources: Interlocuteurs privilégiés
|
||||
@ -213,6 +214,7 @@ No requestor: Pas de demandeur
|
||||
No resources: "Pas d'interlocuteurs privilégiés"
|
||||
Persons associated: Usagers concernés
|
||||
Referrer: Référent
|
||||
Referrers: Référents
|
||||
Some peoples does not belong to any household currently. Add them to an household soon: Certaines personnes n'appartiennent à aucun ménage actuellement. Renseignez leur ménage dès que possible.
|
||||
Add to household now: Ajouter à un ménage
|
||||
Any resource for this accompanying course: Aucun interlocuteur privilégié pour ce parcours
|
||||
@ -566,6 +568,7 @@ household_composition:
|
||||
Currently no composition: Aucune composition familiale renseignée.
|
||||
Add a composition: Ajouter une composition familiale
|
||||
Update composition: Modifier la composition familiale
|
||||
Create: Créér une nouvelle composition familiale
|
||||
|
||||
# docgen
|
||||
Linked evaluations: Évaluations associées
|
||||
@ -576,3 +579,8 @@ My accompanying periods in draft: Mes parcours brouillons
|
||||
|
||||
workflow:
|
||||
Doc for evaluation (n°%eval%): Document de l'évaluation n°%eval%
|
||||
|
||||
period_by_user_list:
|
||||
Period by user: Parcours d'accompagnement par utilisateur
|
||||
Pick a user: Choisissez un utilisateur pour obtenir la liste de ses parcours
|
||||
Any course or no authorization to see them: Aucun parcours pour ce référent, ou aucun droit pour visualiser les parcours de ce référent.
|
||||
|
@ -60,7 +60,7 @@
|
||||
{% if types|length > 0 %}
|
||||
{{ types|join(', ') }}
|
||||
{% else %}
|
||||
<p class="chill-no-data-statement">{{ 'thirdParty.Any categories' }}</p>
|
||||
<p class="chill-no-data-statement">{{ 'thirdparty.no_categories' }}</p>
|
||||
{% endif %}
|
||||
</dd>
|
||||
|
||||
@ -110,7 +110,7 @@
|
||||
<dt>{{ 'Contacts'|trans }}</dt>
|
||||
<dd>
|
||||
{% if thirdParty.activeChildren|length == 0 %}
|
||||
<p class="chill-no-data-statement">{{ 'Any contacts associated'|trans }}</p>
|
||||
<p class="chill-no-data-statement">{{ 'No contacts associated'|trans }}</p>
|
||||
{% else %}
|
||||
<div class="flex-table">
|
||||
{% for tp in thirdParty.activeChildren %}
|
||||
|
@ -63,13 +63,13 @@ Show thirdparty: Voir le tiers
|
||||
Add a contact: Ajouter un contact
|
||||
Remove a contact: Supprimer
|
||||
Contacts: Contacts
|
||||
Any contact: Aucun contact
|
||||
No contacts associated: Aucun contact
|
||||
|
||||
No nameCompany given: Aucune raison sociale renseignée
|
||||
No acronym given: Aucun sigle renseigné
|
||||
No phone given: Aucun téléphone renseigné
|
||||
No email given: Aucune adresse courriel renseignée
|
||||
thirdparty.Any categories: Aucune catégorie
|
||||
thirdparty.no_categories: Aucune catégorie
|
||||
|
||||
The party is visible in those centers: Le tiers est visible dans ces centres
|
||||
The party is not visible in any center: Le tiers n'est associé à aucun centre
|
||||
|
@ -14,7 +14,7 @@ window.addEventListener('DOMContentLoaded', function(e) {
|
||||
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');
|
||||
office_frame.setAttribute('sandbox', 'allow-downloads 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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user