Merge remote-tracking branch 'origin/master' into issue596_admin_user

This commit is contained in:
2022-05-13 15:08:49 +02:00
47 changed files with 916 additions and 212 deletions

View File

@@ -76,7 +76,8 @@ final class AddressReferenceAPIController extends ApiController
protected function customizeQuery(string $action, Request $request, $qb): void
{
if ($request->query->has('postal_code')) {
$qb->where('e.postcode = :postal_code')
$qb->where($qb->expr()->isNull('e.deletedAt'))
->andWhere('e.postcode = :postal_code')
->setParameter('postal_code', $request->query->get('postal_code'));
}
}

View File

@@ -12,13 +12,14 @@ declare(strict_types=1);
namespace Chill\MainBundle\Entity;
use Chill\MainBundle\Doctrine\Model\Point;
use DateTimeImmutable;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @ORM\Entity
* @ORM\Table(name="chill_main_address_reference", indexes={
* @ORM\Index(name="address_refid", columns={"refId"}, options={"where": "refid != ''"})
* @ORM\Index(name="address_refid", columns={"refId"})
* })
* @ORM\HasLifecycleCallbacks
*/
@@ -33,6 +34,18 @@ class AddressReference
*/
private string $addressCanonical = '';
/**
* @ORM\Column(type="datetime_immutable", nullable=true)
* @groups({"read"})
*/
private ?DateTimeImmutable $createdAt = null;
/**
* @ORM\Column(type="datetime_immutable", nullable=true)
* @groups({"read"})
*/
private ?DateTimeImmutable $deletedAt = null;
/**
* @ORM\Id
* @ORM\GeneratedValue
@@ -89,6 +102,22 @@ class AddressReference
*/
private $streetNumber;
/**
* @ORM\Column(type="datetime_immutable", nullable=true)
* @groups({"read"})
*/
private ?DateTimeImmutable $updatedAt = null;
public function getCreatedAt(): ?DateTimeImmutable
{
return $this->createdAt;
}
public function getDeletedAt(): ?DateTimeImmutable
{
return $this->deletedAt;
}
public function getId(): ?int
{
return $this->id;
@@ -134,6 +163,25 @@ class AddressReference
return $this->streetNumber;
}
public function getUpdatedAt(): ?DateTimeImmutable
{
return $this->updatedAt;
}
public function setCreatedAt(?DateTimeImmutable $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function setDeletedAt(?DateTimeImmutable $deletedAt): self
{
$this->deletedAt = $deletedAt;
return $this;
}
public function setMunicipalityCode(?string $municipalityCode): self
{
$this->municipalityCode = $municipalityCode;
@@ -189,4 +237,11 @@ class AddressReference
return $this;
}
public function setUpdatedAt(?DateTimeImmutable $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
}

View File

@@ -21,10 +21,11 @@ use Symfony\Component\Serializer\Annotation\Groups;
* @ORM\Entity
* @ORM\Table(
* name="chill_main_postal_code",
* indexes={@ORM\Index(
* name="search_name_code",
* columns={"code", "label"}
* )})
* indexes={
* @ORM\Index(name="search_name_code", columns={"code", "label"}),
* @ORM\Index(name="search_by_reference_code", columns={"code", "refpostalcodeid"})
* })
*
* @ORM\HasLifecycleCallbacks
*/
class PostalCode

View File

