mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-16 19:54:58 +00:00
Compare commits
44 Commits
issue357_f
...
issue385_c
Author | SHA1 | Date | |
---|---|---|---|
6bb39bc4e0 | |||
45f3bb00d6 | |||
2b9f0e5177 | |||
fcf2ae364f | |||
c736c2b5bb | |||
b3aca957ff | |||
03bd4d1942 | |||
409cd40460 | |||
2811e61439 | |||
2ff34688bb | |||
8133dd7385 | |||
|
256dab3739 | ||
532a751509 | |||
|
f0a7565302 | ||
64c4f1ece2 | |||
|
ad983d80d2 | ||
21d5f974eb | |||
59b2b07a21 | |||
eaf9f72fdd | |||
169442decc | |||
cf8e25e823 | |||
96b1f31665 | |||
2ad798c0bf | |||
7e932e838f | |||
41354097f3 | |||
9a3f35703b | |||
5423de3bd9 | |||
5e3d421b56 | |||
71ca033b08 | |||
|
2c774e814e | ||
3034ba411f | |||
ce6e51df87 | |||
|
6843b4cb2a | ||
dcbce270ad | |||
3f5a6c6b15 | |||
d806551477 | |||
120ce40dbe | |||
22022e5143 | |||
20fcaa5428 | |||
819017112d | |||
d7d7fb5693 | |||
650e0d79be | |||
0afccd12a9 | |||
7abe3e1b2d |
24
CHANGELOG.md
24
CHANGELOG.md
@@ -11,11 +11,31 @@ and this project adheres to
|
||||
## Unreleased
|
||||
|
||||
<!-- write down unreleased development here -->
|
||||
* vuejs: add validation on required fields for AddPerson, Address and Location components
|
||||
* vuejs: treat 422 validation errors in locations and AddPerson components
|
||||
* [person] name suggestions within create person form when person is created departing from a search input (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/377)
|
||||
* [parcours]: bug fix when comment is pinned all other comments remain in the collection (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/385)
|
||||
|
||||
## Test releases
|
||||
|
||||
### test release 2022-01-19
|
||||
* vuejs: add dead information on all on-the-fly person render boxes, in vis graph and other templates (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/271)
|
||||
* [thirdparty] fix bug in 3rd party view: types was replaced by thirdPartyTypes
|
||||
* [main] location form type: fix unmapped address field (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/246)
|
||||
* [activity] fix wrong import of js assets for adding and viewing documents in activity (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/83 & https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/176)
|
||||
* [person]: space added between deathdate and age in twig renderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/380)
|
||||
|
||||
### test release 2022-01-17
|
||||
|
||||
* [main] Add editableByUser field to locationType entity, adapt the admin template and add this condition in the location-type endpoint (see https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/297)
|
||||
* [main] Add mainLocation field to User entity and add it in user form type
|
||||
* rewrite page which allow to select activity
|
||||
* [main] Add mainLocation field to User entity and add it in user form type
|
||||
* [course list in person context] show full username/label for ref
|
||||
* [accompanying period work] remove the possibility to generate document from an accompanying period work
|
||||
|
||||
## Test releases
|
||||
* vuejs: add validation on required fields for AddPerson, Address and Location components
|
||||
* vuejs: treat 422 validation errors in locations and AddPerson components
|
||||
|
||||
### test release 2022-01-12
|
||||
|
||||
* fix thirdparty normalizer on telephone field: https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/322
|
||||
|
@@ -307,6 +307,7 @@ class ActivityType extends AbstractType
|
||||
'allow_add' => true,
|
||||
'button_add_label' => 'activity.Insert a document',
|
||||
'button_remove_label' => 'activity.Remove a document',
|
||||
'empty_collection_explain' => 'No documents',
|
||||
]);
|
||||
}
|
||||
|
||||
|
@@ -9,8 +9,9 @@ div.new-activity-select-type {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
justify-content: flex-start;
|
||||
gap: 12px;
|
||||
margin-bottom: 30px;
|
||||
|
||||
div.bloc {
|
||||
width: 200px;
|
||||
@@ -27,26 +28,26 @@ div.new-activity-select-type {
|
||||
// precise dashboard specific details
|
||||
|
||||
p.date-label {
|
||||
display: inline-block;
|
||||
margin: 0 0.5em 0 0;
|
||||
font-weight: 700;
|
||||
font-size: 18pt;
|
||||
display: inline-block;
|
||||
margin: 0 0.5em 0 0;
|
||||
font-weight: 700;
|
||||
font-size: 18pt;
|
||||
}
|
||||
div.dashboard,
|
||||
h2.badge-title {
|
||||
ul.list-content {
|
||||
font-size: 70%;
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
margin: 0;
|
||||
li {
|
||||
margin-bottom: 0.2em;
|
||||
// exception: change bg color for action badges above dashboard
|
||||
.bg-light {
|
||||
background-color: $chill-light-gray !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
ul.list-content {
|
||||
font-size: 70%;
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
margin: 0;
|
||||
li {
|
||||
margin-bottom: 0.2em;
|
||||
// exception: change bg color for action badges above dashboard
|
||||
.bg-light {
|
||||
background-color: $chill-light-gray !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// ACTIVITY SHOW AND FORM PAGES
|
||||
|
@@ -8,6 +8,7 @@
|
||||
action: 'show', displayBadge: true,
|
||||
targetEntity: { name: type, id: entity.id },
|
||||
buttonText: entity|chill_entity_render_string,
|
||||
isDead: entity.deathdate is not null,
|
||||
parent: parent
|
||||
} %}
|
||||
{% endmacro %}
|
||||
|
@@ -15,7 +15,7 @@
|
||||
|
||||
{% block js %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_link_tags('mod_async_upload') }}
|
||||
{{ encore_entry_script_tags('mod_async_upload') }}
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('DOMContentLoaded', function (e) {
|
||||
chill.displayAlertWhenLeavingModifiedForm('form[name="{{ edit_form.vars.form.vars.name }}"]',
|
||||
|
@@ -30,7 +30,7 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ encore_entry_link_tags('mod_async_upload') }}
|
||||
{{ encore_entry_script_tags('mod_async_upload') }}
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('DOMContentLoaded', function (e) {
|
||||
chill.displayAlertWhenLeavingModifiedForm('form[name="{{ edit_form.vars.form.vars.name }}"]',
|
||||
|
@@ -14,7 +14,7 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ encore_entry_link_tags('mod_async_upload') }}
|
||||
{{ encore_entry_script_tags('mod_async_upload') }}
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('DOMContentLoaded', function (e) {
|
||||
chill.displayAlertWhenLeavingUnsubmittedForm('form[name="{{ form.vars.form.vars.name }}"]',
|
||||
|
@@ -25,7 +25,7 @@
|
||||
'activityData': activityData
|
||||
}) }}">
|
||||
|
||||
<div class="bloc btn btn-primary btn-lg btn-block">
|
||||
<div class="btn btn-primary">
|
||||
{{ activityType.name|localize_translatable_string }}
|
||||
</div>
|
||||
</a>
|
||||
|
@@ -7,11 +7,13 @@
|
||||
{% block js %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_script_tags('mod_notification_toggle_read_status') }}
|
||||
{{ encore_entry_script_tags('mod_async_upload') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_link_tags('mod_notification_toggle_read_status') }}
|
||||
{{ encore_entry_link_tags('mod_async_upload') }}
|
||||
{% endblock %}
|
||||
|
||||
{% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %}
|
||||
|
@@ -7,11 +7,13 @@
|
||||
{% block js %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_script_tags('mod_notification_toggle_read_status') }}
|
||||
{{ encore_entry_link_tags('mod_async_upload') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_link_tags('mod_notification_toggle_read_status') }}
|
||||
{{ encore_entry_link_tags('mod_async_upload') }}
|
||||
{% endblock %}
|
||||
|
||||
{% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %}
|
||||
|
@@ -76,7 +76,7 @@ activity:
|
||||
Insert a document: Insérer un document
|
||||
Remove a document: Supprimer le document
|
||||
comment: Commentaire
|
||||
|
||||
No documents: Pas de documents
|
||||
|
||||
#timeline
|
||||
'%user% has done an %activity_type%': '%user% a effectué une activité de type "%activity_type%"'
|
||||
|
@@ -24,6 +24,7 @@ class LocationTypeApiController extends ApiController
|
||||
$query->andWhere(
|
||||
$query->expr()->andX(
|
||||
$query->expr()->eq('e.availableForUsers', "'TRUE'"),
|
||||
$query->expr()->eq('e.editableByUsers', "'TRUE'"),
|
||||
$query->expr()->eq('e.active', "'TRUE'"),
|
||||
)
|
||||
);
|
||||
|
@@ -67,6 +67,12 @@ class LocationType
|
||||
*/
|
||||
private ?string $defaultFor = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="boolean")
|
||||
* @Serializer\Groups({"read"})
|
||||
*/
|
||||
private bool $editableByUsers = true;
|
||||
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
@@ -107,6 +113,11 @@ class LocationType
|
||||
return $this->defaultFor;
|
||||
}
|
||||
|
||||
public function getEditableByUsers(): ?bool
|
||||
{
|
||||
return $this->editableByUsers;
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
@@ -152,6 +163,13 @@ class LocationType
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setEditableByUsers(bool $editableByUsers): self
|
||||
{
|
||||
$this->editableByUsers = $editableByUsers;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setTitle(array $title): self
|
||||
{
|
||||
$this->title = $title;
|
||||
|
@@ -17,6 +17,7 @@ use DateTimeInterface;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
@@ -32,6 +33,7 @@ class Notification implements TrackUpdateInterface
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity=User::class)
|
||||
* @ORM\JoinTable(name="chill_main_notification_addresses_user")
|
||||
* @Assert\Count(min="1", minMessage="notification.At least one addressee")
|
||||
*/
|
||||
private Collection $addressees;
|
||||
|
||||
@@ -80,6 +82,7 @@ class Notification implements TrackUpdateInterface
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text", options={"default": ""})
|
||||
* @Assert\NotBlank(message="notification.Title must be defined")
|
||||
*/
|
||||
private string $title = '';
|
||||
|
||||
@@ -286,9 +289,9 @@ class Notification implements TrackUpdateInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setMessage(string $message): self
|
||||
public function setMessage(?string $message): self
|
||||
{
|
||||
$this->message = $message;
|
||||
$this->message = (string) $message;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -314,9 +317,9 @@ class Notification implements TrackUpdateInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setTitle(string $title): Notification
|
||||
public function setTitle(?string $title): Notification
|
||||
{
|
||||
$this->title = $title;
|
||||
$this->title = (string) $title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@@ -97,6 +97,11 @@ class User implements AdvancedUserInterface
|
||||
*/
|
||||
private ?Center $mainCenter = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=Location::class)
|
||||
*/
|
||||
private ?Location $mainLocation = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=Scope::class)
|
||||
*/
|
||||
@@ -228,6 +233,11 @@ class User implements AdvancedUserInterface
|
||||
return $this->mainCenter;
|
||||
}
|
||||
|
||||
public function getMainLocation(): ?Location
|
||||
{
|
||||
return $this->mainLocation;
|
||||
}
|
||||
|
||||
public function getMainScope(): ?Scope
|
||||
{
|
||||
return $this->mainScope;
|
||||
@@ -405,6 +415,13 @@ class User implements AdvancedUserInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setMainLocation(?Location $mainLocation): User
|
||||
{
|
||||
$this->mainLocation = $mainLocation;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setMainScope(?Scope $mainScope): User
|
||||
{
|
||||
$this->mainScope = $mainScope;
|
||||
|
@@ -54,7 +54,6 @@ final class LocationFormType extends AbstractType
|
||||
'label' => 'Address',
|
||||
'use_valid_from' => false,
|
||||
'use_valid_to' => false,
|
||||
'mapped' => false,
|
||||
])
|
||||
->add(
|
||||
'active',
|
||||
|
@@ -39,6 +39,17 @@ final class LocationTypeType extends AbstractType
|
||||
'expanded' => true,
|
||||
]
|
||||
)
|
||||
->add(
|
||||
'editableByUsers',
|
||||
ChoiceType::class,
|
||||
[
|
||||
'choices' => [
|
||||
'Yes' => true,
|
||||
'No' => false,
|
||||
],
|
||||
'expanded' => true,
|
||||
]
|
||||
)
|
||||
->add(
|
||||
'addressRequired',
|
||||
ChoiceType::class,
|
||||
|
@@ -12,6 +12,7 @@ declare(strict_types=1);
|
||||
namespace Chill\MainBundle\Form;
|
||||
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Entity\Location;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Entity\UserJob;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
@@ -75,6 +76,22 @@ class UserType extends AbstractType
|
||||
'choice_label' => function (UserJob $c) {
|
||||
return $this->translatableStringHelper->localize($c->getLabel());
|
||||
},
|
||||
])
|
||||
->add('mainLocation', EntityType::class, [
|
||||
'label' => 'Main location',
|
||||
'required' => false,
|
||||
'placeholder' => 'choose a location',
|
||||
'class' => Location::class,
|
||||
'choice_label' => function (Location $l) {
|
||||
return $this->translatableStringHelper->localize($l->getLocationType()->getTitle()) . ' - ' . $l->getName();
|
||||
},
|
||||
'query_builder' => static function (EntityRepository $er) {
|
||||
$qb = $er->createQueryBuilder('l');
|
||||
$qb->orderBy('l.locationType');
|
||||
$qb->where('l.availableForUsers = TRUE');
|
||||
|
||||
return $qb;
|
||||
},
|
||||
]);
|
||||
|
||||
if ($options['is_creation']) {
|
||||
|
@@ -240,6 +240,10 @@ table.table-bordered {
|
||||
color: $gray-800;
|
||||
font-size: 90%;
|
||||
|
||||
p {
|
||||
margin-bottom: 0.75rem !important;
|
||||
}
|
||||
|
||||
// test a bottom right decoration (to be confirmed)
|
||||
&.test {
|
||||
position: relative;
|
||||
@@ -318,6 +322,7 @@ dl.definition-inline {
|
||||
.custom_field_no_data,
|
||||
.chill-no-data-statement {
|
||||
font-style: italic;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
/// flash
|
||||
|
@@ -22,6 +22,7 @@ $chill-theme-buttons: (
|
||||
"choose": $gray-300,
|
||||
"notify": $gray-300,
|
||||
"unlink": $chill-red,
|
||||
"tpchild": $chill-pink,
|
||||
);
|
||||
|
||||
@each $button, $color in $chill-theme-buttons {
|
||||
@@ -50,6 +51,7 @@ $chill-theme-buttons: (
|
||||
&.btn-unlink,
|
||||
&.btn-action,
|
||||
&.btn-edit,
|
||||
&.btn-tpchild,
|
||||
&.btn-update {
|
||||
&, &:hover {
|
||||
color: $light;
|
||||
@@ -75,6 +77,7 @@ $chill-theme-buttons: (
|
||||
&.btn-remove::before,
|
||||
&.btn-choose::before,
|
||||
&.btn-notify::before,
|
||||
&.btn-tpchild::before,
|
||||
&.btn-cancel::before {
|
||||
font: normal normal normal 14px/1 ForkAwesome;
|
||||
margin-right: 0.5em;
|
||||
@@ -101,6 +104,7 @@ $chill-theme-buttons: (
|
||||
&.btn-choose::before { content: "\f00c"; } // fa-check // f046 fa-check-square-o
|
||||
&.btn-unlink::before { content: "\f127"; } // fa-chain-broken
|
||||
&.btn-notify::before { content: "\f1d8"; } // fa-paper-plane
|
||||
&.btn-tpchild::before { content: "\f007"; } // fa-user
|
||||
}
|
||||
|
||||
|
||||
|
@@ -36,27 +36,45 @@ div.notification {
|
||||
div.notification-list,
|
||||
div.notification-show {
|
||||
div.item-bloc {
|
||||
div.item-row.header {
|
||||
|
||||
div.item-col {
|
||||
&:first-child {
|
||||
flex-grow: 1;
|
||||
div.item-row {
|
||||
&.notification-header {
|
||||
div.item-col {
|
||||
&:first-child {
|
||||
flex-grow: 1;
|
||||
|
||||
}
|
||||
&:last-child {
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
&:last-child {
|
||||
flex-grow: 0;
|
||||
ul.small_in_title {
|
||||
list-style-type: circle;
|
||||
li {
|
||||
span.item-key {
|
||||
display: inline-block;
|
||||
width: 3em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul.small_in_title {
|
||||
list-style-type: circle;
|
||||
li {
|
||||
span.item-key {
|
||||
display: inline-block;
|
||||
width: 3em;
|
||||
}
|
||||
div.notification-content {
|
||||
margin: 1.5rem;
|
||||
p {
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Override bootstrap accordion
|
||||
div#notification-fold {
|
||||
.accordion-button {
|
||||
padding: 0;
|
||||
background-color: unset;
|
||||
&:not(.collapsed) {
|
||||
background-color: unset;
|
||||
box-shadow: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ const i18n = _createI18n({});
|
||||
|
||||
window.addEventListener('DOMContentLoaded', function (e) {
|
||||
document.querySelectorAll('.notification_toggle_read_status')
|
||||
.forEach(function (el) {
|
||||
.forEach(function (el, i) {
|
||||
createApp({
|
||||
template: '<notification-read-toggle ' +
|
||||
':notificationId="notificationId" ' +
|
||||
@@ -26,13 +26,25 @@ window.addEventListener('DOMContentLoaded', function (e) {
|
||||
buttonNoText: 'false' === el.dataset.buttonText,
|
||||
showUrl: el.dataset.showButtonUrl,
|
||||
isRead: 1 === +el.dataset.notificationCurrentIsRead,
|
||||
container: el.dataset.container
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getContainer() {
|
||||
return document.querySelectorAll('div.' + this.container);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onMarkRead() {
|
||||
if (typeof this.getContainer[i] !== 'undefined') {
|
||||
this.getContainer[i].classList.replace('read', 'unread');
|
||||
} else { throw 'data-container attribute is missing' }
|
||||
this.isRead = false;
|
||||
},
|
||||
onMarkUnread() {
|
||||
if (typeof this.getContainer[i] !== 'undefined') {
|
||||
this.getContainer[i].classList.replace('unread', 'read');
|
||||
} else { throw 'data-container attribute is missing' }
|
||||
this.isRead = true;
|
||||
},
|
||||
}
|
||||
@@ -40,4 +52,4 @@ window.addEventListener('DOMContentLoaded', function (e) {
|
||||
.use(i18n)
|
||||
.mount(el);
|
||||
});
|
||||
})
|
||||
});
|
||||
|
@@ -5,6 +5,7 @@
|
||||
:action="context.action"
|
||||
:buttonText="options.buttonText"
|
||||
:displayBadge="options.displayBadge === 'true'"
|
||||
:isDead="options.isDead"
|
||||
:parent="options.parent"
|
||||
@saveFormOnTheFly="saveFormOnTheFly">
|
||||
</on-the-fly>
|
||||
|
@@ -2,14 +2,14 @@
|
||||
|
||||
<a v-if="isDisplayBadge" @click="openModal">
|
||||
<span class="chill-entity" :class="badgeType">
|
||||
{{ buttonText }}
|
||||
{{ buttonText }}<span v-if="isDead"> (‡)</span>
|
||||
</span>
|
||||
</a>
|
||||
<a v-else class="btn btn-sm" target="_blank"
|
||||
:class="classAction"
|
||||
:title="$t(titleAction)"
|
||||
@click="openModal">
|
||||
{{ buttonText }}
|
||||
{{ buttonText }}<span v-if="isDead"> (‡)</span>
|
||||
</a>
|
||||
|
||||
<teleport to="body">
|
||||
@@ -90,7 +90,7 @@ export default {
|
||||
OnTheFlyThirdparty,
|
||||
OnTheFlyCreate
|
||||
},
|
||||
props: ['type', 'id', 'action', 'buttonText', 'displayBadge', 'parent', 'canCloseModal'],
|
||||
props: ['type', 'id', 'action', 'buttonText', 'displayBadge', 'isDead', 'parent', 'canCloseModal'],
|
||||
emits: ['saveFormOnTheFly'],
|
||||
data() {
|
||||
return {
|
||||
|
@@ -22,7 +22,8 @@ containers.forEach((container) => {
|
||||
options: {
|
||||
buttonText: container.dataset.buttonText || null,
|
||||
displayBadge: container.dataset.displayBadge || false,
|
||||
parent: JSON.parse(container.dataset.parent) || null,
|
||||
isDead: container.dataset.isDead || false,
|
||||
parent: container.dataset.parent ? JSON.parse(container.dataset.parent) : null,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,4 +34,5 @@ containers.forEach((container) => {
|
||||
.mount(container);
|
||||
|
||||
//console.log('container dataset', container.dataset);
|
||||
//console.log('data-parent', container.dataset.parent);
|
||||
});
|
||||
|
@@ -34,7 +34,7 @@
|
||||
:href="showUrl"
|
||||
:title="$t('action.show')"
|
||||
>
|
||||
<i class="fa fa-sm fa-eye"></i>
|
||||
<i class="fa fa-sm fa-comment-o"></i>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
@@ -23,7 +23,7 @@
|
||||
<td>{{ entity.email }}</td>
|
||||
<td>
|
||||
{% if entity.address is not null %}
|
||||
{{ entity.address.street}}, {{ entity.address.streetnumber }}
|
||||
{{ entity.address| chill_entity_render_box }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td style="text-align:center;">
|
||||
|
@@ -8,6 +8,7 @@
|
||||
<tr>
|
||||
<th>{{ 'Title'|trans }}</th>
|
||||
<th>{{ 'Available for users'|trans }}</th>
|
||||
<th>{{ 'Editable by users'|trans }}</th>
|
||||
<th>{{ 'Address required'|trans }}</th>
|
||||
<th>{{ 'Contact data'|trans }}</th>
|
||||
<th>{{ 'Active'|trans }}</th>
|
||||
@@ -25,6 +26,13 @@
|
||||
<i class="fa fa-square-o"></i>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td style="text-align:center;">
|
||||
{%- if entity.editableByUsers -%}
|
||||
<i class="fa fa-check-square-o"></i>
|
||||
{%- else -%}
|
||||
<i class="fa fa-square-o"></i>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td>{{ entity.addressRequired|trans }}</td>
|
||||
<td>{{ entity.contactData|trans }}</td>
|
||||
<td style="text-align:center;">
|
||||
|
@@ -1,39 +1,41 @@
|
||||
<div class="item-bloc {% if not notification.isReadBy(app.user) %}unread{% else %}read{% endif %}">
|
||||
{% macro title(c) %}
|
||||
<div class="item-row title">
|
||||
<h2 class="notification-title">
|
||||
<a href="{{ chill_path_add_return_path('chill_main_notification_show', {'id': notification.id}) }}">
|
||||
{{ notification.title }}
|
||||
<a href="{{ chill_path_add_return_path('chill_main_notification_show', {'id': c.notification.id}) }}">
|
||||
{{ 'notification.object_prefix'|trans ~ c.notification.title }}
|
||||
</a>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="item-row mt-2 header">
|
||||
{% endmacro %}
|
||||
|
||||
{% macro header(c) %}
|
||||
<div class="item-row notification-header mt-2">
|
||||
<div class="item-col">
|
||||
<ul class="small_in_title">
|
||||
{% if step is not defined or step == 'inbox' %}
|
||||
{% if c.step is not defined or c.step == 'inbox' %}
|
||||
<li class="notification-from">
|
||||
<span class="item-key">
|
||||
<abbr title="{{ 'notification.received_from'|trans }}">
|
||||
{{ 'notification.from'|trans }} :
|
||||
</abbr>
|
||||
</span>
|
||||
{% if not notification.isSystem %}
|
||||
{% if not c.notification.isSystem %}
|
||||
<span class="badge-user">
|
||||
{{ notification.sender|chill_entity_render_string }}
|
||||
</span>
|
||||
{{ c.notification.sender|chill_entity_render_string }}
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="badge-user system">{{ 'notification.is_system'|trans }}</span>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if notification.addressees|length > 0 %}
|
||||
{% if c.notification.addressees|length > 0 %}
|
||||
<li class="notification-to">
|
||||
<span class="item-key">
|
||||
<abbr title="{{ 'notification.sent_to'|trans }}">
|
||||
{{ 'notification.to'|trans }} :
|
||||
</abbr>
|
||||
</span>
|
||||
{% for a in notification.addressees %}
|
||||
{% for a in c.notification.addressees %}
|
||||
<span class="badge-user">
|
||||
{{ a|chill_entity_render_string }}
|
||||
</span>
|
||||
@@ -42,47 +44,76 @@
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="item-col">
|
||||
{{ notification.date|format_datetime('long', 'short') }}
|
||||
{{ c.notification.date|format_datetime('long', 'short') }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro content(c) %}
|
||||
<div class="item-row separator">
|
||||
<div class="mx-3 flex-grow-1">
|
||||
{% include data.template with data.template_data %}
|
||||
{% include c.data.template with c.data.template_data %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-row row">
|
||||
<div>
|
||||
<blockquote class="chill-user-quote">
|
||||
{{ notification.message|u.truncate(250, '…', false)|chill_markdown_to_html }}
|
||||
</blockquote>
|
||||
<div class="item-row">
|
||||
<div class="notification-content">
|
||||
{% if c.full_content is defined and c.full_content == 'true' %}
|
||||
{{ c.notification.message|chill_markdown_to_html }}
|
||||
{% else %}
|
||||
{{ c.notification.message|u.truncate(250, '…', false)|chill_markdown_to_html }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if action_button is not defined or action_button != 'false' %}
|
||||
{% if c.action_button is not defined or c.action_button != 'false' %}
|
||||
<div class="item-row separator">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
{# Vue component #}
|
||||
<span class="notification_toggle_read_status"
|
||||
data-notification-id="{{ notification.id }}"
|
||||
data-notification-current-is-read="{{ notification.isReadBy(app.user) }}"
|
||||
data-notification-id="{{ c.notification.id }}"
|
||||
data-notification-current-is-read="{{ c.notification.isReadBy(app.user) }}"
|
||||
data-container="notification-status"
|
||||
></span>
|
||||
</li>
|
||||
{% if is_granted('CHILL_MAIN_NOTIFICATION_UPDATE', notification) %}
|
||||
{% if is_granted('CHILL_MAIN_NOTIFICATION_UPDATE', c.notification) %}
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_main_notification_edit', {'id': notification.id}) }}"
|
||||
<a href="{{ chill_path_add_return_path('chill_main_notification_edit', {'id': c.notification.id}) }}"
|
||||
class="btn btn-edit" title="{{ 'Edit'|trans }}"></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if is_granted('CHILL_MAIN_NOTIFICATION_SEE', notification) %}
|
||||
{% if is_granted('CHILL_MAIN_NOTIFICATION_SEE', c.notification) %}
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_main_notification_show', {'id': notification.id}) }}"
|
||||
class="btn btn-show" title="{{ 'Show'|trans }}"></a>
|
||||
<a href="{{ chill_path_add_return_path('chill_main_notification_show', {'id': c.notification.id}) }}"
|
||||
class="btn btn-show change-icon" title="{{ 'notification.see_comments_thread'|trans }}"><i class="fa fa-comment"></i></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
<div class="item-bloc notification-status {% if notification.isReadBy(app.user) %}read{% else %}unread{% endif %}">
|
||||
|
||||
{% if fold_item is defined and fold_item != 'false' %}
|
||||
<div class="accordion-header" id="flush-heading-{{ notification.id }}">
|
||||
<button type="button" class="accordion-button collapsed"
|
||||
data-bs-toggle="collapse" data-bs-target="#flush-collapse-{{ notification.id }}"
|
||||
aria-expanded="false" aria-controls="flush-collapse-{{ notification.id }}">
|
||||
{{ _self.title(_context) }}
|
||||
</button>
|
||||
{{ _self.header(_context) }}
|
||||
</div>
|
||||
<div id="flush-collapse-{{ notification.id }}"
|
||||
class="accordion-collapse collapse"
|
||||
aria-labelledby="flush-heading-{{ notification.id }}"
|
||||
data-bs-parent="#notification-fold">
|
||||
{{ _self.content(_context) }}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ _self.title(_context) }}
|
||||
{{ _self.header(_context) }}
|
||||
{{ _self.content(_context) }}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
@@ -4,7 +4,7 @@
|
||||
</div>
|
||||
{# TODO pagination or limit #}
|
||||
{% for notification in notifications %}
|
||||
<div class="list-group-item {% if notification.isReadBy(app.user) %}read{% else %}unread{% endif %}">
|
||||
<div class="list-group-item notification-status {% if notification.isReadBy(app.user) %}read{% else %}unread{% endif %}">
|
||||
|
||||
{% if not notification.isSystem %}
|
||||
{% if notification.sender == app.user %}
|
||||
@@ -17,6 +17,7 @@
|
||||
<span class="notification_toggle_read_status"
|
||||
data-notification-id="{{ notification.id }}"
|
||||
data-notification-current-is-read="{{ notification.isReadBy(app.user) }}"
|
||||
data-container="notification-status"
|
||||
data-show-button-url="{{ chill_path_add_return_path('chill_main_notification_show', {'id': notification.id}) }}"
|
||||
data-button-class="btn-outline-primary"
|
||||
data-button-text="false"
|
||||
|
@@ -46,10 +46,12 @@
|
||||
<p class="chill-no-data-statement">{{ 'notification.Any notification sent'|trans }}</p>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="flex-table">
|
||||
<div class="flex-table accordion accordion-flush" id="notification-fold">
|
||||
{% for data in datas %}
|
||||
{% set notification = data.notification %}
|
||||
{% include 'ChillMainBundle:Notification:_list_item.html.twig' %}
|
||||
{% include 'ChillMainBundle:Notification:_list_item.html.twig' with {
|
||||
'fold_item': 'true'
|
||||
} %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@@ -40,7 +40,8 @@
|
||||
'template': handler.getTemplate(notification),
|
||||
'template_data': handler.getTemplateData(notification)
|
||||
},
|
||||
'action_button': 'false'
|
||||
'action_button': 'false',
|
||||
'full_content': 'true'
|
||||
} %}
|
||||
</div>
|
||||
|
||||
@@ -86,8 +87,9 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if appendCommentForm is not null %}
|
||||
<div class="new-comment my-5">
|
||||
<h2 class="chill-blue">{{ 'Write a new comment'|trans }}</h2>
|
||||
<h2 class="chill-blue mb-4">{{ 'Write a new comment'|trans }}</h2>
|
||||
|
||||
{{ form_start(appendCommentForm) }}
|
||||
{{ form_errors(appendCommentForm) }}
|
||||
@@ -101,6 +103,7 @@
|
||||
{{ form_end(appendCommentForm) }}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
@@ -114,6 +117,7 @@
|
||||
<span class="notification_toggle_read_status"
|
||||
data-notification-id="{{ notification.id }}"
|
||||
data-notification-current-is-read="1"
|
||||
data-container="notification-status"
|
||||
></span>
|
||||
</li>
|
||||
</ul>
|
||||
|
@@ -11,6 +11,7 @@
|
||||
* buttonText string
|
||||
* displayBadge boolean (default: false) replace button by badge, need to define buttonText for content
|
||||
* parent object (optional) pass parent context of the targetEntity (used for course resource comment)
|
||||
* isDead boolean (default: false) is the person dead
|
||||
|
||||
#}
|
||||
<span class="onthefly-container"
|
||||
@@ -28,6 +29,10 @@
|
||||
data-button-text="{{ buttonText|e('html_attr') }}"
|
||||
{% endif %}
|
||||
|
||||
{% if isDead is defined and isDead == 1 %}
|
||||
data-is-dead="true"
|
||||
{% endif %}
|
||||
|
||||
{% if displayBadge is defined and displayBadge == 1 %}
|
||||
data-display-badge="true"
|
||||
{% endif %}
|
||||
|
@@ -58,7 +58,7 @@ class UserNormalizer implements ContextAwareNormalizerInterface, NormalizerAware
|
||||
);
|
||||
$locationContext = array_merge(
|
||||
$context,
|
||||
['docgen:expects' => Location::class, 'groups' => 'dogen:read']
|
||||
['docgen:expects' => Location::class, 'groups' => 'docgen:read']
|
||||
);
|
||||
|
||||
if (null === $user && 'docgen' === $format) {
|
||||
@@ -67,6 +67,7 @@ class UserNormalizer implements ContextAwareNormalizerInterface, NormalizerAware
|
||||
'main_center' => $this->normalizer->normalize(null, $format, $centerContext),
|
||||
'main_scope' => $this->normalizer->normalize(null, $format, $scopeContext),
|
||||
'current_location' => $this->normalizer->normalize(null, $format, $locationContext),
|
||||
'main_location' => $this->normalizer->normalize(null, $format, $locationContext),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -84,6 +85,7 @@ class UserNormalizer implements ContextAwareNormalizerInterface, NormalizerAware
|
||||
|
||||
if ('docgen' === $format) {
|
||||
$data['current_location'] = $this->normalizer->normalize($user->getCurrentLocation(), $format, $locationContext);
|
||||
$data['main_location'] = $this->normalizer->normalize($user->getMainLocation(), $format, $locationContext);
|
||||
}
|
||||
|
||||
return $data;
|
||||
|
@@ -0,0 +1,36 @@
|
||||
<?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\Main;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Add editableByUsers field to ChillMain/LocationType.
|
||||
*/
|
||||
final class Version20220112150413 extends AbstractMigration
|
||||
{
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_main_location_type DROP editableByUsers');
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add editableByUsers field to ChillMain/LocationType';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_main_location_type ADD editableByUsers BOOLEAN DEFAULT TRUE');
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
<?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\Main;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Add mainLocation to User.
|
||||
*/
|
||||
final class Version20220112161136 extends AbstractMigration
|
||||
{
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE users DROP CONSTRAINT FK_1483A5E9DB622A42');
|
||||
$this->addSql('DROP INDEX IDX_1483A5E9DB622A42');
|
||||
$this->addSql('ALTER TABLE users DROP mainLocation_id');
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add mainLocation to User';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE users ADD mainLocation_id INT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE users ADD CONSTRAINT FK_1483A5E9DB622A42 FOREIGN KEY (mainLocation_id) REFERENCES chill_main_location (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('CREATE INDEX IDX_1483A5E9DB622A42 ON users (mainLocation_id)');
|
||||
}
|
||||
}
|
@@ -202,6 +202,7 @@ Location: Localisation
|
||||
Location type list: Liste des types de localisation
|
||||
Create a new location type: Créer un nouveau type de localisation
|
||||
Available for users: Disponible aux utilisateurs
|
||||
Editable by users: Éditable par les utilisateurs
|
||||
Address required: Adresse requise?
|
||||
Contact data: Données de contact?
|
||||
optional: optionnel
|
||||
@@ -380,4 +381,6 @@ notification:
|
||||
you were notified by %sender%: Vous avez été notifié par %sender%
|
||||
you were notified by system: Vous avez été notifié automatiquement
|
||||
subject: Objet
|
||||
see_comments_thread: Voir le fil de commentaires associé
|
||||
object_prefix: "[CHILL] notification - "
|
||||
|
||||
|
@@ -23,3 +23,8 @@ address:
|
||||
street1-should-be-set: Une ligne d'adresse doit être présente
|
||||
date-should-be-set: La date de début de validité doit être présente
|
||||
postcode-should-be-set: Le code postal doit être renseigné
|
||||
|
||||
notification:
|
||||
At least one addressee: Indiquez au moins un destinataire
|
||||
Title must be defined: Un titre doit être indiqué
|
||||
|
||||
|
@@ -1099,6 +1099,9 @@ class AccompanyingPeriod implements
|
||||
}
|
||||
|
||||
if ($comment instanceof Comment) {
|
||||
if (null !== $this->pinnedComment) {
|
||||
$this->addComment($this->pinnedComment);
|
||||
}
|
||||
$this->addComment($comment);
|
||||
}
|
||||
|
||||
|
@@ -151,7 +151,6 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
* @var DateTime
|
||||
*
|
||||
* @ORM\Column(type="date", nullable=true)
|
||||
* @Assert\Date
|
||||
* @Birthdate
|
||||
*/
|
||||
private $birthdate;
|
||||
@@ -259,7 +258,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="string", length=255)
|
||||
* @Assert\NotBlank
|
||||
* @Assert\NotBlank(message="The firstname cannot be empty")
|
||||
* @Assert\Length(
|
||||
* max=255,
|
||||
* )
|
||||
@@ -282,7 +281,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="string", length=9, nullable=true)
|
||||
* @Assert\NotNull
|
||||
* @Assert\NotNull(message="The gender must be set")
|
||||
*/
|
||||
private $gender;
|
||||
|
||||
@@ -326,7 +325,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="string", length=255)
|
||||
* @Assert\NotBlank
|
||||
* @Assert\NotBlank(message="The lastname cannot be empty")
|
||||
* @Assert\Length(
|
||||
* max=255,
|
||||
* )
|
||||
|
@@ -22,6 +22,8 @@ use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TelType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
@@ -52,11 +54,20 @@ final class CreationPersonType extends AbstractType
|
||||
$builder
|
||||
->add('firstName')
|
||||
->add('lastName')
|
||||
->add('gender', GenderType::class, [
|
||||
'required' => true, 'placeholder' => null,
|
||||
])
|
||||
->add('birthdate', ChillDateType::class, [
|
||||
'required' => false,
|
||||
])
|
||||
->add('gender', GenderType::class, [
|
||||
'required' => true, 'placeholder' => null,
|
||||
->add('phonenumber', TelType::class, [
|
||||
'required' => false,
|
||||
])
|
||||
->add('mobilenumber', TelType::class, [
|
||||
'required' => false,
|
||||
])
|
||||
->add('email', EmailType::class, [
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
if ($this->askCenters) {
|
||||
|
@@ -0,0 +1,61 @@
|
||||
function capitalizeFirstLetter(string) {
|
||||
return string.charAt(0).toLocaleUpperCase() + string.slice(1);
|
||||
}
|
||||
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
const uri = decodeURI(location.hash.substring(1))
|
||||
let searchFragments = uri.split(' ')
|
||||
searchFragments = searchFragments.filter((el) => {
|
||||
if ( ( el.startsWith("firstname") || el.startsWith("lastname") ) || (el !== '' && !el.startsWith('birthdate') && !el.startsWith('gender') && !el.startsWith('city') && !el.startsWith('phonenumber') && !el.startsWith('@'))) {
|
||||
return el
|
||||
}
|
||||
})
|
||||
|
||||
searchFragments = searchFragments.map((el) => {
|
||||
if (el.startsWith("firstname")) {
|
||||
return el.slice(10)
|
||||
} else if (el.startsWith("lastname")) {
|
||||
return el.slice(10)
|
||||
}
|
||||
return el.replace('\"', '')
|
||||
})
|
||||
|
||||
if (searchFragments) {
|
||||
const pre = '<ul class="list-suggest add-items inline">';
|
||||
const after = '</ul>';
|
||||
|
||||
document.querySelectorAll('[data-suggest-container]').forEach(function(container) {
|
||||
const suggestions = searchFragments.map((el) => `<li class="suggest-item-name"><span data-suggest-target="${container.dataset.suggestContainer}">${capitalizeFirstLetter(el)}</span></li>`);
|
||||
container.innerHTML = pre + suggestions.join(' ') + after;
|
||||
})
|
||||
}
|
||||
|
||||
const tags = document.querySelectorAll('[data-suggest-target]').forEach((tag) => {
|
||||
tag.addEventListener('click', function(e) {
|
||||
const field = document.querySelector(`[name="${e.target.dataset.suggestTarget}"]`);
|
||||
let suggestion = e.target.textContent.trim();
|
||||
switch (field.dataset.suggestTransform) {
|
||||
case 'uppercase_all':
|
||||
suggestion = suggestion.toLocaleUpperCase();
|
||||
break;
|
||||
case 'uppercase_first_letter':
|
||||
default:
|
||||
suggestion = capitalizeFirstLetter(suggestion);
|
||||
}
|
||||
|
||||
if (field.value === '') {
|
||||
field.value = suggestion;
|
||||
} else {
|
||||
field.value = `${field.value} ${suggestion}`
|
||||
}
|
||||
e.target.style.display = "none";
|
||||
|
||||
[...document.querySelectorAll("[data-suggest-target]")]
|
||||
.filter(p => p.textContent.includes(e.target.textContent))
|
||||
.forEach(p => p.remove());
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
@@ -233,18 +233,6 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<pick-template
|
||||
entityClass="Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork"
|
||||
:templates="this.templatesAvailablesForAction"
|
||||
:entityId="work.id"
|
||||
:beforeMove="beforeGenerateTemplate">
|
||||
<template v-slot:title>
|
||||
<h3>{{ $t('Generate doc') }}</h3>
|
||||
</template>
|
||||
</pick-template>
|
||||
</div>
|
||||
|
||||
<div v-if="errors.length > 0" id="errors" class="alert alert-danger flashbag">
|
||||
<p>{{ $t('fix_these_errors') }}</p>
|
||||
<ul>
|
||||
@@ -458,10 +446,6 @@ export default {
|
||||
submit() {
|
||||
this.$store.dispatch('submit');
|
||||
},
|
||||
beforeGenerateTemplate() {
|
||||
console.log('before generate');
|
||||
return Promise.resolve();
|
||||
},
|
||||
saveFormOnTheFly(payload) {
|
||||
console.log('saveFormOnTheFly: type', payload.type, ', data', payload.data);
|
||||
payload.target = 'resource';
|
||||
|
@@ -130,7 +130,7 @@ const store = createStore({
|
||||
person.group = person.type
|
||||
person._id = person.id
|
||||
person.id = `person_${person.id}`
|
||||
person.label = `*${person.text}*\n_${getGender(person.gender)}${age}_${debug}`
|
||||
person.label = `*${person.text}${person.deathdate ? ' (‡)' : ''}*\n_${getGender(person.gender)}${age}_${debug}`
|
||||
person.folded = false
|
||||
// folded is used for missing persons
|
||||
if (options.folded) {
|
||||
|
@@ -127,6 +127,7 @@
|
||||
<i class="fa fa-stack-1x">T</i>
|
||||
</span>
|
||||
{{ person.text }}
|
||||
<span v-if="person.deathdate" class="deathdate"> (‡)</span>
|
||||
</a>
|
||||
<span v-else>
|
||||
<span v-if="options.isHolder" class="fa-stack fa-holder" :title="$t('renderbox.holder')">
|
||||
@@ -134,6 +135,7 @@
|
||||
<i class="fa fa-stack-1x">T</i>
|
||||
</span>
|
||||
{{ person.text }}
|
||||
<span v-if="person.deathdate" class="deathdate"> (‡)</span>
|
||||
</span>
|
||||
<slot name="post-badge"></slot>
|
||||
</span>
|
||||
|
@@ -3,7 +3,8 @@
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
action: 'show', displayBadge: true,
|
||||
targetEntity: { name: type, id: entity.id },
|
||||
buttonText: entity|chill_entity_render_string
|
||||
buttonText: entity|chill_entity_render_string,
|
||||
isDead: entity.deathdate is not null
|
||||
} %}
|
||||
{% endmacro %}
|
||||
|
||||
|
@@ -9,6 +9,7 @@
|
||||
action: 'show', displayBadge: true,
|
||||
targetEntity: { name: type, id: entity.id },
|
||||
buttonText: entity|chill_entity_render_string,
|
||||
isDead: entity.deathdate is not null,
|
||||
parent: parent
|
||||
} %}
|
||||
{% endmacro %}
|
||||
|
@@ -69,7 +69,8 @@
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
action: 'show', displayBadge: true,
|
||||
targetEntity: { name: 'person', id: p.id },
|
||||
buttonText: p|chill_entity_render_string
|
||||
buttonText: p|chill_entity_render_string,
|
||||
isDead: entity.deathdate is not null
|
||||
} %}
|
||||
</span>
|
||||
{% endfor %}
|
||||
|
@@ -45,7 +45,7 @@
|
||||
{% if chill_accompanying_periods.fields.user == 'visible' %}
|
||||
{% if period.user %}
|
||||
<abbr class="referrer" title="{{ 'Referrer'|trans }}">{{ 'Referrer'|trans }}:</abbr>
|
||||
{{ period.user.username|chill_entity_render_box }}
|
||||
{{ period.user|chill_entity_render_box }}
|
||||
{% else %}
|
||||
<span class="chill-no-data-statement">{{ 'No accompanying user'|trans }}</span>
|
||||
{% endif %}
|
||||
@@ -65,7 +65,8 @@
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
action: 'show', displayBadge: true,
|
||||
targetEntity: { name: 'person', id: period.requestorPerson.id },
|
||||
buttonText: period.requestorPerson|chill_entity_render_string
|
||||
buttonText: period.requestorPerson|chill_entity_render_string,
|
||||
isDead: period.requestorPerson.deathdate is not null
|
||||
} %}
|
||||
</span>
|
||||
{% endif %}
|
||||
@@ -90,7 +91,8 @@
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
action: 'show', displayBadge: true,
|
||||
targetEntity: { name: 'person', id: p.person.id },
|
||||
buttonText: p.person|chill_entity_render_string
|
||||
buttonText: p.person|chill_entity_render_string,
|
||||
isDead: p.person.deathdate is not null
|
||||
} %}
|
||||
</span>
|
||||
{% endfor %}
|
||||
|
@@ -90,7 +90,7 @@
|
||||
{#- must be on one line to avoid spaces with dash -#}
|
||||
<time datetime="{{ person.deathdate|date('Y-m-d') }}" title="{{ 'deathdate'|trans }}">{{ person.deathdate|format_date("medium") }}</time>
|
||||
{%- if options['addAge'] -%}
|
||||
<span class="age">{{ 'years_old'|trans({ 'age': person.age }) }}</span>
|
||||
<span class="age"> {{ 'years_old'|trans({ 'age': person.age }) }}</span>
|
||||
{%- endif -%}
|
||||
{%- elseif person.birthdate is not null -%}
|
||||
<time datetime="{{ person.birthdate|date('Y-m-d') }}" title="{{ 'Birthdate'|trans }}">
|
||||
|
@@ -63,18 +63,43 @@
|
||||
|
||||
{{ form_start(form, {'attr' : {'id' : 'create-form'}}) }}
|
||||
|
||||
<div class="row mb-1" style="display:flex;">
|
||||
{{ form_label(form.lastName, 'Last name'|trans) }}
|
||||
<div class="col-sm-8">
|
||||
{{ form_widget(form.lastName, {'attr': {'data-suggest-transform': 'uppercase_all' } }) }}
|
||||
</div>
|
||||
</div>
|
||||
<div data-suggest-container="{{ form.lastName.vars.full_name|e('html_attr') }}" class="col-sm-8" style="margin-left: auto;"></div>
|
||||
|
||||
{{ form_row(form.lastName, { 'label' : 'Last name'|trans }) }}
|
||||
|
||||
{{ form_row(form.firstName, { 'label' : 'First name'|trans }) }}
|
||||
<div class="row mb-1" style="display:flex;">
|
||||
{{ form_label(form.firstName, 'First name'|trans) }}
|
||||
<div class="col-sm-8">
|
||||
{{ form_widget(form.firstName, {'attr': {'data-suggest-transform': 'uppercase_first_letter' } }) }}
|
||||
</div>
|
||||
</div>
|
||||
<div data-suggest-container="{{ form.firstName.vars.full_name|e('html_attr') }}" class="col-sm-8" style="margin-left: auto;"></div>
|
||||
|
||||
{% if form.altNames is defined %}
|
||||
{{ form_widget(form.altNames) }}
|
||||
{% for altName in form.altNames %}
|
||||
<div class="row mb-1" style="display:flex;">
|
||||
{{ form_label(altName) }}
|
||||
<div class="col-sm-8">
|
||||
{{ form_widget(altName, {'attr': {'data-suggest-transform': 'uppercase_all' } }) }}
|
||||
</div>
|
||||
</div>
|
||||
<div data-suggest-container="{{ altName.vars.full_name|e('html_attr') }}" class="col-sm-8" style="margin-left: auto;"></div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{{ form_row(form.gender, { 'label' : 'Gender'|trans }) }}
|
||||
|
||||
{{ form_row(form.birthdate, { 'label' : 'Date of birth'|trans }) }}
|
||||
|
||||
{{ form_row(form.gender, { 'label' : 'Gender'|trans }) }}
|
||||
{{ form_row(form.phonenumber, { 'label' : 'Phonenumber'|trans }) }}
|
||||
|
||||
{{ form_row(form.mobilenumber, { 'label' : 'Mobilenumber'|trans }) }}
|
||||
|
||||
{{ form_row(form.email, { 'label' : 'Email'|trans }) }}
|
||||
|
||||
{% if form.center is defined %}
|
||||
{{ form_row(form.center) }}
|
||||
@@ -93,7 +118,7 @@
|
||||
<li>
|
||||
{{ form_widget(form.createPeriod, { 'attr': { 'class': 'dropdown-item' }}) }}
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -103,5 +128,5 @@
|
||||
{% endblock content %}
|
||||
|
||||
{% block js %}
|
||||
{# {{ encore_entry_script_tags('mod_disablebuttons') }} #}
|
||||
{{ encore_entry_script_tags('page_suggest_names') }}
|
||||
{% endblock js %}
|
||||
|
@@ -59,7 +59,8 @@
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
action: 'show', displayBadge: true,
|
||||
targetEntity: { name: 'person', id: m.person.id },
|
||||
buttonText: m.person|chill_entity_render_string
|
||||
buttonText: m.person|chill_entity_render_string,
|
||||
isDead: m.person.deathdate is not null
|
||||
} %}
|
||||
{%- endfor -%}
|
||||
{% endif %}
|
||||
|
@@ -83,7 +83,7 @@
|
||||
<ul class="record_actions">
|
||||
{% if is_granted('CHILL_PERSON_CREATE') %}
|
||||
<li>
|
||||
<a href="{{ path('chill_person_new') }}" class="btn btn-create">
|
||||
<a href="{{ path('chill_person_new', { "_fragment": pattern }) }}" class="btn btn-create">
|
||||
{{ 'Add a person'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
|
@@ -26,7 +26,7 @@
|
||||
<ul class="record_actions">
|
||||
{% if is_granted('CHILL_PERSON_CREATE') %}
|
||||
<li>
|
||||
<a href="{{ path('chill_person_new') }}" class="btn btn-create">
|
||||
<a href="{{ path('chill_person_new', { "_fragment": pattern }) }}" class="btn btn-create">
|
||||
{{ 'Add a person'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
@@ -154,7 +154,8 @@
|
||||
targetEntity: { name: 'person', id: part.person.id },
|
||||
action: 'show',
|
||||
displayBadge: true,
|
||||
buttonText: part.person|chill_entity_render_string
|
||||
buttonText: part.person|chill_entity_render_string,
|
||||
isDead: part.person.deathdate is not null
|
||||
} %}
|
||||
{% else %}
|
||||
{% set participating = true %}
|
||||
@@ -190,7 +191,8 @@
|
||||
targetEntity: { name: 'person', id: acp.requestorPerson.id },
|
||||
action: 'show',
|
||||
displayBadge: true,
|
||||
buttonText: acp.requestorPerson|chill_entity_render_string
|
||||
buttonText: acp.requestorPerson|chill_entity_render_string,
|
||||
isDead: acp.requestorPerson.deathdate is not null
|
||||
} %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
@@ -11,9 +11,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\Service\DocGenerator;
|
||||
|
||||
use Chill\DocGeneratorBundle\Context\DocGeneratorContextInterface;
|
||||
use Chill\DocGeneratorBundle\Context\DocGeneratorContextWithAdminFormInterface;
|
||||
use Chill\DocGeneratorBundle\Context\DocGeneratorContextWithPublicFormInterface;
|
||||
use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate;
|
||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
||||
@@ -21,10 +18,7 @@ use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
class AccompanyingPeriodWorkContext implements
|
||||
DocGeneratorContextInterface,
|
||||
DocGeneratorContextWithAdminFormInterface,
|
||||
DocGeneratorContextWithPublicFormInterface
|
||||
class AccompanyingPeriodWorkContext
|
||||
{
|
||||
private NormalizerInterface $normalizer;
|
||||
|
||||
|
@@ -18,4 +18,5 @@ module.exports = function(encore, entries)
|
||||
encore.addEntry('page_person', __dirname + '/Resources/public/page/person/index.js');
|
||||
encore.addEntry('page_accompanying_course_index_person_locate', __dirname + '/Resources/public/page/accompanying_course_index/person_locate.js');
|
||||
encore.addEntry('page_accompanying_course_index_masonry', __dirname + '/Resources/public/page/accompanying_course_index/masonry.js');
|
||||
encore.addEntry('page_suggest_names', __dirname + '/Resources/public/page/person/suggest-names.js');
|
||||
};
|
||||
|
@@ -16,6 +16,9 @@ The birthdate must be before %date%: La date de naissance doit être avant le %d
|
||||
'Invalid phone number: it should begin with the international prefix starting with "+", hold only digits and be smaller than 20 characters. Ex: +33623456789': 'Numéro de téléphone invalide: il doit commencer par le préfixe international précédé de "+", ne comporter que des chiffres et faire moins de 20 caractères. Ex: +33623456789'
|
||||
'The email is not valid': 'Le courriel n''est pas valide'
|
||||
Two addresses has the same validFrom date: La date de validité est identique à celle d'une autre adresse
|
||||
The firstname cannot be empty: Le prénom ne peut pas être vide
|
||||
The lastname cannot be empty: Le nom de famille ne peut pas être vide
|
||||
The gender must be set: Le genre doit être renseigné
|
||||
|
||||
#export list
|
||||
You must select at least one element: Vous devez sélectionner au moins un élément
|
||||
|
@@ -22,7 +22,8 @@
|
||||
targetEntity: { name: 'person', id: task.person.id },
|
||||
action: 'show',
|
||||
displayBadge: true,
|
||||
buttonText: task.person|chill_entity_render_string
|
||||
buttonText: task.person|chill_entity_render_string,
|
||||
isDead: task.person.deathdate is not null
|
||||
} %}
|
||||
</span>
|
||||
{% elseif task.course is not null %}
|
||||
@@ -36,7 +37,8 @@
|
||||
targetEntity: { name: 'person', id: part.person.id },
|
||||
action: 'show',
|
||||
displayBadge: true,
|
||||
buttonText: part.person|chill_entity_render_string
|
||||
buttonText: part.person|chill_entity_render_string,
|
||||
isDead: part.person.deathdate is not null
|
||||
} %}
|
||||
{% endfor %}
|
||||
|
||||
|
@@ -50,7 +50,7 @@
|
||||
|
||||
<dt>{{ 'thirdparty.Categories'|trans }}</dt>
|
||||
{% set types = [] %}
|
||||
{% for t in thirdParty.types %}
|
||||
{% for t in thirdParty.thirdPartyTypes %}
|
||||
{% set types = types|merge( [ ('chill_3party.key_label.'~t)|trans ] ) %}
|
||||
{% endfor %}
|
||||
{% for c in thirdParty.categories %}
|
||||
|
Reference in New Issue
Block a user