Compare commits

..

1 Commits

Author SHA1 Message Date
Boris Waaub
c1320d7ec0 Refactor ButtonLocation component for improved readability and consistency 2026-02-09 15:01:09 +01:00
24 changed files with 174 additions and 410 deletions

View File

@@ -1,7 +0,0 @@
kind: Fixed
body: 'Fix import of postal code: mark postal code as deleted if they are not present in the import any more'
time: 2026-02-23T18:22:12.92214987+01:00
custom:
Issue: "502"
MR: "968"
SchemaChange: No schema change

View File

@@ -1,15 +0,0 @@
## v4.13.0 - 2026-02-23
### Feature
* ([#500](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/500)) ([!964](https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/964)) Limit the number of public download of stored object to 30 downloads
* ([#495](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/495)) ([!967](https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/967)) Send email related to notification in both html and txt format, and render quote correctly
### Fixed
* ([#438](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/438)) Change wrong color of submit button "Désigner comme adresse du parcours"
* ([#498](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/498)) For giving edit permissions on documents, take into account the workflow creator
* Fixed mispelling of address in translations: addresse -> adresse
* ([#499](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/499)) ([!963](https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/963)) Fix: some postal code appears in the UI, although they are marked as deleted
* ([#501](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/501)) ([!966](https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/966)) Fix deprecation in the markdown rendering
* ([#494](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/494)) ([!965](https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/965)) Remove unused all-day slot display
### DX
* ([!960](https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/960)) Configure changie to ask for merge request number for a better tracking of changes

View File

@@ -7,7 +7,7 @@ versionFormat: '## {{.Version}} - {{.Time.Format "2006-01-02"}}'
kindFormat: '### {{.Kind}}'
# Note: it is possible to add a `.custom.Long` text manually into the yaml file produced by `changie new`. This will add a long description.
changeFormat: >-
* {{ if not (eq .Custom.Issue "") }}([#{{ .Custom.Issue }}](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/{{ .Custom.Issue }})) {{ end }}{{ if not (eq .Custom.MR "") }}([!{{ .Custom.MR }}](https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/{{ .Custom.MR }})) {{ end }}{{ .Body }} {{ if and .Custom.SchemaChange (ne .Custom.SchemaChange "No schema change") }}
* {{ if not (eq .Custom.Issue "") }}([#{{ .Custom.Issue }}](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/{{ .Custom.Issue }})) {{ end }}{{ .Body }} {{ if and .Custom.SchemaChange (ne .Custom.SchemaChange "No schema change") }}
**Schema Change**: {{ .Custom.SchemaChange }}
{{- end -}}
@@ -30,12 +30,6 @@ custom:
type: int
minInt: 1
- key: MR
label: Merge request number (on chill-bundles repository) (optional)
optional: true
type: int
minInt: 1
body:
# allow multiline messages
block: true

View File

@@ -6,22 +6,6 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
and is generated by [Changie](https://github.com/miniscruff/changie).
## v4.13.0 - 2026-02-23
### Feature
* ([#500](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/500)) ([!964](https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/964)) Limit the number of public download of stored object to 30 downloads
* ([#495](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/495)) ([!967](https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/967)) Send email related to notification in both html and txt format, and render quote correctly
### Fixed
* ([#438](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/438)) Change wrong color of submit button "Désigner comme adresse du parcours"
* ([#498](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/498)) For giving edit permissions on documents, take into account the workflow creator
* Fixed mispelling of address in translations: addresse -> adresse
* ([#499](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/499)) ([!963](https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/963)) Fix: some postal code appears in the UI, although they are marked as deleted
* ([#501](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/501)) ([!966](https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/966)) Fix deprecation in the markdown rendering
* ([#494](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/494)) ([!965](https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/965)) Remove unused all-day slot display
### DX
* ([!960](https://gitlab.com/Chill-Projet/chill-bundles/-/merge_requests/960)) Configure changie to ask for merge request number for a better tracking of changes
## v4.12.1 - 2026-02-01
### Fixed
* ([#496](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/496)) Add the option to deal with duplicate address in BAN adress importer

View File

@@ -346,7 +346,6 @@ const baseOptions = ref<CalendarOptions>({
center: "title",
right: "timeGridWeek,timeGridDay",
},
allDaySlot: false,
});
const ranges = computed<EventInput[]>(() => {

View File

@@ -79,7 +79,5 @@ final class PostalCodeAPIController extends ApiController
$qb->andWhere('e.origin = :zero')
->setParameter('zero', 0);
$qb->andWhere('e.deletedAt IS NULL');
}
}

View File

@@ -62,15 +62,15 @@ final readonly class WorkflowViewSendPublicController
);
}
if (30 < $workflowSend->getViews()->count()) {
$this->chillLogger->info(self::LOG_PREFIX.'30 view reached, not allowed to see it again');
throw new AccessDeniedHttpException('30 views reached, not allowed to see it again');
if (100 < $workflowSend->getViews()->count()) {
$this->chillLogger->info(self::LOG_PREFIX.'100 view reached, not allowed to see it again');
throw new AccessDeniedHttpException('100 views reached, not allowed to see it again');
}
try {
$metadata = new EntityWorkflowViewMetadataDTO(
$workflowSend->getViews()->count(),
30 - $workflowSend->getViews()->count(),
100 - $workflowSend->getViews()->count(),
);
$response = new Response(
$this->entityWorkflowManager->renderPublicView($workflowSend, $metadata),

View File

@@ -215,14 +215,4 @@ class PostalCode implements TrackUpdateInterface, TrackCreationInterface
return $this;
}
public function isDeleted(): bool
{
return null !== $this->deletedAt;
}
public function getDeletedAt(): ?\DateTimeImmutable
{
return $this->deletedAt;
}
}

View File

@@ -394,10 +394,6 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface
public function isUserInvolved(User $user): bool
{
if ($this->getCreatedBy() === $user) {
return true;
}
foreach ($this->getSteps() as $step) {
if ($step->getAllDestUser()->contains($user)) {
return true;

View File

@@ -59,8 +59,7 @@ readonly class NotificationMailer
$email
->to($dest->getEmail())
->subject('Re: '.$comment->getNotification()->getTitle())
->textTemplate('@ChillMain/Notification/email_notification_comment_persist.txt.twig')
->htmlTemplate('@ChillMain/Notification/email_notification_comment_persist.md.twig')
->textTemplate('@ChillMain/Notification/email_notification_comment_persist.md.twig')
->context([
'comment' => $comment,
'dest' => $dest,
@@ -84,6 +83,7 @@ readonly class NotificationMailer
public function postPersistNotification(Notification $notification, PostPersistEventArgs $eventArgs): void
{
$this->sendNotificationEmailsToAddressees($notification);
$this->sendNotificationEmailsToAddressesEmails($notification);
}
private function sendNotificationEmailsToAddressees(Notification $notification): void
@@ -149,8 +149,7 @@ readonly class NotificationMailer
} else {
$email = new TemplatedEmail();
$email
->textTemplate('@ChillMain/Notification/email_non_system_notification_content.txt.twig')
->htmlTemplate('@ChillMain/Notification/email_non_system_notification_content.md.twig')
->textTemplate('@ChillMain/Notification/email_non_system_notification_content.md.twig')
->context([
'notification' => $notification,
'dest' => $addressee,
@@ -187,8 +186,7 @@ readonly class NotificationMailer
} else {
$email = new TemplatedEmail();
$email
->textTemplate('@ChillMain/Notification/email_non_system_notification_content.txt.twig')
->htmlTemplate('@ChillMain/Notification/email_non_system_notification_content.md.twig')
->textTemplate('@ChillMain/Notification/email_non_system_notification_content.md.twig')
->context([
'notification' => $notification,
'dest' => $addressee,
@@ -288,4 +286,38 @@ readonly class NotificationMailer
throw $e;
}
}
private function sendNotificationEmailsToAddressesEmails(Notification $notification): void
{
foreach ($notification->getAddresseeUserGroups() as $userGroup) {
if (!$userGroup->hasEmail()) {
continue;
}
$emailAddress = $userGroup->getEmail();
$email = new TemplatedEmail();
$email
->textTemplate('@ChillMain/Notification/email_non_system_notification_content_to_email.md.twig')
->context([
'notification' => $notification,
'dest' => $emailAddress,
]);
$email
->subject($notification->getTitle())
->to($emailAddress);
try {
$this->mailer->send($email);
} catch (TransportExceptionInterface $e) {
$this->logger->warning('[NotificationMailer] could not send an email notification', [
'to' => $emailAddress,
'error_message' => $e->getMessage(),
'error_trace' => $e->getTraceAsString(),
]);
}
}
}
}

View File

@@ -100,9 +100,7 @@ final readonly class PostalCodeRepository implements PostalCodeRepositoryInterfa
$query
->setFromClause('chill_main_postal_code cmpc')
->andWhereClause('cmpc.origin = 0')
->andWhereClause('cmpc.deletedAt IS NULL')
;
->andWhereClause('cmpc.origin = 0');
if (null !== $country) {
$query->andWhereClause('cmpc.country_id = ?', [$country->getId()]);

View File

@@ -1,17 +1,20 @@
{% apply markdown_to_html %}
{{ dest.label }},
{{ notification.sender.label }} a créé une notification pour vous:
**Titre de la notification**: {{ notification.title }}
{% for line in notification.message|split("\n") %}
> {{ notification.title }}
>
>
{%- for line in notification.message|split("\n") %}
> {{ line }}
{% endfor %}
{%- if not loop.last %}
>
{%- endif %}
{%- endfor %}
[Vous pouvez visualiser la notification et y répondre ici.]({{ absolute_url(path('chill_main_notification_show', {'_locale': dest.locale, 'id': notification.id }, false)) }})
Vous pouvez visualiser la notification et y répondre ici:
-----
{{ absolute_url(path('chill_main_notification_show', {'_locale': dest.locale, 'id': notification.id }, false)) }}
--
Le logiciel Chill
{% endapply %}

View File

@@ -1,14 +0,0 @@
{{ dest.label }},
{{ notification.sender.label }} a créé une notification pour vous:
Titre de la notification: {{ notification.title }}
{% for line in notification.message|split("\n") %}
> {{ line|raw }}
{% endfor %}
Vous pouvez visualiser la notification et y répondre ici: {{ absolute_url(path('chill_main_notification_show', {'_locale': dest.locale, 'id': notification.id }, false)) }}.
--
Le logiciel Chill

View File

@@ -0,0 +1,20 @@
{{ dest }},
{{ notification.sender.label }} a créé une notification pour vous:
> {{ notification.title }}
>
>
{%- for line in notification.message|split("\n") %}
> {{ line }}
{%- if not loop.last %}
>
{%- endif %}
{%- endfor %}
Vous pouvez cliquer sur ce lien pour obtenir un accès permanent à la notification:
{{ absolute_url(path('chill_main_notification_grant_access_by_access_key', {'_locale': 'fr', 'id': notification.id, 'accessKey': notification.accessKey, 'email': dest})) }}
--
Le logiciel Chill

View File

@@ -1,4 +1,3 @@
{% apply markdown_to_html %}
{{ dest.label }},
{{ comment.createdBy.label }} a créé un commentaire sur la notification "{{ comment.notification.title }}".
@@ -7,11 +6,14 @@ Commentaire:
{% for line in comment.content|split("\n") %}
> {{ line }}
{% endfor %}
{%- if not loop.last %}
>
{%- endif %}
{%- endfor %}
[Vous pouvez visualiser la notification et y répondre ici.]({{ absolute_url(path('chill_main_notification_show', {'_locale': dest.locale, 'id': comment.notification.id }, false)) }})
Vous pouvez visualiser la notification et y répondre ici:
----
{{ absolute_url(path('chill_main_notification_show', {'_locale': dest.locale, 'id': comment.notification.id }, false)) }}
--
Le logiciel Chill
{% endapply %}

View File

@@ -1,14 +0,0 @@
{{ dest.label }},
{{ comment.createdBy.label }} a créé un commentaire sur la notification "{{ comment.notification.title }}".
Commentaire:
{% for line in comment.content|split("\n") %}
> {{ line }}
{%- endfor %}
Vous pouvez visualiser la notification et y répondre ici: {{ absolute_url(path('chill_main_notification_show', {'_locale': dest.locale, 'id': comment.notification.id }, false)) }}
--
Le logiciel Chill

View File

@@ -19,66 +19,31 @@ use Doctrine\DBAL\Statement;
*/
class PostalCodeBaseImporter
{
private const CREATE_TEMP_TABLE = <<<'SQL'
CREATE TEMPORARY TABLE chill_main_postal_code_temp (
countrycode VARCHAR(10),
label VARCHAR(255),
code VARCHAR(100),
refpostalcodeid VARCHAR(255),
postalcodeSource VARCHAR(255),
lon FLOAT,
lat FLOAT,
srid INT
)
SQL;
private const INSERT_TEMP = <<<'SQL'
INSERT INTO chill_main_postal_code_temp
(countrycode, label, code, refpostalcodeid, postalcodeSource, lon, lat, srid)
VALUES
{{ values }}
SQL;
private const UPSERT = <<<'SQL'
private const QUERY = <<<'SQL'
WITH g AS (
SELECT DISTINCT
country.id AS country_id,
temp.*
FROM chill_main_postal_code_temp temp
JOIN country ON country.countrycode = temp.countrycode
g.*
FROM (VALUES
{{ values }}
) AS g (countrycode, label, code, refpostalcodeid, postalcodeSource, lon, lat, srid)
JOIN country ON country.countrycode = g.countrycode
)
INSERT INTO chill_main_postal_code (id, country_id, label, code, origin, refpostalcodeid, postalcodeSource, center, createdAt, updatedAt, deletedAt)
INSERT INTO chill_main_postal_code (id, country_id, label, code, origin, refpostalcodeid, postalcodeSource, center, createdAt, updatedAt)
SELECT
nextval('chill_main_postal_code_id_seq'),
g.country_id,
g.label,
g.label AS glabel,
g.code,
0,
g.refpostalcodeid,
g.postalcodeSource,
CASE WHEN (g.lon != 0.0 AND g.lat != 0.0) THEN ST_Transform(ST_setSrid(ST_point(g.lon, g.lat), g.srid), 4326) ELSE NULL END,
CASE WHEN (g.lon::float != 0.0 AND g.lat::float != 0.0) THEN ST_Transform(ST_setSrid(ST_point(g.lon::float, g.lat::float), g.srid::int), 4326) ELSE NULL END,
NOW(),
NOW(),
NULL
NOW()
FROM g
ON CONFLICT (code, refpostalcodeid, postalcodeSource) WHERE refpostalcodeid IS NOT NULL DO UPDATE
SET label = excluded.label,
center = excluded.center,
deletedAt = NULL,
updatedAt = CASE WHEN NOT st_equals(excluded.center, chill_main_postal_code.center) OR excluded.label != chill_main_postal_code.label OR chill_main_postal_code.deletedAt IS NOT NULL THEN NOW() ELSE chill_main_postal_code.updatedAt END
SQL;
private const DELETE_MISSING = <<<'SQL'
UPDATE chill_main_postal_code
SET deletedAt = NOW(), updatedAt = NOW()
WHERE postalcodeSource = ?
AND deletedAt IS NULL
AND NOT EXISTS (
SELECT 1 FROM chill_main_postal_code_temp temp
WHERE temp.code = chill_main_postal_code.code
AND temp.refpostalcodeid = chill_main_postal_code.refpostalcodeid
AND temp.postalcodeSource = chill_main_postal_code.postalcodeSource
)
SET label = excluded.label, center = excluded.center, updatedAt = CASE WHEN NOT st_equals(excluded.center, chill_main_postal_code.center) OR excluded.label != chill_main_postal_code.label THEN NOW() ELSE chill_main_postal_code.updatedAt END
SQL;
private const VALUE = '(?, ?, ?, ?, ?, ?, ?, ?)';
@@ -90,26 +55,11 @@ class PostalCodeBaseImporter
private array $waitingForInsert = [];
private bool $isInitialized = false;
private ?string $currentSource = null;
public function __construct(private readonly Connection $defaultConnection) {}
public function finalize(): void
{
$this->doInsertPending();
if ($this->isInitialized && null !== $this->currentSource) {
$this->defaultConnection->transactional(function (Connection $connection): void {
$connection->executeStatement(self::UPSERT);
$connection->executeStatement(self::DELETE_MISSING, [$this->currentSource]);
});
$this->deleteTemporaryTable();
}
$this->isInitialized = false;
$this->currentSource = null;
}
public function importCode(
@@ -122,14 +72,6 @@ class PostalCodeBaseImporter
float $centerLon,
int $centerSRID,
): void {
if (!$this->isInitialized) {
$this->initialize($refPostalCodeSource);
}
if ($this->currentSource !== $refPostalCodeSource) {
throw new \LogicException('Cannot store postal codes from different sources during same import. Execute finalize to commit inserts before changing the source');
}
$this->waitingForInsert[] = [
$countryCode,
$label,
@@ -146,32 +88,10 @@ class PostalCodeBaseImporter
}
}
private function initialize(string $source): void
{
$this->currentSource = $source;
$this->deleteTemporaryTable();
$this->createTemporaryTable();
$this->isInitialized = true;
}
private function createTemporaryTable(): void
{
$this->defaultConnection->executeStatement(self::CREATE_TEMP_TABLE);
}
private function deleteTemporaryTable(): void
{
$this->defaultConnection->executeStatement('DROP TABLE IF EXISTS chill_main_postal_code_temp');
}
private function doInsertPending(): void
{
if ([] == $this->waitingForInsert) {
return;
}
if (!\array_key_exists($forNumber = \count($this->waitingForInsert), $this->cachingStatements)) {
$sql = strtr(self::INSERT_TEMP, [
$sql = strtr(self::QUERY, [
'{{ values }}' => implode(
', ',
array_fill(0, $forNumber, self::VALUE)

View File

@@ -41,6 +41,6 @@ final class ChillMarkdownRenderExtension extends AbstractExtension
public function renderMarkdownToHtml(?string $var): string
{
return $this->parsedown->text((string) $var);
return $this->parsedown->parse((string) $var);
}
}

View File

@@ -93,80 +93,4 @@ final class PostalCodeBaseImporterTest extends KernelTestCase
$this->assertStringStartsWith('tested with adapted pattern', $postalCodes[0]->getName());
$this->assertEquals($previousId, $postalCodes[0]->getId());
}
public function testPostalCodeRemoval(): void
{
$source = 'removal_test_'.uniqid();
$refId1 = 'ref1_'.uniqid();
$refId2 = 'ref2_'.uniqid();
// 1. Import two postal codes
$this->importer->importCode('BE', 'Label 1', '1000', $refId1, $source, 50.0, 5.0, 4326);
$this->importer->importCode('BE', 'Label 2', '2000', $refId2, $source, 50.0, 5.0, 4326);
$this->importer->finalize();
$pc1 = $this->postalCodeRepository->findOneBy(['refPostalCodeId' => $refId1, 'postalCodeSource' => $source]);
$pc2 = $this->postalCodeRepository->findOneBy(['refPostalCodeId' => $refId2, 'postalCodeSource' => $source]);
$this->assertNotNull($pc1);
$this->assertNotNull($pc2);
// 2. Import only the first one
$this->importer->importCode('BE', 'Label 1 updated', '1000', $refId1, $source, 50.0, 5.0, 4326);
$this->importer->finalize();
$this->entityManager->clear();
$pc1 = $this->postalCodeRepository->findOneBy(['refPostalCodeId' => $refId1, 'postalCodeSource' => $source]);
$pc2 = $this->postalCodeRepository->findOneBy(['refPostalCodeId' => $refId2, 'postalCodeSource' => $source]);
$this->assertNotNull($pc1);
$this->assertEquals('Label 1 updated', $pc1->getName());
$this->assertFalse($pc1->isDeleted(), 'pc1 should NOT be marked as deleted');
// pc2 should be marked as deleted. Note: findOneBy might still find it if it doesn't filter by deletedAt
$this->assertNotNull($pc2);
$this->assertTrue($pc2->isDeleted(), 'Postal code should be marked as deleted (deletedAt is not null)');
// 3. Reactivate pc2 by re-importing it
$this->importer->importCode('BE', 'Label 2 restored', '2000', $refId2, $source, 50.0, 5.0, 4326);
$this->importer->finalize();
$this->entityManager->clear();
$pc2 = $this->postalCodeRepository->findOneBy(['refPostalCodeId' => $refId2, 'postalCodeSource' => $source]);
$this->assertFalse($pc2->isDeleted(), 'Postal code should NOT be marked as deleted after restoration');
$this->assertEquals('Label 2 restored', $pc2->getName());
}
public function testNoInterferenceBetweenSources(): void
{
$source1 = 'source1_'.uniqid();
$source2 = 'source2_'.uniqid();
$refId1 = 'ref1_'.uniqid();
$refId2 = 'ref2_'.uniqid();
// 1. Import from source1
$this->importer->importCode('BE', 'Label 1', '1000', $refId1, $source1, 50.0, 5.0, 4326);
$this->importer->finalize();
$pc1 = $this->postalCodeRepository->findOneBy(['refPostalCodeId' => $refId1, 'postalCodeSource' => $source1]);
$this->assertNotNull($pc1);
$this->assertFalse($pc1->isDeleted());
// 2. Import from source2
$this->importer->importCode('BE', 'Label 2', '2000', $refId2, $source2, 50.0, 5.0, 4326);
$this->importer->finalize();
$this->entityManager->clear();
$pc1 = $this->postalCodeRepository->findOneBy(['refPostalCodeId' => $refId1, 'postalCodeSource' => $source1]);
$pc2 = $this->postalCodeRepository->findOneBy(['refPostalCodeId' => $refId2, 'postalCodeSource' => $source2]);
$this->assertNotNull($pc1);
$this->assertNotNull($pc2);
$this->assertFalse($pc1->isDeleted(), 'pc1 from source1 should NOT be deleted after import from source2');
$this->assertFalse($pc2->isDeleted(), 'pc2 from source2 should NOT be deleted');
}
}

View File

@@ -37,7 +37,7 @@ final class ChillMarkdownRenderExtensionTest extends TestCase
MD;
private const UNAUTHORIZED_HTML = <<<'HTML'
<p>&lt;script&gt;alert("ok");&lt;/script&gt;</p>
<p>&lt;script&gt;alert(&quot;ok&quot;);&lt;/script&gt;</p>
HTML;
private const UNAUTHORIZED_MARKDOWN = <<<'MD'

View File

@@ -1,41 +0,0 @@
<?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\Migrations\Main;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20260223134919 extends AbstractMigration
{
public function getDescription(): string
{
return 'Create a partial index for postal_code search_name_code, to avoid deleted records';
}
public function up(Schema $schema): void
{
$this->addSql('DROP INDEX public.search_name_code');
$this->addSql('CREATE INDEX search_name_code ON public.chill_main_postal_code USING GIN (LOWER(code) gin_trgm_ops, LOWER(label) gin_trgm_ops) WHERE deletedAt IS NULL');
$this->addSql('DROP INDEX public.chill_internal_postal_code_canonicalized');
$this->addSql('CREATE INDEX chill_internal_postal_code_canonicalized ON chill_main_postal_code USING GIST (canonical gist_trgm_ops) WHERE origin = 0 AND deletedAt IS NULL');
}
public function down(Schema $schema): void
{
$this->addSql('DROP INDEX public.search_name_code');
$this->addSql('CREATE INDEX search_name_code ON chill_main_postal_code USING GIN (LOWER(code) gin_trgm_ops, LOWER(label) gin_trgm_ops)');
$this->addSql('DROP INDEX public.chill_internal_postal_code_canonicalized');
$this->addSql('CREATE INDEX chill_internal_postal_code_canonicalized ON chill_main_postal_code USING GIST (canonical gist_trgm_ops) WHERE origin = 0');
}
}

View File

@@ -1,38 +1,36 @@
<template>
<li>
<button
class="btn btn-sm btn-secondary"
@click="modal.showModal = true"
:title="$t('courselocation.assign_course_address')"
>
<i class="fa fa-map-marker" />
</button>
</li>
<li>
<button
class="btn btn-sm btn-secondary"
@click="modal.showModal = true"
:title="$t('courselocation.assign_course_address')"
>
<i class="fa fa-map-marker" />
</button>
</li>
<teleport to="body">
<modal
v-if="modal.showModal"
:modal-dialog-class="modal.modalDialogClass"
@close="modal.showModal = false"
>
<template #header>
<h2 class="modal-title">
{{ $t("courselocation.sure") }}
</h2>
</template>
<template #body>
<address-render-box
:address="person.current_household_address"
/>
<p>{{ $t("courselocation.sure_description") }}</p>
</template>
<template #footer>
<button class="btn btn-submit" @click="assignAddress">
{{ $t("courselocation.ok") }}
</button>
</template>
</modal>
</teleport>
<teleport to="body">
<modal
v-if="modal.showModal"
:modal-dialog-class="modal.modalDialogClass"
@close="modal.showModal = false"
>
<template #header>
<h2 class="modal-title">
{{ $t("courselocation.sure") }}
</h2>
</template>
<template #body>
<address-render-box :address="person.current_household_address" />
<p>{{ $t("courselocation.sure_description") }}</p>
</template>
<template #footer>
<button class="btn btn-submit" @click="assignAddress">
{{ $t("courselocation.ok") }}
</button>
</template>
</modal>
</teleport>
</template>
<script>
@@ -41,52 +39,49 @@ import Modal from "ChillMainAssets/vuejs/_components/Modal";
import AddressRenderBox from "ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue";
export default {
name: "ButtonLocation",
components: {
AddressRenderBox,
Modal,
},
props: ["person"],
data() {
return {
modal: {
showModal: false,
modalDialogClass: "modal-dialog-centered modal-md",
},
};
},
computed: {
...mapState({
context: (state) => state.addressContext,
}),
},
methods: {
assignAddress() {
//console.log('assignAddress id', this.person.current_household_address);
let payload = {
target: this.context.target.name,
targetId: this.context.target.id,
locationStatusTo: "person",
personId: this.person.id,
};
this.$store
.dispatch("updateLocation", payload)
.catch(({ name, violations }) => {
if (
name === "ValidationException" ||
name === "AccessException"
) {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
name: "ButtonLocation",
components: {
AddressRenderBox,
Modal,
},
props: ["person"],
data() {
return {
modal: {
showModal: false,
modalDialogClass: "modal-dialog-centered modal-md",
},
};
},
computed: {
...mapState({
context: (state) => state.addressContext,
}),
},
methods: {
assignAddress() {
//console.log('assignAddress id', this.person.current_household_address);
let payload = {
target: this.context.target.name,
targetId: this.context.target.id,
locationStatusTo: "person",
personId: this.person.id,
};
this.$store
.dispatch("updateLocation", payload)
.catch(({ name, violations }) => {
if (name === "ValidationException" || name === "AccessException") {
violations.forEach((violation) =>
this.$toast.open({ message: violation }),
);
} else {
this.$toast.open({ message: "An error occurred" });
}
});
window.location.assign("#section-20");
this.modal.showModal = false;
},
window.location.assign("#section-20");
this.modal.showModal = false;
},
},
};
</script>

View File

@@ -453,8 +453,8 @@ Filtered by entrusted child status: Uniquement les usagers qui sont "enfant conf
Filter by nomadic status: Filtrer les usagers "gens du voyage"
Filtered by nomadic status: Uniquement les usagers qui sont "gens du voyage"
"Filter by person's who have a residential address located at another user": Filtrer les usagers qui ont une adresse de résidence chez une autre usager
"Filtered by person's who have a residential address located at another user": Uniquement les usagers qui ont une adresse de résidence chez une autre usager
"Filter by person's who have a residential address located at another user": Filtrer les usagers qui ont une addresse de résidence chez une autre usager
"Filtered by person's who have a residential address located at another user": Uniquement les usagers qui ont une addresse de résidence chez une autre usager
Filter by person's that are alive or have deceased at a certain date: Filtrer les usagers qui sont décédés ou vivantes à une certaine date
Filtered by person's that are alive or have deceased at a certain date: Uniquement les usagers qui sont décédés ou vivantes à une certaine date

View File

@@ -129,11 +129,11 @@ export:
thirdParties: Tiers intervenant
# exports filters/aggregators
Filtered by person\'s who have a residential address located at a thirdparty of type %thirparty_type%: Uniquement les usagers qui ont une adresse de résidence chez un tiers de catégorie %thirdparty_type%
Filtered by person\'s who have a residential address located at a thirdparty of type %thirparty_type%: Uniquement les usagers qui ont une addresse de résidence chez un tiers de catégorie %thirdparty_type%
is thirdparty: Le demandeur est un tiers
Filter by person's who have a residential address located at a thirdparty of type: Filtrer les usagers qui ont une adresse de résidence chez un tiers
"Filtered by person's who have a residential address located at a thirdparty of type %thirdparty_type% and valid on %date_calc%": "Uniquement les usagers qui ont une adresse de résidence chez un tiers de catégorie %thirdparty_type% et valide sur la date %date_calc%"
Filter by person's who have a residential address located at a thirdparty of type: Filtrer les usagers qui ont une addresse de résidence chez un tiers
"Filtered by person's who have a residential address located at a thirdparty of type %thirdparty_type% and valid on %date_calc%": "Uniquement les usagers qui ont une addresse de résidence chez un tiers de catégorie %thirdparty_type% et valide sur la date %date_calc%"
# admin
admin: