mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-23 15:14:58 +00:00
Compare commits
147 Commits
Author | SHA1 | Date | |
---|---|---|---|
c3fce4783a
|
|||
be8901a5c4
|
|||
6f28d154c8
|
|||
5dfbdad13d
|
|||
b3e2d4ff9f | |||
01c2848a83
|
|||
d0ee381627
|
|||
8b1b255050
|
|||
2bef3c3878
|
|||
cea44d1788
|
|||
84069e03dc
|
|||
ad5e780936
|
|||
19accc4d00
|
|||
6cb085f5f7
|
|||
97239ada84
|
|||
643156f822 | |||
ff0b205591 | |||
2d67843901 | |||
2b09e1459c | |||
029524ba2c | |||
fa91e9494d | |||
4e72d6fea1
|
|||
5666b8b647
|
|||
702a5a27d2 | |||
|
0573f56782 | ||
|
3bee18b0fa | ||
|
41dd4d89f7 | ||
|
3a7ed7ef8f | ||
|
843698a1d8 | ||
|
499640e48b | ||
18df08e8c3 | |||
db3961275b
|
|||
cd488d7576 | |||
436661d952 | |||
c3b8d42047 | |||
|
9c28df25a1 | ||
|
c5a24e8ac5 | ||
|
d9c50cffb7 | ||
|
25ccb16308 | ||
|
ba25c181f5 | ||
145419a76b | |||
b1ba5cc608 | |||
87a6757e5e | |||
47f4cfddbb
|
|||
e95f9e9846 | |||
1f4bef754d
|
|||
19e34d5dc0
|
|||
fab00f679c
|
|||
791b3776c5
|
|||
6bd38f1a58
|
|||
68d21c9267
|
|||
e7ca89e0c1
|
|||
fc8bc33ba9
|
|||
cbd9489810
|
|||
90b615c5b2
|
|||
5ca222b501 | |||
3e4495dd6e
|
|||
bca0d04201
|
|||
f66ac50571 | |||
b454774836
|
|||
008f344e49
|
|||
90bfd87ec6
|
|||
cc0030c1cd
|
|||
d60ba3ecb2
|
|||
cd5001ac74 | |||
98f47ac512
|
|||
31b541d12f
|
|||
72045ce082
|
|||
0bfb3de465
|
|||
9ec4c77fb7
|
|||
77c53972c8
|
|||
350d991a85
|
|||
0ce9cdd07a
|
|||
1993fac1c4
|
|||
83883567a2
|
|||
29d57934a1
|
|||
f43d79c940
|
|||
be730679c8
|
|||
f62f1891d8
|
|||
ebb856fe85
|
|||
61877e0157
|
|||
4c3f082163
|
|||
a7ec7c9f37 | |||
c9e13be736 | |||
b9b342fe44 | |||
31f29f0bc5 | |||
0bc9fff825 | |||
25f93e8a89 | |||
4e0d8e4def | |||
1ecc825945 | |||
addc623add | |||
1b96deb4ee | |||
f510acd170 | |||
835409cb94 | |||
2121b3ef28 | |||
6c9101c167 | |||
b46883fe36 | |||
8d58805abd | |||
c3a799cb7d | |||
bc683b28d6 | |||
d91b1a70bf | |||
853014d8d2 | |||
ad6154a1e4 | |||
50c04382ef | |||
d62e9ce269 | |||
2149ef1cb4 | |||
d15fbadd27 | |||
fbbf421d8b | |||
fe695f1a14 | |||
d0ec6f9819 | |||
0b739fda34 | |||
9b8e143855 | |||
a533ab77ed | |||
087032881b | |||
82667a1c0f | |||
db6408926b | |||
f5c7ab6ef0 | |||
a13ada2937 | |||
3be8a39a1a | |||
d7eb1e01da | |||
bd62202d22 | |||
0e3de2ec8a | |||
aa2a398f9e | |||
33187448a0 | |||
a4482ad28b | |||
8ed5a023e8 | |||
653ac1d62b | |||
499009ac43 | |||
192b161e78 | |||
1b1f355123 | |||
39a863448c | |||
0c1a4a5f59 | |||
6f358ee1a9 | |||
0f36b9349b | |||
d18cc29acf | |||
4220d1a2d3 | |||
1ae27152c2 | |||
b946f8c10a | |||
62d6106801 | |||
89fb87f71f | |||
1337360690 | |||
9324c33caf | |||
c2dd9ef676 | |||
a42d7231d9 | |||
38deaf6f36 | |||
04fc5b6614 | |||
384b2be577 |
31
.changes/v2.21.0.md
Normal file
31
.changes/v2.21.0.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
## v2.21.0 - 2024-06-18
|
||||||
|
### Feature
|
||||||
|
* Add flash menu buttons in search results, to open directly a new calendar, or a new activity in an accompanying period
|
||||||
|
* ([#122](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/122)) Improve the list of calendar in the search results: make all calendar clicable, and display a list of calendars
|
||||||
|
* ([#282](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/282)) [export] add start date and end date on filters "filter course by referrer job" and "filter course by referrer scope"
|
||||||
|
* ([#282](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/282)) [export] the aggregator "Group by referrer" now accept a date range.
|
||||||
|
* ([#282](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/282)) [export] add date range on "group course by referrer's scope"
|
||||||
|
* ([#282](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/282)) [export] add date range on "group course by referrer's jobs"
|
||||||
|
* ([#168](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/168) In the UX, display user job and service at the time when he performs an action:
|
||||||
|
now, the job and service is shown:
|
||||||
|
* at the activity's date,
|
||||||
|
* at the appointment's date,
|
||||||
|
* when the user is marked as referrer for an accompanying period work,
|
||||||
|
* when the user apply a transition in a workflow,
|
||||||
|
* when the user updates or creates "something" ("created/updated by ... at ..."),
|
||||||
|
* or when he wrote a comment,
|
||||||
|
* …
|
||||||
|
|
||||||
|
### Traduction francophone
|
||||||
|
* Ajout d'un menu "flash" dans les résultats de recherche, pour créer un rendez-vous ou un échange dans un parcours depuis les résultats de recherche;
|
||||||
|
* Améliore la liste des rendez-vous dans les résultats de recherche: les rendez-vous sont cliquables;
|
||||||
|
* [exports] Ajout d'intervalles de dates pour des filtres et regroupements des parcours par référent, métier du référent, service du référent;
|
||||||
|
* Affiche le métier et le service des utilisateurs à la date à laquelle il a exécuté une action. Le métier et le service est affiché:
|
||||||
|
* à la date d'un échange,
|
||||||
|
* au jour d'un rendez-vous,
|
||||||
|
* quand l'utilisateur est devenu référent d'un parcours d'accompagnement,
|
||||||
|
* quand il a appliqué une transition sur un workflow,
|
||||||
|
* quand il a mise à jour ou créé une fiche, dans les mentions "créé / mise à jour par ..., le ...",
|
||||||
|
* quand il a mis à jour un commentaire,
|
||||||
|
* …
|
||||||
|
|
6
.changes/v2.22.0.md
Normal file
6
.changes/v2.22.0.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
## v2.22.0 - 2024-06-25
|
||||||
|
### Feature
|
||||||
|
* ([#216](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/216)) [event bundle] exports added for the event module
|
||||||
|
|
||||||
|
### Traduction francophone
|
||||||
|
* Exports sont ajoutés pour la module événement.
|
5
.changes/v2.22.1.md
Normal file
5
.changes/v2.22.1.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
## v2.22.1 - 2024-07-01
|
||||||
|
### Fixed
|
||||||
|
* Remove debug word
|
||||||
|
### DX
|
||||||
|
* Add a command for reading official address DB from Luxembourg and update chill addresses
|
3
.changes/v2.22.2.md
Normal file
3
.changes/v2.22.2.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
## v2.22.2 - 2024-07-03
|
||||||
|
### Fixed
|
||||||
|
* Remove scope required for event participation stats
|
22
.changes/v2.23.0.md
Normal file
22
.changes/v2.23.0.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
## v2.23.0 - 2024-07-19
|
||||||
|
### Feature
|
||||||
|
* ([#123](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/123)) Add a button to duplicate calendar ranges from a week to another one
|
||||||
|
* [admin] filter users by active / inactive in the admin user's list
|
||||||
|
* ([#273](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/273)) Add the possibility to mark all notifications as read
|
||||||
|
|
||||||
|
|
||||||
|
* Handle duplicate reference id in the import of reference addresses
|
||||||
|
* Do not update the "createdAt" column when importing postal code which does not change
|
||||||
|
* Display filename on file upload within the UI interface
|
||||||
|
### Fixed
|
||||||
|
* ([#271](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/271)) Take into account the acp closing date in the acp works date filter
|
||||||
|
|
||||||
|
### Traduction française des principaux changements
|
||||||
|
- Ajout d'un bouton pour dupliquer les périodes de disponibilités d'une semaine à une autre;
|
||||||
|
- dans l'interface d'administration, filtre sur les utilisateurs actifs. Par défaut, seul les utilisateurs
|
||||||
|
actifs sont affichés;
|
||||||
|
- Nouveau bouton pour indiquer toutes les notifications comme lues;
|
||||||
|
- Améliorations sur l'import des adresses et des codes postaux;
|
||||||
|
- Affiche le nom du fichier déposé quand on téléverse un fichier depuis le poste de travail local;
|
||||||
|
- Agrandit l'icône du type de fichier dans l'interface de dépôt de fichier;
|
||||||
|
- correction: tient compte de la date de fermeture du parcours dans les filtres sur les actions d'accompagnement.
|
3
.changes/v2.24.0.md
Normal file
3
.changes/v2.24.0.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
## v2.24.0 - 2024-09-11
|
||||||
|
### Feature
|
||||||
|
* ([#306](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/306)) When a document is converted or downloaded in the browser, this document is removed from the browser memory after 45s. Future click on the button re-download the document.
|
5
.changes/v2.24.1.md
Normal file
5
.changes/v2.24.1.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
## v2.24.1 - 2024-10-02
|
||||||
|
### Fixed
|
||||||
|
* ([#308](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/308)) Show only the current referrer in the page "show" for an accompanying period workf
|
||||||
|
* ([#309](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/309)) Correctly compute the grouping by referrer aggregator
|
||||||
|
|
82
CHANGELOG.md
82
CHANGELOG.md
@@ -6,6 +6,88 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
|
|||||||
and is generated by [Changie](https://github.com/miniscruff/changie).
|
and is generated by [Changie](https://github.com/miniscruff/changie).
|
||||||
|
|
||||||
|
|
||||||
|
## v2.24.1 - 2024-10-02
|
||||||
|
### Fixed
|
||||||
|
* ([#308](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/308)) Show only the current referrer in the page "show" for an accompanying period workf
|
||||||
|
* ([#309](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/309)) Correctly compute the grouping by referrer aggregator
|
||||||
|
|
||||||
|
|
||||||
|
## v2.24.0 - 2024-09-11
|
||||||
|
### Feature
|
||||||
|
* ([#306](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/306)) When a document is converted or downloaded in the browser, this document is removed from the browser memory after 45s. Future click on the button re-download the document.
|
||||||
|
|
||||||
|
## v2.23.0 - 2024-07-19
|
||||||
|
### Feature
|
||||||
|
* ([#123](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/123)) Add a button to duplicate calendar ranges from a week to another one
|
||||||
|
* [admin] filter users by active / inactive in the admin user's list
|
||||||
|
* ([#273](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/273)) Add the possibility to mark all notifications as read
|
||||||
|
|
||||||
|
|
||||||
|
* Handle duplicate reference id in the import of reference addresses
|
||||||
|
* Do not update the "createdAt" column when importing postal code which does not change
|
||||||
|
* Display filename on file upload within the UI interface
|
||||||
|
### Fixed
|
||||||
|
* ([#271](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/271)) Take into account the acp closing date in the acp works date filter
|
||||||
|
|
||||||
|
### Traduction française des principaux changements
|
||||||
|
- Ajout d'un bouton pour dupliquer les périodes de disponibilités d'une semaine à une autre;
|
||||||
|
- dans l'interface d'administration, filtre sur les utilisateurs actifs. Par défaut, seul les utilisateurs
|
||||||
|
actifs sont affichés;
|
||||||
|
- Nouveau bouton pour indiquer toutes les notifications comme lues;
|
||||||
|
- Améliorations sur l'import des adresses et des codes postaux;
|
||||||
|
- Affiche le nom du fichier déposé quand on téléverse un fichier depuis le poste de travail local;
|
||||||
|
- Agrandit l'icône du type de fichier dans l'interface de dépôt de fichier;
|
||||||
|
- correction: tient compte de la date de fermeture du parcours dans les filtres sur les actions d'accompagnement.
|
||||||
|
|
||||||
|
## v2.22.2 - 2024-07-03
|
||||||
|
### Fixed
|
||||||
|
* Remove scope required for event participation stats
|
||||||
|
|
||||||
|
## v2.22.1 - 2024-07-01
|
||||||
|
### Fixed
|
||||||
|
* Remove debug word
|
||||||
|
### DX
|
||||||
|
* Add a command for reading official address DB from Luxembourg and update chill addresses
|
||||||
|
|
||||||
|
## v2.22.0 - 2024-06-25
|
||||||
|
### Feature
|
||||||
|
* ([#216](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/216)) [event bundle] exports added for the event module
|
||||||
|
|
||||||
|
### Traduction francophone
|
||||||
|
* Exports sont ajoutés pour la module événement.
|
||||||
|
|
||||||
|
## v2.21.0 - 2024-06-18
|
||||||
|
### Feature
|
||||||
|
* Add flash menu buttons in search results, to open directly a new calendar, or a new activity in an accompanying period
|
||||||
|
* ([#122](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/122)) Improve the list of calendar in the search results: make all calendar clicable, and display a list of calendars
|
||||||
|
* ([#282](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/282)) [export] add start date and end date on filters "filter course by referrer job" and "filter course by referrer scope"
|
||||||
|
* ([#282](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/282)) [export] the aggregator "Group by referrer" now accept a date range.
|
||||||
|
* ([#282](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/282)) [export] add date range on "group course by referrer's scope"
|
||||||
|
* ([#282](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/282)) [export] add date range on "group course by referrer's jobs"
|
||||||
|
* ([#168](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/168) In the UX, display user job and service at the time when he performs an action:
|
||||||
|
now, the job and service is shown:
|
||||||
|
* at the activity's date,
|
||||||
|
* at the appointment's date,
|
||||||
|
* when the user is marked as referrer for an accompanying period work,
|
||||||
|
* when the user apply a transition in a workflow,
|
||||||
|
* when the user updates or creates "something" ("created/updated by ... at ..."),
|
||||||
|
* or when he wrote a comment,
|
||||||
|
* …
|
||||||
|
|
||||||
|
### Traduction francophone
|
||||||
|
* Ajout d'un menu "flash" dans les résultats de recherche, pour créer un rendez-vous ou un échange dans un parcours depuis les résultats de recherche;
|
||||||
|
* Améliore la liste des rendez-vous dans les résultats de recherche: les rendez-vous sont cliquables;
|
||||||
|
* [exports] Ajout d'intervalles de dates pour des filtres et regroupements des parcours par référent, métier du référent, service du référent;
|
||||||
|
* Affiche le métier et le service des utilisateurs à la date à laquelle il a exécuté une action. Le métier et le service est affiché:
|
||||||
|
* à la date d'un échange,
|
||||||
|
* au jour d'un rendez-vous,
|
||||||
|
* quand l'utilisateur est devenu référent d'un parcours d'accompagnement,
|
||||||
|
* quand il a appliqué une transition sur un workflow,
|
||||||
|
* quand il a mise à jour ou créé une fiche, dans les mentions "créé / mise à jour par ..., le ...",
|
||||||
|
* quand il a mis à jour un commentaire,
|
||||||
|
* …
|
||||||
|
|
||||||
|
|
||||||
## v2.20.1 - 2024-06-05
|
## v2.20.1 - 2024-06-05
|
||||||
### Fixed
|
### Fixed
|
||||||
* Do not allow StoredObjectCreated for edit and convert buttons
|
* Do not allow StoredObjectCreated for edit and convert buttons
|
||||||
|
@@ -76,7 +76,7 @@
|
|||||||
"phpunit/phpunit": ">= 7.5",
|
"phpunit/phpunit": ">= 7.5",
|
||||||
"psalm/plugin-phpunit": "^0.18.4",
|
"psalm/plugin-phpunit": "^0.18.4",
|
||||||
"psalm/plugin-symfony": "^4.0.2",
|
"psalm/plugin-symfony": "^4.0.2",
|
||||||
"rector/rector": "^1.1.0",
|
"rector/rector": "1.1.1",
|
||||||
"symfony/debug-bundle": "^5.1",
|
"symfony/debug-bundle": "^5.1",
|
||||||
"symfony/dotenv": "^4.4",
|
"symfony/dotenv": "^4.4",
|
||||||
"symfony/maker-bundle": "^1.20",
|
"symfony/maker-bundle": "^1.20",
|
||||||
|
@@ -39,9 +39,12 @@ Implements a :code:`Chill\MainBundle\Cron\CronJobInterface`. Here is an example:
|
|||||||
use Chill\MainBundle\Entity\CronJobExecution;
|
use Chill\MainBundle\Entity\CronJobExecution;
|
||||||
use DateInterval;
|
use DateInterval;
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
|
use Symfony\Component\Clock\ClockInterface;
|
||||||
|
|
||||||
class MyCronJob implements CronJobInterface
|
class MyCronJob implements CronJobInterface
|
||||||
{
|
{
|
||||||
|
function __construct(private ClockInterface $clock) {}
|
||||||
|
|
||||||
public function canRun(?CronJobExecution $cronJobExecution): bool
|
public function canRun(?CronJobExecution $cronJobExecution): bool
|
||||||
{
|
{
|
||||||
// the parameter $cronJobExecution contains data about the last execution of the cronjob
|
// the parameter $cronJobExecution contains data about the last execution of the cronjob
|
||||||
@@ -56,7 +59,7 @@ Implements a :code:`Chill\MainBundle\Cron\CronJobInterface`. Here is an example:
|
|||||||
|
|
||||||
// this cron job should be executed if the last execution is greater than one day, but only during the night
|
// this cron job should be executed if the last execution is greater than one day, but only during the night
|
||||||
|
|
||||||
$now = new DateTimeImmutable('now');
|
$now = $clock->now();
|
||||||
|
|
||||||
return $cronJobExecution->getLastStart() < $now->sub(new DateInterval('P1D'))
|
return $cronJobExecution->getLastStart() < $now->sub(new DateInterval('P1D'))
|
||||||
&& in_array($now->format('H'), self::ACCEPTED_HOURS, true)
|
&& in_array($now->format('H'), self::ACCEPTED_HOURS, true)
|
||||||
@@ -69,10 +72,15 @@ Implements a :code:`Chill\MainBundle\Cron\CronJobInterface`. Here is an example:
|
|||||||
return 'arbitrary-and-unique-key';
|
return 'arbitrary-and-unique-key';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run(): void
|
public function run(array $lastExecutionData): void
|
||||||
{
|
{
|
||||||
// here, we execute the command
|
// here, we execute the command
|
||||||
}
|
|
||||||
|
// we return execution data, which will be served for next execution
|
||||||
|
// this data should be easily serializable in a json column: it should contains
|
||||||
|
// only int, string, etc. Avoid storing object
|
||||||
|
return ['last-execution-id' => 0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
How are cron job scheduled ?
|
How are cron job scheduled ?
|
||||||
|
@@ -42,11 +42,13 @@
|
|||||||
"@fullcalendar/vue3": "^6.1.4",
|
"@fullcalendar/vue3": "^6.1.4",
|
||||||
"@popperjs/core": "^2.9.2",
|
"@popperjs/core": "^2.9.2",
|
||||||
"@types/leaflet": "^1.9.3",
|
"@types/leaflet": "^1.9.3",
|
||||||
|
"@types/dompurify": "^3.0.5",
|
||||||
"dropzone": "^5.7.6",
|
"dropzone": "^5.7.6",
|
||||||
"es6-promise": "^4.2.8",
|
"es6-promise": "^4.2.8",
|
||||||
"leaflet": "^1.7.1",
|
"leaflet": "^1.7.1",
|
||||||
|
"marked": "^12.0.2",
|
||||||
"masonry-layout": "^4.2.2",
|
"masonry-layout": "^4.2.2",
|
||||||
"mime": "^3.0.0",
|
"mime": "^4.0.0",
|
||||||
"swagger-ui": "^4.15.5",
|
"swagger-ui": "^4.15.5",
|
||||||
"vis-network": "^9.1.0",
|
"vis-network": "^9.1.0",
|
||||||
"vue": "^3.2.37",
|
"vue": "^3.2.37",
|
||||||
|
@@ -32,9 +32,13 @@ return static function (RectorConfig $rectorConfig): void {
|
|||||||
//define sets of rules
|
//define sets of rules
|
||||||
$rectorConfig->sets([
|
$rectorConfig->sets([
|
||||||
LevelSetList::UP_TO_PHP_82,
|
LevelSetList::UP_TO_PHP_82,
|
||||||
\Rector\Symfony\Set\SymfonyLevelSetList::UP_TO_SYMFONY_44,
|
\Rector\Symfony\Set\SymfonySetList::SYMFONY_40,
|
||||||
|
\Rector\Symfony\Set\SymfonySetList::SYMFONY_41,
|
||||||
|
\Rector\Symfony\Set\SymfonySetList::SYMFONY_42,
|
||||||
|
\Rector\Symfony\Set\SymfonySetList::SYMFONY_43,
|
||||||
|
\Rector\Symfony\Set\SymfonySetList::SYMFONY_44,
|
||||||
\Rector\Doctrine\Set\DoctrineSetList::DOCTRINE_CODE_QUALITY,
|
\Rector\Doctrine\Set\DoctrineSetList::DOCTRINE_CODE_QUALITY,
|
||||||
\Rector\PHPUnit\Set\PHPUnitLevelSetList::UP_TO_PHPUNIT_90,
|
\Rector\PHPUnit\Set\PHPUnitSetList::PHPUNIT_90,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// some routes are added twice if it remains activated
|
// some routes are added twice if it remains activated
|
||||||
|
@@ -28,7 +28,7 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected ActivityReasonCategoryRepository $activityReasonCategoryRepository,
|
protected ActivityReasonCategoryRepository $activityReasonCategoryRepository,
|
||||||
protected ActivityReasonRepository $activityReasonRepository,
|
protected ActivityReasonRepository $activityReasonRepository,
|
||||||
protected TranslatableStringHelper $translatableStringHelper
|
protected TranslatableStringHelper $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,7 +26,7 @@ class ActivityUsersJobAggregator implements AggregatorInterface
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly UserJobRepositoryInterface $userJobRepository,
|
private readonly UserJobRepositoryInterface $userJobRepository,
|
||||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,7 +26,7 @@ class ActivityUsersScopeAggregator implements AggregatorInterface
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly ScopeRepositoryInterface $scopeRepository,
|
private readonly ScopeRepositoryInterface $scopeRepository,
|
||||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,7 +26,7 @@ class CreatorJobAggregator implements AggregatorInterface
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly UserJobRepositoryInterface $userJobRepository,
|
private readonly UserJobRepositoryInterface $userJobRepository,
|
||||||
private readonly TranslatableStringHelper $translatableStringHelper
|
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,7 +26,7 @@ class CreatorScopeAggregator implements AggregatorInterface
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly ScopeRepository $scopeRepository,
|
private readonly ScopeRepository $scopeRepository,
|
||||||
private readonly TranslatableStringHelper $translatableStringHelper
|
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -42,7 +42,7 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
|
|||||||
/**
|
/**
|
||||||
* The action for this report.
|
* The action for this report.
|
||||||
*/
|
*/
|
||||||
protected string $action = 'sum'
|
protected string $action = 'sum',
|
||||||
) {
|
) {
|
||||||
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
|
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
|
||||||
}
|
}
|
||||||
|
@@ -39,7 +39,7 @@ class ListActivityHelper
|
|||||||
private readonly TranslatorInterface $translator,
|
private readonly TranslatorInterface $translator,
|
||||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
private readonly TranslatableStringExportLabelHelper $translatableStringLabelHelper,
|
private readonly TranslatableStringExportLabelHelper $translatableStringLabelHelper,
|
||||||
private readonly UserHelper $userHelper
|
private readonly UserHelper $userHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -25,7 +25,7 @@ final readonly class ActivityPresenceFilter implements FilterInterface
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private TranslatableStringHelperInterface $translatableStringHelper,
|
private TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
private TranslatorInterface $translator
|
private TranslatorInterface $translator,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,7 +26,7 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected TranslatableStringHelperInterface $translatableStringHelper,
|
protected TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
protected ActivityTypeRepositoryInterface $activityTypeRepository
|
protected ActivityTypeRepositoryInterface $activityTypeRepository,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -29,7 +29,7 @@ class UsersJobFilter implements FilterInterface
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
private readonly UserJobRepositoryInterface $userJobRepository
|
private readonly UserJobRepositoryInterface $userJobRepository,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -29,7 +29,7 @@ class UsersScopeFilter implements FilterInterface
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly ScopeRepositoryInterface $scopeRepository,
|
private readonly ScopeRepositoryInterface $scopeRepository,
|
||||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -59,7 +59,7 @@ class ActivityType extends AbstractType
|
|||||||
protected TranslatableStringHelper $translatableStringHelper,
|
protected TranslatableStringHelper $translatableStringHelper,
|
||||||
protected array $timeChoices,
|
protected array $timeChoices,
|
||||||
protected SocialIssueRender $socialIssueRender,
|
protected SocialIssueRender $socialIssueRender,
|
||||||
protected SocialActionRender $socialActionRender
|
protected SocialActionRender $socialActionRender,
|
||||||
) {
|
) {
|
||||||
if (!$tokenStorage->getToken()->getUser() instanceof User) {
|
if (!$tokenStorage->getToken()->getUser() instanceof User) {
|
||||||
throw new \RuntimeException('you should have a valid user');
|
throw new \RuntimeException('you should have a valid user');
|
||||||
|
@@ -27,7 +27,7 @@ class PickActivityReasonType extends AbstractType
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly ActivityReasonRepository $activityReasonRepository,
|
private readonly ActivityReasonRepository $activityReasonRepository,
|
||||||
private readonly ActivityReasonRender $reasonRender,
|
private readonly ActivityReasonRender $reasonRender,
|
||||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\ActivityBundle\Menu;
|
||||||
|
|
||||||
|
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
|
||||||
|
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||||
|
use Knp\Menu\MenuItem;
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
|
||||||
|
final readonly class AccompanyingCourseQuickMenuBuilder implements LocalMenuBuilderInterface
|
||||||
|
{
|
||||||
|
public function __construct(private Security $security)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getMenuIds(): array
|
||||||
|
{
|
||||||
|
return ['accompanying_course_quick_menu'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||||
|
{
|
||||||
|
/** @var \Chill\PersonBundle\Entity\AccompanyingPeriod $accompanyingCourse */
|
||||||
|
$accompanyingCourse = $parameters['accompanying-course'];
|
||||||
|
|
||||||
|
if ($this->security->isGranted(ActivityVoter::CREATE, $accompanyingCourse)) {
|
||||||
|
$menu
|
||||||
|
->addChild('Create a new activity in accompanying course', [
|
||||||
|
'route' => 'chill_activity_activity_new',
|
||||||
|
'routeParameters' => [
|
||||||
|
// 'activityType_id' => '',
|
||||||
|
'accompanying_period_id' => $accompanyingCourse->getId(),
|
||||||
|
],
|
||||||
|
])
|
||||||
|
->setExtras([
|
||||||
|
'order' => 10,
|
||||||
|
'icon' => 'plus',
|
||||||
|
])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -32,7 +32,7 @@ final readonly class ActivityDocumentACLAwareRepository implements ActivityDocum
|
|||||||
private EntityManagerInterface $em,
|
private EntityManagerInterface $em,
|
||||||
private CenterResolverManagerInterface $centerResolverManager,
|
private CenterResolverManagerInterface $centerResolverManager,
|
||||||
private AuthorizationHelperForCurrentUserInterface $authorizationHelperForCurrentUser,
|
private AuthorizationHelperForCurrentUserInterface $authorizationHelperForCurrentUser,
|
||||||
private Security $security
|
private Security $security,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -25,7 +25,7 @@ class ActivityReasonRepository extends ServiceEntityRepository
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ManagerRegistry $registry,
|
ManagerRegistry $registry,
|
||||||
private readonly RequestStack $requestStack
|
private readonly RequestStack $requestStack,
|
||||||
) {
|
) {
|
||||||
parent::__construct($registry, ActivityReason::class);
|
parent::__construct($registry, ActivityReason::class);
|
||||||
}
|
}
|
||||||
|
@@ -68,7 +68,7 @@
|
|||||||
<div class="wl-col title"><h3>{{ 'Referrer'|trans }}</h3></div>
|
<div class="wl-col title"><h3>{{ 'Referrer'|trans }}</h3></div>
|
||||||
<div class="wl-col list">
|
<div class="wl-col list">
|
||||||
<p class="wl-item">
|
<p class="wl-item">
|
||||||
<span class="badge-user">{{ activity.user|chill_entity_render_box }}</span>
|
<span class="badge-user">{{ activity.user|chill_entity_render_box({'at_date': activity.date}) }}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -87,7 +87,7 @@
|
|||||||
<li>
|
<li>
|
||||||
{% if bloc.type == 'user' %}
|
{% if bloc.type == 'user' %}
|
||||||
<span class="badge-user">
|
<span class="badge-user">
|
||||||
{{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false }) }}
|
{{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false, 'at_date': entity.date }) }}
|
||||||
</span>
|
</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ _self.insert_onthefly(bloc.type, item) }}
|
{{ _self.insert_onthefly(bloc.type, item) }}
|
||||||
@@ -114,7 +114,7 @@
|
|||||||
<li>
|
<li>
|
||||||
{% if bloc.type == 'user' %}
|
{% if bloc.type == 'user' %}
|
||||||
<span class="badge-user">
|
<span class="badge-user">
|
||||||
{{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false }) }}
|
{{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false, 'at_date': entity.date }) }}
|
||||||
</span>
|
</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ _self.insert_onthefly(bloc.type, item) }}
|
{{ _self.insert_onthefly(bloc.type, item) }}
|
||||||
@@ -142,7 +142,7 @@
|
|||||||
<span class="wl-item">
|
<span class="wl-item">
|
||||||
{% if bloc.type == 'user' %}
|
{% if bloc.type == 'user' %}
|
||||||
<span class="badge-user">
|
<span class="badge-user">
|
||||||
{{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false }) }}
|
{{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false, 'at_date': entity.date }) }}
|
||||||
{%- if context == 'calendar_accompanyingCourse' or context == 'calendar_person' %}
|
{%- if context == 'calendar_accompanyingCourse' or context == 'calendar_person' %}
|
||||||
{% set invite = entity.inviteForUser(item) %}
|
{% set invite = entity.inviteForUser(item) %}
|
||||||
{% if invite is not null %}
|
{% if invite is not null %}
|
||||||
|
@@ -41,7 +41,7 @@
|
|||||||
{% if activity.user and t.userVisible %}
|
{% if activity.user and t.userVisible %}
|
||||||
<li>
|
<li>
|
||||||
<span class="item-key">{{ 'Referrer'|trans ~ ': ' }}</span>
|
<span class="item-key">{{ 'Referrer'|trans ~ ': ' }}</span>
|
||||||
<span class="badge-user">{{ activity.user|chill_entity_render_box }}</span>
|
<span class="badge-user">{{ activity.user|chill_entity_render_box({'at_date': activity.date}) }}</span>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@@ -37,7 +37,7 @@
|
|||||||
{%- if entity.user is not null %}
|
{%- if entity.user is not null %}
|
||||||
<dt class="inline">{{ 'Referrer'|trans|capitalize }}</dt>
|
<dt class="inline">{{ 'Referrer'|trans|capitalize }}</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<span class="badge-user">{{ entity.user|chill_entity_render_box }}</span>
|
<span class="badge-user">{{ entity.user|chill_entity_render_box({'at_date': entity.date}) }}</span>
|
||||||
</dd>
|
</dd>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@@ -75,7 +75,7 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected Security $security,
|
protected Security $security,
|
||||||
VoterHelperFactoryInterface $voterHelperFactory
|
VoterHelperFactoryInterface $voterHelperFactory,
|
||||||
) {
|
) {
|
||||||
$this->voterHelper = $voterHelperFactory->generate(self::class)
|
$this->voterHelper = $voterHelperFactory->generate(self::class)
|
||||||
->addCheckFor(Person::class, [self::SEE, self::CREATE])
|
->addCheckFor(Person::class, [self::SEE, self::CREATE])
|
||||||
@@ -145,7 +145,7 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
|
|||||||
throw new \RuntimeException('Could not determine context of activity.');
|
throw new \RuntimeException('Could not determine context of activity.');
|
||||||
}
|
}
|
||||||
} elseif ($subject instanceof AccompanyingPeriod) {
|
} elseif ($subject instanceof AccompanyingPeriod) {
|
||||||
if (AccompanyingPeriod::STEP_CLOSED === $subject->getStep()) {
|
if (AccompanyingPeriod::STEP_CLOSED === $subject->getStep() || AccompanyingPeriod::STEP_DRAFT === $subject->getStep()) {
|
||||||
if (\in_array($attribute, [self::UPDATE, self::CREATE, self::DELETE], true)) {
|
if (\in_array($attribute, [self::UPDATE, self::CREATE, self::DELETE], true)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -50,7 +50,7 @@ class ActivityContext implements
|
|||||||
private readonly TranslatorInterface $translator,
|
private readonly TranslatorInterface $translator,
|
||||||
private readonly BaseContextData $baseContextData,
|
private readonly BaseContextData $baseContextData,
|
||||||
private readonly ThirdPartyRender $thirdPartyRender,
|
private readonly ThirdPartyRender $thirdPartyRender,
|
||||||
private readonly ThirdPartyRepository $thirdPartyRepository
|
private readonly ThirdPartyRepository $thirdPartyRepository,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -56,7 +56,7 @@ class ListActivitiesByAccompanyingPeriodContext implements
|
|||||||
private readonly SocialIssueRepository $socialIssueRepository,
|
private readonly SocialIssueRepository $socialIssueRepository,
|
||||||
private readonly ThirdPartyRepository $thirdPartyRepository,
|
private readonly ThirdPartyRepository $thirdPartyRepository,
|
||||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
private readonly UserRepository $userRepository
|
private readonly UserRepository $userRepository,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -76,7 +76,7 @@ final class TranslatableActivityReasonTest extends TypeTestCase
|
|||||||
*/
|
*/
|
||||||
protected function getTranslatableStringHelper(
|
protected function getTranslatableStringHelper(
|
||||||
$locale = 'en',
|
$locale = 'en',
|
||||||
$fallbackLocale = 'en'
|
$fallbackLocale = 'en',
|
||||||
) {
|
) {
|
||||||
$prophet = new \Prophecy\Prophet();
|
$prophet = new \Prophecy\Prophet();
|
||||||
$requestStack = $prophet->prophesize();
|
$requestStack = $prophet->prophesize();
|
||||||
|
@@ -60,7 +60,7 @@ final class TranslatableActivityTypeTest extends KernelTestCase
|
|||||||
$this->assertInstanceOf(
|
$this->assertInstanceOf(
|
||||||
ActivityType::class,
|
ActivityType::class,
|
||||||
$form->getData()['type'],
|
$form->getData()['type'],
|
||||||
'The data is an instance of Chill\\ActivityBundle\\Entity\\ActivityType'
|
'The data is an instance of Chill\ActivityBundle\Entity\ActivityType'
|
||||||
);
|
);
|
||||||
$this->assertEquals($type->getId(), $form->getData()['type']->getId());
|
$this->assertEquals($type->getId(), $form->getData()['type']->getId());
|
||||||
|
|
||||||
|
@@ -138,7 +138,7 @@ final class ActivityVoterTest extends KernelTestCase
|
|||||||
Scope $scope,
|
Scope $scope,
|
||||||
Center $center,
|
Center $center,
|
||||||
$attribute,
|
$attribute,
|
||||||
$message
|
$message,
|
||||||
) {
|
) {
|
||||||
$token = $this->prepareToken($user);
|
$token = $this->prepareToken($user);
|
||||||
$activity = $this->prepareActivity($scope, $this->preparePerson($center));
|
$activity = $this->prepareActivity($scope, $this->preparePerson($center));
|
||||||
|
@@ -32,7 +32,7 @@ class TimelineActivityProvider implements TimelineProviderInterface
|
|||||||
protected EntityManagerInterface $em,
|
protected EntityManagerInterface $em,
|
||||||
protected AuthorizationHelperInterface $helper,
|
protected AuthorizationHelperInterface $helper,
|
||||||
TokenStorageInterface $storage,
|
TokenStorageInterface $storage,
|
||||||
protected ActivityACLAwareRepository $aclAwareRepository
|
protected ActivityACLAwareRepository $aclAwareRepository,
|
||||||
) {
|
) {
|
||||||
if (!$storage->getToken()->getUser() instanceof User) {
|
if (!$storage->getToken()->getUser() instanceof User) {
|
||||||
throw new \RuntimeException('A user should be authenticated !');
|
throw new \RuntimeException('A user should be authenticated !');
|
||||||
|
@@ -222,6 +222,7 @@ Documents label: Libellé du champ Documents
|
|||||||
# activity type category admin
|
# activity type category admin
|
||||||
ActivityTypeCategory list: Liste des catégories des types d'échange
|
ActivityTypeCategory list: Liste des catégories des types d'échange
|
||||||
Create a new activity type category: Créer une nouvelle catégorie de type d'échange
|
Create a new activity type category: Créer une nouvelle catégorie de type d'échange
|
||||||
|
Create a new activity in accompanying course: Créer un échange dans le parcours
|
||||||
|
|
||||||
# activity delete
|
# activity delete
|
||||||
Remove activity: Supprimer un échange
|
Remove activity: Supprimer un échange
|
||||||
|
@@ -66,7 +66,7 @@ final class AsideActivityController extends CRUDController
|
|||||||
string $action,
|
string $action,
|
||||||
$query,
|
$query,
|
||||||
Request $request,
|
Request $request,
|
||||||
PaginatorInterface $paginator
|
PaginatorInterface $paginator,
|
||||||
) {
|
) {
|
||||||
if ('index' === $action) {
|
if ('index' === $action) {
|
||||||
return $query->orderBy('e.date', 'DESC');
|
return $query->orderBy('e.date', 'DESC');
|
||||||
|
@@ -22,7 +22,7 @@ class ByActivityTypeAggregator implements AggregatorInterface
|
|||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly AsideActivityCategoryRepository $asideActivityCategoryRepository,
|
private readonly AsideActivityCategoryRepository $asideActivityCategoryRepository,
|
||||||
private readonly TranslatableStringHelper $translatableStringHelper
|
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,7 +26,7 @@ class ByUserJobAggregator implements AggregatorInterface
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly UserJobRepositoryInterface $userJobRepository,
|
private readonly UserJobRepositoryInterface $userJobRepository,
|
||||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,7 +26,7 @@ class ByUserScopeAggregator implements AggregatorInterface
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly ScopeRepositoryInterface $scopeRepository,
|
private readonly ScopeRepositoryInterface $scopeRepository,
|
||||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -41,7 +41,7 @@ final readonly class ListAsideActivity implements ListInterface, GroupedExportIn
|
|||||||
private AsideActivityCategoryRepository $asideActivityCategoryRepository,
|
private AsideActivityCategoryRepository $asideActivityCategoryRepository,
|
||||||
private CategoryRender $categoryRender,
|
private CategoryRender $categoryRender,
|
||||||
private LocationRepository $locationRepository,
|
private LocationRepository $locationRepository,
|
||||||
private TranslatableStringHelperInterface $translatableStringHelper
|
private TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -27,7 +27,7 @@ class ByActivityTypeFilter implements FilterInterface
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly CategoryRender $categoryRender,
|
private readonly CategoryRender $categoryRender,
|
||||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
private readonly AsideActivityCategoryRepository $asideActivityTypeRepository
|
private readonly AsideActivityCategoryRepository $asideActivityTypeRepository,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,7 +24,7 @@ use Symfony\Component\Security\Core\Security;
|
|||||||
final readonly class ByLocationFilter implements FilterInterface
|
final readonly class ByLocationFilter implements FilterInterface
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private Security $security
|
private Security $security,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -29,7 +29,7 @@ class ByUserJobFilter implements FilterInterface
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
private readonly UserJobRepositoryInterface $userJobRepository
|
private readonly UserJobRepositoryInterface $userJobRepository,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -29,7 +29,7 @@ class ByUserScopeFilter implements FilterInterface
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly ScopeRepositoryInterface $scopeRepository,
|
private readonly ScopeRepositoryInterface $scopeRepository,
|
||||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -44,7 +44,7 @@ class UserMenuBuilder implements LocalMenuBuilderInterface
|
|||||||
CountNotificationTask $counter,
|
CountNotificationTask $counter,
|
||||||
TokenStorageInterface $tokenStorage,
|
TokenStorageInterface $tokenStorage,
|
||||||
TranslatorInterface $translator,
|
TranslatorInterface $translator,
|
||||||
AuthorizationCheckerInterface $authorizationChecker
|
AuthorizationCheckerInterface $authorizationChecker,
|
||||||
) {
|
) {
|
||||||
$this->counter = $counter;
|
$this->counter = $counter;
|
||||||
$this->tokenStorage = $tokenStorage;
|
$this->tokenStorage = $tokenStorage;
|
||||||
|
@@ -49,13 +49,13 @@
|
|||||||
<li>
|
<li>
|
||||||
<span>
|
<span>
|
||||||
<abbr class="referrer" title={{ 'Created by'|trans }}>{{ 'By'|trans }}:</abbr>
|
<abbr class="referrer" title={{ 'Created by'|trans }}>{{ 'By'|trans }}:</abbr>
|
||||||
<b>{{ entity.createdBy|chill_entity_render_box }}</b>
|
<b>{{ entity.createdBy|chill_entity_render_box({'at_date': entity.date}) }}</b>
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span>
|
<span>
|
||||||
<abbr class="referrer" title={{ 'Created for'|trans }}>{{ 'For'|trans }}:</abbr>
|
<abbr class="referrer" title={{ 'Created for'|trans }}>{{ 'For'|trans }}:</abbr>
|
||||||
<b>{{ entity.agent|chill_entity_render_box }}</b>
|
<b>{{ entity.agent|chill_entity_render_box({'at_date': entity.date}) }}</b>
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
|
@@ -18,11 +18,11 @@
|
|||||||
<dd>{{ entity.type|chill_entity_render_box }}</dd>
|
<dd>{{ entity.type|chill_entity_render_box }}</dd>
|
||||||
|
|
||||||
<dt class="inline">{{ 'Created by'|trans }}</dt>
|
<dt class="inline">{{ 'Created by'|trans }}</dt>
|
||||||
<dd>{{ entity.createdBy }}</dd>
|
<dd>{{ entity.createdBy|chill_entity_render_box({'at_date': entity.date}) }}</dd>
|
||||||
|
|
||||||
<dt class="inline">{{ 'Created for'|trans }}</dt>
|
<dt class="inline">{{ 'Created for'|trans }}</dt>
|
||||||
<dd>{{ entity.agent }}</dd>
|
<dd>{{ entity.agent|chill_entity_render_box({'at_date': entity.date}) }}</dd>
|
||||||
|
|
||||||
<dt class="inline">{{ 'Asideactivity location'|trans }}</dt>
|
<dt class="inline">{{ 'Asideactivity location'|trans }}</dt>
|
||||||
{%- if entity.location.name is defined -%}
|
{%- if entity.location.name is defined -%}
|
||||||
<dd>{{ entity.location.name }}</dd>
|
<dd>{{ entity.location.name }}</dd>
|
||||||
|
@@ -26,7 +26,7 @@ class AsideActivityVoter extends AbstractChillVoter implements ProvideRoleHierar
|
|||||||
private readonly VoterHelperInterface $voterHelper;
|
private readonly VoterHelperInterface $voterHelper;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
VoterHelperFactoryInterface $voterHelperFactory
|
VoterHelperFactoryInterface $voterHelperFactory,
|
||||||
) {
|
) {
|
||||||
$this->voterHelper = $voterHelperFactory
|
$this->voterHelper = $voterHelperFactory
|
||||||
->generate(self::class)
|
->generate(self::class)
|
||||||
|
@@ -45,7 +45,7 @@ class SendTestShortMessageOnCalendarCommand extends Command
|
|||||||
private readonly PhoneNumberHelperInterface $phoneNumberHelper,
|
private readonly PhoneNumberHelperInterface $phoneNumberHelper,
|
||||||
private readonly ShortMessageForCalendarBuilderInterface $messageForCalendarBuilder,
|
private readonly ShortMessageForCalendarBuilderInterface $messageForCalendarBuilder,
|
||||||
private readonly ShortMessageTransporterInterface $transporter,
|
private readonly ShortMessageTransporterInterface $transporter,
|
||||||
private readonly UserRepositoryInterface $userRepository
|
private readonly UserRepositoryInterface $userRepository,
|
||||||
) {
|
) {
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
@@ -58,7 +58,7 @@ class CalendarController extends AbstractController
|
|||||||
private readonly PersonRepository $personRepository,
|
private readonly PersonRepository $personRepository,
|
||||||
private readonly AccompanyingPeriodRepository $accompanyingPeriodRepository,
|
private readonly AccompanyingPeriodRepository $accompanyingPeriodRepository,
|
||||||
private readonly UserRepositoryInterface $userRepository,
|
private readonly UserRepositoryInterface $userRepository,
|
||||||
private readonly TranslatorInterface $translator
|
private readonly TranslatorInterface $translator,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -524,6 +524,16 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface, HasCente
|
|||||||
return $this->startDate;
|
return $this->startDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the date of the calendar.
|
||||||
|
*
|
||||||
|
* Useful for showing the date of the calendar event, required by twig in some places.
|
||||||
|
*/
|
||||||
|
public function getDate(): ?\DateTimeImmutable
|
||||||
|
{
|
||||||
|
return $this->getStartDate();
|
||||||
|
}
|
||||||
|
|
||||||
public function getStatus(): ?string
|
public function getStatus(): ?string
|
||||||
{
|
{
|
||||||
return $this->status;
|
return $this->status;
|
||||||
|
@@ -26,7 +26,7 @@ final readonly class JobAggregator implements AggregatorInterface
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private UserJobRepository $jobRepository,
|
private UserJobRepository $jobRepository,
|
||||||
private TranslatableStringHelper $translatableStringHelper
|
private TranslatableStringHelper $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,7 +26,7 @@ final readonly class ScopeAggregator implements AggregatorInterface
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private ScopeRepository $scopeRepository,
|
private ScopeRepository $scopeRepository,
|
||||||
private TranslatableStringHelper $translatableStringHelper
|
private TranslatableStringHelper $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -28,7 +28,7 @@ final readonly class JobFilter implements FilterInterface
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private TranslatableStringHelper $translatableStringHelper,
|
private TranslatableStringHelper $translatableStringHelper,
|
||||||
private UserJobRepositoryInterface $userJobRepository
|
private UserJobRepositoryInterface $userJobRepository,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -30,7 +30,7 @@ class ScopeFilter implements FilterInterface
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected TranslatorInterface $translator,
|
protected TranslatorInterface $translator,
|
||||||
private readonly TranslatableStringHelper $translatableStringHelper,
|
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||||
private readonly ScopeRepositoryInterface $scopeRepository
|
private readonly ScopeRepositoryInterface $scopeRepository,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -37,7 +37,7 @@ class CalendarType extends AbstractType
|
|||||||
private readonly IdToUsersDataTransformer $idToUsersDataTransformer,
|
private readonly IdToUsersDataTransformer $idToUsersDataTransformer,
|
||||||
private readonly IdToLocationDataTransformer $idToLocationDataTransformer,
|
private readonly IdToLocationDataTransformer $idToLocationDataTransformer,
|
||||||
private readonly ThirdPartiesToIdDataTransformer $partiesToIdDataTransformer,
|
private readonly ThirdPartiesToIdDataTransformer $partiesToIdDataTransformer,
|
||||||
private readonly IdToCalendarRangeDataTransformer $calendarRangeDataTransformer
|
private readonly IdToCalendarRangeDataTransformer $calendarRangeDataTransformer,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\CalendarBundle\Menu;
|
||||||
|
|
||||||
|
use Chill\CalendarBundle\Security\Voter\CalendarVoter;
|
||||||
|
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||||
|
use Knp\Menu\MenuItem;
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
|
||||||
|
final readonly class AccompanyingCourseQuickMenuBuilder implements LocalMenuBuilderInterface
|
||||||
|
{
|
||||||
|
public function __construct(private Security $security)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getMenuIds(): array
|
||||||
|
{
|
||||||
|
return ['accompanying_course_quick_menu'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||||
|
{
|
||||||
|
/** @var \Chill\PersonBundle\Entity\AccompanyingPeriod $accompanyingCourse */
|
||||||
|
$accompanyingCourse = $parameters['accompanying-course'];
|
||||||
|
|
||||||
|
if ($this->security->isGranted(CalendarVoter::CREATE, $accompanyingCourse)) {
|
||||||
|
$menu
|
||||||
|
->addChild('Create a new calendar in accompanying course', [
|
||||||
|
'route' => 'chill_calendar_calendar_new',
|
||||||
|
'routeParameters' => [
|
||||||
|
'accompanying_period_id' => $accompanyingCourse->getId(),
|
||||||
|
],
|
||||||
|
])
|
||||||
|
->setExtras([
|
||||||
|
'order' => 20,
|
||||||
|
'icon' => 'plus',
|
||||||
|
])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -46,7 +46,7 @@ class CalendarMessage
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
Calendar $calendar,
|
Calendar $calendar,
|
||||||
private readonly string $action,
|
private readonly string $action,
|
||||||
User $byUser
|
User $byUser,
|
||||||
) {
|
) {
|
||||||
$this->calendarId = $calendar->getId();
|
$this->calendarId = $calendar->getId();
|
||||||
$this->byUserId = $byUser->getId();
|
$this->byUserId = $byUser->getId();
|
||||||
|
@@ -60,7 +60,7 @@ final readonly class MSUserAbsenceReader implements MSUserAbsenceReaderInterface
|
|||||||
'alwaysEnabled' => true,
|
'alwaysEnabled' => true,
|
||||||
'scheduled' => RemoteEventConverter::convertStringDateWithoutTimezone($automaticRepliesSettings['scheduledStartDateTime']['dateTime']) < $this->clock->now()
|
'scheduled' => RemoteEventConverter::convertStringDateWithoutTimezone($automaticRepliesSettings['scheduledStartDateTime']['dateTime']) < $this->clock->now()
|
||||||
&& RemoteEventConverter::convertStringDateWithoutTimezone($automaticRepliesSettings['scheduledEndDateTime']['dateTime']) > $this->clock->now(),
|
&& RemoteEventConverter::convertStringDateWithoutTimezone($automaticRepliesSettings['scheduledEndDateTime']['dateTime']) > $this->clock->now(),
|
||||||
default => throw new UserAbsenceSyncException('this status is not documented by Microsoft')
|
default => throw new UserAbsenceSyncException('this status is not documented by Microsoft'),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -179,7 +179,7 @@ class MapCalendarToUser
|
|||||||
User $user,
|
User $user,
|
||||||
int $expiration,
|
int $expiration,
|
||||||
?string $id = null,
|
?string $id = null,
|
||||||
?string $secret = null
|
?string $secret = null,
|
||||||
): void {
|
): void {
|
||||||
$user->setAttributeByDomain(self::METADATA_KEY, self::EXPIRATION_SUBSCRIPTION_EVENT, $expiration);
|
$user->setAttributeByDomain(self::METADATA_KEY, self::EXPIRATION_SUBSCRIPTION_EVENT, $expiration);
|
||||||
|
|
||||||
|
@@ -37,12 +37,12 @@ class RemoteEventConverter
|
|||||||
* valid when the remote string contains also a timezone, like in
|
* valid when the remote string contains also a timezone, like in
|
||||||
* lastModifiedDate.
|
* lastModifiedDate.
|
||||||
*/
|
*/
|
||||||
final public const REMOTE_DATETIMEZONE_FORMAT = 'Y-m-d\\TH:i:s.u?P';
|
final public const REMOTE_DATETIMEZONE_FORMAT = 'Y-m-d\TH:i:s.u?P';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as above, but sometimes the date is expressed with only 6 milliseconds.
|
* Same as above, but sometimes the date is expressed with only 6 milliseconds.
|
||||||
*/
|
*/
|
||||||
final public const REMOTE_DATETIMEZONE_FORMAT_ALT = 'Y-m-d\\TH:i:s.uP';
|
final public const REMOTE_DATETIMEZONE_FORMAT_ALT = 'Y-m-d\TH:i:s.uP';
|
||||||
|
|
||||||
private const REMOTE_DATE_FORMAT = 'Y-m-d\TH:i:s.u0';
|
private const REMOTE_DATE_FORMAT = 'Y-m-d\TH:i:s.u0';
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ class RemoteEventConverter
|
|||||||
private readonly LocationConverter $locationConverter,
|
private readonly LocationConverter $locationConverter,
|
||||||
private readonly LoggerInterface $logger,
|
private readonly LoggerInterface $logger,
|
||||||
private readonly PersonRenderInterface $personRender,
|
private readonly PersonRenderInterface $personRender,
|
||||||
private readonly TranslatorInterface $translator
|
private readonly TranslatorInterface $translator,
|
||||||
) {
|
) {
|
||||||
$this->defaultDateTimeZone = (new \DateTimeImmutable())->getTimezone();
|
$this->defaultDateTimeZone = (new \DateTimeImmutable())->getTimezone();
|
||||||
$this->remoteDateTimeZone = self::getRemoteTimeZone();
|
$this->remoteDateTimeZone = self::getRemoteTimeZone();
|
||||||
|
@@ -353,7 +353,7 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface
|
|||||||
[
|
[
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
'lastModifiedDateTime' => $lastModified,
|
'lastModifiedDateTime' => $lastModified,
|
||||||
'changeKey' => $changeKey
|
'changeKey' => $changeKey,
|
||||||
] = $this->createOnRemote($eventData, $calendar->getMainUser(), 'calendar_'.$calendar->getId());
|
] = $this->createOnRemote($eventData, $calendar->getMainUser(), 'calendar_'.$calendar->getId());
|
||||||
|
|
||||||
if (null === $id) {
|
if (null === $id) {
|
||||||
@@ -429,7 +429,7 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface
|
|||||||
[
|
[
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
'lastModifiedDateTime' => $lastModified,
|
'lastModifiedDateTime' => $lastModified,
|
||||||
'changeKey' => $changeKey
|
'changeKey' => $changeKey,
|
||||||
] = $this->createOnRemote(
|
] = $this->createOnRemote(
|
||||||
$eventData,
|
$eventData,
|
||||||
$calendarRange->getUser(),
|
$calendarRange->getUser(),
|
||||||
@@ -566,7 +566,7 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface
|
|||||||
[
|
[
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
'lastModifiedDateTime' => $lastModified,
|
'lastModifiedDateTime' => $lastModified,
|
||||||
'changeKey' => $changeKey
|
'changeKey' => $changeKey,
|
||||||
] = $this->patchOnRemote(
|
] = $this->patchOnRemote(
|
||||||
$calendar->getRemoteId(),
|
$calendar->getRemoteId(),
|
||||||
$eventData,
|
$eventData,
|
||||||
|
@@ -43,7 +43,7 @@ class RemoteEvent
|
|||||||
/**
|
/**
|
||||||
* @Serializer\Groups({"read"})
|
* @Serializer\Groups({"read"})
|
||||||
*/
|
*/
|
||||||
public bool $isAllDay = false
|
public bool $isAllDay = false,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -65,7 +65,7 @@ class CalendarRangeRepository implements ObjectRepository
|
|||||||
\DateTimeImmutable $from,
|
\DateTimeImmutable $from,
|
||||||
\DateTimeImmutable $to,
|
\DateTimeImmutable $to,
|
||||||
?int $limit = null,
|
?int $limit = null,
|
||||||
?int $offset = null
|
?int $offset = null,
|
||||||
): array {
|
): array {
|
||||||
$qb = $this->buildQueryAvailableRangesForUser($user, $from, $to);
|
$qb = $this->buildQueryAvailableRangesForUser($user, $from, $to);
|
||||||
|
|
||||||
|
@@ -1 +1,2 @@
|
|||||||
import './scss/badge.scss';
|
import './scss/badge.scss';
|
||||||
|
import './scss/calendar-list.scss';
|
||||||
|
@@ -0,0 +1,26 @@
|
|||||||
|
ul.calendar-list {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
& > li {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
& > li:nth-child(n+2) {
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div.calendar-list {
|
||||||
|
|
||||||
|
ul.calendar-list {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > a.calendar-list__global {
|
||||||
|
display: inline-block;;
|
||||||
|
padding: 0.2rem;
|
||||||
|
min-width: 2rem;
|
||||||
|
border: 1px solid var(--bs-chill-blue);
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
@@ -16,6 +16,7 @@
|
|||||||
:removableIfSet="false"
|
:removableIfSet="false"
|
||||||
:displayPicked="false"
|
:displayPicked="false"
|
||||||
:suggested="this.suggestedUsers"
|
:suggested="this.suggestedUsers"
|
||||||
|
:label="'Utilisateur principal'"
|
||||||
@addNewEntity="setMainUser"
|
@addNewEntity="setMainUser"
|
||||||
></pick-entity>
|
></pick-entity>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<label class="form-label">{{ $t('created_availabilities') }}</label>
|
<label class="form-label">{{ $t("created_availabilities") }}</label>
|
||||||
<vue-multiselect
|
<vue-multiselect
|
||||||
v-model="pickedLocation"
|
v-model="pickedLocation"
|
||||||
:options="locations"
|
:options="locations"
|
||||||
@@ -14,10 +14,15 @@
|
|||||||
></vue-multiselect>
|
></vue-multiselect>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="display-options row justify-content-between" style="margin-top: 1rem;">
|
<div
|
||||||
|
class="display-options row justify-content-between"
|
||||||
|
style="margin-top: 1rem"
|
||||||
|
>
|
||||||
<div class="col-sm-9 col-xs-12">
|
<div class="col-sm-9 col-xs-12">
|
||||||
<div class="input-group mb-3">
|
<div class="input-group mb-3">
|
||||||
<label class="input-group-text" for="slotDuration">Durée des créneaux</label>
|
<label class="input-group-text" for="slotDuration"
|
||||||
|
>Durée des créneaux</label
|
||||||
|
>
|
||||||
<select v-model="slotDuration" id="slotDuration" class="form-select">
|
<select v-model="slotDuration" id="slotDuration" class="form-select">
|
||||||
<option value="00:05:00">5 minutes</option>
|
<option value="00:05:00">5 minutes</option>
|
||||||
<option value="00:10:00">10 minutes</option>
|
<option value="00:10:00">10 minutes</option>
|
||||||
@@ -58,13 +63,20 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3 col-xs-12">
|
<div class="col-xs-12 col-sm-3">
|
||||||
<div class="float-end">
|
<div class="float-end">
|
||||||
<div class="form-check input-group">
|
<div class="form-check input-group">
|
||||||
<span class="input-group-text">
|
<span class="input-group-text">
|
||||||
<input id="showHideWE" class="mt-0" type="checkbox" v-model="showWeekends">
|
<input
|
||||||
|
id="showHideWE"
|
||||||
|
class="mt-0"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="showWeekends"
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
<label for="showHideWE" class="form-check-label input-group-text">Week-ends</label>
|
<label for="showHideWE" class="form-check-label input-group-text"
|
||||||
|
>Week-ends</label
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -72,39 +84,86 @@
|
|||||||
<FullCalendar :options="calendarOptions" ref="calendarRef">
|
<FullCalendar :options="calendarOptions" ref="calendarRef">
|
||||||
<template v-slot:eventContent="arg: EventApi">
|
<template v-slot:eventContent="arg: EventApi">
|
||||||
<span :class="eventClasses(arg.event)">
|
<span :class="eventClasses(arg.event)">
|
||||||
<b v-if="arg.event.extendedProps.is === 'remote'">{{ arg.event.title}}</b>
|
<b v-if="arg.event.extendedProps.is === 'remote'">{{
|
||||||
<b v-else-if="arg.event.extendedProps.is === 'range'">{{ arg.timeText }} - {{ arg.event.extendedProps.locationName }}</b>
|
arg.event.title
|
||||||
<b v-else-if="arg.event.extendedProps.is === 'local'">{{ arg.event.title}}</b>
|
}}</b>
|
||||||
<b v-else >no 'is'</b>
|
<b v-else-if="arg.event.extendedProps.is === 'range'"
|
||||||
<a v-if="arg.event.extendedProps.is === 'range'" class="fa fa-fw fa-times delete"
|
>{{ arg.timeText }} - {{ arg.event.extendedProps.locationName }}</b
|
||||||
@click.prevent="onClickDelete(arg.event)">
|
>
|
||||||
</a>
|
<b v-else-if="arg.event.extendedProps.is === 'local'">{{
|
||||||
</span>
|
arg.event.title
|
||||||
|
}}</b>
|
||||||
|
<b v-else>no 'is'</b>
|
||||||
|
<a
|
||||||
|
v-if="arg.event.extendedProps.is === 'range'"
|
||||||
|
class="fa fa-fw fa-times delete"
|
||||||
|
@click.prevent="onClickDelete(arg.event)"
|
||||||
|
>
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</FullCalendar>
|
</FullCalendar>
|
||||||
|
|
||||||
<div id="copy-widget">
|
<div id="copy-widget">
|
||||||
<div class="container">
|
<div class="container mt-2 mb-2">
|
||||||
<div class="row align-items-center">
|
|
||||||
<div class="col-sm-4 col-xs-12">
|
<div class="row justify-content-between align-items-center mb-4">
|
||||||
<h6 class="chill-red">{{ $t('copy_range_from_to') }}</h6>
|
<div class="col-xs-12 col-sm-3 col-md-2">
|
||||||
</div>
|
<h6 class="chill-red">{{ $t("copy_range_from_to") }}</h6>
|
||||||
<div class="col-sm-3 col-xs-12">
|
</div>
|
||||||
<input class="form-control" type="date" v-model="copyFrom" />
|
<div class="col-xs-12 col-sm-9 col-md-2">
|
||||||
</div>
|
<select v-model="dayOrWeek" id="dayOrWeek" class="form-select">
|
||||||
<div class="col-sm-1 col-xs-12" style="text-align: center; font-size: x-large;">
|
<option value="day">{{ $t("from_day_to_day") }}</option>
|
||||||
<i class="fa fa-angle-double-right"></i>
|
<option value="week">{{ $t("from_week_to_week") }}</option>
|
||||||
</div>
|
</select>
|
||||||
<div class="col-sm-3 col-xs-12" >
|
</div>
|
||||||
<input class="form-control" type="date" v-model="copyTo" />
|
<template v-if="dayOrWeek === 'day'">
|
||||||
</div>
|
<div class="col-xs-12 col-sm-3 col-md-3">
|
||||||
<div class="col-sm-1">
|
<input class="form-control" type="date" v-model="copyFrom" />
|
||||||
<button class="btn btn-action" @click="copyDay">
|
</div>
|
||||||
{{ $t('copy_range') }}
|
<div class="col-xs-12 col-sm-1 col-md-1 copy-chevron">
|
||||||
</button>
|
<i class="fa fa-angle-double-right"></i>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-3 col-md-3">
|
||||||
|
<input class="form-control" type="date" v-model="copyTo" />
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-5 col-md-1">
|
||||||
|
<button class="btn btn-action float-end" @click="copyDay">
|
||||||
|
{{ $t("copy_range") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div class="col-xs-12 col-sm-3 col-md-3">
|
||||||
|
<select
|
||||||
|
v-model="copyFromWeek"
|
||||||
|
id="copyFromWeek"
|
||||||
|
class="form-select"
|
||||||
|
>
|
||||||
|
<option v-for="w in lastWeeks" :value="w.value" :key="w.value">
|
||||||
|
{{ w.text }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-1 col-md-1 copy-chevron">
|
||||||
|
<i class="fa fa-angle-double-right"></i>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-3 col-md-3">
|
||||||
|
<select v-model="copyToWeek" id="copyToWeek" class="form-select">
|
||||||
|
<option v-for="w in nextWeeks" :value="w.value" :key="w.value">
|
||||||
|
{{ w.text }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-sm-5 col-md-1">
|
||||||
|
<button class="btn btn-action float-end" @click="copyWeek">
|
||||||
|
{{ $t("copy_range") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- not directly seen, but include in a modal -->
|
<!-- not directly seen, but include in a modal -->
|
||||||
@@ -112,42 +171,95 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
CalendarOptions,
|
CalendarOptions,
|
||||||
DatesSetArg,
|
DatesSetArg,
|
||||||
EventInput
|
EventInput,
|
||||||
} from '@fullcalendar/core';
|
} from "@fullcalendar/core";
|
||||||
import {reactive, computed, ref} from "vue";
|
import { reactive, computed, ref, onMounted } from "vue";
|
||||||
import {useStore} from "vuex";
|
import { useStore } from "vuex";
|
||||||
import {key} from './store';
|
import { key } from "./store";
|
||||||
import FullCalendar from '@fullcalendar/vue3';
|
import FullCalendar from "@fullcalendar/vue3";
|
||||||
import frLocale from '@fullcalendar/core/locales/fr';
|
import frLocale from "@fullcalendar/core/locales/fr";
|
||||||
import interactionPlugin, {DropArg, EventResizeDoneArg} from "@fullcalendar/interaction";
|
import interactionPlugin, {
|
||||||
|
DropArg,
|
||||||
|
EventResizeDoneArg,
|
||||||
|
} from "@fullcalendar/interaction";
|
||||||
import timeGridPlugin from "@fullcalendar/timegrid";
|
import timeGridPlugin from "@fullcalendar/timegrid";
|
||||||
import {EventApi, DateSelectArg, EventDropArg, EventClickArg} from "@fullcalendar/core";
|
import {
|
||||||
import {ISOToDate} from "../../../../../ChillMainBundle/Resources/public/chill/js/date";
|
EventApi,
|
||||||
|
DateSelectArg,
|
||||||
|
EventDropArg,
|
||||||
|
EventClickArg,
|
||||||
|
} from "@fullcalendar/core";
|
||||||
|
import {
|
||||||
|
dateToISO,
|
||||||
|
ISOToDate,
|
||||||
|
} from "../../../../../ChillMainBundle/Resources/public/chill/js/date";
|
||||||
import VueMultiselect from "vue-multiselect";
|
import VueMultiselect from "vue-multiselect";
|
||||||
import {Location} from "../../../../../ChillMainBundle/Resources/public/types";
|
import { Location } from "../../../../../ChillMainBundle/Resources/public/types";
|
||||||
import EditLocation from "./Components/EditLocation.vue";
|
import EditLocation from "./Components/EditLocation.vue";
|
||||||
import {useI18n} from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
|
||||||
const store = useStore(key);
|
const store = useStore(key);
|
||||||
|
|
||||||
const {t} = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const showWeekends = ref(false);
|
const showWeekends = ref(false);
|
||||||
const slotDuration = ref('00:05:00');
|
const slotDuration = ref("00:15:00");
|
||||||
const slotMinTime = ref('09:00:00');
|
const slotMinTime = ref("09:00:00");
|
||||||
const slotMaxTime = ref('18:00:00');
|
const slotMaxTime = ref("18:00:00");
|
||||||
const copyFrom = ref<string | null>(null);
|
const copyFrom = ref<string | null>(null);
|
||||||
const copyTo = ref<string | null>(null);
|
const copyTo = ref<string | null>(null);
|
||||||
const editLocation = ref<InstanceType<typeof EditLocation> | null>(null)
|
const editLocation = ref<InstanceType<typeof EditLocation> | null>(null);
|
||||||
|
const dayOrWeek = ref("day");
|
||||||
|
const copyFromWeek = ref<string | null>(null);
|
||||||
|
const copyToWeek = ref<string | null>(null);
|
||||||
|
|
||||||
|
interface Weeks {
|
||||||
|
value: string | null;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMonday = (week: number): Date => {
|
||||||
|
const lastMonday = new Date();
|
||||||
|
lastMonday.setDate(
|
||||||
|
lastMonday.getDate() - ((lastMonday.getDay() + 6) % 7) + week * 7
|
||||||
|
);
|
||||||
|
return lastMonday;
|
||||||
|
};
|
||||||
|
|
||||||
|
const dateOptions: Intl.DateTimeFormatOptions = {
|
||||||
|
weekday: "long",
|
||||||
|
year: "numeric",
|
||||||
|
month: "long",
|
||||||
|
day: "numeric",
|
||||||
|
};
|
||||||
|
|
||||||
|
const lastWeeks = computed((): Weeks[] =>
|
||||||
|
Array.from(Array(30).keys()).map((w) => {
|
||||||
|
const lastMonday = getMonday(15-w);
|
||||||
|
return {
|
||||||
|
value: dateToISO(lastMonday),
|
||||||
|
text: `Semaine du ${lastMonday.toLocaleDateString("fr-FR", dateOptions)}`,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const nextWeeks = computed((): Weeks[] =>
|
||||||
|
Array.from(Array(52).keys()).map((w) => {
|
||||||
|
const nextMonday = getMonday(w + 1);
|
||||||
|
return {
|
||||||
|
value: dateToISO(nextMonday),
|
||||||
|
text: `Semaine du ${nextMonday.toLocaleDateString("fr-FR", dateOptions)}`,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const baseOptions = ref<CalendarOptions>({
|
const baseOptions = ref<CalendarOptions>({
|
||||||
locale: frLocale,
|
locale: frLocale,
|
||||||
plugins: [interactionPlugin, timeGridPlugin],
|
plugins: [interactionPlugin, timeGridPlugin],
|
||||||
initialView: 'timeGridWeek',
|
initialView: "timeGridWeek",
|
||||||
initialDate: new Date(),
|
initialDate: new Date(),
|
||||||
scrollTimeReset: false,
|
scrollTimeReset: false,
|
||||||
selectable: true,
|
selectable: true,
|
||||||
@@ -164,9 +276,9 @@ const baseOptions = ref<CalendarOptions>({
|
|||||||
selectMirror: false,
|
selectMirror: false,
|
||||||
editable: true,
|
editable: true,
|
||||||
headerToolbar: {
|
headerToolbar: {
|
||||||
left: 'prev,next today',
|
left: "prev,next today",
|
||||||
center: 'title',
|
center: "title",
|
||||||
right: 'timeGridWeek,timeGridDay'
|
right: "timeGridWeek,timeGridDay",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -180,20 +292,23 @@ const locations = computed<Location[]>(() => {
|
|||||||
|
|
||||||
const pickedLocation = computed<Location | null>({
|
const pickedLocation = computed<Location | null>({
|
||||||
get(): Location | null {
|
get(): Location | null {
|
||||||
return store.state.locations.locationPicked || store.state.locations.currentLocation;
|
return (
|
||||||
|
store.state.locations.locationPicked ||
|
||||||
|
store.state.locations.currentLocation
|
||||||
|
);
|
||||||
},
|
},
|
||||||
set(newLocation: Location | null): void {
|
set(newLocation: Location | null): void {
|
||||||
store.commit('locations/setLocationPicked', newLocation, {root: true});
|
store.commit("locations/setLocationPicked", newLocation, { root: true });
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return the show classes for the event
|
* return the show classes for the event
|
||||||
* @param arg
|
* @param arg
|
||||||
*/
|
*/
|
||||||
const eventClasses = function(arg: EventApi): object {
|
const eventClasses = function (arg: EventApi): object {
|
||||||
return {'calendarRangeItems': true};
|
return { calendarRangeItems: true };
|
||||||
}
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// currently, all events are stored into calendarRanges, due to reactivity bug
|
// currently, all events are stored into calendarRanges, due to reactivity bug
|
||||||
@@ -230,51 +345,60 @@ const calendarOptions = computed((): CalendarOptions => {
|
|||||||
* launched when the calendar range date change
|
* launched when the calendar range date change
|
||||||
*/
|
*/
|
||||||
function onDatesSet(event: DatesSetArg): void {
|
function onDatesSet(event: DatesSetArg): void {
|
||||||
store.dispatch('fullCalendar/setCurrentDatesView', {start: event.start, end: event.end});
|
store.dispatch("fullCalendar/setCurrentDatesView", {
|
||||||
|
start: event.start,
|
||||||
|
end: event.end,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDateSelect(event: DateSelectArg): void {
|
function onDateSelect(event: DateSelectArg): void {
|
||||||
|
|
||||||
if (null === pickedLocation.value) {
|
if (null === pickedLocation.value) {
|
||||||
window.alert("Indiquez une localisation avant de créer une période de disponibilité.");
|
window.alert(
|
||||||
|
"Indiquez une localisation avant de créer une période de disponibilité."
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dispatch('calendarRanges/createRange', {start: event.start, end: event.end, location: pickedLocation.value});
|
store.dispatch("calendarRanges/createRange", {
|
||||||
|
start: event.start,
|
||||||
|
end: event.end,
|
||||||
|
location: pickedLocation.value,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When a calendar range is deleted
|
* When a calendar range is deleted
|
||||||
*/
|
*/
|
||||||
function onClickDelete(event: EventApi): void {
|
function onClickDelete(event: EventApi): void {
|
||||||
console.log('onClickDelete', event);
|
if (event.extendedProps.is !== "range") {
|
||||||
|
|
||||||
if (event.extendedProps.is !== 'range') {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dispatch('calendarRanges/deleteRange', event.extendedProps.calendarRangeId);
|
store.dispatch(
|
||||||
|
"calendarRanges/deleteRange",
|
||||||
|
event.extendedProps.calendarRangeId
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onEventDropOrResize(payload: EventDropArg | EventResizeDoneArg) {
|
function onEventDropOrResize(payload: EventDropArg | EventResizeDoneArg) {
|
||||||
if (payload.event.extendedProps.is !== 'range') {
|
if (payload.event.extendedProps.is !== "range") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const changedEvent = payload.event;
|
const changedEvent = payload.event;
|
||||||
|
|
||||||
store.dispatch('calendarRanges/patchRangeTime', {
|
store.dispatch("calendarRanges/patchRangeTime", {
|
||||||
calendarRangeId: payload.event.extendedProps.calendarRangeId,
|
calendarRangeId: payload.event.extendedProps.calendarRangeId,
|
||||||
start: payload.event.start,
|
start: payload.event.start,
|
||||||
end: payload.event.end,
|
end: payload.event.end,
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
function onEventClick(payload: EventClickArg): void {
|
function onEventClick(payload: EventClickArg): void {
|
||||||
// @ts-ignore TS does not recognize the target. But it does exists.
|
// @ts-ignore TS does not recognize the target. But it does exists.
|
||||||
if (payload.jsEvent.target.classList.contains('delete')) {
|
if (payload.jsEvent.target.classList.contains("delete")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (payload.event.extendedProps.is !== 'range') {
|
if (payload.event.extendedProps.is !== "range") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,10 +409,26 @@ function copyDay() {
|
|||||||
if (null === copyFrom.value || null === copyTo.value) {
|
if (null === copyFrom.value || null === copyTo.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
store.dispatch("calendarRanges/copyFromDayToAnotherDay", {
|
||||||
store.dispatch('calendarRanges/copyFromDayToAnotherDay', {from: ISOToDate(copyFrom.value), to: ISOToDate(copyTo.value)})
|
from: ISOToDate(copyFrom.value),
|
||||||
|
to: ISOToDate(copyTo.value),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function copyWeek() {
|
||||||
|
if (null === copyFromWeek.value || null === copyToWeek.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
store.dispatch("calendarRanges/copyFromWeekToAnotherWeek", {
|
||||||
|
fromMonday: ISOToDate(copyFromWeek.value),
|
||||||
|
toMonday: ISOToDate(copyToWeek.value),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
copyFromWeek.value = dateToISO(getMonday(0));
|
||||||
|
copyToWeek.value = dateToISO(getMonday(1));
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -299,4 +439,9 @@ function copyDay() {
|
|||||||
z-index: 9999999999;
|
z-index: 9999999999;
|
||||||
padding: 0.25rem 0 0.25rem;
|
padding: 0.25rem 0 0.25rem;
|
||||||
}
|
}
|
||||||
|
div.copy-chevron {
|
||||||
|
text-align: center;
|
||||||
|
font-size: x-large;
|
||||||
|
width: 2rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -5,11 +5,9 @@ const appMessages = {
|
|||||||
show_my_calendar: "Afficher mon calendrier",
|
show_my_calendar: "Afficher mon calendrier",
|
||||||
show_weekends: "Afficher les week-ends",
|
show_weekends: "Afficher les week-ends",
|
||||||
copy_range: "Copier",
|
copy_range: "Copier",
|
||||||
copy_range_from_to: "Copier les plages d'un jour à l'autre",
|
copy_range_from_to: "Copier les plages",
|
||||||
copy_range_to_next_day: "Copier les plages du jour au jour suivant",
|
from_day_to_day: "d'un jour à l'autre",
|
||||||
copy_range_from_day: "Copier les plages du ",
|
from_week_to_week: "d'une semaine à l'autre",
|
||||||
to_the_next_day: " au jour suivant",
|
|
||||||
copy_range_to_next_week: "Copier les plages de la semaine à la semaine suivante",
|
|
||||||
copy_range_how_to: "Créez les plages de disponibilités durant une journée et copiez-les facilement au jour suivant avec ce bouton. Si les week-ends sont cachés, le jour suivant un vendredi sera le lundi.",
|
copy_range_how_to: "Créez les plages de disponibilités durant une journée et copiez-les facilement au jour suivant avec ce bouton. Si les week-ends sont cachés, le jour suivant un vendredi sera le lundi.",
|
||||||
new_range_to_save: "Nouvelles plages à enregistrer",
|
new_range_to_save: "Nouvelles plages à enregistrer",
|
||||||
update_range_to_save: "Plages à modifier",
|
update_range_to_save: "Plages à modifier",
|
||||||
|
@@ -52,6 +52,23 @@ export default <Module<CalendarRangesState, State>>{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return founds;
|
||||||
|
},
|
||||||
|
getRangesOnWeek: (state: CalendarRangesState) => (mondayDate: Date): EventInputCalendarRange[] => {
|
||||||
|
const founds = [];
|
||||||
|
for (let d of Array.from(Array(7).keys())) {
|
||||||
|
const dateOfWeek = new Date(mondayDate);
|
||||||
|
dateOfWeek.setDate(mondayDate.getDate() + d);
|
||||||
|
const dateStr = <string>dateToISO(dateOfWeek);
|
||||||
|
for (let range of state.ranges) {
|
||||||
|
if (isEventInputCalendarRange(range)
|
||||||
|
&& range.start.startsWith(dateStr)
|
||||||
|
) {
|
||||||
|
founds.push(range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return founds;
|
return founds;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -238,7 +255,7 @@ export default <Module<CalendarRangesState, State>>{
|
|||||||
|
|
||||||
for (let r of rangesToCopy) {
|
for (let r of rangesToCopy) {
|
||||||
let start = new Date(<Date>ISOToDatetime(r.start));
|
let start = new Date(<Date>ISOToDatetime(r.start));
|
||||||
start.setFullYear(to.getFullYear(), to.getMonth(), to.getDate())
|
start.setFullYear(to.getFullYear(), to.getMonth(), to.getDate());
|
||||||
let end = new Date(<Date>ISOToDatetime(r.end));
|
let end = new Date(<Date>ISOToDatetime(r.end));
|
||||||
end.setFullYear(to.getFullYear(), to.getMonth(), to.getDate());
|
end.setFullYear(to.getFullYear(), to.getMonth(), to.getDate());
|
||||||
let location = ctx.rootGetters['locations/getLocationById'](r.locationId);
|
let location = ctx.rootGetters['locations/getLocationById'](r.locationId);
|
||||||
@@ -246,6 +263,23 @@ export default <Module<CalendarRangesState, State>>{
|
|||||||
promises.push(ctx.dispatch('createRange', {start, end, location}));
|
promises.push(ctx.dispatch('createRange', {start, end, location}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Promise.all(promises).then(_ => Promise.resolve(null));
|
||||||
|
},
|
||||||
|
copyFromWeekToAnotherWeek(ctx, {fromMonday, toMonday}: {fromMonday: Date, toMonday: Date}): Promise<null> {
|
||||||
|
|
||||||
|
const rangesToCopy: EventInputCalendarRange[] = ctx.getters['getRangesOnWeek'](fromMonday);
|
||||||
|
const promises = [];
|
||||||
|
const diffTime = toMonday.getTime() - fromMonday.getTime();
|
||||||
|
for (let r of rangesToCopy) {
|
||||||
|
let start = new Date(<Date>ISOToDatetime(r.start));
|
||||||
|
let end = new Date(<Date>ISOToDatetime(r.end));
|
||||||
|
start.setTime(start.getTime() + diffTime);
|
||||||
|
end.setTime(end.getTime() + diffTime);
|
||||||
|
let location = ctx.rootGetters['locations/getLocationById'](r.locationId);
|
||||||
|
|
||||||
|
promises.push(ctx.dispatch('createRange', {start, end, location}));
|
||||||
|
}
|
||||||
|
|
||||||
return Promise.all(promises).then(_ => Promise.resolve(null));
|
return Promise.all(promises).then(_ => Promise.resolve(null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -55,7 +55,7 @@
|
|||||||
<div class="item-col">
|
<div class="item-col">
|
||||||
<ul class="list-content">
|
<ul class="list-content">
|
||||||
{% if calendar.mainUser is not empty %}
|
{% if calendar.mainUser is not empty %}
|
||||||
<span class="badge-user">{{ calendar.mainUser|chill_entity_render_box }}</span>
|
<span class="badge-user">{{ calendar.mainUser|chill_entity_render_box({'at_date': calendar.startDate}) }}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -132,7 +132,7 @@
|
|||||||
<li class="cancel">
|
<li class="cancel">
|
||||||
<span class="createdBy">
|
<span class="createdBy">
|
||||||
{{ 'Created by'|trans }}
|
{{ 'Created by'|trans }}
|
||||||
<b>{{ calendar.activity.createdBy|chill_entity_render_string }}</b>, {{ 'on'|trans }} {{ calendar.activity.createdAt|format_datetime('short', 'short') }}
|
<b>{{ calendar.activity.createdBy|chill_entity_render_string({'at_date': calendar.activity.createdAt}) }}</b>, {{ 'on'|trans }} {{ calendar.activity.createdAt|format_datetime('short', 'short') }}
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
{% if is_granted('CHILL_ACTIVITY_SEE', calendar.activity) %}
|
{% if is_granted('CHILL_ACTIVITY_SEE', calendar.activity) %}
|
||||||
|
@@ -89,7 +89,7 @@ class CalendarVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
|
|||||||
switch ($attribute) {
|
switch ($attribute) {
|
||||||
case self::SEE:
|
case self::SEE:
|
||||||
case self::CREATE:
|
case self::CREATE:
|
||||||
if (AccompanyingPeriod::STEP_DRAFT === $subject->getStep()) {
|
if (AccompanyingPeriod::STEP_DRAFT === $subject->getStep() || AccompanyingPeriod::STEP_CLOSED === $subject->getStep()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -40,7 +40,7 @@ final readonly class CalendarContext implements CalendarContextInterface
|
|||||||
private PersonRepository $personRepository,
|
private PersonRepository $personRepository,
|
||||||
private ThirdPartyRender $thirdPartyRender,
|
private ThirdPartyRender $thirdPartyRender,
|
||||||
private ThirdPartyRepository $thirdPartyRepository,
|
private ThirdPartyRepository $thirdPartyRepository,
|
||||||
private TranslatableStringHelperInterface $translatableStringHelper
|
private TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -37,7 +37,7 @@ final readonly class AccompanyingPeriodCalendarGenericDocProvider implements Gen
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private Security $security,
|
private Security $security,
|
||||||
private EntityManagerInterface $em
|
private EntityManagerInterface $em,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -36,7 +36,7 @@ final readonly class PersonCalendarGenericDocProvider implements GenericDocForPe
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private Security $security,
|
private Security $security,
|
||||||
private EntityManagerInterface $em
|
private EntityManagerInterface $em,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -156,7 +156,7 @@ final class CalendarTypeTest extends TypeTestCase
|
|||||||
|
|
||||||
private function buildMultiToIdDataTransformer(
|
private function buildMultiToIdDataTransformer(
|
||||||
string $classTransformer,
|
string $classTransformer,
|
||||||
string $objClass
|
string $objClass,
|
||||||
) {
|
) {
|
||||||
$transformer = $this->prophesize($classTransformer);
|
$transformer = $this->prophesize($classTransformer);
|
||||||
$transformer->transform(Argument::type('array'))
|
$transformer->transform(Argument::type('array'))
|
||||||
@@ -195,7 +195,7 @@ final class CalendarTypeTest extends TypeTestCase
|
|||||||
|
|
||||||
private function buildSingleToIdDataTransformer(
|
private function buildSingleToIdDataTransformer(
|
||||||
string $classTransformer,
|
string $classTransformer,
|
||||||
string $class
|
string $class,
|
||||||
) {
|
) {
|
||||||
$transformer = $this->prophesize($classTransformer);
|
$transformer = $this->prophesize($classTransformer);
|
||||||
$transformer->transform(Argument::type('object'))
|
$transformer->transform(Argument::type('object'))
|
||||||
|
@@ -203,7 +203,7 @@ final class CalendarContextTest extends TestCase
|
|||||||
|
|
||||||
private function buildCalendarContext(
|
private function buildCalendarContext(
|
||||||
?EntityManagerInterface $entityManager = null,
|
?EntityManagerInterface $entityManager = null,
|
||||||
?NormalizerInterface $normalizer = null
|
?NormalizerInterface $normalizer = null,
|
||||||
): CalendarContext {
|
): CalendarContext {
|
||||||
$baseContext = $this->prophesize(BaseContextData::class);
|
$baseContext = $this->prophesize(BaseContextData::class);
|
||||||
$baseContext->getData(null)->willReturn(['base_context' => 'data']);
|
$baseContext->getData(null)->willReturn(['base_context' => 'data']);
|
||||||
|
@@ -26,6 +26,7 @@ The calendar item has been successfully removed.: Le rendez-vous a été supprim
|
|||||||
From the day: Du
|
From the day: Du
|
||||||
to the day: au
|
to the day: au
|
||||||
Transform to activity: Transformer en échange
|
Transform to activity: Transformer en échange
|
||||||
|
Create a new calendar in accompanying course: Créer un rendez-vous dans le parcours
|
||||||
Will send SMS: Un SMS de rappel sera envoyé
|
Will send SMS: Un SMS de rappel sera envoyé
|
||||||
Will not send SMS: Aucun SMS de rappel ne sera envoyé
|
Will not send SMS: Aucun SMS de rappel ne sera envoyé
|
||||||
SMS already sent: Un SMS a été envoyé
|
SMS already sent: Un SMS a été envoyé
|
||||||
|
@@ -43,7 +43,7 @@ class CreateFieldsOnGroupCommand extends Command
|
|||||||
private readonly EntityManager $entityManager,
|
private readonly EntityManager $entityManager,
|
||||||
private readonly ValidatorInterface $validator,
|
private readonly ValidatorInterface $validator,
|
||||||
private $availableLanguages,
|
private $availableLanguages,
|
||||||
private $customizablesEntities
|
private $customizablesEntities,
|
||||||
) {
|
) {
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
@@ -42,7 +42,7 @@ class CustomFieldChoice extends AbstractCustomField
|
|||||||
/**
|
/**
|
||||||
* @var TranslatableStringHelper Helper that find the string in current locale from an array of translation
|
* @var TranslatableStringHelper Helper that find the string in current locale from an array of translation
|
||||||
*/
|
*/
|
||||||
private readonly TranslatableStringHelper $translatableStringHelper
|
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -44,7 +44,7 @@ class CustomFieldDate extends AbstractCustomField
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly Environment $templating,
|
private readonly Environment $templating,
|
||||||
private readonly TranslatableStringHelper $translatableStringHelper
|
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -41,7 +41,7 @@ class CustomFieldNumber extends AbstractCustomField
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly Environment $templating,
|
private readonly Environment $templating,
|
||||||
private readonly TranslatableStringHelper $translatableStringHelper
|
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -28,7 +28,7 @@ class CustomFieldText extends AbstractCustomField
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly Environment $templating,
|
private readonly Environment $templating,
|
||||||
private readonly TranslatableStringHelper $translatableStringHelper
|
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -31,7 +31,7 @@ class CustomFieldTitle extends AbstractCustomField
|
|||||||
/**
|
/**
|
||||||
* @var TranslatableStringHelper Helper that find the string in current locale from an array of translation
|
* @var TranslatableStringHelper Helper that find the string in current locale from an array of translation
|
||||||
*/
|
*/
|
||||||
private readonly TranslatableStringHelper $translatableStringHelper
|
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,7 +26,7 @@ class CustomFieldsGroupType extends AbstractType
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly array $customizableEntities,
|
private readonly array $customizableEntities,
|
||||||
// TODO : add comment about this variable
|
// TODO : add comment about this variable
|
||||||
private readonly TranslatorInterface $translator
|
private readonly TranslatorInterface $translator,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -64,7 +64,7 @@ final class DocGeneratorTemplateController extends AbstractController
|
|||||||
DocGeneratorTemplate $template,
|
DocGeneratorTemplate $template,
|
||||||
string $entityClassName,
|
string $entityClassName,
|
||||||
int $entityId,
|
int $entityId,
|
||||||
Request $request
|
Request $request,
|
||||||
): Response {
|
): Response {
|
||||||
return $this->generateDocFromTemplate(
|
return $this->generateDocFromTemplate(
|
||||||
$template,
|
$template,
|
||||||
@@ -84,7 +84,7 @@ final class DocGeneratorTemplateController extends AbstractController
|
|||||||
DocGeneratorTemplate $template,
|
DocGeneratorTemplate $template,
|
||||||
string $entityClassName,
|
string $entityClassName,
|
||||||
int $entityId,
|
int $entityId,
|
||||||
Request $request
|
Request $request,
|
||||||
): Response {
|
): Response {
|
||||||
return $this->generateDocFromTemplate(
|
return $this->generateDocFromTemplate(
|
||||||
$template,
|
$template,
|
||||||
@@ -159,7 +159,7 @@ final class DocGeneratorTemplateController extends AbstractController
|
|||||||
DocGeneratorTemplate $template,
|
DocGeneratorTemplate $template,
|
||||||
int $entityId,
|
int $entityId,
|
||||||
Request $request,
|
Request $request,
|
||||||
bool $isTest
|
bool $isTest,
|
||||||
): Response {
|
): Response {
|
||||||
try {
|
try {
|
||||||
$context = $this->contextManager->getContextByDocGeneratorTemplate($template);
|
$context = $this->contextManager->getContextByDocGeneratorTemplate($template);
|
||||||
|
@@ -28,7 +28,7 @@ final class RelatorioDriver implements DriverInterface
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly HttpClientInterface $client,
|
private readonly HttpClientInterface $client,
|
||||||
ParameterBagInterface $parameterBag,
|
ParameterBagInterface $parameterBag,
|
||||||
private readonly LoggerInterface $logger
|
private readonly LoggerInterface $logger,
|
||||||
) {
|
) {
|
||||||
$this->url = $parameterBag->get('chill_doc_generator')['driver']['relatorio']['url'];
|
$this->url = $parameterBag->get('chill_doc_generator')['driver']['relatorio']['url'];
|
||||||
}
|
}
|
||||||
|
@@ -35,7 +35,7 @@ class DocGenObjectNormalizer implements NormalizerAwareInterface, NormalizerInte
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly ClassMetadataFactoryInterface $classMetadataFactory,
|
private readonly ClassMetadataFactoryInterface $classMetadataFactory,
|
||||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
) {
|
) {
|
||||||
$this->propertyAccess = PropertyAccess::createPropertyAccessor();
|
$this->propertyAccess = PropertyAccess::createPropertyAccessor();
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,7 @@ class Generator implements GeneratorInterface
|
|||||||
private readonly DriverInterface $driver,
|
private readonly DriverInterface $driver,
|
||||||
private readonly ManagerRegistry $objectManagerRegistry,
|
private readonly ManagerRegistry $objectManagerRegistry,
|
||||||
private readonly LoggerInterface $logger,
|
private readonly LoggerInterface $logger,
|
||||||
private readonly StoredObjectManagerInterface $storedObjectManager
|
private readonly StoredObjectManagerInterface $storedObjectManager,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -39,7 +39,7 @@ final readonly class OnGenerationFails implements EventSubscriberInterface
|
|||||||
private MailerInterface $mailer,
|
private MailerInterface $mailer,
|
||||||
private StoredObjectRepositoryInterface $storedObjectRepository,
|
private StoredObjectRepositoryInterface $storedObjectRepository,
|
||||||
private TranslatorInterface $translator,
|
private TranslatorInterface $translator,
|
||||||
private UserRepositoryInterface $userRepository
|
private UserRepositoryInterface $userRepository,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\DocGeneratorBundle\Test;
|
||||||
|
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template T of object
|
||||||
|
*/
|
||||||
|
abstract class DocGenNormalizerTestAbstract extends KernelTestCase
|
||||||
|
{
|
||||||
|
public function testNullValueHasSameKeysAsNull(): void
|
||||||
|
{
|
||||||
|
$normalizedObject = $this->getNormalizer()->normalize($this->provideNotNullObject(), 'docgen', [
|
||||||
|
AbstractNormalizer::GROUPS => ['docgen:read'], 'docgen:expects' => $this->provideDocGenExpectClass(),
|
||||||
|
]);
|
||||||
|
$nullNormalizedObject = $this->getNormalizer()->normalize(null, 'docgen', [
|
||||||
|
AbstractNormalizer::GROUPS => ['docgen:read'], 'docgen:expects' => $this->provideDocGenExpectClass(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
self::assertEqualsCanonicalizing(array_keys($normalizedObject), array_keys($nullNormalizedObject));
|
||||||
|
self::assertArrayHasKey('isNull', $nullNormalizedObject, 'each object must have an "isNull" key');
|
||||||
|
self::assertTrue($nullNormalizedObject['isNull'], 'isNull key must be true for null objects');
|
||||||
|
self::assertFalse($normalizedObject['isNull'], 'isNull key must be false for null objects');
|
||||||
|
|
||||||
|
foreach ($normalizedObject as $key => $value) {
|
||||||
|
if (in_array($key, ['isNull', 'type'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($value)) {
|
||||||
|
if (array_is_list($value)) {
|
||||||
|
self::assertEquals([], $nullNormalizedObject[$key], "list must be serialized as an empty array, in {$key}");
|
||||||
|
} else {
|
||||||
|
self::assertEqualsCanonicalizing(array_keys($value), array_keys($nullNormalizedObject[$key]), "sub-object must have the same keys, in {$key}");
|
||||||
|
}
|
||||||
|
} elseif (is_string($value)) {
|
||||||
|
self::assertEquals('', $nullNormalizedObject[$key], 'strings must be ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return T
|
||||||
|
*/
|
||||||
|
abstract public function provideNotNullObject(): object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return class-string<T>
|
||||||
|
*/
|
||||||
|
abstract public function provideDocGenExpectClass(): string;
|
||||||
|
|
||||||
|
abstract public function getNormalizer(): NormalizerInterface;
|
||||||
|
}
|
@@ -56,7 +56,7 @@ final class BaseContextDataTest extends KernelTestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function buildBaseContext(
|
private function buildBaseContext(
|
||||||
?NormalizerInterface $normalizer = null
|
?NormalizerInterface $normalizer = null,
|
||||||
): BaseContextData {
|
): BaseContextData {
|
||||||
return new BaseContextData(
|
return new BaseContextData(
|
||||||
$normalizer ?? self::$container->get(NormalizerInterface::class)
|
$normalizer ?? self::$container->get(NormalizerInterface::class)
|
||||||
|
@@ -36,7 +36,7 @@ class DocumentAccompanyingCourseController extends AbstractController
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected TranslatorInterface $translator,
|
protected TranslatorInterface $translator,
|
||||||
protected EventDispatcherInterface $eventDispatcher,
|
protected EventDispatcherInterface $eventDispatcher,
|
||||||
protected AuthorizationHelper $authorizationHelper
|
protected AuthorizationHelper $authorizationHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -42,7 +42,7 @@ class DocumentPersonController extends AbstractController
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
protected TranslatorInterface $translator,
|
protected TranslatorInterface $translator,
|
||||||
protected EventDispatcherInterface $eventDispatcher,
|
protected EventDispatcherInterface $eventDispatcher,
|
||||||
protected AuthorizationHelper $authorizationHelper
|
protected AuthorizationHelper $authorizationHelper,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -52,7 +52,7 @@ class DocumentCategory
|
|||||||
*
|
*
|
||||||
* @var int The id which is unique inside the bundle
|
* @var int The id which is unique inside the bundle
|
||||||
*/
|
*/
|
||||||
private $idInsideBundle
|
private $idInsideBundle,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user