mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-25 08:05:00 +00:00
Compare commits
159 Commits
manage-tra
...
v3.2.3
Author | SHA1 | Date | |
---|---|---|---|
8cb2bb1ef4 | |||
cc7e9235b5 | |||
973ffcbffa | |||
8c3de682d6 | |||
e71c2f162c | |||
32459e6092 | |||
1e02fed32b | |||
2c3818258a | |||
64f3b40694 | |||
1cadc71d5a | |||
2b45a51f57 | |||
4c66adee86 | |||
6c8fd99cd1 | |||
e886387f17 | |||
c79f030310 | |||
a648fd09b0 | |||
1bd5e6d582 | |||
80940a7b19 | |||
7541238c1e | |||
34748dca76 | |||
12bb264eb5 | |||
ac3ac432e1 | |||
d04f9ae9ff | |||
086f391dc9 | |||
06cbfdd0c3 | |||
f1844ae02b | |||
73b0dd6009 | |||
4d8bcc5a5a | |||
5dfa5e1e7f | |||
588f02cdf4 | |||
30b66d5806 | |||
5786759daa | |||
0c1c1cbf8b | |||
9741794f7a | |||
5ca558bba3 | |||
9d05f2ac2b | |||
566c40dd84 | |||
0d2e0b4e91 | |||
30ebd00693 | |||
8b1d73356f | |||
ddfaa2861e | |||
9416a19d85 | |||
34bbee2031 | |||
7f1764658a | |||
43c3cc26ea | |||
74593a7d28 | |||
e629dbf994 | |||
8e02db6c85 | |||
7183d9a3b1 | |||
70335a6360 | |||
fa64f44cf1 | |||
f34c94fd65 | |||
73d80af80a | |||
363cbc8a76 | |||
9f3893243e | |||
7520d746e8 | |||
052e09cf64 | |||
77ece243c0 | |||
a47c8d916b | |||
5fce9ee9fb | |||
47d954fe9f | |||
d9dc2d1f4e | |||
37cfc035a3 | |||
2eb686ffdb | |||
34e2a26d1e | |||
789c977aba | |||
0ba93ec7c6 | |||
b9d2f5efa3 | |||
567c01f395 | |||
67a6eb17db | |||
b78f0980f5 | |||
f428afc7ca | |||
18899d665d | |||
59f9ac25ba | |||
2da6b746fb | |||
11f75bf6f1 | |||
a1db1a1d65 | |||
bdfdabe10e | |||
843a2a4b5b | |||
6781fdbd9b | |||
e6102d339b | |||
06cb3ddcd1 | |||
05d56c6eeb | |||
23e7f4a120 | |||
3eeb105913 | |||
726cdb385f | |||
406eba80d2 | |||
236e8117d4 | |||
e6bfcddae2 | |||
d61c090cee | |||
43dd94dad6 | |||
f7f8319749 | |||
376ce59917 | |||
06d6227d0e | |||
de914f4f17 | |||
e831cb1656 | |||
94875d83b3 | |||
8e30873001 | |||
be8901a5c4
|
|||
7206e13984
|
|||
6f28d154c8
|
|||
1c0d334b91
|
|||
bc34d84d63
|
|||
f0f651edea
|
|||
5dfbdad13d
|
|||
b3e2d4ff9f | |||
01c2848a83
|
|||
d0ee381627
|
|||
8b1b255050
|
|||
5d0b531820 | |||
5be3cae288 | |||
4587f66402 | |||
3738c110f8
|
|||
f57fdb2b4c
|
|||
b57824fc7e
|
|||
6b4e1ed2d3
|
|||
b0485dbcc8
|
|||
c16219dc6d
|
|||
ad47804c91 | |||
85e2466611 | |||
94d6b5eff8 | |||
d87f380f16 | |||
58bf722fae | |||
50fb79ebbf | |||
58912f1d98 | |||
9604ba5f4b | |||
b689a51a48 | |||
8c0d2f58ba | |||
212230448b | |||
2bfb8fe387 | |||
6362b98a00 | |||
6e2a08cae8 | |||
305105faae | |||
85811cc6ae | |||
7eee995627 | |||
c0c448fb39 | |||
6445342136 | |||
d52e54fd2a | |||
2f9884072c | |||
ee45ff61a6 | |||
2bef3c3878
|
|||
cea44d1788
|
|||
84069e03dc
|
|||
ad5e780936
|
|||
19accc4d00
|
|||
6cb085f5f7
|
|||
97239ada84
|
|||
643156f822 | |||
ff0b205591 | |||
2d67843901 | |||
2b09e1459c | |||
029524ba2c | |||
fa91e9494d | |||
4e72d6fea1
|
|||
5666b8b647
|
|||
|
0573f56782 | ||
|
3bee18b0fa | ||
|
843698a1d8 | ||
|
499640e48b |
@@ -1,7 +0,0 @@
|
||||
kind: Feature
|
||||
body: "Implementation of new translation management with one source of truth for both
|
||||
twig and vue component templates using YAML files. \nDuplicate translation keys
|
||||
can also be detected with new command."
|
||||
time: 2024-11-18T15:06:27.929549251+01:00
|
||||
custom:
|
||||
Issue: ""
|
@@ -1,11 +1,30 @@
|
||||
## v2.23.0 - 2024-07-23
|
||||
## v2.23.0 - 2024-07-23 & 2024-07-19
|
||||
### Feature
|
||||
* ([#221](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/221)) [DX] move async-upload-bundle features into chill-bundles
|
||||
* Add job bundle (module emploi)
|
||||
* ([#221](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/221)) [DX] move async-upload-bundle features into chill-bundles
|
||||
* Add job bundle (module emploi)
|
||||
* Upgrade import of address list to the last version of compiled addresses of belgian-best-address
|
||||
|
||||
|
||||
* Upgrade CKEditor and refactor configuration with use of typescript
|
||||
|
||||
|
||||
* ([#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
|
||||
* Fix resolving of centers for an household, which will fix in turn the access control
|
||||
* Resolved type hinting error in activity list export
|
||||
* Fix resolving of centers for an household, which will fix in turn the access control
|
||||
* Resolved type hinting error in activity list export
|
||||
* ([#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/v3.0.0.md
Normal file
5
.changes/v3.0.0.md
Normal file
@@ -0,0 +1,5 @@
|
||||
## v3.0.0 - 2024-08-26
|
||||
### Fixed
|
||||
* Fix delete action for accompanying periods in draft state
|
||||
* Fix connection to azure when making an calendar event in chill
|
||||
* CollectionType js fixes for remove button and adding multiple entries
|
3
.changes/v3.1.0.md
Normal file
3
.changes/v3.1.0.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## v3.1.0 - 2024-08-30
|
||||
### Feature
|
||||
* Add export aggregator to aggregate activities by household + filter persons that are not part of an accompanyingperiod during a certain timeframe.
|
6
.changes/v3.1.1.md
Normal file
6
.changes/v3.1.1.md
Normal file
@@ -0,0 +1,6 @@
|
||||
## v3.1.1 - 2024-10-01
|
||||
### 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
|
||||
|
||||
* Fixed typing of custom field long choice and custom field group
|
3
.changes/v3.2.0.md
Normal file
3
.changes/v3.2.0.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## v3.2.0 - 2024-10-30
|
||||
### Feature
|
||||
* Introduce a gender entity
|
4
.changes/v3.2.1.md
Normal file
4
.changes/v3.2.1.md
Normal file
@@ -0,0 +1,4 @@
|
||||
## v3.2.1 - 2024-10-31
|
||||
### Fixed
|
||||
* Add the possibility of unknown to the gender entity
|
||||
* Fix the fusion of person doubles by excluding accompanyingPeriod work entities to be deleted. They are moved instead.
|
3
.changes/v3.2.2.md
Normal file
3
.changes/v3.2.2.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## v3.2.2 - 2024-10-31
|
||||
### Fixed
|
||||
* Fix gender translation for unknown
|
4
.changes/v3.2.3.md
Normal file
4
.changes/v3.2.3.md
Normal file
@@ -0,0 +1,4 @@
|
||||
## v3.2.3 - 2024-11-05
|
||||
### Fixed
|
||||
* ([#315](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/315)) Fix display of accompanying period work referrers. Only current referrers should be displayed.
|
||||
Fix color of Chill footer
|
@@ -138,4 +138,4 @@ release:
|
||||
- echo "running release_job"
|
||||
release:
|
||||
tag_name: '$CI_COMMIT_TAG'
|
||||
description: "./.changes/v$CI_COMMIT_TAG.md"
|
||||
description: "./.changes/$CI_COMMIT_TAG.md"
|
||||
|
78
CHANGELOG.md
78
CHANGELOG.md
@@ -6,17 +6,75 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
|
||||
and is generated by [Changie](https://github.com/miniscruff/changie).
|
||||
|
||||
|
||||
## v2.23.0 - 2024-07-23
|
||||
### Feature
|
||||
* ([#221](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/221)) [DX] move async-upload-bundle features into chill-bundles
|
||||
* Add job bundle (module emploi)
|
||||
* Upgrade import of address list to the last version of compiled addresses of belgian-best-address
|
||||
|
||||
* Upgrade CKEditor and refactor configuration with use of typescript
|
||||
|
||||
## v3.2.3 - 2024-11-05
|
||||
### Fixed
|
||||
* Fix resolving of centers for an household, which will fix in turn the access control
|
||||
* Resolved type hinting error in activity list export
|
||||
* ([#315](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/315)) Fix display of accompanying period work referrers. Only current referrers should be displayed.
|
||||
Fix color of Chill footer
|
||||
|
||||
## v3.2.2 - 2024-10-31
|
||||
### Fixed
|
||||
* Fix gender translation for unknown
|
||||
|
||||
## v3.2.1 - 2024-10-31
|
||||
### Fixed
|
||||
* Add the possibility of unknown to the gender entity
|
||||
* Fix the fusion of person doubles by excluding accompanyingPeriod work entities to be deleted. They are moved instead.
|
||||
|
||||
## v3.2.0 - 2024-10-30
|
||||
### Feature
|
||||
* Introduce a gender entity
|
||||
|
||||
## v3.1.1 - 2024-10-01
|
||||
### 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
|
||||
|
||||
* Fixed typing of custom field long choice and custom field group
|
||||
|
||||
## v3.1.0 - 2024-08-30
|
||||
### Feature
|
||||
* Add export aggregator to aggregate activities by household + filter persons that are not part of an accompanyingperiod during a certain timeframe.
|
||||
|
||||
## v3.0.0 - 2024-08-26
|
||||
### Fixed
|
||||
* Fix delete action for accompanying periods in draft state
|
||||
* Fix connection to azure when making an calendar event in chill
|
||||
* CollectionType js fixes for remove button and adding multiple entries
|
||||
|
||||
## 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-23 & 2024-07-19
|
||||
### Feature
|
||||
* ([#221](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/221)) [DX] move async-upload-bundle features into chill-bundles
|
||||
* Add job bundle (module emploi)
|
||||
* Upgrade import of address list to the last version of compiled addresses of belgian-best-address
|
||||
|
||||
* Upgrade CKEditor and refactor configuration with use of typescript
|
||||
|
||||
* ([#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
|
||||
* Fix resolving of centers for an household, which will fix in turn the access control
|
||||
* Resolved type hinting error in activity list export
|
||||
* ([#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
|
||||
|
@@ -42,6 +42,7 @@
|
||||
"symfony/dom-crawler": "^5.4",
|
||||
"symfony/error-handler": "^5.4",
|
||||
"symfony/event-dispatcher": "^5.4",
|
||||
"symfony/event-dispatcher-contracts": "^2.4",
|
||||
"symfony/expression-language": "^5.4",
|
||||
"symfony/filesystem": "^5.4",
|
||||
"symfony/finder": "^5.4",
|
||||
@@ -65,12 +66,10 @@
|
||||
"symfony/security-guard": "^5.4",
|
||||
"symfony/security-http": "^5.4",
|
||||
"symfony/serializer": "^5.4",
|
||||
"symfony/stimulus-bundle": "^2.19",
|
||||
"symfony/string": "^5.4",
|
||||
"symfony/templating": "^5.4",
|
||||
"symfony/translation": "^5.4",
|
||||
"symfony/twig-bundle": "^5.4",
|
||||
"symfony/ux-translator": "^2.19",
|
||||
"symfony/validator": "^5.4",
|
||||
"symfony/webpack-encore-bundle": "^1.11",
|
||||
"symfony/workflow": "^5.4",
|
||||
|
@@ -39,9 +39,12 @@ Implements a :code:`Chill\MainBundle\Cron\CronJobInterface`. Here is an example:
|
||||
use Chill\MainBundle\Entity\CronJobExecution;
|
||||
use DateInterval;
|
||||
use DateTimeImmutable;
|
||||
use Symfony\Component\Clock\ClockInterface;
|
||||
|
||||
class MyCronJob implements CronJobInterface
|
||||
{
|
||||
function __construct(private ClockInterface $clock) {}
|
||||
|
||||
public function canRun(?CronJobExecution $cronJobExecution): bool
|
||||
{
|
||||
// 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
|
||||
|
||||
$now = new DateTimeImmutable('now');
|
||||
$now = $clock->now();
|
||||
|
||||
return $cronJobExecution->getLastStart() < $now->sub(new DateInterval('P1D'))
|
||||
&& 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';
|
||||
}
|
||||
|
||||
public function run(): void
|
||||
public function run(array $lastExecutionData): void
|
||||
{
|
||||
// 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 ?
|
||||
|
@@ -1,31 +0,0 @@
|
||||
Translations
|
||||
*************
|
||||
|
||||
Translator-UX: one source of truth
|
||||
==================================
|
||||
|
||||
The Translator-ux integration streamlines the process of managing and using translation keys dynamically in our views, whether they be in twig or vue components. The goal is to have one source of truth
|
||||
for all translations and avoid having to add translation keys in the YAML files as well as in i18ns files.
|
||||
|
||||
To add new translation keys, you can define them in your translation YAML files. Running `symfony console cache:clear` will subsequently update the compiled translation keys which can then also be imported and
|
||||
used within any vue component. For use within a twig template they can be leveraged by using the |trans function.
|
||||
Within vue components you will have to import the translation keys you require and then they can be used in the template with the trans() function.
|
||||
|
||||
It is advisable, before adding a translation key to do a search on the existing translation keys of the translation you require. An IDE will allow you to do so easily.
|
||||
However to avoid the creation of duplicate translation keys a command also exists to detect them. We also strongly advise you to use this command as explained below.
|
||||
|
||||
Detect duplicates command
|
||||
=========================
|
||||
|
||||
The DetectTranslationDuplicatesCommand `chill:detect-duplicate-translations` is a Symfony console command designed to identify duplicate translations across YAML files in a project.
|
||||
It checks for repeated translation values linked to different keys within a specified locale.
|
||||
The command accepts two main options:
|
||||
|
||||
1. `--locale`: to specify the language locale to check (defaulting to 'en')
|
||||
2. `--exclude-namespaces`: to list namespaces to ignore during the check.
|
||||
3. [optional] `--verify-hash`: can be used to ensure that the hash of current duplicates matches a given expected value,
|
||||
aiding in maintaining translation integrity.
|
||||
|
||||
When duplicates are detected, they are displayed in a table format, listing the repeated translations alongside the keys where they are found.
|
||||
If a mismatch occurs between the computed and expected hash values, an error message is displayed to signal a potential issue in translation consistency.
|
||||
This command is useful for maintaining clean and consistent translations, avoiding redundancy in your YAML files.
|
@@ -59,7 +59,8 @@
|
||||
"vue-i18n": "^9.1.6",
|
||||
"vue-multiselect": "3.0.0-alpha.2",
|
||||
"vue-toast-notification": "^3.1.2",
|
||||
"vuex": "^4.0.0"
|
||||
"vuex": "^4.0.0",
|
||||
"bootstrap-icons": "^1.11.3"
|
||||
},
|
||||
"browserslist": [
|
||||
"Firefox ESR"
|
||||
|
@@ -69,9 +69,8 @@ return static function (RectorConfig $rectorConfig): void {
|
||||
|
||||
// skip some path...
|
||||
$rectorConfig->skip([
|
||||
// we must adapt service definition
|
||||
\Rector\Symfony\Symfony28\Rector\MethodCall\GetToConstructorInjectionRector::class,
|
||||
\Rector\Symfony\Symfony34\Rector\Closure\ContainerGetNameToTypeInTestsRector::class,
|
||||
// waiting for fixing this bug: https://github.com/rectorphp/rector-doctrine/issues/342
|
||||
\Rector\Doctrine\CodeQuality\Rector\Property\ImproveDoctrineCollectionDocTypeInEntityRector::class,
|
||||
]);
|
||||
|
||||
$rectorConfig->ruleWithConfiguration(AnnotationToAttributeRector::class, [
|
||||
|
@@ -68,7 +68,7 @@ final class ActivityController extends AbstractController
|
||||
private readonly FilterOrderHelperFactoryInterface $filterOrderHelperFactory,
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||
private readonly PaginatorFactory $paginatorFactory,
|
||||
private readonly ChillSecurity $security
|
||||
private readonly ChillSecurity $security,
|
||||
) {}
|
||||
|
||||
/**
|
||||
|
@@ -80,7 +80,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
private \DateTime $date;
|
||||
|
||||
/**
|
||||
* @var Collection<StoredObject>
|
||||
* @var Collection<int, StoredObject>
|
||||
*/
|
||||
#[Assert\Valid(traverse: true)]
|
||||
#[ORM\ManyToMany(targetEntity: StoredObject::class, cascade: ['persist'])]
|
||||
@@ -107,7 +107,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
private ?Person $person = null;
|
||||
|
||||
/**
|
||||
* @var Collection<Person>
|
||||
* @var Collection<int, \Chill\PersonBundle\Entity\Person>
|
||||
*/
|
||||
#[Groups(['read', 'docgen:read'])]
|
||||
#[ORM\ManyToMany(targetEntity: Person::class)]
|
||||
@@ -117,7 +117,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
private PrivateCommentEmbeddable $privateComment;
|
||||
|
||||
/**
|
||||
* @var Collection<ActivityReason>
|
||||
* @var Collection<int, ActivityReason>
|
||||
*/
|
||||
#[Groups(['docgen:read'])]
|
||||
#[ORM\ManyToMany(targetEntity: ActivityReason::class)]
|
||||
@@ -132,7 +132,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
private string $sentReceived = '';
|
||||
|
||||
/**
|
||||
* @var Collection<SocialAction>
|
||||
* @var Collection<int, \Chill\PersonBundle\Entity\SocialWork\SocialAction>
|
||||
*/
|
||||
#[Groups(['read', 'docgen:read'])]
|
||||
#[ORM\ManyToMany(targetEntity: SocialAction::class)]
|
||||
@@ -140,7 +140,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
private Collection $socialActions;
|
||||
|
||||
/**
|
||||
* @var Collection<SocialIssue>
|
||||
* @var Collection<int, SocialIssue>
|
||||
*/
|
||||
#[Groups(['read', 'docgen:read'])]
|
||||
#[ORM\ManyToMany(targetEntity: SocialIssue::class)]
|
||||
@@ -148,7 +148,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
private Collection $socialIssues;
|
||||
|
||||
/**
|
||||
* @var Collection<ThirdParty>
|
||||
* @var Collection<int, ThirdParty>
|
||||
*/
|
||||
#[Groups(['read', 'docgen:read'])]
|
||||
#[ORM\ManyToMany(targetEntity: ThirdParty::class)]
|
||||
@@ -162,7 +162,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
||||
private ?User $user = null;
|
||||
|
||||
/**
|
||||
* @var Collection<User>
|
||||
* @var Collection<int, User>
|
||||
*/
|
||||
#[Groups(['read', 'docgen:read'])]
|
||||
#[ORM\ManyToMany(targetEntity: User::class)]
|
||||
|
@@ -40,9 +40,9 @@ class ActivityReasonCategory implements \Stringable
|
||||
/**
|
||||
* Array of ActivityReason.
|
||||
*
|
||||
* @var Collection<ActivityReason>
|
||||
* @var Collection<int, ActivityReason>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: ActivityReason::class, mappedBy: 'category')]
|
||||
#[ORM\OneToMany(mappedBy: 'category', targetEntity: ActivityReason::class)]
|
||||
private Collection $reasons;
|
||||
|
||||
/**
|
||||
|
@@ -28,7 +28,7 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
|
||||
public function __construct(
|
||||
protected ActivityReasonCategoryRepository $activityReasonCategoryRepository,
|
||||
protected ActivityReasonRepository $activityReasonRepository,
|
||||
protected TranslatableStringHelper $translatableStringHelper
|
||||
protected TranslatableStringHelper $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -26,7 +26,7 @@ class ActivityUsersJobAggregator implements AggregatorInterface
|
||||
|
||||
public function __construct(
|
||||
private readonly UserJobRepositoryInterface $userJobRepository,
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -26,7 +26,7 @@ class ActivityUsersScopeAggregator implements AggregatorInterface
|
||||
|
||||
public function __construct(
|
||||
private readonly ScopeRepositoryInterface $scopeRepository,
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -26,7 +26,7 @@ class CreatorJobAggregator implements AggregatorInterface
|
||||
|
||||
public function __construct(
|
||||
private readonly UserJobRepositoryInterface $userJobRepository,
|
||||
private readonly TranslatableStringHelper $translatableStringHelper
|
||||
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -26,7 +26,7 @@ class CreatorScopeAggregator implements AggregatorInterface
|
||||
|
||||
public function __construct(
|
||||
private readonly ScopeRepository $scopeRepository,
|
||||
private readonly TranslatableStringHelper $translatableStringHelper
|
||||
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -0,0 +1,99 @@
|
||||
<?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\Export\Aggregator\PersonAggregators;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\PersonBundle\Entity\Household\Household;
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdMember;
|
||||
use Chill\PersonBundle\Repository\Household\HouseholdRepository;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
final readonly class HouseholdAggregator implements AggregatorInterface
|
||||
{
|
||||
public function __construct(private HouseholdRepository $householdRepository) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// nothing to add here
|
||||
}
|
||||
|
||||
public function getFormDefaultData(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, mixed $data)
|
||||
{
|
||||
return function (int|string|null $value): string|int {
|
||||
if ('_header' === $value) {
|
||||
return 'export.aggregator.person.by_household.household';
|
||||
}
|
||||
|
||||
if ('' === $value || null === $value || null === $household = $this->householdRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $household->getId();
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
return ['activity_household_agg'];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'export.aggregator.person.by_household.title';
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->join(
|
||||
HouseholdMember::class,
|
||||
'activity_household_agg_household_member',
|
||||
Join::WITH,
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->eq('activity_household_agg_household_member.person', 'activity.person'),
|
||||
$qb->expr()->lte('activity_household_agg_household_member.startDate', 'activity.date'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->gte('activity_household_agg_household_member.endDate', 'activity.date'),
|
||||
$qb->expr()->isNull('activity_household_agg_household_member.endDate')
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$qb->join(
|
||||
Household::class,
|
||||
'activity_household_agg_household',
|
||||
Join::WITH,
|
||||
$qb->expr()->eq('activity_household_agg_household_member.household', 'activity_household_agg_household')
|
||||
);
|
||||
|
||||
$qb
|
||||
->addSelect('activity_household_agg_household.id AS activity_household_agg')
|
||||
->addGroupBy('activity_household_agg');
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::ACTIVITY_PERSON;
|
||||
}
|
||||
}
|
@@ -19,6 +19,7 @@ use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\MainBundle\Export\ListInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdMember;
|
||||
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||
use Doctrine\DBAL\Exception\InvalidArgumentException;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
@@ -44,6 +45,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
'person_firstname',
|
||||
'person_lastname',
|
||||
'person_id',
|
||||
'household_id',
|
||||
];
|
||||
private readonly bool $filterStatsByCenters;
|
||||
|
||||
@@ -189,19 +191,26 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
{
|
||||
$centers = array_map(static fn ($el) => $el['center'], $acl);
|
||||
|
||||
// throw an error if any fields are present
|
||||
// throw an error if no fields are present
|
||||
if (!\array_key_exists('fields', $data)) {
|
||||
throw new InvalidArgumentException('Any fields have been checked.');
|
||||
throw new InvalidArgumentException('No fields have been checked.');
|
||||
}
|
||||
|
||||
$qb = $this->entityManager->createQueryBuilder();
|
||||
|
||||
$qb
|
||||
->from('ChillActivityBundle:Activity', 'activity')
|
||||
->join('activity.person', 'actperson');
|
||||
->join('activity.person', 'person')
|
||||
->join(
|
||||
HouseholdMember::class,
|
||||
'householdmember',
|
||||
Query\Expr\Join::WITH,
|
||||
'person = householdmember.person AND householdmember.startDate <= activity.date AND (householdmember.endDate IS NULL OR householdmember.endDate > activity.date)'
|
||||
)
|
||||
->join('householdmember.household', 'household');
|
||||
|
||||
if ($this->filterStatsByCenters) {
|
||||
$qb->join('actperson.centerHistory', 'centerHistory');
|
||||
$qb->join('person.centerHistory', 'centerHistory');
|
||||
$qb->where(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte('centerHistory.startDate', 'activity.date'),
|
||||
@@ -224,17 +233,22 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
break;
|
||||
|
||||
case 'person_firstname':
|
||||
$qb->addSelect('actperson.firstName AS person_firstname');
|
||||
$qb->addSelect('person.firstName AS person_firstname');
|
||||
|
||||
break;
|
||||
|
||||
case 'person_lastname':
|
||||
$qb->addSelect('actperson.lastName AS person_lastname');
|
||||
$qb->addSelect('person.lastName AS person_lastname');
|
||||
|
||||
break;
|
||||
|
||||
case 'person_id':
|
||||
$qb->addSelect('actperson.id AS person_id');
|
||||
$qb->addSelect('person.id AS person_id');
|
||||
|
||||
break;
|
||||
|
||||
case 'household_id':
|
||||
$qb->addSelect('household.id AS household_id');
|
||||
|
||||
break;
|
||||
|
||||
@@ -284,7 +298,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
return ActivityStatsVoter::LISTS;
|
||||
}
|
||||
|
||||
public function supportsModifiers()
|
||||
public function supportsModifiers(): array
|
||||
{
|
||||
return [
|
||||
Declarations::ACTIVITY,
|
||||
|
@@ -42,7 +42,7 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
/**
|
||||
* The action for this report.
|
||||
*/
|
||||
protected string $action = 'sum'
|
||||
protected string $action = 'sum',
|
||||
) {
|
||||
$this->filterStatsByCenters = $parameterBag->get('chill_main')['acl']['filter_stats_by_center'];
|
||||
}
|
||||
|
@@ -39,7 +39,7 @@ class ListActivityHelper
|
||||
private readonly TranslatorInterface $translator,
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||
private readonly TranslatableStringExportLabelHelper $translatableStringLabelHelper,
|
||||
private readonly UserHelper $userHelper
|
||||
private readonly UserHelper $userHelper,
|
||||
) {}
|
||||
|
||||
public function addSelect(QueryBuilder $qb): void
|
||||
|
@@ -73,7 +73,7 @@ final readonly class PeriodHavingActivityBetweenDatesFilter implements FilterInt
|
||||
|
||||
$qb->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM '.Activity::class." {$alias} WHERE {$alias}.date >= :{$from} AND {$alias}.date < :{$to} AND {$alias}.accompanyingPeriod = activity.accompanyingPeriod"
|
||||
'SELECT 1 FROM '.Activity::class." {$alias} WHERE {$alias}.date >= :{$from} AND {$alias}.date < :{$to} AND {$alias}.accompanyingPeriod = acp"
|
||||
)
|
||||
);
|
||||
|
||||
|
@@ -25,7 +25,7 @@ final readonly class ActivityPresenceFilter implements FilterInterface
|
||||
{
|
||||
public function __construct(
|
||||
private TranslatableStringHelperInterface $translatableStringHelper,
|
||||
private TranslatorInterface $translator
|
||||
private TranslatorInterface $translator,
|
||||
) {}
|
||||
|
||||
public function getTitle()
|
||||
|
@@ -26,7 +26,7 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
|
||||
{
|
||||
public function __construct(
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper,
|
||||
protected ActivityTypeRepositoryInterface $activityTypeRepository
|
||||
protected ActivityTypeRepositoryInterface $activityTypeRepository,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -39,7 +39,7 @@ final readonly class PersonHavingActivityBetweenDateFilter implements ExportElem
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
public function alterQuery(QueryBuilder $qb, $data): void
|
||||
{
|
||||
// create a subquery for activity
|
||||
$sqb = $qb->getEntityManager()->createQueryBuilder();
|
||||
@@ -121,7 +121,7 @@ final readonly class PersonHavingActivityBetweenDateFilter implements ExportElem
|
||||
];
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
return [
|
||||
[] === $data['reasons'] ?
|
||||
@@ -141,7 +141,7 @@ final readonly class PersonHavingActivityBetweenDateFilter implements ExportElem
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'export.filter.activity.person_between_dates.title';
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@ class UsersJobFilter implements FilterInterface
|
||||
|
||||
public function __construct(
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||
private readonly UserJobRepositoryInterface $userJobRepository
|
||||
private readonly UserJobRepositoryInterface $userJobRepository,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -29,7 +29,7 @@ class UsersScopeFilter implements FilterInterface
|
||||
|
||||
public function __construct(
|
||||
private readonly ScopeRepositoryInterface $scopeRepository,
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -59,7 +59,7 @@ class ActivityType extends AbstractType
|
||||
protected TranslatableStringHelper $translatableStringHelper,
|
||||
protected array $timeChoices,
|
||||
protected SocialIssueRender $socialIssueRender,
|
||||
protected SocialActionRender $socialActionRender
|
||||
protected SocialActionRender $socialActionRender,
|
||||
) {
|
||||
if (!$tokenStorage->getToken()->getUser() instanceof User) {
|
||||
throw new \RuntimeException('you should have a valid user');
|
||||
|
@@ -27,7 +27,7 @@ class PickActivityReasonType extends AbstractType
|
||||
public function __construct(
|
||||
private readonly ActivityReasonRepository $activityReasonRepository,
|
||||
private readonly ActivityReasonRender $reasonRender,
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
|
@@ -32,7 +32,7 @@ final readonly class ActivityDocumentACLAwareRepository implements ActivityDocum
|
||||
private EntityManagerInterface $em,
|
||||
private CenterResolverManagerInterface $centerResolverManager,
|
||||
private AuthorizationHelperForCurrentUserInterface $authorizationHelperForCurrentUser,
|
||||
private Security $security
|
||||
private Security $security,
|
||||
) {}
|
||||
|
||||
public function buildFetchQueryActivityDocumentLinkedToPersonFromPersonContext(Person $person, ?\DateTimeImmutable $startDate = null, ?\DateTimeImmutable $endDate = null, ?string $content = null): FetchQueryInterface
|
||||
|
@@ -25,7 +25,7 @@ class ActivityReasonRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(
|
||||
ManagerRegistry $registry,
|
||||
private readonly RequestStack $requestStack
|
||||
private readonly RequestStack $requestStack,
|
||||
) {
|
||||
parent::__construct($registry, ActivityReason::class);
|
||||
}
|
||||
|
@@ -22,8 +22,8 @@
|
||||
<ul class="record_actions">
|
||||
<li class="add-persons">
|
||||
<add-persons
|
||||
:buttonTitle="trans(ACTIVITY_ADD_PERSONS)"
|
||||
:modalTitle="trans(ACTIVITY_ADD_PERSONS)"
|
||||
buttonTitle="activity.add_persons"
|
||||
modalTitle="activity.add_persons"
|
||||
v-bind:key="addPersons.key"
|
||||
v-bind:options="addPersonsOptions"
|
||||
@addNewPersons="addNewPersons"
|
||||
@@ -40,20 +40,6 @@ import { mapState, mapGetters } from 'vuex';
|
||||
import AddPersons from 'ChillPersonAssets/vuejs/_components/AddPersons.vue';
|
||||
import PersonsBloc from './ConcernedGroups/PersonsBloc.vue';
|
||||
import PersonText from 'ChillPersonAssets/vuejs/_components/Entity/PersonText.vue';
|
||||
import {
|
||||
ACTIVITY_BLOC_PERSONS,
|
||||
ACTIVITY_BLOC_PERSONS_ASSOCIATED,
|
||||
ACTIVITY_BLOC_PERSONS_NOT_ASSOCIATED,
|
||||
ACTIVITY_BLOC_THIRDPARTY,
|
||||
ACTIVITY_BLOC_USERS,
|
||||
ACTIVITY_ADD_PERSONS,
|
||||
ACTIVITY_LOCATION,
|
||||
ACTIVITY_CHOOSE_LOCATION,
|
||||
MULTISELECT_SELECT_LABEL,
|
||||
MULTISELECT_DESELECT_LABEL,
|
||||
MULTISELECT_SELECTED_LABEL,
|
||||
trans,
|
||||
} from "../../../../../../../../../../../assets/translator";
|
||||
|
||||
export default {
|
||||
name: "ConcernedGroups",
|
||||
@@ -62,22 +48,16 @@ export default {
|
||||
PersonsBloc,
|
||||
PersonText
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
trans,
|
||||
ACTIVITY_ADD_PERSONS
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
personsBlocs: [
|
||||
{ key: 'persons',
|
||||
title: trans(ACTIVITY_BLOC_PERSONS),
|
||||
title: 'activity.bloc_persons',
|
||||
persons: [],
|
||||
included: false
|
||||
},
|
||||
{ key: 'personsAssociated',
|
||||
title: trans(ACTIVITY_BLOC_PERSONS_ASSOCIATED),
|
||||
title: 'activity.bloc_persons_associated',
|
||||
persons: [],
|
||||
included: window.activity ? window.activity.activityType.personsVisible !== 0 : true
|
||||
},
|
||||
@@ -87,12 +67,12 @@ export default {
|
||||
included: window.activity ? window.activity.activityType.personsVisible !== 0 : true
|
||||
},
|
||||
{ key: 'thirdparty',
|
||||
title: trans(ACTIVITY_BLOC_THIRDPARTY),
|
||||
title: 'activity.bloc_thirdparty',
|
||||
persons: [],
|
||||
included: window.activity ? window.activity.activityType.thirdPartiesVisible !== 0 : true
|
||||
},
|
||||
{ key: 'users',
|
||||
title: trans(ACTIVITY_BLOC_USERS),
|
||||
title: 'activity.bloc_users',
|
||||
persons: [],
|
||||
included: window.activity ? window.activity.activityType.usersVisible !== 0 : true
|
||||
},
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<teleport to="#location">
|
||||
<div class="mb-3 row">
|
||||
<label :class="locationClassList">
|
||||
{{ trans(ACTIVITY_LOCATION) }}
|
||||
{{ $t("activity.location") }}
|
||||
</label>
|
||||
<div class="col-sm-8">
|
||||
<VueMultiselect
|
||||
@@ -13,11 +13,11 @@
|
||||
open-direction="top"
|
||||
:multiple="false"
|
||||
:searchable="true"
|
||||
:placeholder="trans(ACTIVITY_CHOOSE_LOCATION)"
|
||||
:placeholder="$t('activity.choose_location')"
|
||||
:custom-label="customLabel"
|
||||
:select-label="trans(MULTISELECT_SELECT_LABEL)"
|
||||
:deselect-label="trans(MULTISELECT_DESELECT_LABEL)"
|
||||
:selected-label="trans(MULTISELECT_SELECTED_LABEL)"
|
||||
:select-label="$t('multiselect.select_label')"
|
||||
:deselect-label="$t('multiselect.deselect_label')"
|
||||
:selected-label="$t('multiselect.selected_label')"
|
||||
:options="availableLocations"
|
||||
group-values="locations"
|
||||
group-label="locationGroup"
|
||||
@@ -34,14 +34,6 @@
|
||||
import { mapState, mapGetters } from "vuex";
|
||||
import VueMultiselect from "vue-multiselect";
|
||||
import NewLocation from "./Location/NewLocation.vue";
|
||||
import {
|
||||
trans,
|
||||
ACTIVITY_LOCATION,
|
||||
ACTIVITY_CHOOSE_LOCATION,
|
||||
MULTISELECT_SELECT_LABEL,
|
||||
MULTISELECT_DESELECT_LABEL,
|
||||
MULTISELECT_SELECTED_LABEL
|
||||
} from '../../../../../../../../../../../assets/translator'
|
||||
|
||||
export default {
|
||||
name: "Location",
|
||||
@@ -49,16 +41,6 @@ export default {
|
||||
NewLocation,
|
||||
VueMultiselect,
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
trans,
|
||||
ACTIVITY_LOCATION,
|
||||
ACTIVITY_CHOOSE_LOCATION,
|
||||
MULTISELECT_SELECT_LABEL,
|
||||
MULTISELECT_DESELECT_LABEL,
|
||||
MULTISELECT_SELECTED_LABEL
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
locationClassList:
|
||||
|
@@ -3,7 +3,7 @@
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a class="btn btn-sm btn-create" @click="openModal">
|
||||
{{ trans(ACTIVITY_CREATE_NEW_LOCATION) }}
|
||||
{{ $t('activity.create_new_location') }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -14,7 +14,7 @@
|
||||
@close="modal.showModal = false">
|
||||
|
||||
<template v-slot:header>
|
||||
<h3 class="modal-title">{{ trans(ACTIVITY_CREATE_NEW_LOCATION) }}</h3>
|
||||
<h3 class="modal-title">{{ $t('activity.create_new_location') }}</h3>
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<form>
|
||||
@@ -26,17 +26,17 @@
|
||||
|
||||
<div class="form-floating mb-3">
|
||||
<select class="form-select form-select-lg" id="type" required v-model="selectType">
|
||||
<option selected disabled value="">{{ trans(ACTIVITY_CHOOSE_LOCATION_TYPE) }}</option>
|
||||
<option selected disabled value="">{{ $t('activity.choose_location_type') }}</option>
|
||||
<option v-for="t in locationTypes" :value="t" :key="t.id">
|
||||
{{ t.title.fr }}
|
||||
</option>
|
||||
</select>
|
||||
<label>{{ trans(ACTIVITY_LOCATION_FIELDS_TYPE) }}</label>
|
||||
<label>{{ $t('activity.location_fields.type') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="form-floating mb-3">
|
||||
<input class="form-control form-control-lg" id="name" v-model="inputName" placeholder />
|
||||
<label for="name">{{ trans(ACTIVITY_LOCATION_FIELDS_NAME) }}</label>
|
||||
<label for="name">{{ $t('activity.location_fields.name') }}</label>
|
||||
</div>
|
||||
|
||||
<add-address
|
||||
@@ -49,15 +49,15 @@
|
||||
|
||||
<div class="form-floating mb-3" v-if="showContactData">
|
||||
<input class="form-control form-control-lg" id="phonenumber1" v-model="inputPhonenumber1" placeholder />
|
||||
<label for="phonenumber1">{{ trans(ACTIVITY_LOCATION_FIELDS_PHONENUMBER1) }}</label>
|
||||
<label for="phonenumber1">{{ $t('activity.location_fields.phonenumber1') }}</label>
|
||||
</div>
|
||||
<div class="form-floating mb-3" v-if="hasPhonenumber1">
|
||||
<input class="form-control form-control-lg" id="phonenumber2" v-model="inputPhonenumber2" placeholder />
|
||||
<label for="phonenumber2">{{ trans(ACTIVITY_LOCATION_FIELDS_PHONENUMBER2) }}</label>
|
||||
<label for="phonenumber2">{{ $t('activity.location_fields.phonenumber2') }}</label>
|
||||
</div>
|
||||
<div class="form-floating mb-3" v-if="showContactData">
|
||||
<input class="form-control form-control-lg" id="email" v-model="inputEmail" placeholder />
|
||||
<label for="email">{{ trans(ACTIVITY_LOCATION_FIELDS_EMAIL) }}</label>
|
||||
<label for="email">{{ $t('activity.location_fields.email') }}</label>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
@@ -66,7 +66,7 @@
|
||||
<button class="btn btn-save"
|
||||
@click.prevent="saveNewLocation"
|
||||
>
|
||||
{{ trans(SAVE) }}
|
||||
{{ $t('action.save') }}
|
||||
</button>
|
||||
</template>
|
||||
|
||||
@@ -81,13 +81,6 @@ import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue"
|
||||
import { mapState } from "vuex";
|
||||
import { getLocationTypes } from "../../api";
|
||||
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods';
|
||||
import {
|
||||
SAVE,
|
||||
ACTIVITY_LOCATION_FIELDS_EMAIL, ACTIVITY_LOCATION_FIELDS_PHONENUMBER1,
|
||||
ACTIVITY_LOCATION_FIELDS_PHONENUMBER2, ACTIVITY_LOCATION_FIELDS_NAME,
|
||||
ACTIVITY_LOCATION_FIELDS_TYPE, ACTIVITY_CHOOSE_LOCATION_TYPE, ACTIVITY_CREATE_NEW_LOCATION,
|
||||
trans
|
||||
} from "../../../../../../../../../../../../assets/translator";
|
||||
|
||||
export default {
|
||||
name: "NewLocation",
|
||||
@@ -95,19 +88,6 @@ export default {
|
||||
Modal,
|
||||
AddAddress,
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
trans,
|
||||
SAVE,
|
||||
ACTIVITY_LOCATION_FIELDS_EMAIL,
|
||||
ACTIVITY_LOCATION_FIELDS_PHONENUMBER1,
|
||||
ACTIVITY_LOCATION_FIELDS_PHONENUMBER2,
|
||||
ACTIVITY_LOCATION_FIELDS_NAME,
|
||||
ACTIVITY_LOCATION_FIELDS_TYPE,
|
||||
ACTIVITY_CHOOSE_LOCATION_TYPE,
|
||||
ACTIVITY_CREATE_NEW_LOCATION,
|
||||
};
|
||||
},
|
||||
props: ['availableLocations'],
|
||||
data() {
|
||||
return {
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
<div class="mb-3 row">
|
||||
<div class="col-4">
|
||||
<label :class="socialIssuesClassList">{{ trans(ACTIVITY_SOCIAL_ISSUES) }}</label>
|
||||
<label :class="socialIssuesClassList">{{ $t('activity.social_issues') }}</label>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
:allow-empty="true"
|
||||
:show-labels="false"
|
||||
:loading="issueIsLoading"
|
||||
:placeholder="trans(ACTIVITY_CHOOSE_OTHER_SOCIAL_ISSUE)"
|
||||
:placeholder="$t('activity.choose_other_social_issue')"
|
||||
:options="socialIssuesOther"
|
||||
@select="addIssueInList">
|
||||
</VueMultiselect>
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
<div class="mb-3 row">
|
||||
<div class="col-4">
|
||||
<label :class="socialActionsClassList">{{ trans(ACTIVITY_SOCIAL_ACTIONS) }}</label>
|
||||
<label :class="socialActionsClassList">{{ $t('activity.social_actions') }}</label>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
</div>
|
||||
|
||||
<span v-else-if="socialIssuesSelected.length === 0" class="inline-choice chill-no-data-statement mt-3">
|
||||
{{ trans(ACTIVITY_SELECT_FIRST_A_SOCIAL_ISSUE) }}
|
||||
{{ $t('activity.select_first_a_social_issue') }}
|
||||
</span>
|
||||
|
||||
<template v-else-if="socialActionsList.length > 0">
|
||||
@@ -66,7 +66,7 @@
|
||||
</template>
|
||||
|
||||
<span v-else-if="actionAreLoaded && socialActionsList.length === 0" class="inline-choice chill-no-data-statement mt-3">
|
||||
{{ trans(ACTIVITY_SOCIAL_ACTION_LIST_EMPTY) }}
|
||||
{{ $t('activity.social_action_list_empty') }}
|
||||
</span>
|
||||
|
||||
|
||||
@@ -81,11 +81,6 @@ import VueMultiselect from 'vue-multiselect';
|
||||
import CheckSocialIssue from './SocialIssuesAcc/CheckSocialIssue.vue';
|
||||
import CheckSocialAction from './SocialIssuesAcc/CheckSocialAction.vue';
|
||||
import { getSocialIssues, getSocialActionByIssue } from '../api.js';
|
||||
import {
|
||||
ACTIVITY_SOCIAL_ACTION_LIST_EMPTY,
|
||||
ACTIVITY_SELECT_FIRST_A_SOCIAL_ISSUE, ACTIVITY_SOCIAL_ACTIONS,
|
||||
ACTIVITY_SOCIAL_ISSUES, ACTIVITY_CHOOSE_OTHER_SOCIAL_ISSUE, trans
|
||||
} from "../../../../../../../../../../../assets/translator";
|
||||
|
||||
export default {
|
||||
name: "SocialIssuesAcc",
|
||||
@@ -94,16 +89,6 @@ export default {
|
||||
CheckSocialAction,
|
||||
VueMultiselect
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
trans,
|
||||
ACTIVITY_SOCIAL_ACTION_LIST_EMPTY,
|
||||
ACTIVITY_SELECT_FIRST_A_SOCIAL_ISSUE,
|
||||
ACTIVITY_SOCIAL_ACTIONS,
|
||||
ACTIVITY_SOCIAL_ISSUES,
|
||||
ACTIVITY_CHOOSE_OTHER_SOCIAL_ISSUE
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
issueIsLoading: false,
|
||||
|
@@ -75,7 +75,7 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleHierarchyIn
|
||||
|
||||
public function __construct(
|
||||
protected Security $security,
|
||||
VoterHelperFactoryInterface $voterHelperFactory
|
||||
VoterHelperFactoryInterface $voterHelperFactory,
|
||||
) {
|
||||
$this->voterHelper = $voterHelperFactory->generate(self::class)
|
||||
->addCheckFor(Person::class, [self::SEE, self::CREATE])
|
||||
|
@@ -50,7 +50,7 @@ class ActivityContext implements
|
||||
private readonly TranslatorInterface $translator,
|
||||
private readonly BaseContextData $baseContextData,
|
||||
private readonly ThirdPartyRender $thirdPartyRender,
|
||||
private readonly ThirdPartyRepository $thirdPartyRepository
|
||||
private readonly ThirdPartyRepository $thirdPartyRepository,
|
||||
) {}
|
||||
|
||||
public function adminFormReverseTransform(array $data): array
|
||||
|
@@ -56,7 +56,7 @@ class ListActivitiesByAccompanyingPeriodContext implements
|
||||
private readonly SocialIssueRepository $socialIssueRepository,
|
||||
private readonly ThirdPartyRepository $thirdPartyRepository,
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||
private readonly UserRepository $userRepository
|
||||
private readonly UserRepository $userRepository,
|
||||
) {}
|
||||
|
||||
public function adminFormReverseTransform(array $data): array
|
||||
|
@@ -76,7 +76,7 @@ final class TranslatableActivityReasonTest extends TypeTestCase
|
||||
*/
|
||||
protected function getTranslatableStringHelper(
|
||||
$locale = 'en',
|
||||
$fallbackLocale = 'en'
|
||||
$fallbackLocale = 'en',
|
||||
) {
|
||||
$prophet = new \Prophecy\Prophet();
|
||||
$requestStack = $prophet->prophesize();
|
||||
|
@@ -138,7 +138,7 @@ final class ActivityVoterTest extends KernelTestCase
|
||||
Scope $scope,
|
||||
Center $center,
|
||||
$attribute,
|
||||
$message
|
||||
$message,
|
||||
) {
|
||||
$token = $this->prepareToken($user);
|
||||
$activity = $this->prepareActivity($scope, $this->preparePerson($center));
|
||||
|
@@ -32,7 +32,7 @@ class TimelineActivityProvider implements TimelineProviderInterface
|
||||
protected EntityManagerInterface $em,
|
||||
protected AuthorizationHelperInterface $helper,
|
||||
TokenStorageInterface $storage,
|
||||
protected ActivityACLAwareRepository $aclAwareRepository
|
||||
protected ActivityACLAwareRepository $aclAwareRepository,
|
||||
) {
|
||||
if (!$storage->getToken()->getUser() instanceof User) {
|
||||
throw new \RuntimeException('A user should be authenticated !');
|
||||
|
@@ -243,3 +243,7 @@ services:
|
||||
Chill\ActivityBundle\Export\Aggregator\PersonAggregators\PersonAggregator:
|
||||
tags:
|
||||
- { name: chill.export_aggregator, alias: activity_person_agg }
|
||||
|
||||
Chill\ActivityBundle\Export\Aggregator\PersonAggregators\HouseholdAggregator:
|
||||
tags:
|
||||
- { name: chill.export_aggregator, alias: activity_household_agg }
|
||||
|
@@ -101,31 +101,6 @@ activity:
|
||||
Insert a document: Insérer un document
|
||||
Remove a document: Supprimer le document
|
||||
comment: Commentaire
|
||||
errors: Le formulaire contient des erreurs
|
||||
social_issues: Problématiques sociales
|
||||
choose_other_social_issue: Ajouter une autre problématique sociale...
|
||||
social_actions: Actions d'accompagnement
|
||||
select_first_a_social_issue: Sélectionnez d'abord une problématique sociale
|
||||
social_action_list_empty: Aucune action sociale disponible
|
||||
add_persons: Ajouter des personnes concernées
|
||||
bloc_persons: Usagers
|
||||
bloc_persons_associated: Usagers du parcours
|
||||
bloc_persons_not_associated: Tiers non-pro.
|
||||
bloc_thirdparty: Tiers professionnels
|
||||
bloc_users: T(M)S
|
||||
location: Localisation
|
||||
choose_location: Choisissez une localisation
|
||||
choose_location_type: Choisissez un type de localisation
|
||||
create_new_location: Créer une nouvelle localisation
|
||||
location_fields:
|
||||
name: Nom
|
||||
type: Type
|
||||
phonenumber1: Téléphone
|
||||
phonenumber2: Autre téléphone
|
||||
email: Adresse courriel
|
||||
create_address: Créer une adresse
|
||||
edit_address: Modifier l'adresse
|
||||
|
||||
No documents: Aucun document
|
||||
|
||||
# activity filter in list page
|
||||
@@ -453,6 +428,9 @@ export:
|
||||
by_person:
|
||||
title: Grouper les échanges par usager (dossier d'usager dans lequel l'échange est enregistré)
|
||||
person: Usager
|
||||
by_household:
|
||||
title: Grouper les échanges par ménage
|
||||
household: Identifiant ménage
|
||||
acp:
|
||||
by_activity_type:
|
||||
title: Grouper les parcours par type d'échange
|
||||
|
@@ -25,7 +25,7 @@ final class AsideActivityController extends CRUDController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly AsideActivityCategoryRepository $categoryRepository,
|
||||
private readonly Security $security
|
||||
private readonly Security $security,
|
||||
) {}
|
||||
|
||||
public function createEntity(string $action, Request $request): object
|
||||
@@ -76,7 +76,7 @@ final class AsideActivityController extends CRUDController
|
||||
string $action,
|
||||
$query,
|
||||
Request $request,
|
||||
PaginatorInterface $paginator
|
||||
PaginatorInterface $paginator,
|
||||
) {
|
||||
if ('index' === $action) {
|
||||
return $query->orderBy('e.date', 'DESC');
|
||||
|
@@ -22,9 +22,9 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
class AsideActivityCategory
|
||||
{
|
||||
/**
|
||||
* @var Collection<AsideActivityCategory>
|
||||
* @var Collection<int, AsideActivityCategory>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: AsideActivityCategory::class, mappedBy: 'parent')]
|
||||
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: AsideActivityCategory::class)]
|
||||
private Collection $children;
|
||||
|
||||
#[ORM\Id]
|
||||
|
@@ -22,7 +22,7 @@ class ByActivityTypeAggregator implements AggregatorInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly AsideActivityCategoryRepository $asideActivityCategoryRepository,
|
||||
private readonly TranslatableStringHelper $translatableStringHelper
|
||||
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -26,7 +26,7 @@ class ByUserJobAggregator implements AggregatorInterface
|
||||
|
||||
public function __construct(
|
||||
private readonly UserJobRepositoryInterface $userJobRepository,
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -26,7 +26,7 @@ class ByUserScopeAggregator implements AggregatorInterface
|
||||
|
||||
public function __construct(
|
||||
private readonly ScopeRepositoryInterface $scopeRepository,
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -41,7 +41,7 @@ final readonly class ListAsideActivity implements ListInterface, GroupedExportIn
|
||||
private AsideActivityCategoryRepository $asideActivityCategoryRepository,
|
||||
private CategoryRender $categoryRender,
|
||||
private LocationRepository $locationRepository,
|
||||
private TranslatableStringHelperInterface $translatableStringHelper
|
||||
private TranslatableStringHelperInterface $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder) {}
|
||||
|
@@ -27,7 +27,7 @@ class ByActivityTypeFilter implements FilterInterface
|
||||
public function __construct(
|
||||
private readonly CategoryRender $categoryRender,
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||
private readonly AsideActivityCategoryRepository $asideActivityTypeRepository
|
||||
private readonly AsideActivityCategoryRepository $asideActivityTypeRepository,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -24,7 +24,7 @@ use Symfony\Component\Security\Core\Security;
|
||||
final readonly class ByLocationFilter implements FilterInterface
|
||||
{
|
||||
public function __construct(
|
||||
private Security $security
|
||||
private Security $security,
|
||||
) {}
|
||||
|
||||
public function getTitle(): string
|
||||
|
@@ -29,7 +29,7 @@ class ByUserJobFilter implements FilterInterface
|
||||
|
||||
public function __construct(
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||
private readonly UserJobRepositoryInterface $userJobRepository
|
||||
private readonly UserJobRepositoryInterface $userJobRepository,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -29,7 +29,7 @@ class ByUserScopeFilter implements FilterInterface
|
||||
|
||||
public function __construct(
|
||||
private readonly ScopeRepositoryInterface $scopeRepository,
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper
|
||||
private readonly TranslatableStringHelperInterface $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -44,7 +44,7 @@ class UserMenuBuilder implements LocalMenuBuilderInterface
|
||||
CountNotificationTask $counter,
|
||||
TokenStorageInterface $tokenStorage,
|
||||
TranslatorInterface $translator,
|
||||
AuthorizationCheckerInterface $authorizationChecker
|
||||
AuthorizationCheckerInterface $authorizationChecker,
|
||||
) {
|
||||
$this->counter = $counter;
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
|
@@ -26,7 +26,7 @@ class AsideActivityVoter extends AbstractChillVoter implements ProvideRoleHierar
|
||||
private readonly VoterHelperInterface $voterHelper;
|
||||
|
||||
public function __construct(
|
||||
VoterHelperFactoryInterface $voterHelperFactory
|
||||
VoterHelperFactoryInterface $voterHelperFactory,
|
||||
) {
|
||||
$this->voterHelper = $voterHelperFactory
|
||||
->generate(self::class)
|
||||
|
@@ -47,7 +47,7 @@ class SendTestShortMessageOnCalendarCommand extends Command
|
||||
private readonly PhoneNumberHelperInterface $phoneNumberHelper,
|
||||
private readonly ShortMessageForCalendarBuilderInterface $messageForCalendarBuilder,
|
||||
private readonly ShortMessageTransporterInterface $transporter,
|
||||
private readonly UserRepositoryInterface $userRepository
|
||||
private readonly UserRepositoryInterface $userRepository,
|
||||
) {
|
||||
parent::__construct('chill:calendar:test-send-short-message');
|
||||
}
|
||||
|
@@ -59,7 +59,7 @@ class CalendarController extends AbstractController
|
||||
private readonly AccompanyingPeriodRepository $accompanyingPeriodRepository,
|
||||
private readonly UserRepositoryInterface $userRepository,
|
||||
private readonly TranslatorInterface $translator,
|
||||
private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry
|
||||
private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry,
|
||||
) {}
|
||||
|
||||
/**
|
||||
|
@@ -103,7 +103,7 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface, HasCente
|
||||
private int $dateTimeVersion = 0;
|
||||
|
||||
/**
|
||||
* @var Collection<CalendarDoc>
|
||||
* @var Collection<int, \Chill\CalendarBundle\Entity\CalendarDoc>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'calendar', targetEntity: CalendarDoc::class, orphanRemoval: true)]
|
||||
private Collection $documents;
|
||||
@@ -120,7 +120,7 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface, HasCente
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @var Collection&Selectable<int, Invite>
|
||||
* @var \Doctrine\Common\Collections\Collection<int, \Chill\CalendarBundle\Entity\Invite>&Selectable
|
||||
*/
|
||||
#[Serializer\Groups(['read', 'docgen:read'])]
|
||||
#[ORM\OneToMany(mappedBy: 'calendar', targetEntity: Invite::class, cascade: ['persist', 'remove', 'merge', 'detach'], orphanRemoval: true)]
|
||||
@@ -143,7 +143,7 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface, HasCente
|
||||
private ?Person $person = null;
|
||||
|
||||
/**
|
||||
* @var Collection<Person>
|
||||
* @var Collection<int, Person>
|
||||
*/
|
||||
#[Serializer\Groups(['calendar:read', 'read', 'calendar:light', 'docgen:read'])]
|
||||
#[Assert\Count(min: 1, minMessage: 'calendar.At least {{ limit }} person is required.')]
|
||||
@@ -157,7 +157,7 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface, HasCente
|
||||
private PrivateCommentEmbeddable $privateComment;
|
||||
|
||||
/**
|
||||
* @var Collection<ThirdParty>
|
||||
* @var Collection<int, ThirdParty>
|
||||
*/
|
||||
#[Serializer\Groups(['calendar:read', 'read', 'calendar:light', 'docgen:read'])]
|
||||
#[ORM\ManyToMany(targetEntity: ThirdParty::class)]
|
||||
|
@@ -47,7 +47,7 @@ class CalendarDoc implements TrackCreationInterface, TrackUpdateInterface
|
||||
Calendar $calendar,
|
||||
#[ORM\ManyToOne(targetEntity: StoredObject::class, cascade: ['persist'])]
|
||||
#[ORM\JoinColumn(nullable: false)]
|
||||
private ?StoredObject $storedObject
|
||||
private ?StoredObject $storedObject,
|
||||
) {
|
||||
$this->setCalendar($calendar);
|
||||
$this->datetimeVersion = $calendar->getDateTimeVersion();
|
||||
|
@@ -26,7 +26,7 @@ final readonly class JobAggregator implements AggregatorInterface
|
||||
|
||||
public function __construct(
|
||||
private UserJobRepository $jobRepository,
|
||||
private TranslatableStringHelper $translatableStringHelper
|
||||
private TranslatableStringHelper $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -26,7 +26,7 @@ final readonly class ScopeAggregator implements AggregatorInterface
|
||||
|
||||
public function __construct(
|
||||
private ScopeRepository $scopeRepository,
|
||||
private TranslatableStringHelper $translatableStringHelper
|
||||
private TranslatableStringHelper $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -28,7 +28,7 @@ final readonly class JobFilter implements FilterInterface
|
||||
|
||||
public function __construct(
|
||||
private TranslatableStringHelper $translatableStringHelper,
|
||||
private UserJobRepositoryInterface $userJobRepository
|
||||
private UserJobRepositoryInterface $userJobRepository,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -30,7 +30,7 @@ class ScopeFilter implements FilterInterface
|
||||
public function __construct(
|
||||
protected TranslatorInterface $translator,
|
||||
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||
private readonly ScopeRepositoryInterface $scopeRepository
|
||||
private readonly ScopeRepositoryInterface $scopeRepository,
|
||||
) {}
|
||||
|
||||
public function addRole(): ?string
|
||||
|
@@ -37,7 +37,7 @@ class CalendarType extends AbstractType
|
||||
private readonly IdToUsersDataTransformer $idToUsersDataTransformer,
|
||||
private readonly IdToLocationDataTransformer $idToLocationDataTransformer,
|
||||
private readonly ThirdPartiesToIdDataTransformer $partiesToIdDataTransformer,
|
||||
private readonly IdToCalendarRangeDataTransformer $calendarRangeDataTransformer
|
||||
private readonly IdToCalendarRangeDataTransformer $calendarRangeDataTransformer,
|
||||
) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
|
@@ -46,7 +46,7 @@ class CalendarMessage
|
||||
public function __construct(
|
||||
Calendar $calendar,
|
||||
private readonly string $action,
|
||||
User $byUser
|
||||
User $byUser,
|
||||
) {
|
||||
$this->calendarId = $calendar->getId();
|
||||
$this->byUserId = $byUser->getId();
|
||||
|
@@ -59,7 +59,7 @@ final readonly class MSUserAbsenceReader implements MSUserAbsenceReaderInterface
|
||||
'alwaysEnabled' => true,
|
||||
'scheduled' => RemoteEventConverter::convertStringDateWithoutTimezone($automaticRepliesSettings['scheduledStartDateTime']['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'),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -177,7 +177,7 @@ class MapCalendarToUser
|
||||
User $user,
|
||||
int $expiration,
|
||||
?string $id = null,
|
||||
?string $secret = null
|
||||
?string $secret = null,
|
||||
): void {
|
||||
$user->setAttributeByDomain(self::METADATA_KEY, self::EXPIRATION_SUBSCRIPTION_EVENT, $expiration);
|
||||
|
||||
|
@@ -57,7 +57,7 @@ class RemoteEventConverter
|
||||
private readonly LocationConverter $locationConverter,
|
||||
private readonly LoggerInterface $logger,
|
||||
private readonly PersonRenderInterface $personRender,
|
||||
private readonly TranslatorInterface $translator
|
||||
private readonly TranslatorInterface $translator,
|
||||
) {
|
||||
$this->defaultDateTimeZone = (new \DateTimeImmutable())->getTimezone();
|
||||
$this->remoteDateTimeZone = self::getRemoteTimeZone();
|
||||
|
@@ -351,7 +351,7 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface
|
||||
[
|
||||
'id' => $id,
|
||||
'lastModifiedDateTime' => $lastModified,
|
||||
'changeKey' => $changeKey
|
||||
'changeKey' => $changeKey,
|
||||
] = $this->createOnRemote($eventData, $calendar->getMainUser(), 'calendar_'.$calendar->getId());
|
||||
|
||||
if (null === $id) {
|
||||
@@ -427,7 +427,7 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface
|
||||
[
|
||||
'id' => $id,
|
||||
'lastModifiedDateTime' => $lastModified,
|
||||
'changeKey' => $changeKey
|
||||
'changeKey' => $changeKey,
|
||||
] = $this->createOnRemote(
|
||||
$eventData,
|
||||
$calendarRange->getUser(),
|
||||
@@ -564,7 +564,7 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface
|
||||
[
|
||||
'id' => $id,
|
||||
'lastModifiedDateTime' => $lastModified,
|
||||
'changeKey' => $changeKey
|
||||
'changeKey' => $changeKey,
|
||||
] = $this->patchOnRemote(
|
||||
$calendar->getRemoteId(),
|
||||
$eventData,
|
||||
|
@@ -33,6 +33,6 @@ class RemoteEvent
|
||||
#[Serializer\Groups(['read'])]
|
||||
public \DateTimeImmutable $endDate,
|
||||
#[Serializer\Groups(['read'])]
|
||||
public bool $isAllDay = false
|
||||
public bool $isAllDay = false,
|
||||
) {}
|
||||
}
|
||||
|
@@ -65,7 +65,7 @@ class CalendarRangeRepository implements ObjectRepository
|
||||
\DateTimeImmutable $from,
|
||||
\DateTimeImmutable $to,
|
||||
?int $limit = null,
|
||||
?int $offset = null
|
||||
?int $offset = null,
|
||||
): array {
|
||||
$qb = $this->buildQueryAvailableRangesForUser($user, $from, $to);
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<label class="form-label">{{ $t('created_availabilities') }}</label>
|
||||
<label class="form-label">{{ $t("created_availabilities") }}</label>
|
||||
<vue-multiselect
|
||||
v-model="pickedLocation"
|
||||
:options="locations"
|
||||
@@ -14,10 +14,15 @@
|
||||
></vue-multiselect>
|
||||
</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="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">
|
||||
<option value="00:05:00">5 minutes</option>
|
||||
<option value="00:10:00">10 minutes</option>
|
||||
@@ -58,13 +63,20 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3 col-xs-12">
|
||||
<div class="col-xs-12 col-sm-3">
|
||||
<div class="float-end">
|
||||
<div class="form-check input-group">
|
||||
<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>
|
||||
<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>
|
||||
@@ -72,39 +84,86 @@
|
||||
<FullCalendar :options="calendarOptions" ref="calendarRef">
|
||||
<template v-slot:eventContent="arg: EventApi">
|
||||
<span :class="eventClasses(arg.event)">
|
||||
<b v-if="arg.event.extendedProps.is === 'remote'">{{ arg.event.title}}</b>
|
||||
<b v-else-if="arg.event.extendedProps.is === 'range'">{{ arg.timeText }} - {{ arg.event.extendedProps.locationName }}</b>
|
||||
<b v-else-if="arg.event.extendedProps.is === 'local'">{{ 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>
|
||||
<b v-if="arg.event.extendedProps.is === 'remote'">{{
|
||||
arg.event.title
|
||||
}}</b>
|
||||
<b v-else-if="arg.event.extendedProps.is === 'range'"
|
||||
>{{ arg.timeText }} - {{ arg.event.extendedProps.locationName }}</b
|
||||
>
|
||||
<b v-else-if="arg.event.extendedProps.is === 'local'">{{
|
||||
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>
|
||||
</FullCalendar>
|
||||
|
||||
<div id="copy-widget">
|
||||
<div class="container">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-sm-4 col-xs-12">
|
||||
<h6 class="chill-red">{{ $t('copy_range_from_to') }}</h6>
|
||||
</div>
|
||||
<div class="col-sm-3 col-xs-12">
|
||||
<input class="form-control" type="date" v-model="copyFrom" />
|
||||
</div>
|
||||
<div class="col-sm-1 col-xs-12" style="text-align: center; font-size: x-large;">
|
||||
<i class="fa fa-angle-double-right"></i>
|
||||
</div>
|
||||
<div class="col-sm-3 col-xs-12" >
|
||||
<input class="form-control" type="date" v-model="copyTo" />
|
||||
</div>
|
||||
<div class="col-sm-1">
|
||||
<button class="btn btn-action" @click="copyDay">
|
||||
{{ $t('copy_range') }}
|
||||
</button>
|
||||
<div class="container mt-2 mb-2">
|
||||
|
||||
<div class="row justify-content-between align-items-center mb-4">
|
||||
<div class="col-xs-12 col-sm-3 col-md-2">
|
||||
<h6 class="chill-red">{{ $t("copy_range_from_to") }}</h6>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-9 col-md-2">
|
||||
<select v-model="dayOrWeek" id="dayOrWeek" class="form-select">
|
||||
<option value="day">{{ $t("from_day_to_day") }}</option>
|
||||
<option value="week">{{ $t("from_week_to_week") }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<template v-if="dayOrWeek === 'day'">
|
||||
<div class="col-xs-12 col-sm-3 col-md-3">
|
||||
<input class="form-control" type="date" v-model="copyFrom" />
|
||||
</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">
|
||||
<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>
|
||||
|
||||
<!-- not directly seen, but include in a modal -->
|
||||
@@ -112,42 +171,95 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
import type {
|
||||
CalendarOptions,
|
||||
DatesSetArg,
|
||||
EventInput
|
||||
} from '@fullcalendar/core';
|
||||
import {reactive, computed, ref} from "vue";
|
||||
import {useStore} from "vuex";
|
||||
import {key} from './store';
|
||||
import FullCalendar from '@fullcalendar/vue3';
|
||||
import frLocale from '@fullcalendar/core/locales/fr';
|
||||
import interactionPlugin, {DropArg, EventResizeDoneArg} from "@fullcalendar/interaction";
|
||||
EventInput,
|
||||
} from "@fullcalendar/core";
|
||||
import { reactive, computed, ref, onMounted } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { key } from "./store";
|
||||
import FullCalendar from "@fullcalendar/vue3";
|
||||
import frLocale from "@fullcalendar/core/locales/fr";
|
||||
import interactionPlugin, {
|
||||
DropArg,
|
||||
EventResizeDoneArg,
|
||||
} from "@fullcalendar/interaction";
|
||||
import timeGridPlugin from "@fullcalendar/timegrid";
|
||||
import {EventApi, DateSelectArg, EventDropArg, EventClickArg} from "@fullcalendar/core";
|
||||
import {ISOToDate} from "../../../../../ChillMainBundle/Resources/public/chill/js/date";
|
||||
import {
|
||||
EventApi,
|
||||
DateSelectArg,
|
||||
EventDropArg,
|
||||
EventClickArg,
|
||||
} from "@fullcalendar/core";
|
||||
import {
|
||||
dateToISO,
|
||||
ISOToDate,
|
||||
} from "../../../../../ChillMainBundle/Resources/public/chill/js/date";
|
||||
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 {useI18n} from "vue-i18n";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const store = useStore(key);
|
||||
|
||||
const {t} = useI18n();
|
||||
const { t } = useI18n();
|
||||
|
||||
const showWeekends = ref(false);
|
||||
const slotDuration = ref('00:05:00');
|
||||
const slotMinTime = ref('09:00:00');
|
||||
const slotMaxTime = ref('18:00:00');
|
||||
const slotDuration = ref("00:15:00");
|
||||
const slotMinTime = ref("09:00:00");
|
||||
const slotMaxTime = ref("18:00:00");
|
||||
const copyFrom = 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>({
|
||||
locale: frLocale,
|
||||
plugins: [interactionPlugin, timeGridPlugin],
|
||||
initialView: 'timeGridWeek',
|
||||
initialView: "timeGridWeek",
|
||||
initialDate: new Date(),
|
||||
scrollTimeReset: false,
|
||||
selectable: true,
|
||||
@@ -164,9 +276,9 @@ const baseOptions = ref<CalendarOptions>({
|
||||
selectMirror: false,
|
||||
editable: true,
|
||||
headerToolbar: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'timeGridWeek,timeGridDay'
|
||||
left: "prev,next today",
|
||||
center: "title",
|
||||
right: "timeGridWeek,timeGridDay",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -180,20 +292,23 @@ const locations = computed<Location[]>(() => {
|
||||
|
||||
const pickedLocation = computed<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 {
|
||||
store.commit('locations/setLocationPicked', newLocation, {root: true});
|
||||
}
|
||||
})
|
||||
store.commit("locations/setLocationPicked", newLocation, { root: true });
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* return the show classes for the event
|
||||
* @param arg
|
||||
*/
|
||||
const eventClasses = function(arg: EventApi): object {
|
||||
return {'calendarRangeItems': true};
|
||||
}
|
||||
const eventClasses = function (arg: EventApi): object {
|
||||
return { calendarRangeItems: true };
|
||||
};
|
||||
|
||||
/*
|
||||
// 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
|
||||
*/
|
||||
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 {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
function onClickDelete(event: EventApi): void {
|
||||
console.log('onClickDelete', event);
|
||||
|
||||
if (event.extendedProps.is !== 'range') {
|
||||
if (event.extendedProps.is !== "range") {
|
||||
return;
|
||||
}
|
||||
|
||||
store.dispatch('calendarRanges/deleteRange', event.extendedProps.calendarRangeId);
|
||||
store.dispatch(
|
||||
"calendarRanges/deleteRange",
|
||||
event.extendedProps.calendarRangeId
|
||||
);
|
||||
}
|
||||
|
||||
function onEventDropOrResize(payload: EventDropArg | EventResizeDoneArg) {
|
||||
if (payload.event.extendedProps.is !== 'range') {
|
||||
if (payload.event.extendedProps.is !== "range") {
|
||||
return;
|
||||
}
|
||||
const changedEvent = payload.event;
|
||||
|
||||
store.dispatch('calendarRanges/patchRangeTime', {
|
||||
store.dispatch("calendarRanges/patchRangeTime", {
|
||||
calendarRangeId: payload.event.extendedProps.calendarRangeId,
|
||||
start: payload.event.start,
|
||||
end: payload.event.end,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function onEventClick(payload: EventClickArg): void {
|
||||
// @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;
|
||||
}
|
||||
if (payload.event.extendedProps.is !== 'range') {
|
||||
if (payload.event.extendedProps.is !== "range") {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -285,10 +409,26 @@ function copyDay() {
|
||||
if (null === copyFrom.value || null === copyTo.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
store.dispatch('calendarRanges/copyFromDayToAnotherDay', {from: ISOToDate(copyFrom.value), to: ISOToDate(copyTo.value)})
|
||||
store.dispatch("calendarRanges/copyFromDayToAnotherDay", {
|
||||
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>
|
||||
|
||||
<style scoped>
|
||||
@@ -299,4 +439,9 @@ function copyDay() {
|
||||
z-index: 9999999999;
|
||||
padding: 0.25rem 0 0.25rem;
|
||||
}
|
||||
div.copy-chevron {
|
||||
text-align: center;
|
||||
font-size: x-large;
|
||||
width: 2rem;
|
||||
}
|
||||
</style>
|
||||
|
@@ -5,11 +5,9 @@ const appMessages = {
|
||||
show_my_calendar: "Afficher mon calendrier",
|
||||
show_weekends: "Afficher les week-ends",
|
||||
copy_range: "Copier",
|
||||
copy_range_from_to: "Copier les plages d'un jour à l'autre",
|
||||
copy_range_to_next_day: "Copier les plages du jour au jour suivant",
|
||||
copy_range_from_day: "Copier les plages du ",
|
||||
to_the_next_day: " au jour suivant",
|
||||
copy_range_to_next_week: "Copier les plages de la semaine à la semaine suivante",
|
||||
copy_range_from_to: "Copier les plages",
|
||||
from_day_to_day: "d'un jour à l'autre",
|
||||
from_week_to_week: "d'une semaine à l'autre",
|
||||
copy_range_how_to: "Créez les plages de disponibilités durant une journée et copiez-les facilement au jour suivant avec ce bouton. Si les week-ends sont cachés, le jour suivant un vendredi sera le lundi.",
|
||||
new_range_to_save: "Nouvelles plages à enregistrer",
|
||||
update_range_to_save: "Plages à modifier",
|
||||
|
@@ -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;
|
||||
},
|
||||
},
|
||||
@@ -238,7 +255,7 @@ export default <Module<CalendarRangesState, State>>{
|
||||
|
||||
for (let r of rangesToCopy) {
|
||||
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));
|
||||
end.setFullYear(to.getFullYear(), to.getMonth(), to.getDate());
|
||||
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}));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@@ -40,7 +40,7 @@ final readonly class CalendarContext implements CalendarContextInterface
|
||||
private PersonRepository $personRepository,
|
||||
private ThirdPartyRender $thirdPartyRender,
|
||||
private ThirdPartyRepository $thirdPartyRepository,
|
||||
private TranslatableStringHelperInterface $translatableStringHelper
|
||||
private TranslatableStringHelperInterface $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function adminFormReverseTransform(array $data): array
|
||||
|
@@ -37,7 +37,7 @@ final readonly class AccompanyingPeriodCalendarGenericDocProvider implements Gen
|
||||
|
||||
public function __construct(
|
||||
private Security $security,
|
||||
private EntityManagerInterface $em
|
||||
private EntityManagerInterface $em,
|
||||
) {}
|
||||
|
||||
/**
|
||||
|
@@ -36,7 +36,7 @@ final readonly class PersonCalendarGenericDocProvider implements GenericDocForPe
|
||||
|
||||
public function __construct(
|
||||
private Security $security,
|
||||
private EntityManagerInterface $em
|
||||
private EntityManagerInterface $em,
|
||||
) {}
|
||||
|
||||
private function addWhereClausesToQuery(FetchQuery $query, ?\DateTimeImmutable $startDate = null, ?\DateTimeImmutable $endDate = null, ?string $content = null): FetchQuery
|
||||
|
@@ -156,7 +156,7 @@ final class CalendarTypeTest extends TypeTestCase
|
||||
|
||||
private function buildMultiToIdDataTransformer(
|
||||
string $classTransformer,
|
||||
string $objClass
|
||||
string $objClass,
|
||||
) {
|
||||
$transformer = $this->prophesize($classTransformer);
|
||||
$transformer->transform(Argument::type('array'))
|
||||
@@ -195,7 +195,7 @@ final class CalendarTypeTest extends TypeTestCase
|
||||
|
||||
private function buildSingleToIdDataTransformer(
|
||||
string $classTransformer,
|
||||
string $class
|
||||
string $class,
|
||||
) {
|
||||
$transformer = $this->prophesize($classTransformer);
|
||||
$transformer->transform(Argument::type('object'))
|
||||
|
@@ -47,7 +47,7 @@ final class CalendarContextTest extends TestCase
|
||||
{
|
||||
$expected =
|
||||
[
|
||||
'track_datetime' => true,
|
||||
'trackDatetime' => true,
|
||||
'askMainPerson' => true,
|
||||
'mainPersonLabel' => 'docgen.calendar.Destinee',
|
||||
'askThirdParty' => false,
|
||||
@@ -61,7 +61,7 @@ final class CalendarContextTest extends TestCase
|
||||
{
|
||||
$expected =
|
||||
[
|
||||
'track_datetime' => true,
|
||||
'trackDatetime' => true,
|
||||
'askMainPerson' => true,
|
||||
'mainPersonLabel' => 'docgen.calendar.Destinee',
|
||||
'askThirdParty' => false,
|
||||
@@ -203,7 +203,7 @@ final class CalendarContextTest extends TestCase
|
||||
|
||||
private function buildCalendarContext(
|
||||
?EntityManagerInterface $entityManager = null,
|
||||
?NormalizerInterface $normalizer = null
|
||||
?NormalizerInterface $normalizer = null,
|
||||
): CalendarContext {
|
||||
$baseContext = $this->prophesize(BaseContextData::class);
|
||||
$baseContext->getData(null)->willReturn(['base_context' => 'data']);
|
||||
|
@@ -44,7 +44,7 @@ class CreateFieldsOnGroupCommand extends Command
|
||||
private readonly EntityManager $entityManager,
|
||||
private readonly ValidatorInterface $validator,
|
||||
private $availableLanguages,
|
||||
private $customizablesEntities
|
||||
private $customizablesEntities,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
@@ -39,7 +39,7 @@ class CustomFieldsGroupController extends AbstractController
|
||||
public function __construct(
|
||||
private readonly CustomFieldProvider $customFieldProvider,
|
||||
private readonly TranslatorInterface $translator,
|
||||
private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry
|
||||
private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry,
|
||||
) {}
|
||||
|
||||
/**
|
||||
|
@@ -42,7 +42,7 @@ class CustomFieldChoice extends AbstractCustomField
|
||||
/**
|
||||
* @var TranslatableStringHelper Helper that find the string in current locale from an array of translation
|
||||
*/
|
||||
private readonly TranslatableStringHelper $translatableStringHelper
|
||||
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function allowOtherChoice(CustomField $cf)
|
||||
|
@@ -44,7 +44,7 @@ class CustomFieldDate extends AbstractCustomField
|
||||
|
||||
public function __construct(
|
||||
private readonly Environment $templating,
|
||||
private readonly TranslatableStringHelper $translatableStringHelper
|
||||
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, CustomField $customField)
|
||||
|
@@ -42,8 +42,8 @@ class CustomFieldLongChoice extends AbstractCustomField
|
||||
$translatableStringHelper = $this->translatableStringHelper;
|
||||
$builder->add($customField->getSlug(), Select2ChoiceType::class, [
|
||||
'choices' => $entries,
|
||||
'choice_label' => static fn (Option $option) => $translatableStringHelper->localize($option->getText()),
|
||||
'choice_value' => static fn (Option $key): ?int => null === $key ? null : $key->getId(),
|
||||
'choice_label' => static fn (?Option $option) => $translatableStringHelper->localize($option->getText()),
|
||||
'choice_value' => static fn (?Option $key): ?int => $key?->getId(),
|
||||
'multiple' => false,
|
||||
'expanded' => false,
|
||||
'required' => $customField->isRequired(),
|
||||
|
@@ -41,7 +41,7 @@ class CustomFieldNumber extends AbstractCustomField
|
||||
|
||||
public function __construct(
|
||||
private readonly Environment $templating,
|
||||
private readonly TranslatableStringHelper $translatableStringHelper
|
||||
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, CustomField $customField)
|
||||
|
@@ -28,7 +28,7 @@ class CustomFieldText extends AbstractCustomField
|
||||
|
||||
public function __construct(
|
||||
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
|
||||
*/
|
||||
private readonly TranslatableStringHelper $translatableStringHelper
|
||||
private readonly TranslatableStringHelper $translatableStringHelper,
|
||||
) {}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, CustomField $customField)
|
||||
|
@@ -23,9 +23,9 @@ class Option
|
||||
private bool $active = true;
|
||||
|
||||
/**
|
||||
* @var Collection<Option>
|
||||
* @var Collection<int, Option>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: Option::class, mappedBy: 'parent')]
|
||||
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: Option::class)]
|
||||
private Collection $children;
|
||||
|
||||
#[ORM\Id]
|
||||
|
@@ -32,9 +32,9 @@ class CustomFieldsGroup
|
||||
* The custom fields of the group.
|
||||
* The custom fields are asc-ordered regarding to their property "ordering".
|
||||
*
|
||||
* @var Collection<CustomField>
|
||||
* @var Collection<int, CustomField>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: CustomField::class, mappedBy: 'customFieldGroup')]
|
||||
#[ORM\OneToMany(mappedBy: 'customFieldGroup', targetEntity: CustomField::class)]
|
||||
#[ORM\OrderBy(['ordering' => \Doctrine\Common\Collections\Criteria::ASC])]
|
||||
private Collection $customFields;
|
||||
|
||||
@@ -46,11 +46,8 @@ class CustomFieldsGroup
|
||||
#[ORM\GeneratedValue(strategy: 'AUTO')]
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)]
|
||||
private $name;
|
||||
private array|string $name;
|
||||
|
||||
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)]
|
||||
private array $options = [];
|
||||
@@ -181,7 +178,7 @@ class CustomFieldsGroup
|
||||
*
|
||||
* @return CustomFieldsGroup
|
||||
*/
|
||||
public function setName($name)
|
||||
public function setName(array|string $name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
|
@@ -26,7 +26,7 @@ class CustomFieldsGroupType extends AbstractType
|
||||
public function __construct(
|
||||
private readonly array $customizableEntities,
|
||||
// TODO : add comment about this variable
|
||||
private readonly TranslatorInterface $translator
|
||||
private readonly TranslatorInterface $translator,
|
||||
) {}
|
||||
|
||||
// TODO : details about the function
|
||||
|
@@ -48,7 +48,7 @@ final class DocGeneratorTemplateController extends AbstractController
|
||||
private readonly PaginatorFactory $paginatorFactory,
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly ClockInterface $clock,
|
||||
private readonly ChillSecurity $security
|
||||
private readonly ChillSecurity $security,
|
||||
) {}
|
||||
|
||||
#[Route(path: '{_locale}/admin/doc/gen/generate/test/from/{template}/for/{entityClassName}/{entityId}', name: 'chill_docgenerator_test_generate_from_template')]
|
||||
@@ -56,7 +56,7 @@ final class DocGeneratorTemplateController extends AbstractController
|
||||
DocGeneratorTemplate $template,
|
||||
string $entityClassName,
|
||||
int $entityId,
|
||||
Request $request
|
||||
Request $request,
|
||||
): Response {
|
||||
return $this->generateDocFromTemplate(
|
||||
$template,
|
||||
@@ -71,7 +71,7 @@ final class DocGeneratorTemplateController extends AbstractController
|
||||
DocGeneratorTemplate $template,
|
||||
string $entityClassName,
|
||||
int $entityId,
|
||||
Request $request
|
||||
Request $request,
|
||||
): Response {
|
||||
return $this->generateDocFromTemplate(
|
||||
$template,
|
||||
@@ -137,7 +137,7 @@ final class DocGeneratorTemplateController extends AbstractController
|
||||
DocGeneratorTemplate $template,
|
||||
int $entityId,
|
||||
Request $request,
|
||||
bool $isTest
|
||||
bool $isTest,
|
||||
): Response {
|
||||
try {
|
||||
$context = $this->contextManager->getContextByDocGeneratorTemplate($template);
|
||||
|
@@ -28,7 +28,7 @@ final readonly class RelatorioDriver implements DriverInterface
|
||||
public function __construct(
|
||||
private HttpClientInterface $client,
|
||||
ParameterBagInterface $parameterBag,
|
||||
private LoggerInterface $logger
|
||||
private LoggerInterface $logger,
|
||||
) {
|
||||
$this->url = $parameterBag->get('chill_doc_generator')['driver']['relatorio']['url'];
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user