diff --git a/.editorconfig b/.editorconfig index d769b46a4..fe115d4c0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,6 +7,7 @@ charset = utf-8 end_of_line = LF insert_final_newline = true trim_trailing_whitespace = true +indent_size = 4 [*.{php,html,twig}] indent_style = space diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..cf27b41f2 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,18 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to + +* [Semantic Versioning](https://semver.org/spec/v2.0.0.html) for stable releases; +* date versioning for test releases + +## Unreleased + +* [Household editor][UI] Update how household suggestion and addresses are picked; +* [AddAddress] Handle address suggestion; + +## Test release yyyy-mm-dd + + diff --git a/composer.json b/composer.json index 747747290..0d134cbf8 100644 --- a/composer.json +++ b/composer.json @@ -22,6 +22,7 @@ "league/csv": "^9.7.1", "nyholm/psr7": "^1.4", "phpoffice/phpspreadsheet": "^1.16", + "ramsey/uuid-doctrine": "^1.7", "sensio/framework-extra-bundle": "^5.5", "symfony/asset": "4.*", "symfony/browser-kit": "^5.2", @@ -29,6 +30,7 @@ "symfony/expression-language": "4.*", "symfony/form": "4.*", "symfony/intl": "4.*", + "symfony/mime": "^4 || ^5", "symfony/monolog-bundle": "^3.5", "symfony/security-bundle": "4.*", "symfony/serializer": "^5.2", diff --git a/src/Bundle/ChillCalendarBundle/Event/ListenToActivityCreate.php b/src/Bundle/ChillCalendarBundle/Event/ListenToActivityCreate.php index f3c4e7a59..d7073597a 100644 --- a/src/Bundle/ChillCalendarBundle/Event/ListenToActivityCreate.php +++ b/src/Bundle/ChillCalendarBundle/Event/ListenToActivityCreate.php @@ -29,17 +29,19 @@ class ListenToActivityCreate $activityData = $request->query->get('activityData'); if (array_key_exists('calendarId', $activityData)) { $calendarId = $activityData['calendarId']; + + // Attach the activity to the calendar + $em = $event->getObjectManager(); + + $calendar = $em->getRepository(\Chill\CalendarBundle\Entity\Calendar::class)->find($calendarId); + $calendar->setActivity($activity); + + $em->persist($calendar); + $em->flush(); } } - // Attach the activity to the calendar - $em = $event->getObjectManager(); - $calendar = $em->getRepository(\Chill\CalendarBundle\Entity\Calendar::class)->find($calendarId); - $calendar->setActivity($activity); - - $em->persist($calendar); - $em->flush(); } } diff --git a/src/Bundle/ChillCalendarBundle/Menu/AccompanyingCourseMenuBuilder.php b/src/Bundle/ChillCalendarBundle/Menu/AccompanyingCourseMenuBuilder.php index 244d7db78..4f0cf7b30 100644 --- a/src/Bundle/ChillCalendarBundle/Menu/AccompanyingCourseMenuBuilder.php +++ b/src/Bundle/ChillCalendarBundle/Menu/AccompanyingCourseMenuBuilder.php @@ -41,7 +41,7 @@ class AccompanyingCourseMenuBuilder implements LocalMenuBuilderInterface 'routeParameters' => [ 'accompanying_period_id' => $period->getId(), ]]) - ->setExtras(['order' => 41]); + ->setExtras(['order' => 35]); } } } diff --git a/src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorTemplateController.php b/src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorTemplateController.php index f8fd69431..93068de3f 100644 --- a/src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorTemplateController.php +++ b/src/Bundle/ChillDocGeneratorBundle/Controller/DocGeneratorTemplateController.php @@ -138,7 +138,7 @@ class DocGeneratorTemplateController extends AbstractController $em->flush(); return $this->redirectToRoute('chill_wopi_file_edit', [ - 'fileId' => $genDocName, + 'fileId' => $storedObject->getUuid(), 'returnPath' => $request->query->get('returnPath', "/") ]); } diff --git a/src/Bundle/ChillDocStoreBundle/Entity/StoredObject.php b/src/Bundle/ChillDocStoreBundle/Entity/StoredObject.php index 9c88e502d..a0e614025 100644 --- a/src/Bundle/ChillDocStoreBundle/Entity/StoredObject.php +++ b/src/Bundle/ChillDocStoreBundle/Entity/StoredObject.php @@ -7,7 +7,10 @@ namespace Chill\DocStoreBundle\Entity; use Doctrine\ORM\Mapping as ORM; use ChampsLibres\AsyncUploaderBundle\Model\AsyncFileInterface; use ChampsLibres\AsyncUploaderBundle\Validator\Constraints\AsyncFileExists; +use ChampsLibres\WopiLib\Contract\Entity\Document; use DateTimeInterface; +use Ramsey\Uuid\Uuid; +use Ramsey\Uuid\UuidInterface; use Symfony\Component\Serializer\Annotation as Serializer; /** @@ -19,7 +22,7 @@ use Symfony\Component\Serializer\Annotation as Serializer; * message="The file is not stored properly" * ) */ -class StoredObject implements AsyncFileInterface +class StoredObject implements AsyncFileInterface, Document { /** * @ORM\Id() @@ -47,6 +50,12 @@ class StoredObject implements AsyncFileInterface */ private array $iv = []; + /** + * @ORM\Column(type="uuid", unique=true) + * @Serializer\Groups({"read"}) + */ + private UuidInterface $uuid; + /** * @ORM\Column(type="datetime", name="creation_date") * @Serializer\Groups({"read"}) @@ -68,6 +77,7 @@ class StoredObject implements AsyncFileInterface public function __construct() { $this->creationDate = new \DateTime(); + $this->uuid = Uuid::uuid4(); } public function getId() @@ -155,5 +165,13 @@ class StoredObject implements AsyncFileInterface return $this; } + public function getUuid(): UuidInterface + { + return $this->uuid; + } + public function getWopiDocId(): string + { + return (string) $this->uuid; + } } diff --git a/src/Bundle/ChillDocStoreBundle/composer.json b/src/Bundle/ChillDocStoreBundle/composer.json index 384f6c093..c011ce29b 100644 --- a/src/Bundle/ChillDocStoreBundle/composer.json +++ b/src/Bundle/ChillDocStoreBundle/composer.json @@ -3,9 +3,12 @@ "description": "A Chill bundle to store documents", "type": "symfony-bundle", "autoload": { - "psr-4": { "Chill\\DocStoreBundle\\" : "" } + "psr-4": { + "Chill\\DocStoreBundle\\": "" + } }, "require": { + "symfony/mime": "^4 || ^5" }, "license": "AGPL-3.0" } diff --git a/src/Bundle/ChillDocStoreBundle/migrations/Version20210928182542.php b/src/Bundle/ChillDocStoreBundle/migrations/Version20210928182542.php new file mode 100644 index 000000000..20d45ca37 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/migrations/Version20210928182542.php @@ -0,0 +1,30 @@ +addSql('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"'); + $this->addSql('ALTER TABLE chill_doc.stored_object ADD uuid UUID DEFAULT NULL'); + $this->addSql('UPDATE chill_doc.stored_object SET uuid=uuid_generate_v4()'); + $this->addSql('ALTER TABLE chill_doc.stored_object ALTER uuid SET NOT NULL'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_49604E36D17F50A6 ON chill_doc.stored_object (uuid)'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_doc.stored_object DROP uuid'); + } +} diff --git a/src/Bundle/ChillMainBundle/Controller/AddressApiController.php b/src/Bundle/ChillMainBundle/Controller/AddressApiController.php new file mode 100644 index 000000000..5c90cc9a7 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Controller/AddressApiController.php @@ -0,0 +1,38 @@ +denyAccessUnlessGranted('ROLE_USER'); + $new = Address::createFromAddress($address); + + $em = $this->getDoctrine()->getManager(); + + $em->persist($new); + $em->flush(); + + return $this->json($new, Response::HTTP_OK, [], [ + AbstractNormalizer::GROUPS => ['read'] + ]); + + } + +} diff --git a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php index f196b8a2b..21217c80e 100644 --- a/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php +++ b/src/Bundle/ChillMainBundle/DependencyInjection/ChillMainExtension.php @@ -19,6 +19,7 @@ namespace Chill\MainBundle\DependencyInjection; +use Chill\MainBundle\Controller\AddressApiController; use Chill\MainBundle\Controller\UserController; use Chill\MainBundle\Doctrine\DQL\STContains; use Chill\MainBundle\Doctrine\DQL\StrictWordSimilarityOPS; @@ -319,6 +320,7 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface, 'apis' => [ [ 'class' => \Chill\MainBundle\Entity\Address::class, + 'controller' => AddressApiController::class, 'name' => 'address', 'base_path' => '/api/1.0/main/address', 'base_role' => 'ROLE_USER', diff --git a/src/Bundle/ChillMainBundle/Entity/Address.php b/src/Bundle/ChillMainBundle/Entity/Address.php index 22e4848bf..4cc5c37ba 100644 --- a/src/Bundle/ChillMainBundle/Entity/Address.php +++ b/src/Bundle/ChillMainBundle/Entity/Address.php @@ -376,10 +376,22 @@ class Address public static function createFromAddress(Address $original) : Address { return (new Address()) + ->setBuildingName($original->getBuildingName()) + ->setCorridor($original->getCorridor()) + ->setCustoms($original->getCustoms()) + ->setDistribution($original->getDistribution()) + ->setExtra($original->getExtra()) + ->setFlat($original->getFlat()) + ->setFloor($original->getFloor()) + ->setIsNoAddress($original->getIsNoAddress()) + ->setLinkedToThirdParty($original->getLinkedToThirdParty()) + ->setPoint($original->getPoint()) ->setPostcode($original->getPostcode()) - ->setStreetAddress1($original->getStreetAddress1()) - ->setStreetAddress2($original->getStreetAddress2()) + ->setSteps($original->getSteps()) + ->setStreet($original->getStreet()) + ->setStreetNumber($original->getStreetNumber()) ->setValidFrom($original->getValidFrom()) + ->setValidTo($original->getValidTo()) ; } @@ -506,7 +518,7 @@ class Address return $this->validTo; } - public function setValidTo(\DateTimeInterface $validTo): self + public function setValidTo(?\DateTimeInterface $validTo = null): self { $this->validTo = $validTo; diff --git a/src/Bundle/ChillMainBundle/Repository/AddressRepository.php b/src/Bundle/ChillMainBundle/Repository/AddressRepository.php index 76f6c93bb..08e2da708 100644 --- a/src/Bundle/ChillMainBundle/Repository/AddressRepository.php +++ b/src/Bundle/ChillMainBundle/Repository/AddressRepository.php @@ -7,6 +7,7 @@ namespace Chill\MainBundle\Repository; use Chill\MainBundle\Entity\Address; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; +use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; final class AddressRepository implements ObjectRepository @@ -47,4 +48,9 @@ final class AddressRepository implements ObjectRepository public function getClassName() { return Address::class; } + + public function createQueryBuilder(string $alias, ?string $indexBy = null): QueryBuilder + { + return $this->repository->createQueryBuilder($alias, $indexBy); + } } diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/api.js b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/api.js index 14fa0490f..62065b3ad 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/api.js +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/api.js @@ -1,4 +1,4 @@ -/* +/** * Endpoint chill_api_single_country__index * method GET, get Country Object * @returns {Promise} a promise containing all Country object @@ -14,7 +14,7 @@ const fetchCountries = () => { }); }; -/* +/** * Endpoint chill_api_single_postal_code__index * method GET, get Country Object * @returns {Promise} a promise containing all Postal Code objects filtered with country @@ -29,7 +29,7 @@ const fetchCities = (country) => { }); }; -/* +/** * Endpoint chill_api_single_address_reference__index * method GET, get AddressReference Object * @returns {Promise} a promise containing all AddressReference objects filtered with postal code @@ -44,7 +44,7 @@ const fetchReferenceAddresses = (postalCode) => { }); }; -/* +/** * Endpoint chill_api_single_address_reference__index * method GET, get AddressReference Object * @returns {Promise} a promise containing all AddressReference objects filtered with postal code @@ -60,7 +60,7 @@ const fetchAddresses = () => { }); }; -/* +/** * Endpoint chill_api_single_address__entity__create * method POST, post Address Object * @returns {Promise} @@ -81,8 +81,28 @@ const postAddress = (address) => { }); }; +/** + * + * @param address + * @returns {Promise} + */ +const duplicateAddress = (address) => { + const url = `/api/1.0/main/address/${address.address_id}/duplicate.json`; + return fetch(url, { + 'method': 'POST', + headers: { + 'Content-Type': 'application/json;charset=utf-8' + }, + }).then(response => { + if (response.ok) { + return response.json(); + } + throw Error('Error with request resource response'); + }); +}; -/* + +/** * Endpoint chill_api_single_address__entity__create * method PATCH, patch Address Instance * @@ -142,6 +162,7 @@ const getAddress = (id) => { }; export { + duplicateAddress, fetchCountries, fetchCities, fetchReferenceAddresses, diff --git a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue index 8f60ef1c1..0a2904bff 100644 --- a/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue +++ b/src/Bundle/ChillMainBundle/Resources/public/vuejs/Address/components/AddAddress.vue @@ -34,6 +34,7 @@ v-bind:defaultz="this.defaultz" v-bind:entity="this.entity" v-bind:flag="this.flag" + @pick-address="this.pickAddress" ref="suggestAddress"> @@ -55,6 +56,7 @@ v-bind:entity="this.entity" v-bind:flag="this.flag" v-bind:insideModal="false" + @pick-address="this.pickAddress" ref="suggestAddress">