@@ -45,7 +45,7 @@ class User implements AdvancedUserInterface
*
* @ORM\Column(type="json", nullable=true)
*/
private array $attributes;
private array $attributes = [];
/**
* @ORM\ManyToOne(targetEntity=Location::class)

View File

@@ -130,12 +130,13 @@ final class AddressReferenceRepository implements ObjectRepository
$query
->setFromClause('chill_main_address_reference cma')
->andWhereClause('postcode_id = ?', [$postalCode->getId()]);
->andWhereClause('postcode_id = ?', [$postalCode->getId()])
->andWhereClause('deletedAt IS NULL', []);
$pertinenceClause = ['STRICT_WORD_SIMILARITY(addresscanonical, UNACCENT(?))'];
$pertinenceArgs = [$pattern];
$orWhere = ['addresscanonical %>> UNACCENT(?)'];
$orWhereArgs = [$pattern];
$andWhere = [];
$andWhereArgs = [];
foreach (explode(' ', $pattern) as $part) {
$part = trim($part);
@@ -144,8 +145,8 @@ final class AddressReferenceRepository implements ObjectRepository
continue;
}
$orWhere[] = "addresscanonical LIKE '%' || UNACCENT(LOWER(?)) || '%'";
$orWhereArgs[] = $part;
$andWhere[] = "(addresscanonical LIKE '%' || UNACCENT(LOWER(?)) || '%')";
$andWhereArgs[] = $part;
$pertinenceClause[] =
"(EXISTS (SELECT 1 FROM unnest(string_to_array(addresscanonical, ' ')) AS t WHERE starts_with(t, UNACCENT(LOWER(?)))))::int";
$pertinenceClause[] =
@@ -154,7 +155,7 @@ final class AddressReferenceRepository implements ObjectRepository
}
$query
->setSelectPertinence(implode(' + ', $pertinenceClause), $pertinenceArgs)
->andWhereClause(implode(' OR ', $orWhere), $orWhereArgs);
->andWhereClause(implode(' AND ', $andWhere), $andWhereArgs);
return $query;
}

View File

@@ -51,9 +51,7 @@ function loadDynamicPicker(element) {
},
methods: {
addNewEntity(entity) {
console.log('addNewEntity', entity);
if (this.multiple) {
console.log('adding multiple');
if (!this.picked.some(el => {
return el.type === entity.type && el.id === entity.id;
})) {
@@ -71,7 +69,6 @@ function loadDynamicPicker(element) {
}
},
removeEntity(entity) {
console.log('removeEntity', entity);
this.picked = this.picked.filter(e => !(e.type === entity.type && e.id === entity.id));
input.value = JSON.stringify(this.picked);
},
@@ -86,7 +83,6 @@ function loadDynamicPicker(element) {
document.addEventListener('show-hide-show', function(e) {
console.log('creation event caught')
loadDynamicPicker(e.detail.container)
})
@@ -94,17 +90,14 @@ document.addEventListener('show-hide-hide', function(e) {
console.log('hiding event caught')
e.detail.container.querySelectorAll('[data-module="pick-dynamic"]').forEach((el) => {
let uniqId = el.dataset.uniqid;
console.log(uniqId);
if (appsOnPage.has(uniqId)) {
appsOnPage.get(uniqId).unmount();
console.log('App has been unmounted')
appsOnPage.delete(uniqId);
}
})
})
document.addEventListener('DOMContentLoaded', function(e) {
console.log('loaded event', e)
loadDynamicPicker(document)
})

View File

@@ -1,7 +1,7 @@
<template>
<h4 class="h3">{{ $t('fill_an_address') }}</h4>
<div class="row my-3">
<div class="col-lg-6">
<div class="col-lg-6" v-if="!isNoAddress">
<div class="form-floating my-1">
<input class="form-control"
type="text"
@@ -35,8 +35,8 @@
<label for="flat">{{ $t('flat') }}</label>
</div>
</div>
<div class="col-lg-6">
<div class="form-floating my-1">
<div :class="isNoAddress ? 'col-lg-12' : 'col-lg-6'">
<div class="form-floating my-1" v-if="!isNoAddress">
<input class="form-control"
type="text"
name="buildingName"
@@ -54,7 +54,7 @@
v-model="extra"/>
<label for="extra">{{ $t('extra') }}</label>
</div>
<div class="form-floating my-1">
<div class="form-floating my-1" v-if="!isNoAddress">
<input class="form-control"
type="text"
name="distribution"
@@ -70,7 +70,7 @@
<script>
export default {
name: "AddressMore",
props: ['entity'],
props: ['entity', 'isNoAddress'],
computed: {
floor: {
set(value) {

View File

@@ -75,8 +75,9 @@
</div>
</div>
<address-more v-if="!isNoAddress"
v-bind:entity="entity">
<address-more
v-bind:entity="entity"
v-bind:isNoAddress="isNoAddress">
</address-more>
<action-buttons v-if="insideModal === false"

View File

@@ -210,10 +210,10 @@ export default {
let
type = this.type,
data = {} ;
switch (type) {
case 'person':
data = this.$refs.castPerson.$data.person;
console.log('person data are', data);
break;
case 'thirdparty':
@@ -238,7 +238,7 @@ export default {
if (typeof data.civility !== 'undefined' && null !== data.civility) {
data.civility = data.civility !== null ? {type: 'chill_main_civility', id: data.civility.id} : null;
}
if (typeof data.civility !== 'undefined' && null !== data.profession) {
if (typeof data.profession !== 'undefined' && null !== data.profession) {
data.profession = data.profession !== null ? {type: 'third_party_profession', id: data.profession.id} : null;
}
// console.log('onthefly data', data);

View File

@@ -66,9 +66,18 @@ export default {
translatedListOfTypes() {
let trans = [];
this.types.forEach(t => {
trans.push(appMessages.fr.pick_entity[t].toLowerCase());
if (this.$props.multiple) {
trans.push(appMessages.fr.pick_entity[t].toLowerCase());
} else {
trans.push(appMessages.fr.pick_entity[t + '_one'].toLowerCase());
}
})
return appMessages.fr.pick_entity.modal_title + trans.join(', ');
if (this.$props.multiple) {
return appMessages.fr.pick_entity.modal_title + trans.join(', ');
} else {
return appMessages.fr.pick_entity.modal_title_one + trans.join(', ');
}
}
},
methods: {
@@ -79,15 +88,10 @@ export default {
);
this.$refs.addPersons.resetSearch(); // to cast child method
modal.showModal = false;
console.log(this.picked)
},
removeEntity(entity) {
console.log('remove entity', entity);
this.$emit('removeEntity', entity);
}
},
mounted() {
console.log(this.picked);
}
}
</script>

View File

@@ -11,6 +11,10 @@ const appMessages = {
user: 'Utilisateurs',
person: 'Usagers',
thirdparty: 'Tiers',
modal_title_one: 'Indiquer un ',
user_one: 'Utilisateur',
thirdparty_one: 'Tiers',
person_one: 'Usager',
}
}
}

View File

@@ -29,6 +29,11 @@
</p>
<p class="country">{{ address.postCode.country.name|localize_translatable_string }}</p>
{% endif %}
{% if address.extra is not empty %}
<span>
{{ address.extra }}
</span>
{% endif %}
<span class="noaddress">
{{ 'address.consider homeless'|trans }}
</span>
@@ -89,6 +94,11 @@
<p class="country">{{ address.postCode.country.name|localize_translatable_string }}</p>
</div>
{% endif %}
{% if address.extra is not empty %}
<div>
{{ address.extra }}
</div>
{% endif %}
<div class="noaddress">
{{ 'address.consider homeless'|trans }}
</div>

View File

@@ -217,6 +217,7 @@
{% endblock %}
{% block pick_entity_dynamic_widget %}
{{ form_help(form)}}
<input type="hidden" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %} data-input-uniqid="{{ form.vars['uniqid'] }}"/>
<div data-module="pick-dynamic" data-types="{{ form.vars['types']|json_encode }}" data-multiple="{{ form.vars['multiple'] }}" data-uniqid="{{ form.vars['uniqid'] }}"></div>
{% endblock %}

View File

@@ -36,33 +36,35 @@
{# Flash messages ! #}
{% if app.session.flashbag.keys()|length > 0 %}
<div class="col-8 mb-5 flash_message">
<div class="row justify-content-center">
<div class="col-10 mb-5 flash_message">
{% for flashMessage in app.session.flashbag.get('success') %}
<div class="alert alert-success flash_message">
<span>{{ flashMessage|raw }}</span>
</div>
{% endfor %}
{% for flashMessage in app.session.flashbag.get('error') %}
<div class="alert alert-danger flash_message">
<span>{{ flashMessage|raw }}</span>
</div>
{% endfor %}
{% for flashMessage in app.session.flashbag.get('notice') %}
<div class="alert alert-warning flash_message">
<span>{{ flashMessage|raw }}</span>
</div>
{% endfor %}
{% for flashMessage in app.session.flashbag.get('success') %}
<div class="alert alert-success flash_message">
<span>{{ flashMessage|raw }}</span>
</div>
{% endfor %}
{% for flashMessage in app.session.flashbag.get('error') %}
<div class="alert alert-danger flash_message">
<span>{{ flashMessage|raw }}</span>
</div>
{% endfor %}
{% for flashMessage in app.session.flashbag.get('notice') %}
<div class="alert alert-warning flash_message">
<span>{{ flashMessage|raw }}</span>
</div>
{% endfor %}
</div>
</div>
{% endif %}
{% block content %}
<div class="col-8 main_search">
<h2>{{ 'Search'|trans }}</h2>
<form action="{{ path('chill_main_search') }}" method="get">
<input class="form-control form-control-lg" name="q" type="search" placeholder="{{ 'Search persons, ...'|trans }}" />
<center>
@@ -75,11 +77,11 @@
</center>
</form>
</div>
{# DISABLED {{ chill_widget('homepage', {} ) }} #}
{% include '@ChillMain/Homepage/index.html.twig' %}
{% endblock %}
</div>

View File

@@ -0,0 +1,49 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\Migrations\Main;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Add 3 fields on AddressReference.
*/
final class Version20220325134944 extends AbstractMigration
{
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE chill_main_address_reference DROP createdAt');
$this->addSql('ALTER TABLE chill_main_address_reference DROP deletedAt');
$this->addSql('ALTER TABLE chill_main_address_reference DROP updatedAt');
$this->addSql('DROP INDEX address_refid');
$this->addSql('create index address_refid
on chill_main_address_reference (refid)
where ((refid)::text <> \'\'::text)');
}
public function getDescription(): string
{
return 'Add 3 fields on AddressReference';
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE chill_main_address_reference ADD createdAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
$this->addSql('ALTER TABLE chill_main_address_reference ADD deletedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
$this->addSql('ALTER TABLE chill_main_address_reference ADD updatedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
$this->addSql('COMMENT ON COLUMN chill_main_address_reference.createdAt IS \'(DC2Type:datetime_immutable)\'');
$this->addSql('COMMENT ON COLUMN chill_main_address_reference.deletedAt IS \'(DC2Type:datetime_immutable)\'');
$this->addSql('COMMENT ON COLUMN chill_main_address_reference.updatedAt IS \'(DC2Type:datetime_immutable)\'');
$this->addSql('DROP INDEX address_refid');
$this->addSql('CREATE INDEX address_refid ON chill_main_address_reference (refId)');
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\Migrations\Main;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20220506131307 extends AbstractMigration
{
public function down(Schema $schema): void
{
$this->addSql('DROP INDEX chill_internal_address_reference_canonicalized');
$this->addSql('create index chill_internal_address_reference_canonicalized
on chill_main_address_reference using gist (postcode_id, addresscanonical gist_trgm_ops);');
}
public function getDescription(): string
{
return 'Adapt search index on address reference canonicalized';
}
public function up(Schema $schema): void
{
$this->addSql('DROP INDEX chill_internal_address_reference_canonicalized');
$this->addSql('create index chill_internal_address_reference_canonicalized
on chill_main_address_reference using gist (postcode_id, addresscanonical gist_trgm_ops) WHERE deletedat IS NULL;');
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\Migrations\Main;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20220506145935 extends AbstractMigration
{
public function down(Schema $schema): void
{
$this->addSql('DROP INDEX search_by_reference_code');
}
public function getDescription(): string
{
return 'Add index to search postal code by references';
}
public function up(Schema $schema): void
{
$this->addSql('CREATE INDEX search_by_reference_code ON chill_main_postal_code (code, refpostalcodeid)');
}
}