From 3ace435af3203488ecc648b8cd500800ce57f9ac Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Sun, 9 Jun 2024 00:21:47 +0200 Subject: [PATCH 01/69] Entity Checklist --- .../schema/Version20240608215345.php | 33 +++++ api/src/Entity/Camp.php | 44 +++++++ api/src/Entity/Checklist.php | 114 ++++++++++++++++++ api/src/Repository/ChecklistRepository.php | 29 +++++ api/src/State/ChecklistCreateProcessor.php | 31 +++++ 5 files changed, 251 insertions(+) create mode 100644 api/migrations/schema/Version20240608215345.php create mode 100644 api/src/Entity/Checklist.php create mode 100644 api/src/Repository/ChecklistRepository.php create mode 100644 api/src/State/ChecklistCreateProcessor.php diff --git a/api/migrations/schema/Version20240608215345.php b/api/migrations/schema/Version20240608215345.php new file mode 100644 index 0000000000..f5addee3d0 --- /dev/null +++ b/api/migrations/schema/Version20240608215345.php @@ -0,0 +1,33 @@ +addSql('CREATE TABLE checklist (id VARCHAR(16) NOT NULL, createTime TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updateTime TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, name TEXT NOT NULL, campId VARCHAR(16) NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_5C696D2F6D299429 ON checklist (campId)'); + $this->addSql('CREATE INDEX IDX_5C696D2F9D468A55 ON checklist (createTime)'); + $this->addSql('CREATE INDEX IDX_5C696D2F55AA53E2 ON checklist (updateTime)'); + $this->addSql('ALTER TABLE checklist ADD CONSTRAINT FK_5C696D2F6D299429 FOREIGN KEY (campId) REFERENCES camp (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE SCHEMA public'); + $this->addSql('ALTER TABLE checklist DROP CONSTRAINT FK_5C696D2F6D299429'); + $this->addSql('DROP TABLE checklist'); + } +} diff --git a/api/src/Entity/Camp.php b/api/src/Entity/Camp.php index eea7559c5e..88a895869c 100644 --- a/api/src/Entity/Camp.php +++ b/api/src/Entity/Camp.php @@ -136,6 +136,15 @@ class Camp extends BaseEntity implements BelongsToCampInterface, CopyFromPrototy #[ORM\OneToMany(targetEntity: MaterialList::class, mappedBy: 'camp', orphanRemoval: true, cascade: ['persist'])] public Collection $materialLists; + /** + * List of all Checklists of this Camp. + * Each Checklist is a List of ChecklistItems. + */ + #[ApiProperty(writable: false, example: '["/checklists/1a2b3c4d"]')] + #[Groups(['read'])] + #[ORM\OneToMany(targetEntity: Checklist::class, mappedBy: 'camp', orphanRemoval: true, cascade: ['persist'])] + public Collection $checklists; + /** * List all CampRootContentNodes of this Camp; * Calculated by the View view_camp_root_content_node. @@ -378,6 +387,7 @@ public function __construct() { $this->progressLabels = new ArrayCollection(); $this->activities = new ArrayCollection(); $this->materialLists = new ArrayCollection(); + $this->checklists = new ArrayCollection(); $this->campRootContentNodes = new ArrayCollection(); } @@ -591,6 +601,32 @@ public function removeMaterialList(MaterialList $materialList): self { return $this; } + /** + * @return Checklist[] + */ + public function getChecklists(): array { + return $this->checklists->getValues(); + } + + public function addChecklist(Checklist $checklist): self { + if (!$this->checklists->contains($checklist)) { + $this->checklists[] = $checklist; + $checklist->camp = $this; + } + + return $this; + } + + public function removeChecklist(Checklist $checklist): self { + if ($this->checklists->removeElement($checklist)) { + if ($checklist->camp === $this) { + $checklist->camp = null; + } + } + + return $this; + } + /** * @param Camp $prototype * @param EntityMap $entityMap @@ -608,6 +644,14 @@ public function copyFromPrototype($prototype, $entityMap): void { $materialList->copyFromPrototype($materialListPrototype, $entityMap); } + // copy Checklists + foreach ($prototype->getChecklists() as $checklistPrototype) { + $checklist = new Checklist(); + $this->addChecklist($checklist); + + $checklist->copyFromPrototype($checklistPrototype, $entityMap); + } + // copy Categories foreach ($prototype->getCategories() as $categoryPrototype) { $category = new Category(); diff --git a/api/src/Entity/Checklist.php b/api/src/Entity/Checklist.php new file mode 100644 index 0000000000..5b839f2ff5 --- /dev/null +++ b/api/src/Entity/Checklist.php @@ -0,0 +1,114 @@ + ['delete']] + ), + new GetCollection( + security: 'is_authenticated()' + ), + new Post( + processor: ChecklistCreateProcessor::class, + denormalizationContext: ['groups' => ['write', 'create']], + securityPostDenormalize: 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)' + ), + new GetCollection( + name: 'BelongsToCamp_App\Entity\Checklist_get_collection', + uriTemplate: self::CAMP_SUBRESOURCE_URI_TEMPLATE, + uriVariables: [ + 'campId' => new Link( + fromClass: Camp::class, + toProperty: 'camp', + security: 'is_granted("CAMP_COLLABORATOR", camp) or is_granted("CAMP_IS_PROTOTYPE", camp)' + ), + ], + ), + ], + denormalizationContext: ['groups' => ['write']], + normalizationContext: ['groups' => ['read']], + order: ['camp.id', 'name'], +)] +#[ApiFilter(filterClass: SearchFilter::class, properties: ['camp'])] +#[ORM\Entity(repositoryClass: ChecklistRepository::class)] +class Checklist extends BaseEntity implements BelongsToCampInterface, CopyFromPrototypeInterface { + public const CAMP_SUBRESOURCE_URI_TEMPLATE = '/camps/{campId}/checklists.{_format}'; + + /** + * The camp this checklist belongs to. + */ + #[ApiProperty(example: '/camps/1a2b3c4d')] + #[Groups(['read', 'create'])] + #[ORM\ManyToOne(targetEntity: Camp::class, inversedBy: 'checklists')] + #[ORM\JoinColumn(nullable: false, onDelete: 'cascade')] + public ?Camp $camp = null; + + /** + * Copy contents from this source checklist. + */ + #[ApiProperty(example: '/checklists/1a2b3c4d')] + #[Groups(['create'])] + public ?Checklist $copyChecklistSource; + + /** + * The human readable name of the checklist. + */ + #[ApiProperty(example: 'PBS Ausbildungsziele')] + #[Groups(['read', 'write'])] + #[InputFilter\Trim] + #[InputFilter\CleanText] + #[Assert\NotBlank] + #[Assert\Length(max: 32)] + #[ORM\Column(type: 'text')] + public ?string $name = null; + + public function __construct() { + parent::__construct(); + } + + public function getCamp(): ?Camp { + return $this->camp; + } + + /** + * @param Checklist $prototype + * @param EntityMap $entityMap + */ + public function copyFromPrototype($prototype, $entityMap): void { + $entityMap->add($prototype, $this); + + $this->name = $prototype->name; + } +} diff --git a/api/src/Repository/ChecklistRepository.php b/api/src/Repository/ChecklistRepository.php new file mode 100644 index 0000000000..4325bb3a5a --- /dev/null +++ b/api/src/Repository/ChecklistRepository.php @@ -0,0 +1,29 @@ +getRootAliases()[0]; + $this->filterByCampCollaboration($queryBuilder, $user, "{$rootAlias}.camp"); + } +} diff --git a/api/src/State/ChecklistCreateProcessor.php b/api/src/State/ChecklistCreateProcessor.php new file mode 100644 index 0000000000..bbac6635f5 --- /dev/null +++ b/api/src/State/ChecklistCreateProcessor.php @@ -0,0 +1,31 @@ + + */ +class ChecklistCreateProcessor extends AbstractPersistProcessor { + public function __construct(ProcessorInterface $decorated) { + parent::__construct($decorated); + } + + /** + * @param Checklist $data + */ + public function onBefore($data, Operation $operation, array $uriVariables = [], array $context = []): Checklist { + if (isset($data->copyChecklistSource)) { + // CopyChecklist Source is set -> copy it's content + $entityMap = new EntityMap(); + $data->copyFromPrototype($data->copyChecklistSource, $entityMap); + } + + return $data; + } +} From 764c4d9437202cb453b7d3da11cad5010194beab Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Mon, 10 Jun 2024 19:48:55 +0200 Subject: [PATCH 02/69] add checklist-fixtures --- api/fixtures/checklists.yml | 16 ++++++++++++++++ api/fixtures/performance_test/checklists.yml | 10 ++++++++++ 2 files changed, 26 insertions(+) create mode 100644 api/fixtures/checklists.yml create mode 100644 api/fixtures/performance_test/checklists.yml diff --git a/api/fixtures/checklists.yml b/api/fixtures/checklists.yml new file mode 100644 index 0000000000..e4515cedbd --- /dev/null +++ b/api/fixtures/checklists.yml @@ -0,0 +1,16 @@ +App\Entity\Checklist: + checklist1: + camp: '@camp1' + name: 'J+S Ausbildungsziele' + checklist2WithNoItems: + camp: '@camp1' + name: 'PBS Ausbildungsziele' + checklist1camp2: + camp: '@camp2' + name: 'J+S Ausbildungsziele' + checklist1campUnrelated: + camp: '@campUnrelated' + name: 'J+S Ausbildungsziele' + checklist1campPrototype: + camp: '@campPrototype' + name: 'J+S Ausbildungsziele' diff --git a/api/fixtures/performance_test/checklists.yml b/api/fixtures/performance_test/checklists.yml new file mode 100644 index 0000000000..43a5cd4d59 --- /dev/null +++ b/api/fixtures/performance_test/checklists.yml @@ -0,0 +1,10 @@ +App\Entity\Checklist: + additional_checklist1_{1..400}: + camp: '@additionalCamp_' + name: 'J+S Ausbildungsziele' + additional_checklist2_{1..400}: + camp: '@additionalCamp_' + name: 'PBS Ausbildungsziele' + additional_checklist_camp1_{1..12}: + camp: '@camp1' + name: From 67b0b2b098523148940b2e7737f7d52348a778f6 Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Mon, 10 Jun 2024 20:50:02 +0200 Subject: [PATCH 03/69] fix unittests fix unittest --- .../ListCampCollaborationsTest.php | 2 +- .../ReadCampCollaborationTest.php | 2 +- .../Api/SnapshotTests/ReadItemFixtureMap.php | 1 + ... with data set camp_collaborations__1.json | 36 + ...tchesStructure with data set camps__1.json | 9 + ...Structure with data set checklists__1.json | 74 ++ ... with data set camp_collaborations__1.json | 3 + ...tchesStructure with data set camps__1.json | 3 + ...Structure with data set checklists__1.json | 12 + ...hesStructure with data set periods__1.json | 3 + ...est__testOpenApiSpecMatchesSnapshot__1.yml | 917 ++++++++++++++++-- ...t__testRootEndpointMatchesSnapshot__1.json | 4 + ...manceDidNotChangeForStableEndpoints__1.yml | 16 +- 13 files changed, 977 insertions(+), 105 deletions(-) create mode 100644 api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set checklists__1.json create mode 100644 api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set checklists__1.json diff --git a/api/tests/Api/CampCollaborations/ListCampCollaborationsTest.php b/api/tests/Api/CampCollaborations/ListCampCollaborationsTest.php index 06975241fe..8ce744e353 100644 --- a/api/tests/Api/CampCollaborations/ListCampCollaborationsTest.php +++ b/api/tests/Api/CampCollaborations/ListCampCollaborationsTest.php @@ -114,6 +114,6 @@ public function testSqlQueryCount() { $client->enableProfiler(); $client->request('GET', '/camp_collaborations'); - $this->assertSqlQueryCount($client, 22); + $this->assertSqlQueryCount($client, 25); } } diff --git a/api/tests/Api/CampCollaborations/ReadCampCollaborationTest.php b/api/tests/Api/CampCollaborations/ReadCampCollaborationTest.php index a9916e6211..8c9eaf027f 100644 --- a/api/tests/Api/CampCollaborations/ReadCampCollaborationTest.php +++ b/api/tests/Api/CampCollaborations/ReadCampCollaborationTest.php @@ -126,6 +126,6 @@ public function testSqlQueryCount() { $client->enableProfiler(); $client->request('GET', '/camp_collaborations/'.$campCollaboration->getId()); - $this->assertSqlQueryCount($client, 14); + $this->assertSqlQueryCount($client, 15); } } diff --git a/api/tests/Api/SnapshotTests/ReadItemFixtureMap.php b/api/tests/Api/SnapshotTests/ReadItemFixtureMap.php index 15b893263b..f434e34a8a 100644 --- a/api/tests/Api/SnapshotTests/ReadItemFixtureMap.php +++ b/api/tests/Api/SnapshotTests/ReadItemFixtureMap.php @@ -11,6 +11,7 @@ public static function get(string $collectionEndpoint, array $fixtures): mixed { '/camp_collaborations' => $fixtures['campCollaboration1manager'], '/camps' => $fixtures['camp1'], '/categories' => $fixtures['category1'], + '/checklists' => $fixtures['checklist1'], '/content_node/column_layouts' => $fixtures['columnLayout2'], '/content_node/responsive_layouts' => $fixtures['responsiveLayout1'], '/content_types' => $fixtures['contentTypeSafetyConcept'], diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set camp_collaborations__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set camp_collaborations__1.json index e2ff2cbcd4..e347c3664d 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set camp_collaborations__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set camp_collaborations__1.json @@ -14,6 +14,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, @@ -81,6 +84,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, @@ -163,6 +169,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, @@ -245,6 +254,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, @@ -327,6 +339,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, @@ -409,6 +424,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, @@ -491,6 +509,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, @@ -573,6 +594,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, @@ -655,6 +679,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, @@ -737,6 +764,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, @@ -819,6 +849,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, @@ -901,6 +934,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set camps__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set camps__1.json index 2fa972bec6..567ab885bd 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set camps__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set camps__1.json @@ -12,6 +12,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, @@ -59,6 +62,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, @@ -106,6 +112,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set checklists__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set checklists__1.json new file mode 100644 index 0000000000..16ae186f1b --- /dev/null +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set checklists__1.json @@ -0,0 +1,74 @@ +{ + "_embedded": { + "items": [ + { + "_links": { + "camp": { + "href": "escaped_value" + }, + "self": { + "href": "escaped_value" + } + }, + "id": "escaped_value", + "name": "escaped_value" + }, + { + "_links": { + "camp": { + "href": "escaped_value" + }, + "self": { + "href": "escaped_value" + } + }, + "id": "escaped_value", + "name": "escaped_value" + }, + { + "_links": { + "camp": { + "href": "escaped_value" + }, + "self": { + "href": "escaped_value" + } + }, + "id": "escaped_value", + "name": "escaped_value" + }, + { + "_links": { + "camp": { + "href": "escaped_value" + }, + "self": { + "href": "escaped_value" + } + }, + "id": "escaped_value", + "name": "escaped_value" + } + ] + }, + "_links": { + "items": [ + { + "href": "escaped_value" + }, + { + "href": "escaped_value" + }, + { + "href": "escaped_value" + }, + { + "href": "escaped_value" + } + ], + "self": { + "href": "escaped_value" + } + }, + "totalItems": "escaped_value" +} diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set camp_collaborations__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set camp_collaborations__1.json index c84f1c605b..5867857e14 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set camp_collaborations__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set camp_collaborations__1.json @@ -11,6 +11,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set camps__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set camps__1.json index 9afc1cba01..d7d5123b20 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set camps__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set camps__1.json @@ -402,6 +402,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set checklists__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set checklists__1.json new file mode 100644 index 0000000000..39e7e3d07f --- /dev/null +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set checklists__1.json @@ -0,0 +1,12 @@ +{ + "_links": { + "camp": { + "href": "escaped_value" + }, + "self": { + "href": "escaped_value" + } + }, + "id": "escaped_value", + "name": "escaped_value" +} diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set periods__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set periods__1.json index 2075727cda..e8083f1bbd 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set periods__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set periods__1.json @@ -11,6 +11,9 @@ "categories": { "href": "escaped_value" }, + "checklists": { + "href": "escaped_value" + }, "creator": { "href": "escaped_value" }, diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml index d1f260203b..52c7add8a6 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml @@ -2333,6 +2333,15 @@ components: format: iri-reference readOnly: true type: string + checklists: + description: 'List of all Checklists of this Camp.' + example: '["/checklists/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -2460,6 +2469,7 @@ components: - activities - campCollaborations - categories + - checklists - materialLists - name - periods @@ -2526,6 +2536,15 @@ components: format: iri-reference readOnly: true type: string + checklists: + description: 'List of all Checklists of this Camp.' + example: '["/checklists/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -2646,6 +2665,7 @@ components: - activities - campCollaborations - categories + - checklists - materialLists - name - periods @@ -2708,6 +2728,15 @@ components: format: iri-reference readOnly: true type: string + checklists: + description: 'List of all Checklists of this Camp.' + example: '["/checklists/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -2835,6 +2864,7 @@ components: - activities - campCollaborations - categories + - checklists - materialLists - name - periods @@ -2897,6 +2927,15 @@ components: format: iri-reference readOnly: true type: string + checklists: + description: 'List of all Checklists of this Camp.' + example: '["/checklists/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -3024,6 +3063,7 @@ components: - activities - campCollaborations - categories + - checklists - materialLists - name - periods @@ -3368,6 +3408,8 @@ components: properties: { data: { items: { properties: { id: { format: iri-reference, type: string }, type: { type: string } }, type: object }, type: array } } categories: properties: { data: { items: { properties: { id: { format: iri-reference, type: string }, type: { type: string } }, type: object }, type: array } } + checklists: + properties: { data: { items: { properties: { id: { format: iri-reference, type: string }, type: { type: string } }, type: object }, type: array } } creator: properties: { data: { properties: { id: { format: iri-reference, type: string }, type: { type: string } }, type: object } } materialLists: @@ -3380,6 +3422,7 @@ components: - activities - campCollaborations - categories + - checklists - materialLists - periods - progressLabels @@ -3410,6 +3453,8 @@ components: $ref: '#/components/schemas/CampCollaboration.jsonapi' - $ref: '#/components/schemas/CampCollaboration.jsonapi' + - + $ref: '#/components/schemas/CampCollaboration.jsonapi' readOnly: true type: array periods: @@ -3493,6 +3538,15 @@ components: format: iri-reference readOnly: true type: string + checklists: + description: 'List of all Checklists of this Camp.' + example: '["/checklists/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -3620,6 +3674,7 @@ components: - activities - campCollaborations - categories + - checklists - materialLists - name - periods @@ -3695,6 +3750,15 @@ components: format: iri-reference readOnly: true type: string + checklists: + description: 'List of all Checklists of this Camp.' + example: '["/checklists/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -3815,6 +3879,7 @@ components: - activities - campCollaborations - categories + - checklists - materialLists - name - periods @@ -3886,6 +3951,15 @@ components: format: iri-reference readOnly: true type: string + checklists: + description: 'List of all Checklists of this Camp.' + example: '["/checklists/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -4013,6 +4087,7 @@ components: - activities - campCollaborations - categories + - checklists - materialLists - name - periods @@ -4084,6 +4159,15 @@ components: format: iri-reference readOnly: true type: string + checklists: + description: 'List of all Checklists of this Camp.' + example: '["/checklists/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -4211,6 +4295,7 @@ components: - activities - campCollaborations - categories + - checklists - materialLists - name - periods @@ -4429,6 +4514,15 @@ components: format: iri-reference readOnly: true type: string + checklists: + description: 'List of all Checklists of this Camp.' + example: '["/checklists/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -4556,6 +4650,7 @@ components: - activities - campCollaborations - categories + - checklists - materialLists - name - periods @@ -4645,6 +4740,15 @@ components: format: iri-reference readOnly: true type: string + checklists: + description: 'List of all Checklists of this Camp.' + example: '["/checklists/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -4765,6 +4869,7 @@ components: - activities - campCollaborations - categories + - checklists - materialLists - name - periods @@ -4850,6 +4955,15 @@ components: format: iri-reference readOnly: true type: string + checklists: + description: 'List of all Checklists of this Camp.' + example: '["/checklists/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -4977,6 +5091,7 @@ components: - activities - campCollaborations - categories + - checklists - materialLists - name - periods @@ -5062,6 +5177,15 @@ components: format: iri-reference readOnly: true type: string + checklists: + description: 'List of all Checklists of this Camp.' + example: '["/checklists/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -5189,6 +5313,7 @@ components: - activities - campCollaborations - categories + - checklists - materialLists - name - periods @@ -7487,128 +7612,392 @@ components: - preferredContentTypes - short type: object - ColumnLayout-read: + Checklist-read: deprecated: false - description: '' + description: |- + A Checklist + Tree-Structure with ChecklistItems. properties: - children: - description: 'All content nodes that are direct children of this content node.' - example: '["/content_nodes/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string - readOnly: true - type: array - contentType: - description: |- - Defines the type of this content node. There is a fixed list of types that are implemented - in eCamp. Depending on the type, different content data and different slots may be allowed - in a content node. The content type may not be changed once the content node is created. - example: /content_types/1a2b3c4d + camp: + description: 'The camp this checklist belongs to.' + example: /camps/1a2b3c4d format: iri-reference type: string - contentTypeName: - description: 'The name of the content type of this content node. Read-only, for convenience.' - example: SafetyConcept - readOnly: true - type: string - data: - default: '{"columns":[{"slot":"1","width":6},{"slot":"2","width":6}]}' - description: |- - Holds the actual data of the content node - (overridden from abstract class in order to add specific validation). - example: - columns: - - - slot: '1' - width: 12 - items: - type: string - type: - - array - - 'null' id: description: 'An internal, unique, randomly generated identifier of this entity.' example: 1a2b3c4d maxLength: 16 readOnly: true type: string - instanceName: - description: |- - An optional name for this content node. This is useful when planning e.g. an alternative - version of the programme suited for bad weather, in addition to the normal version. - example: Schlechtwetterprogramm + name: + description: 'The human readable name of the checklist.' + example: 'PBS Ausbildungsziele' maxLength: 32 - type: - - 'null' - - string - parent: - description: |- - The parent to which this content node belongs. Is null in case this content node is the - root of a content node tree. For non-root content nodes, the parent can be changed, as long - as the new parent is in the same camp as the old one. - example: /content_nodes/1a2b3c4d + type: string + required: + - camp + - name + type: object + Checklist-write: + deprecated: false + description: |- + A Checklist + Tree-Structure with ChecklistItems. + properties: + name: + description: 'The human readable name of the checklist.' + example: 'PBS Ausbildungsziele' + maxLength: 32 + type: string + required: + - name + type: object + Checklist-write_create: + deprecated: false + description: |- + A Checklist + Tree-Structure with ChecklistItems. + properties: + camp: + description: 'The camp this checklist belongs to.' + example: /camps/1a2b3c4d format: iri-reference - type: - - 'null' - - string - position: - default: -1 - description: |- - A whole number used for ordering multiple content nodes that are in the same slot of the - same parent. The API does not guarantee the uniqueness of parent+slot+position. - example: -1 - type: integer - root: - description: |- - The content node that is the root of the content node tree. Refers to itself in case this - content node is the root. - example: /content_nodes/1a2b3c4d + type: string + copyChecklistSource: + description: 'Copy contents from this source checklist.' + example: /checklists/1a2b3c4d format: iri-reference - readOnly: true type: - 'null' - string - slot: - description: |- - The name of the slot in the parent in which this content node resides. The valid slot names - are defined by the content type of the parent. - example: '1' + name: + description: 'The human readable name of the checklist.' + example: 'PBS Ausbildungsziele' maxLength: 32 - type: - - 'null' - - string + type: string required: - - children - - contentType - - data - - position + - camp + - name type: object - ColumnLayout-read_Activity.ActivityProgressLabel_Activity.ActivityResponsibles_Activity.ScheduleEntries: + Checklist.jsonapi: deprecated: false - description: '' + description: |- + A Checklist + Tree-Structure with ChecklistItems. properties: - children: - description: 'All content nodes that are direct children of this content node.' - example: '["/content_nodes/1a2b3c4d"]' + data: + properties: + attributes: + properties: + _id: + description: 'An internal, unique, randomly generated identifier of this entity.' + example: 1a2b3c4d + maxLength: 16 + readOnly: true + type: string + name: + description: 'The human readable name of the checklist.' + example: 'PBS Ausbildungsziele' + maxLength: 32 + type: string + required: + - name + type: object + id: + type: string + relationships: + properties: + camp: + properties: { data: { properties: { id: { format: iri-reference, type: string }, type: { type: string } }, type: object } } + required: + - camp + type: object + type: + type: string + required: + - id + - type + type: object + included: + description: 'Related resources requested via the "include" query parameter.' + externalDocs: + url: 'https://jsonapi.org/format/#fetching-includes' items: - example: 'https://example.com/' - format: iri-reference - type: string + anyOf: + - + $ref: '#/components/schemas/Checklist.jsonapi' readOnly: true type: array - contentType: - description: |- - Defines the type of this content node. There is a fixed list of types that are implemented - in eCamp. Depending on the type, different content data and different slots may be allowed - in a content node. The content type may not be changed once the content node is created. - example: /content_types/1a2b3c4d + type: object + Checklist.jsonhal-read: + deprecated: false + description: |- + A Checklist + Tree-Structure with ChecklistItems. + properties: + _links: + properties: + self: + properties: + href: + format: iri-reference + type: string + type: object + type: object + camp: + description: 'The camp this checklist belongs to.' + example: /camps/1a2b3c4d format: iri-reference type: string - contentTypeName: - description: 'The name of the content type of this content node. Read-only, for convenience.' - example: SafetyConcept + id: + description: 'An internal, unique, randomly generated identifier of this entity.' + example: 1a2b3c4d + maxLength: 16 + readOnly: true + type: string + name: + description: 'The human readable name of the checklist.' + example: 'PBS Ausbildungsziele' + maxLength: 32 + type: string + required: + - camp + - name + type: object + Checklist.jsonhal-write_create: + deprecated: false + description: |- + A Checklist + Tree-Structure with ChecklistItems. + properties: + _links: + properties: + self: + properties: + href: + format: iri-reference + type: string + type: object + type: object + camp: + description: 'The camp this checklist belongs to.' + example: /camps/1a2b3c4d + format: iri-reference + type: string + copyChecklistSource: + description: 'Copy contents from this source checklist.' + example: /checklists/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + name: + description: 'The human readable name of the checklist.' + example: 'PBS Ausbildungsziele' + maxLength: 32 + type: string + required: + - camp + - name + type: object + Checklist.jsonld-read: + deprecated: false + description: |- + A Checklist + Tree-Structure with ChecklistItems. + properties: + '@context': + oneOf: + - + additionalProperties: true + properties: + '@vocab': + type: string + hydra: + enum: ['http://www.w3.org/ns/hydra/core#'] + type: string + required: + - '@vocab' + - hydra + type: object + - + type: string + readOnly: true + '@id': + readOnly: true + type: string + '@type': + readOnly: true + type: string + camp: + description: 'The camp this checklist belongs to.' + example: /camps/1a2b3c4d + format: iri-reference + type: string + id: + description: 'An internal, unique, randomly generated identifier of this entity.' + example: 1a2b3c4d + maxLength: 16 + readOnly: true + type: string + name: + description: 'The human readable name of the checklist.' + example: 'PBS Ausbildungsziele' + maxLength: 32 + type: string + required: + - camp + - name + type: object + Checklist.jsonld-write_create: + deprecated: false + description: |- + A Checklist + Tree-Structure with ChecklistItems. + properties: + camp: + description: 'The camp this checklist belongs to.' + example: /camps/1a2b3c4d + format: iri-reference + type: string + copyChecklistSource: + description: 'Copy contents from this source checklist.' + example: /checklists/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + name: + description: 'The human readable name of the checklist.' + example: 'PBS Ausbildungsziele' + maxLength: 32 + type: string + required: + - camp + - name + type: object + ColumnLayout-read: + deprecated: false + description: '' + properties: + children: + description: 'All content nodes that are direct children of this content node.' + example: '["/content_nodes/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array + contentType: + description: |- + Defines the type of this content node. There is a fixed list of types that are implemented + in eCamp. Depending on the type, different content data and different slots may be allowed + in a content node. The content type may not be changed once the content node is created. + example: /content_types/1a2b3c4d + format: iri-reference + type: string + contentTypeName: + description: 'The name of the content type of this content node. Read-only, for convenience.' + example: SafetyConcept + readOnly: true + type: string + data: + default: '{"columns":[{"slot":"1","width":6},{"slot":"2","width":6}]}' + description: |- + Holds the actual data of the content node + (overridden from abstract class in order to add specific validation). + example: + columns: + - + slot: '1' + width: 12 + items: + type: string + type: + - array + - 'null' + id: + description: 'An internal, unique, randomly generated identifier of this entity.' + example: 1a2b3c4d + maxLength: 16 + readOnly: true + type: string + instanceName: + description: |- + An optional name for this content node. This is useful when planning e.g. an alternative + version of the programme suited for bad weather, in addition to the normal version. + example: Schlechtwetterprogramm + maxLength: 32 + type: + - 'null' + - string + parent: + description: |- + The parent to which this content node belongs. Is null in case this content node is the + root of a content node tree. For non-root content nodes, the parent can be changed, as long + as the new parent is in the same camp as the old one. + example: /content_nodes/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + position: + default: -1 + description: |- + A whole number used for ordering multiple content nodes that are in the same slot of the + same parent. The API does not guarantee the uniqueness of parent+slot+position. + example: -1 + type: integer + root: + description: |- + The content node that is the root of the content node tree. Refers to itself in case this + content node is the root. + example: /content_nodes/1a2b3c4d + format: iri-reference + readOnly: true + type: + - 'null' + - string + slot: + description: |- + The name of the slot in the parent in which this content node resides. The valid slot names + are defined by the content type of the parent. + example: '1' + maxLength: 32 + type: + - 'null' + - string + required: + - children + - contentType + - data + - position + type: object + ColumnLayout-read_Activity.ActivityProgressLabel_Activity.ActivityResponsibles_Activity.ScheduleEntries: + deprecated: false + description: '' + properties: + children: + description: 'All content nodes that are direct children of this content node.' + example: '["/content_nodes/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array + contentType: + description: |- + Defines the type of this content node. There is a fixed list of types that are implemented + in eCamp. Depending on the type, different content data and different slots may be allowed + in a content node. The content type may not be changed once the content node is created. + example: /content_types/1a2b3c4d + format: iri-reference + type: string + contentTypeName: + description: 'The name of the content type of this content node. Read-only, for convenience.' + example: SafetyConcept readOnly: true type: string data: @@ -22742,6 +23131,93 @@ paths: summary: 'Retrieves the collection of Category resources.' tags: - Category + '/camps/{campId}/checklists': + get: + deprecated: false + description: 'Retrieves the collection of Checklist resources.' + operationId: BelongsToCamp_App\Entity\Checklist_get_collection + parameters: + - + allowEmptyValue: false + allowReserved: false + deprecated: false + description: 'Checklist identifier' + explode: false + in: path + name: campId + required: true + schema: + type: string + style: simple + - + allowEmptyValue: true + allowReserved: false + deprecated: false + description: '' + explode: false + in: query + name: camp + required: false + schema: + type: string + style: form + - + allowEmptyValue: true + allowReserved: false + deprecated: false + description: '' + explode: true + in: query + name: 'camp[]' + required: false + schema: + items: + type: string + type: array + style: form + responses: + 200: + content: + application/hal+json: + schema: + properties: + _embedded: { anyOf: [{ properties: { item: { items: { $ref: '#/components/schemas/Checklist.jsonhal-read' }, type: array } }, type: object }, { type: object }] } + _links: { properties: { first: { properties: { href: { format: iri-reference, type: string } }, type: object }, last: { properties: { href: { format: iri-reference, type: string } }, type: object }, next: { properties: { href: { format: iri-reference, type: string } }, type: object }, previous: { properties: { href: { format: iri-reference, type: string } }, type: object }, self: { properties: { href: { format: iri-reference, type: string } }, type: object } }, type: object } + itemsPerPage: { minimum: 0, type: integer } + totalItems: { minimum: 0, type: integer } + required: + - _embedded + - _links + type: object + application/json: + schema: + items: + $ref: '#/components/schemas/Checklist-read' + type: array + application/ld+json: + schema: + properties: + 'hydra:member': { items: { $ref: '#/components/schemas/Checklist.jsonld-read' }, type: array } + 'hydra:search': { properties: { '@type': { type: string }, 'hydra:mapping': { items: { properties: { '@type': { type: string }, property: { type: ['null', string] }, required: { type: boolean }, variable: { type: string } }, type: object }, type: array }, 'hydra:template': { type: string }, 'hydra:variableRepresentation': { type: string } }, type: object } + 'hydra:totalItems': { minimum: 0, type: integer } + 'hydra:view': { example: { '@id': string, 'hydra:first': string, 'hydra:last': string, 'hydra:next': string, 'hydra:previous': string, type: string }, properties: { '@id': { format: iri-reference, type: string }, '@type': { type: string }, 'hydra:first': { format: iri-reference, type: string }, 'hydra:last': { format: iri-reference, type: string }, 'hydra:next': { format: iri-reference, type: string }, 'hydra:previous': { format: iri-reference, type: string } }, type: object } + required: + - 'hydra:member' + type: object + application/vnd.api+json: + schema: + items: + $ref: '#/components/schemas/Checklist.jsonapi' + type: array + text/html: + schema: + items: + $ref: '#/components/schemas/Checklist-read' + type: array + description: 'Checklist collection' + summary: 'Retrieves the collection of Checklist resources.' + tags: + - Checklist '/camps/{id}': delete: deprecated: false @@ -23114,6 +23590,255 @@ paths: summary: 'Updates the Category resource.' tags: - Category + /checklists: + get: + deprecated: false + description: 'Retrieves the collection of Checklist resources.' + operationId: api_checklists_get_collection + parameters: + - + allowEmptyValue: true + allowReserved: false + deprecated: false + description: '' + explode: false + in: query + name: camp + required: false + schema: + type: string + style: form + - + allowEmptyValue: true + allowReserved: false + deprecated: false + description: '' + explode: true + in: query + name: 'camp[]' + required: false + schema: + items: + type: string + type: array + style: form + responses: + 200: + content: + application/hal+json: + schema: + properties: + _embedded: { anyOf: [{ properties: { item: { items: { $ref: '#/components/schemas/Checklist.jsonhal-read' }, type: array } }, type: object }, { type: object }] } + _links: { properties: { first: { properties: { href: { format: iri-reference, type: string } }, type: object }, last: { properties: { href: { format: iri-reference, type: string } }, type: object }, next: { properties: { href: { format: iri-reference, type: string } }, type: object }, previous: { properties: { href: { format: iri-reference, type: string } }, type: object }, self: { properties: { href: { format: iri-reference, type: string } }, type: object } }, type: object } + itemsPerPage: { minimum: 0, type: integer } + totalItems: { minimum: 0, type: integer } + required: + - _embedded + - _links + type: object + application/json: + schema: + items: + $ref: '#/components/schemas/Checklist-read' + type: array + application/ld+json: + schema: + properties: + 'hydra:member': { items: { $ref: '#/components/schemas/Checklist.jsonld-read' }, type: array } + 'hydra:search': { properties: { '@type': { type: string }, 'hydra:mapping': { items: { properties: { '@type': { type: string }, property: { type: ['null', string] }, required: { type: boolean }, variable: { type: string } }, type: object }, type: array }, 'hydra:template': { type: string }, 'hydra:variableRepresentation': { type: string } }, type: object } + 'hydra:totalItems': { minimum: 0, type: integer } + 'hydra:view': { example: { '@id': string, 'hydra:first': string, 'hydra:last': string, 'hydra:next': string, 'hydra:previous': string, type: string }, properties: { '@id': { format: iri-reference, type: string }, '@type': { type: string }, 'hydra:first': { format: iri-reference, type: string }, 'hydra:last': { format: iri-reference, type: string }, 'hydra:next': { format: iri-reference, type: string }, 'hydra:previous': { format: iri-reference, type: string } }, type: object } + required: + - 'hydra:member' + type: object + application/vnd.api+json: + schema: + items: + $ref: '#/components/schemas/Checklist.jsonapi' + type: array + text/html: + schema: + items: + $ref: '#/components/schemas/Checklist-read' + type: array + description: 'Checklist collection' + summary: 'Retrieves the collection of Checklist resources.' + tags: + - Checklist + post: + deprecated: false + description: 'Creates a Checklist resource.' + operationId: api_checklists_post + parameters: [] + requestBody: + content: + application/hal+json: + schema: + $ref: '#/components/schemas/Checklist.jsonhal-write_create' + application/json: + schema: + $ref: '#/components/schemas/Checklist-write_create' + application/ld+json: + schema: + $ref: '#/components/schemas/Checklist.jsonld-write_create' + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Checklist.jsonapi' + text/html: + schema: + $ref: '#/components/schemas/Checklist-write_create' + description: 'The new Checklist resource' + required: true + responses: + 201: + content: + application/hal+json: + schema: + $ref: '#/components/schemas/Checklist.jsonhal-read' + application/json: + schema: + $ref: '#/components/schemas/Checklist-read' + application/ld+json: + schema: + $ref: '#/components/schemas/Checklist.jsonld-read' + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Checklist.jsonapi' + text/html: + schema: + $ref: '#/components/schemas/Checklist-read' + description: 'Checklist resource created' + links: [] + 400: + description: 'Invalid input' + 422: + description: 'Unprocessable entity' + summary: 'Creates a Checklist resource.' + tags: + - Checklist + '/checklists/{id}': + delete: + deprecated: false + description: 'Removes the Checklist resource.' + operationId: api_checklists_id_delete + parameters: + - + allowEmptyValue: false + allowReserved: false + deprecated: false + description: 'Checklist identifier' + explode: false + in: path + name: id + required: true + schema: + type: string + style: simple + responses: + 204: + description: 'Checklist resource deleted' + 404: + description: 'Resource not found' + summary: 'Removes the Checklist resource.' + tags: + - Checklist + get: + deprecated: false + description: 'Retrieves a Checklist resource.' + operationId: api_checklists_id_get + parameters: + - + allowEmptyValue: false + allowReserved: false + deprecated: false + description: 'Checklist identifier' + explode: false + in: path + name: id + required: true + schema: + type: string + style: simple + responses: + 200: + content: + application/hal+json: + schema: + $ref: '#/components/schemas/Checklist.jsonhal-read' + application/json: + schema: + $ref: '#/components/schemas/Checklist-read' + application/ld+json: + schema: + $ref: '#/components/schemas/Checklist.jsonld-read' + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Checklist.jsonapi' + text/html: + schema: + $ref: '#/components/schemas/Checklist-read' + description: 'Checklist resource' + 404: + description: 'Resource not found' + summary: 'Retrieves a Checklist resource.' + tags: + - Checklist + patch: + deprecated: false + description: 'Updates the Checklist resource.' + operationId: api_checklists_id_patch + parameters: + - + allowEmptyValue: false + allowReserved: false + deprecated: false + description: 'Checklist identifier' + explode: false + in: path + name: id + required: true + schema: + type: string + style: simple + requestBody: + content: + application/merge-patch+json: + schema: + $ref: '#/components/schemas/Checklist-write' + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Checklist.jsonapi' + description: 'The updated Checklist resource' + required: true + responses: + 200: + content: + application/hal+json: + schema: + $ref: '#/components/schemas/Checklist.jsonhal-read' + application/json: + schema: + $ref: '#/components/schemas/Checklist-read' + application/ld+json: + schema: + $ref: '#/components/schemas/Checklist.jsonld-read' + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Checklist.jsonapi' + text/html: + schema: + $ref: '#/components/schemas/Checklist-read' + description: 'Checklist resource updated' + links: [] + 400: + description: 'Invalid input' + 404: + description: 'Resource not found' + 422: + description: 'Unprocessable entity' + summary: 'Updates the Checklist resource.' + tags: + - Checklist /content_node/column_layouts: get: deprecated: false diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testRootEndpointMatchesSnapshot__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testRootEndpointMatchesSnapshot__1.json index 69c3aebd5f..84921e20f9 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testRootEndpointMatchesSnapshot__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testRootEndpointMatchesSnapshot__1.json @@ -24,6 +24,10 @@ "href": "\/categories{\/id}{?camp,camp[]}", "templated": true }, + "checklists": { + "href": "\/checklists{\/id}{?camp,camp[]}", + "templated": true + }, "columnLayouts": { "href": "\/content_node\/column_layouts{\/id}{?contentType,contentType[],root,root[],period}", "templated": true diff --git a/api/tests/Api/SnapshotTests/__snapshots__/test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml b/api/tests/Api/SnapshotTests/__snapshots__/test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml index 1e0924898b..71b7a0fd66 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml +++ b/api/tests/Api/SnapshotTests/__snapshots__/test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml @@ -4,12 +4,14 @@ /activity_progress_labels/item: 7 /activity_responsibles: 6 /activity_responsibles/item: 8 -/camps: 26 -/camps/item: 21 -/camp_collaborations: 22 -/camp_collaborations/item: 14 +/camps: 29 +/camps/item: 22 +/camp_collaborations: 25 +/camp_collaborations/item: 15 /categories: 11 /categories/item: 9 +/checklists: 6 +/checklists/item: 7 /content_types: 6 /content_types/item: 6 /days: 26 @@ -21,7 +23,7 @@ /material_lists: 6 /material_lists/item: 7 /periods: 6 -/periods/item: 17 +/periods/item: 18 /profiles: 6 /profiles/item: 6 /schedule_entries: 23 @@ -30,8 +32,8 @@ '/activities?camp=': 13 '/activity_progress_labels?camp=': 6 '/activity_responsibles?activity.camp=': 6 -'/camp_collaborations?camp=': 12 -'/camp_collaborations?activityResponsibles.activity=': 14 +'/camp_collaborations?camp=': 13 +'/camp_collaborations?activityResponsibles.activity=': 15 '/categories?camp=': 9 '/content_types?categories=': 6 '/day_responsibles?day.period=': 6 From 988f96c17c4bc7472066c9e94b151a1561c0c1a2 Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Sat, 15 Jun 2024 17:49:12 +0200 Subject: [PATCH 04/69] add Unittests --- .../Api/Checklists/CreateChecklistTest.php | 311 ++++++++++++++++++ .../Api/Checklists/DeleteChecklistTest.php | 87 +++++ .../Api/Checklists/ListChecklistTest.php | 125 +++++++ .../Api/Checklists/ReadChecklistTest.php | 108 ++++++ .../Api/Checklists/UpdateChecklistTest.php | 220 +++++++++++++ 5 files changed, 851 insertions(+) create mode 100644 api/tests/Api/Checklists/CreateChecklistTest.php create mode 100644 api/tests/Api/Checklists/DeleteChecklistTest.php create mode 100644 api/tests/Api/Checklists/ListChecklistTest.php create mode 100644 api/tests/Api/Checklists/ReadChecklistTest.php create mode 100644 api/tests/Api/Checklists/UpdateChecklistTest.php diff --git a/api/tests/Api/Checklists/CreateChecklistTest.php b/api/tests/Api/Checklists/CreateChecklistTest.php new file mode 100644 index 0000000000..12392aca9d --- /dev/null +++ b/api/tests/Api/Checklists/CreateChecklistTest.php @@ -0,0 +1,311 @@ +request('POST', '/checklists', ['json' => $this->getExampleWritePayload()]); + + $this->assertResponseStatusCodeSame(401); + $this->assertJsonContains([ + 'code' => 401, + 'message' => 'JWT Token not found', + ]); + } + + public function testCreateChecklistIsNotPossibleForUnrelatedUserBecauseCampIsNotReadable() { + static::createClientWithCredentials(['email' => static::$fixtures['user4unrelated']->getEmail()]) + ->request('POST', '/checklists', ['json' => $this->getExampleWritePayload()]) + ; + + $this->assertResponseStatusCodeSame(400); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Item not found for "'.$this->getIriFor('camp1').'".', + ]); + } + + public function testCreateChecklistIsNotPossibleForInactiveCollaboratorBecauseCampIsNotReadable() { + static::createClientWithCredentials(['email' => static::$fixtures['user5inactive']->getEmail()]) + ->request('POST', '/checklists', ['json' => $this->getExampleWritePayload()]) + ; + + $this->assertResponseStatusCodeSame(400); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Item not found for "'.$this->getIriFor('camp1').'".', + ]); + } + + public function testCreateChecklistIsDeniedForGuest() { + static::createClientWithCredentials(['email' => static::$fixtures['user3guest']->getEmail()]) + ->request('POST', '/checklists', ['json' => $this->getExampleWritePayload()]) + ; + + $this->assertResponseStatusCodeSame(403); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Access Denied.', + ]); + } + + public function testCreateChecklistIsAllowedForMember() { + static::createClientWithCredentials(['email' => static::$fixtures['user2member']->getEmail()]) + ->request('POST', '/checklists', ['json' => $this->getExampleWritePayload()]) + ; + + $this->assertResponseStatusCodeSame(201); + $this->assertJsonContains($this->getExampleReadPayload()); + } + + public function testCreateChecklistIsAllowedForManager() { + static::createClientWithCredentials()->request('POST', '/checklists', ['json' => $this->getExampleWritePayload()]); + + $this->assertResponseStatusCodeSame(201); + $this->assertJsonContains($this->getExampleReadPayload()); + } + + public function testCreateChecklistInCampPrototypeIsDeniedForUnrelatedUser() { + static::createClientWithCredentials()->request('POST', '/checklists', ['json' => $this->getExampleWritePayload([ + 'camp' => $this->getIriFor('campPrototype'), + ])]); + + $this->assertResponseStatusCodeSame(403); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Access Denied.', + ]); + } + + public function testCreateChecklistValidatesMissingCamp() { + static::createClientWithCredentials()->request('POST', '/checklists', ['json' => $this->getExampleWritePayload([], ['camp'])]); + + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'violations' => [ + [ + 'propertyPath' => 'camp', + 'message' => 'This value should not be null.', + ], + ], + ]); + } + + public function testCreateChecklistValidatesMissingName() { + static::createClientWithCredentials()->request('POST', '/checklists', ['json' => $this->getExampleWritePayload([], ['name'])]); + + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'violations' => [ + [ + 'propertyPath' => 'name', + 'message' => 'This value should not be blank.', + ], + ], + ]); + } + + public function testCreateChecklistValidatesBlankName() { + static::createClientWithCredentials()->request( + 'POST', + '/checklists', + [ + 'json' => $this->getExampleWritePayload( + [ + 'name' => '', + ] + ), + ] + ); + + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'violations' => [ + [ + 'propertyPath' => 'name', + 'message' => 'This value should not be blank.', + ], + ], + ]); + } + + public function testCreateChecklistValidatesTooLongName() { + static::createClientWithCredentials()->request( + 'POST', + '/checklists', + [ + 'json' => $this->getExampleWritePayload( + [ + 'name' => str_repeat('l', 33), + ] + ), + ] + ); + + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'violations' => [ + [ + 'propertyPath' => 'name', + 'message' => 'This value is too long. It should have 32 characters or less.', + ], + ], + ]); + } + + public function testCreateChecklistTrimsName() { + static::createClientWithCredentials()->request( + 'POST', + '/checklists', + [ + 'json' => $this->getExampleWritePayload( + [ + 'name' => " \t Ausbildungsziele\t ", + ] + ), + ] + ); + + $this->assertResponseStatusCodeSame(201); + $this->assertJsonContains($this->getExampleReadPayload( + [ + 'name' => 'Ausbildungsziele', + ] + )); + } + + public function testCreateChecklistCleansForbiddenCharactersFromName() { + static::createClientWithCredentials()->request( + 'POST', + '/checklists', + [ + 'json' => $this->getExampleWritePayload( + [ + 'name' => "\n\tAusbildungsziele", + ] + ), + ] + ); + + $this->assertResponseStatusCodeSame(201); + $this->assertJsonContains($this->getExampleReadPayload( + [ + 'name' => 'Ausbildungsziele', + ] + )); + } + + public function testCreateChecklistFromCopySourceValidatesAccess() { + static::createClientWithCredentials(['email' => static::$fixtures['user8memberOnlyInCamp2']->getEmail()])->request( + 'POST', + '/checklists', + ['json' => $this->getExampleWritePayload( + [ + 'camp' => $this->getIriFor('camp2'), + 'copyChecklistSource' => $this->getIriFor('checklist1'), + ] + )] + ); + + // No Access on checklist1 -> BadRequest + $this->assertResponseStatusCodeSame(400); + } + + public function testCreateChecklistFromCopySourceWithinSameCamp() { + static::createClientWithCredentials()->request( + 'POST', + '/checklists', + ['json' => $this->getExampleWritePayload( + [ + 'camp' => $this->getIriFor('camp1'), + 'copyChecklistSource' => $this->getIriFor('checklist1'), + ], + )] + ); + + // Checklist created + $this->assertResponseStatusCodeSame(201); + } + + public function testCreateChecklistFromCopySourceAcrossCamp() { + static::createClientWithCredentials()->request( + 'POST', + '/checklists', + ['json' => $this->getExampleWritePayload( + [ + 'camp' => $this->getIriFor('camp2'), + 'copyChecklistSource' => $this->getIriFor('checklist1'), + ], + )] + ); + + // Checklist created + $this->assertResponseStatusCodeSame(201); + } + + /** + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + */ + public function testCreateResponseStructureMatchesReadResponseStructure() { + $client = static::createClientWithCredentials(); + $client->disableReboot(); + $createResponse = $client->request( + 'POST', + '/checklists', + [ + 'json' => $this->getExampleWritePayload(), + ] + ); + + $this->assertResponseStatusCodeSame(201); + + $createArray = $createResponse->toArray(); + $newItemLink = $createArray['_links']['self']['href']; + $getItemResponse = $client->request('GET', $newItemLink); + + assertThat($createArray, CompatibleHalResponse::isHalCompatibleWith($getItemResponse->toArray())); + } + + public function getExampleWritePayload($attributes = [], $except = []) { + return $this->getExamplePayload( + Checklist::class, + Post::class, + array_merge([ + 'copyChecklistSource' => null, + 'camp' => $this->getIriFor('camp1'), + ], $attributes), + [], + $except + ); + } + + public function getExampleReadPayload($attributes = [], $except = []) { + return $this->getExamplePayload( + Checklist::class, + Get::class, + $attributes, + ['camp', 'preferredContentTypes'], + $except + ); + } +} diff --git a/api/tests/Api/Checklists/DeleteChecklistTest.php b/api/tests/Api/Checklists/DeleteChecklistTest.php new file mode 100644 index 0000000000..f2033769e3 --- /dev/null +++ b/api/tests/Api/Checklists/DeleteChecklistTest.php @@ -0,0 +1,87 @@ +request('DELETE', '/checklists/'.$checklist->getId()); + $this->assertResponseStatusCodeSame(401); + $this->assertJsonContains([ + 'code' => 401, + 'message' => 'JWT Token not found', + ]); + } + + public function testDeleteChecklistIsDeniedForUnrelatedUser() { + $Checklist = static::getFixture('checklist2WithNoItems'); + static::createClientWithCredentials(['email' => static::$fixtures['user4unrelated']->getEmail()]) + ->request('DELETE', '/checklists/'.$Checklist->getId()) + ; + + $this->assertResponseStatusCodeSame(404); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Not Found', + ]); + } + + public function testDeleteChecklistIsDeniedForInactiveCollaborator() { + $Checklist = static::getFixture('checklist2WithNoItems'); + static::createClientWithCredentials(['email' => static::$fixtures['user5inactive']->getEmail()]) + ->request('DELETE', '/checklists/'.$Checklist->getId()) + ; + + $this->assertResponseStatusCodeSame(404); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Not Found', + ]); + } + + public function testDeleteChecklistIsDeniedForGuest() { + $Checklist = static::getFixture('checklist2WithNoItems'); + static::createClientWithCredentials(['email' => static::$fixtures['user3guest']->getEmail()]) + ->request('DELETE', '/checklists/'.$Checklist->getId()) + ; + + $this->assertResponseStatusCodeSame(403); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Access Denied.', + ]); + } + + public function testDeleteChecklistIsAllowedForMember() { + $Checklist = static::getFixture('checklist2WithNoItems'); + static::createClientWithCredentials(['email' => static::$fixtures['user2member']->getEmail()]) + ->request('DELETE', '/checklists/'.$Checklist->getId()) + ; + $this->assertResponseStatusCodeSame(204); + $this->assertNull($this->getEntityManager()->getRepository(Checklist::class)->find($Checklist->getId())); + } + + public function testDeleteChecklistIsAllowedForManager() { + $Checklist = static::getFixture('checklist2WithNoItems'); + static::createClientWithCredentials()->request('DELETE', '/checklists/'.$Checklist->getId()); + $this->assertResponseStatusCodeSame(204); + $this->assertNull($this->getEntityManager()->getRepository(Checklist::class)->find($Checklist->getId())); + } + + public function testDeleteChecklistFromCampPrototypeIsDeniedForUnrelatedUser() { + $Checklist = static::getFixture('checklist1campPrototype'); + static::createClientWithCredentials()->request('DELETE', '/checklists/'.$Checklist->getId()); + + $this->assertResponseStatusCodeSame(403); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Access Denied.', + ]); + } +} diff --git a/api/tests/Api/Checklists/ListChecklistTest.php b/api/tests/Api/Checklists/ListChecklistTest.php new file mode 100644 index 0000000000..ef75a68b01 --- /dev/null +++ b/api/tests/Api/Checklists/ListChecklistTest.php @@ -0,0 +1,125 @@ +request('GET', '/checklists'); + $this->assertResponseStatusCodeSame(401); + $this->assertJsonContains([ + 'code' => 401, + 'message' => 'JWT Token not found', + ]); + } + + public function testListChecklistsIsAllowedForLoggedInUserButFiltered() { + // precondition: There is a checklist that the user doesn't have access to + $this->assertNotEmpty(static::$fixtures['checklist1campUnrelated']); + + $response = static::createClientWithCredentials()->request('GET', '/checklists'); + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'totalItems' => 4, + '_links' => [ + 'items' => [], + ], + '_embedded' => [ + 'items' => [], + ], + ]); + $this->assertEqualsCanonicalizing([ + ['href' => $this->getIriFor('checklist1')], + ['href' => $this->getIriFor('checklist2WithNoItems')], + ['href' => $this->getIriFor('checklist1camp2')], + ['href' => $this->getIriFor('checklist1campPrototype')], + ], $response->toArray()['_links']['items']); + } + + public function testListChecklistsFilteredByCampIsAllowedForCollaborator() { + $camp = static::getFixture('camp1'); + $response = static::createClientWithCredentials()->request('GET', '/checklists?camp=%2Fcamps%2F'.$camp->getId()); + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'totalItems' => 2, + '_links' => [ + 'items' => [], + ], + '_embedded' => [ + 'items' => [], + ], + ]); + $this->assertEqualsCanonicalizing([ + ['href' => $this->getIriFor('checklist1')], + ['href' => $this->getIriFor('checklist2WithNoItems')], + ], $response->toArray()['_links']['items']); + } + + public function testListChecklistsFilteredByCampIsDeniedForUnrelatedUser() { + $camp = static::getFixture('camp1'); + $response = static::createClientWithCredentials(['email' => static::$fixtures['user4unrelated']->getEmail()]) + ->request('GET', '/checklists?camp=%2Fcamps%2F'.$camp->getId()) + ; + + $this->assertResponseStatusCodeSame(200); + + $this->assertJsonContains(['totalItems' => 0]); + $this->assertArrayNotHasKey('items', $response->toArray()['_links']); + } + + public function testListChecklistsFilteredByCampIsDeniedForInactiveCollaborator() { + $camp = static::getFixture('camp1'); + $response = static::createClientWithCredentials(['email' => static::$fixtures['user5inactive']->getEmail()]) + ->request('GET', '/checklists?camp=%2Fcamps%2F'.$camp->getId()) + ; + + $this->assertResponseStatusCodeSame(200); + + $this->assertJsonContains(['totalItems' => 0]); + $this->assertArrayNotHasKey('items', $response->toArray()['_links']); + } + + public function testListChecklistsFilteredByCampPrototypeIsAllowedForUnrelatedUser() { + $camp = static::getFixture('campPrototype'); + $response = static::createClientWithCredentials()->request('GET', '/checklists?camp=%2Fcamps%2F'.$camp->getId()); + + $this->assertResponseStatusCodeSame(200); + + $this->assertJsonContains(['totalItems' => 1]); + $this->assertEqualsCanonicalizing([ + ['href' => $this->getIriFor('checklist1campPrototype')], + ], $response->toArray()['_links']['items']); + } + + public function testListChecklistsAsCampSubresourceIsAllowedForCollaborator() { + $camp = static::getFixture('camp1'); + $response = static::createClientWithCredentials()->request('GET', '/camps/'.$camp->getId().'/checklists'); + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'totalItems' => 2, + '_links' => [ + 'items' => [], + ], + '_embedded' => [ + 'items' => [], + ], + ]); + $this->assertEqualsCanonicalizing([ + ['href' => $this->getIriFor('checklist1')], + ['href' => $this->getIriFor('checklist2WithNoItems')], + ], $response->toArray()['_links']['items']); + } + + public function testListChecklistsAsCampSubresourceIsDeniedForUnrelatedUser() { + $camp = static::getFixture('camp1'); + static::createClientWithCredentials(['email' => static::$fixtures['user4unrelated']->getEmail()]) + ->request('GET', '/camps/'.$camp->getId().'/checklists') + ; + + $this->assertResponseStatusCodeSame(404); + } +} diff --git a/api/tests/Api/Checklists/ReadChecklistTest.php b/api/tests/Api/Checklists/ReadChecklistTest.php new file mode 100644 index 0000000000..1857746c1c --- /dev/null +++ b/api/tests/Api/Checklists/ReadChecklistTest.php @@ -0,0 +1,108 @@ +request('GET', '/checklists/'.$checklist->getId()); + $this->assertResponseStatusCodeSame(401); + $this->assertJsonContains([ + 'code' => 401, + 'message' => 'JWT Token not found', + ]); + } + + public function testGetSingleChecklistIsDeniedForUnrelatedUser() { + /** @var Checklist $checklist */ + $checklist = static::getFixture('checklist1'); + static::createClientWithCredentials(['email' => static::$fixtures['user4unrelated']->getEmail()]) + ->request('GET', '/checklists/'.$checklist->getId()) + ; + $this->assertResponseStatusCodeSame(404); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Not Found', + ]); + } + + public function testGetSingleChecklistIsDeniedForInactiveCollaborator() { + /** @var Checklist $checklist */ + $checklist = static::getFixture('checklist1'); + static::createClientWithCredentials(['email' => static::$fixtures['user5inactive']->getEmail()]) + ->request('GET', '/checklists/'.$checklist->getId()) + ; + $this->assertResponseStatusCodeSame(404); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Not Found', + ]); + } + + public function testGetSingleChecklistIsAllowedForGuest() { + /** @var Checklist $checklist */ + $checklist = static::getFixture('checklist1'); + static::createClientWithCredentials(['email' => static::$fixtures['user3guest']->getEmail()]) + ->request('GET', '/checklists/'.$checklist->getId()) + ; + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'id' => $checklist->getId(), + 'name' => $checklist->name, + '_links' => [ + 'camp' => ['href' => $this->getIriFor('camp1')], + ], + ]); + } + + public function testGetSingleChecklistIsAllowedForMember() { + /** @var Checklist $checklist */ + $checklist = static::getFixture('checklist1'); + static::createClientWithCredentials(['email' => static::$fixtures['user2member']->getEmail()]) + ->request('GET', '/checklists/'.$checklist->getId()) + ; + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'id' => $checklist->getId(), + 'name' => $checklist->name, + '_links' => [ + 'camp' => ['href' => $this->getIriFor('camp1')], + ], + ]); + } + + public function testGetSingleChecklistIsAllowedForManager() { + /** @var Checklist $checklist */ + $checklist = static::getFixture('checklist1'); + static::createClientWithCredentials()->request('GET', '/checklists/'.$checklist->getId()); + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'id' => $checklist->getId(), + 'name' => $checklist->name, + '_links' => [ + 'camp' => ['href' => $this->getIriFor('camp1')], + ], + ]); + } + + public function testGetSingleChecklistFromCampPrototypeIsAllowedForUnrelatedUser() { + /** @var Checklist $checklist */ + $checklist = static::getFixture('checklist1campPrototype'); + static::createClientWithCredentials()->request('GET', '/checklists/'.$checklist->getId()); + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'id' => $checklist->getId(), + 'name' => $checklist->name, + '_links' => [ + 'camp' => ['href' => $this->getIriFor('campPrototype')], + ], + ]); + } +} diff --git a/api/tests/Api/Checklists/UpdateChecklistTest.php b/api/tests/Api/Checklists/UpdateChecklistTest.php new file mode 100644 index 0000000000..3006e3a38e --- /dev/null +++ b/api/tests/Api/Checklists/UpdateChecklistTest.php @@ -0,0 +1,220 @@ +request('PATCH', '/checklists/'.$checklist->getId(), ['json' => [ + 'name' => 'ChecklistName', + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]); + $this->assertResponseStatusCodeSame(401); + $this->assertJsonContains([ + 'code' => 401, + 'message' => 'JWT Token not found', + ]); + } + + public function testPatchChecklistIsDeniedForUnrelatedUser() { + $checklist = static::getFixture('checklist1'); + static::createClientWithCredentials(['email' => static::$fixtures['user4unrelated']->getEmail()]) + ->request('PATCH', '/checklists/'.$checklist->getId(), ['json' => [ + 'name' => 'ChecklistName', + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]) + ; + $this->assertResponseStatusCodeSame(404); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Not Found', + ]); + } + + public function testPatchChecklistIsDeniedForInactiveCollaborator() { + $checklist = static::getFixture('checklist1'); + static::createClientWithCredentials(['email' => static::$fixtures['user5inactive']->getEmail()]) + ->request('PATCH', '/checklists/'.$checklist->getId(), ['json' => [ + 'name' => 'ChecklistName', + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]) + ; + $this->assertResponseStatusCodeSame(404); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Not Found', + ]); + } + + public function testPatchChecklistIsDeniedForGuest() { + $checklist = static::getFixture('checklist1'); + static::createClientWithCredentials(['email' => static::$fixtures['user3guest']->getEmail()]) + ->request('PATCH', '/checklists/'.$checklist->getId(), ['json' => [ + 'name' => 'ChecklistName', + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]) + ; + $this->assertResponseStatusCodeSame(403); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Access Denied.', + ]); + } + + public function testPatchChecklistIsAllowedForMember() { + $checklist = static::getFixture('checklist1'); + $response = static::createClientWithCredentials(['email' => static::$fixtures['user2member']->getEmail()]) + ->request('PATCH', '/checklists/'.$checklist->getId(), ['json' => [ + 'name' => 'ChecklistName', + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]) + ; + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'name' => 'ChecklistName', + ]); + } + + public function testPatchChecklistIsAllowedForManager() { + $checklist = static::getFixture('checklist1'); + $response = static::createClientWithCredentials()->request('PATCH', '/checklists/'.$checklist->getId(), ['json' => [ + 'name' => 'ChecklistName', + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]); + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'name' => 'ChecklistName', + ]); + } + + public function testPatchChecklistInCampPrototypeIsDeniedForUnrelatedUser() { + $checklist = static::getFixture('checklist1campPrototype'); + $response = static::createClientWithCredentials()->request('PATCH', '/checklists/'.$checklist->getId(), ['json' => [ + 'name' => 'ChecklistName', + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]); + $this->assertResponseStatusCodeSame(403); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Access Denied.', + ]); + } + + public function testPatchChecklistDisallowsChangingCamp() { + $checklist = static::getFixture('checklist1'); + static::createClientWithCredentials()->request('PATCH', '/checklists/'.$checklist->getId(), ['json' => [ + 'camp' => $this->getIriFor('camp2'), + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]); + + $this->assertResponseStatusCodeSame(400); + $this->assertJsonContains([ + 'detail' => 'Extra attributes are not allowed ("camp" is unknown).', + ]); + } + + public function testPatchChecklistValidatesNullName() { + $checklist = static::getFixture('checklist1'); + static::createClientWithCredentials()->request( + 'PATCH', + '/checklists/'.$checklist->getId(), + [ + 'json' => [ + 'name' => null, + ], + 'headers' => ['Content-Type' => 'application/merge-patch+json'], + ] + ); + + $this->assertResponseStatusCodeSame(400); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'The type of the "name" attribute must be "string", "NULL" given.', + ]); + } + + public function testPatchChecklistValidatesBlankName() { + $checklist = static::getFixture('checklist1'); + static::createClientWithCredentials()->request( + 'PATCH', + '/checklists/'.$checklist->getId(), + [ + 'json' => [ + 'name' => ' ', + ], + 'headers' => ['Content-Type' => 'application/merge-patch+json'], + ] + ); + + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'violations' => [ + [ + 'propertyPath' => 'name', + 'message' => 'This value should not be blank.', + ], + ], + ]); + } + + public function testPatchChecklistValidatesTooLongName() { + $checklist = static::getFixture('checklist1'); + static::createClientWithCredentials()->request( + 'PATCH', + '/checklists/'.$checklist->getId(), + [ + 'json' => [ + 'name' => str_repeat('l', 33), + ], + 'headers' => ['Content-Type' => 'application/merge-patch+json'], + ] + ); + + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'violations' => [ + [ + 'propertyPath' => 'name', + 'message' => 'This value is too long. It should have 32 characters or less.', + ], + ], + ]); + } + + public function testPatchChecklistTrimsName() { + $checklist = static::getFixture('checklist1'); + static::createClientWithCredentials()->request( + 'PATCH', + '/checklists/'.$checklist->getId(), + [ + 'json' => [ + 'name' => " \t ChecklistName\t ", + ], + 'headers' => ['Content-Type' => 'application/merge-patch+json'], ] + ); + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains( + [ + 'name' => 'ChecklistName', + ] + ); + } + + public function testPatchChecklistCleansForbiddenCharactersFromName() { + $checklist = static::getFixture('checklist1'); + $client = static::createClientWithCredentials(); + $client->disableReboot(); + $client->request( + 'PATCH', + '/checklists/'.$checklist->getId(), + [ + 'json' => [ + 'name' => "ChecklistName\n\t", + ], + 'headers' => ['Content-Type' => 'application/merge-patch+json'], ] + ); + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains( + [ + 'name' => 'ChecklistName', + ] + ); + } +} From 27a811819d12eae35af64b969208c6101e22fbe3 Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Sat, 15 Jun 2024 20:34:05 +0200 Subject: [PATCH 05/69] Add ChecklistItem --- api/fixtures/checklistItems.yml | 23 + .../performance_test/checklistItems.yml | 10 + .../schema/Version20240615180024.php | 36 + api/src/Entity/Checklist.php | 51 + api/src/Entity/ChecklistItem.php | 181 +++ .../Repository/ChecklistItemRepository.php | 37 + .../AssertBelongsToChecklist.php | 10 + .../AssertBelongsToChecklistValidator.php | 39 + .../Validator/ChecklistItem/AssertNoLoop.php | 10 + .../ChecklistItem/AssertNoLoopValidator.php | 46 + .../Api/SnapshotTests/ReadItemFixtureMap.php | 1 + ...ture with data set checklist_items__1.json | 110 ++ ...Structure with data set checklists__1.json | 12 + ...ture with data set checklist_items__1.json | 15 + ...Structure with data set checklists__1.json | 3 + ...est__testOpenApiSpecMatchesSnapshot__1.yml | 1024 +++++++++++++++-- ...t__testRootEndpointMatchesSnapshot__1.json | 4 + ...manceDidNotChangeForStableEndpoints__1.yml | 2 + 18 files changed, 1489 insertions(+), 125 deletions(-) create mode 100644 api/fixtures/checklistItems.yml create mode 100644 api/fixtures/performance_test/checklistItems.yml create mode 100644 api/migrations/schema/Version20240615180024.php create mode 100644 api/src/Entity/ChecklistItem.php create mode 100644 api/src/Repository/ChecklistItemRepository.php create mode 100644 api/src/Validator/ChecklistItem/AssertBelongsToChecklist.php create mode 100644 api/src/Validator/ChecklistItem/AssertBelongsToChecklistValidator.php create mode 100644 api/src/Validator/ChecklistItem/AssertNoLoop.php create mode 100644 api/src/Validator/ChecklistItem/AssertNoLoopValidator.php create mode 100644 api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set checklist_items__1.json create mode 100644 api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set checklist_items__1.json diff --git a/api/fixtures/checklistItems.yml b/api/fixtures/checklistItems.yml new file mode 100644 index 0000000000..3892d00a43 --- /dev/null +++ b/api/fixtures/checklistItems.yml @@ -0,0 +1,23 @@ +App\Entity\ChecklistItem: + checklistItem1_1_1: + checklist: '@checklist1' + text: 'Camp1_List1_Item1' + checklistItem1_1_2: + checklist: '@checklist1' + text: 'Camp1_List1_Item2' + checklistItem1_1_2_3: + checklist: '@checklist1' + parent: '@checklistItem1_1_2' + text: 'Camp1_List1_Item2_Item3' +# checklist2WithNoItems: +# checklist: '@checklist2WithNoItems' +# text: 'Camp1_List2_Item1' + checklistItem2_1_1: + checklist: '@checklist1camp2' + text: 'Camp2_List1_Item1' + checklistItemUnrelated_1_1: + checklist: '@checklist1campUnrelated' + text: 'CampUnrelated_List1_Item1' + checklistItemPrototype_1_1: + checklist: '@checklist1campPrototype' + text: 'CampPrototype_List1_Item1' diff --git a/api/fixtures/performance_test/checklistItems.yml b/api/fixtures/performance_test/checklistItems.yml new file mode 100644 index 0000000000..ea01fe011d --- /dev/null +++ b/api/fixtures/performance_test/checklistItems.yml @@ -0,0 +1,10 @@ +App\Entity\ChecklistItem: + additional_checklistItem1_{1..400}: + checklist: '@additional_checklist1_' + text: 'Item_' + additional_checklistItem2_{1..400}: + checklist: '@additional_checklist2_' + text: 'Item_' + additional_checklistItem_camp1_{1..12}: + camp: '@additional_checklist_camp1_1' + text: 'Item_' diff --git a/api/migrations/schema/Version20240615180024.php b/api/migrations/schema/Version20240615180024.php new file mode 100644 index 0000000000..0b3570cb64 --- /dev/null +++ b/api/migrations/schema/Version20240615180024.php @@ -0,0 +1,36 @@ +addSql('CREATE TABLE checklist_item (id VARCHAR(16) NOT NULL, createTime TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updateTime TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, text TEXT NOT NULL, position INT NOT NULL, checklistId VARCHAR(16) NOT NULL, parentId VARCHAR(16) DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_99EB20F9BA23A13 ON checklist_item (checklistId)'); + $this->addSql('CREATE INDEX IDX_99EB20F910EE4CEE ON checklist_item (parentId)'); + $this->addSql('CREATE INDEX IDX_99EB20F99D468A55 ON checklist_item (createTime)'); + $this->addSql('CREATE INDEX IDX_99EB20F955AA53E2 ON checklist_item (updateTime)'); + $this->addSql('ALTER TABLE checklist_item ADD CONSTRAINT FK_99EB20F9BA23A13 FOREIGN KEY (checklistId) REFERENCES checklist (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE checklist_item ADD CONSTRAINT FK_99EB20F910EE4CEE FOREIGN KEY (parentId) REFERENCES checklist_item (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE SCHEMA public'); + $this->addSql('ALTER TABLE checklist_item DROP CONSTRAINT FK_99EB20F9BA23A13'); + $this->addSql('ALTER TABLE checklist_item DROP CONSTRAINT FK_99EB20F910EE4CEE'); + $this->addSql('DROP TABLE checklist_item'); + } +} diff --git a/api/src/Entity/Checklist.php b/api/src/Entity/Checklist.php index 5b839f2ff5..9a5ba7fd2c 100644 --- a/api/src/Entity/Checklist.php +++ b/api/src/Entity/Checklist.php @@ -16,6 +16,8 @@ use App\Repository\ChecklistRepository; use App\State\ChecklistCreateProcessor; use App\Util\EntityMap; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -82,6 +84,14 @@ class Checklist extends BaseEntity implements BelongsToCampInterface, CopyFromPr #[Groups(['create'])] public ?Checklist $copyChecklistSource; + /** + * All ChecklistItems that belong to this Checklist. + */ + #[ApiProperty(writable: false, example: '["/checklist_items/1a2b3c4d"]')] + #[Groups(['read'])] + #[ORM\OneToMany(targetEntity: ChecklistItem::class, mappedBy: 'checklist', cascade: ['persist'])] + public Collection $checklistItems; + /** * The human readable name of the checklist. */ @@ -96,12 +106,40 @@ class Checklist extends BaseEntity implements BelongsToCampInterface, CopyFromPr public function __construct() { parent::__construct(); + $this->checklistItems = new ArrayCollection(); } public function getCamp(): ?Camp { return $this->camp; } + /** + * @return ChecklistItem[] + */ + public function getChecklistItems(): array { + return $this->checklistItems->getValues(); + } + + public function addChecklistItem(ChecklistItem $checklistItem): self { + if (!$this->checklistItems->contains($checklistItem)) { + $this->checklistItems[] = $checklistItem; + $checklistItem->checklist = $this; + } + + return $this; + } + + public function removeChecklistItem(ChecklistItem $checklistItem): self { + if ($this->checklistItems->removeElement($checklistItem)) { + // set the owning side to null (unless already changed) + if ($checklistItem->checklist === $this) { + $checklistItem->checklist = null; + } + } + + return $this; + } + /** * @param Checklist $prototype * @param EntityMap $entityMap @@ -109,6 +147,19 @@ public function getCamp(): ?Camp { public function copyFromPrototype($prototype, $entityMap): void { $entityMap->add($prototype, $this); + // copy Checklist base properties $this->name = $prototype->name; + + // deep copy ChecklistItems + foreach ($prototype->getChecklistItems() as $checklistItemPrototype) { + // deep copy root ChecklistItems + // skip non-root ChecklistItems as these are copyed by there parent + if (null == $checklistItemPrototype->parent) { + $checklistItem = new ChecklistItem(); + $this->addChecklistItem($checklistItem); + + $checklistItem->copyFromPrototype($checklistItemPrototype, $entityMap); + } + } } } diff --git a/api/src/Entity/ChecklistItem.php b/api/src/Entity/ChecklistItem.php new file mode 100644 index 0000000000..aee087b9a6 --- /dev/null +++ b/api/src/Entity/ChecklistItem.php @@ -0,0 +1,181 @@ + ['delete']] + ), + new GetCollection( + security: 'is_authenticated()' + ), + new Post( + denormalizationContext: ['groups' => ['write', 'create']], + securityPostDenormalize: 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)' + ), + new GetCollection( + name: 'BelongsToChecklist_App\Entity\ChecklistItem_get_collection', + uriTemplate: self::CHECKLIST_SUBRESOURCE_URI_TEMPLATE, + uriVariables: [ + 'checklistId' => new Link( + fromClass: Checklist::class, + toProperty: 'checklist', + security: 'is_granted("CAMP_COLLABORATOR", checklist) or is_granted("CAMP_IS_PROTOTYPE", checklist)' + ), + ], + ), + ], + denormalizationContext: ['groups' => ['write']], + normalizationContext: ['groups' => ['read']], + order: ['checklist.id', 'id'], +)] +#[ApiFilter(filterClass: SearchFilter::class, properties: ['checklist'])] +#[ORM\Entity(repositoryClass: ChecklistItemRepository::class)] +class ChecklistItem extends BaseEntity implements BelongsToCampInterface, CopyFromPrototypeInterface { + public const CHECKLIST_SUBRESOURCE_URI_TEMPLATE = '/checklists/{checklistId}/checklist_items.{_format}'; + + /** + * The Checklist this Item belongs to. + */ + #[ApiProperty(example: '/checklists/1a2b3c4d')] + #[Groups(['read', 'create'])] + #[ORM\ManyToOne(targetEntity: Checklist::class, inversedBy: 'checklistItems')] + #[ORM\JoinColumn(nullable: false, onDelete: 'cascade')] + public ?Checklist $checklist = null; + + /** + * The parent to which ChecklistItem item belongs. Is null in case this ChecklistItem is the + * root of a ChecklistItem tree. For non-root ChecklistItems, the parent can be changed, as long + * as the new parent is in the same checklist as the old one. + */ + #[AssertBelongsToChecklist(groups: ['update'])] + #[AssertNoLoop(groups: ['update'])] + #[ApiProperty(example: '/checklist_items/1a2b3c4d')] + #[Gedmo\SortableGroup] + #[Groups(['read', 'write'])] + #[ORM\ManyToOne(targetEntity: ChecklistItem::class, inversedBy: 'children')] + #[ORM\JoinColumn(onDelete: 'CASCADE')] + public ?ChecklistItem $parent = null; + + /** + * All ChecklistItems that are direct children of this ChecklistItem. + */ + #[ApiProperty(writable: false, example: '["/checklist_items/1a2b3c4d"]')] + #[Groups(['read'])] + #[ORM\OneToMany(targetEntity: ChecklistItem::class, mappedBy: 'parent', cascade: ['persist'])] + public Collection $children; + + /** + * The human readable text of the checklist-item. + */ + #[ApiProperty(example: 'Pfaditechnick')] + #[Groups(['read', 'write'])] + #[InputFilter\Trim] + #[InputFilter\CleanText] + #[Assert\NotBlank] + #[Assert\Length(max: 64)] + #[ORM\Column(type: 'text')] + public ?string $text = null; + + /** + * A whole number used for ordering multiple checklist items that are in the same parent. + * The API does not guarantee the uniqueness of parent+position. + */ + #[ApiProperty(example: '0')] + #[Gedmo\SortablePosition] + #[Groups(['read', 'write'])] + #[ORM\Column(type: 'integer', nullable: false)] + public int $position = -1; + + public function __construct() { + parent::__construct(); + $this->children = new ArrayCollection(); + } + + #[ApiProperty(readable: false)] + public function getCamp(): ?Camp { + return $this->checklist?->getCamp(); + } + + /** + * @return ChecklistItem[] + */ + public function getChildren(): array { + return $this->children->getValues(); + } + + public function addChild(self $child): self { + if (!$this->children->contains($child)) { + $this->children[] = $child; + $child->parent = $this; + } + + return $this; + } + + public function removeChild(self $child): self { + if ($this->children->removeElement($child)) { + // set the owning side to null (unless already changed) + if ($child->parent === $this) { + $child->parent = null; + } + } + + return $this; + } + + /** + * @param ChecklistItem $prototype + * @param EntityMap $entityMap + */ + public function copyFromPrototype($prototype, $entityMap): void { + $entityMap->add($prototype, $this); + + // copy ChecklistItem base properties + $this->text = $prototype->text; + + // deep copy ChecklistItems + foreach ($prototype->getChildren() as $childPrototype) { + $child = new ChecklistItem(); + $this->addChild($child); + $this->checklist->addChecklistItem($child); + + $child->copyFromPrototype($childPrototype, $entityMap); + } + } +} diff --git a/api/src/Repository/ChecklistItemRepository.php b/api/src/Repository/ChecklistItemRepository.php new file mode 100644 index 0000000000..b7e45f2d10 --- /dev/null +++ b/api/src/Repository/ChecklistItemRepository.php @@ -0,0 +1,37 @@ +getEntityManager()->createQueryBuilder(); + $checklistQry->select('c'); + $checklistQry->from(Checklist::class, 'c'); + $checklistQry->join(UserCamp::class, 'uc', Join::WITH, 'c.camp = uc.camp'); + $checklistQry->where('uc.user = :current_user'); + + $rootAlias = $queryBuilder->getRootAliases()[0]; + $queryBuilder->andWhere($queryBuilder->expr()->in("{$rootAlias}.checklist", $checklistQry->getDQL())); + $queryBuilder->setParameter('current_user', $user); + } +} diff --git a/api/src/Validator/ChecklistItem/AssertBelongsToChecklist.php b/api/src/Validator/ChecklistItem/AssertBelongsToChecklist.php new file mode 100644 index 0000000000..ceb67ccc17 --- /dev/null +++ b/api/src/Validator/ChecklistItem/AssertBelongsToChecklist.php @@ -0,0 +1,10 @@ +context->getObject(); + if (!$object instanceof ChecklistItem) { + throw new UnexpectedValueException($object, ChecklistItem::class); + } + + if ($value->checklist->getId() !== $object->checklist->getId()) { + $this->context->buildViolation($constraint->message) + ->addViolation() + ; + } + } +} diff --git a/api/src/Validator/ChecklistItem/AssertNoLoop.php b/api/src/Validator/ChecklistItem/AssertNoLoop.php new file mode 100644 index 0000000000..f60e2bba67 --- /dev/null +++ b/api/src/Validator/ChecklistItem/AssertNoLoop.php @@ -0,0 +1,10 @@ +context->getObject(); + if (!$object instanceof ChecklistItem) { + throw new UnexpectedValueException($object, ChecklistItem::class); + } + + /** @var ChecklistItem $parent */ + $parent = $value; + + // $seen keeps track of all parents that we have visited. This is for a safety + // bailout mechanism to avoid an infinite loop in case there is flawed data in the DB + $seen = []; + + while (null !== $parent && !in_array($parent->getId(), $seen)) { + if ($parent->getId() === $object->getId()) { + $this->context->buildViolation($constraint->message) + ->addViolation() + ; + + return; + } + + $seen[] = $parent->getId(); + $parent = $parent->parent; + } + } +} diff --git a/api/tests/Api/SnapshotTests/ReadItemFixtureMap.php b/api/tests/Api/SnapshotTests/ReadItemFixtureMap.php index f434e34a8a..a734aa4518 100644 --- a/api/tests/Api/SnapshotTests/ReadItemFixtureMap.php +++ b/api/tests/Api/SnapshotTests/ReadItemFixtureMap.php @@ -12,6 +12,7 @@ public static function get(string $collectionEndpoint, array $fixtures): mixed { '/camps' => $fixtures['camp1'], '/categories' => $fixtures['category1'], '/checklists' => $fixtures['checklist1'], + '/checklist_items' => $fixtures['checklistItem1_1_1'], '/content_node/column_layouts' => $fixtures['columnLayout2'], '/content_node/responsive_layouts' => $fixtures['responsiveLayout1'], '/content_types' => $fixtures['contentTypeSafetyConcept'], diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set checklist_items__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set checklist_items__1.json new file mode 100644 index 0000000000..82a195c448 --- /dev/null +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set checklist_items__1.json @@ -0,0 +1,110 @@ +{ + "_embedded": { + "items": [ + { + "_links": { + "checklist": { + "href": "escaped_value" + }, + "children": [], + "parent": "escaped_value", + "self": { + "href": "escaped_value" + } + }, + "id": "escaped_value", + "position": "escaped_value", + "text": "escaped_value" + }, + { + "_links": { + "checklist": { + "href": "escaped_value" + }, + "children": [], + "parent": "escaped_value", + "self": { + "href": "escaped_value" + } + }, + "id": "escaped_value", + "position": "escaped_value", + "text": "escaped_value" + }, + { + "_links": { + "checklist": { + "href": "escaped_value" + }, + "children": [], + "parent": "escaped_value", + "self": { + "href": "escaped_value" + } + }, + "id": "escaped_value", + "position": "escaped_value", + "text": "escaped_value" + }, + { + "_links": { + "checklist": { + "href": "escaped_value" + }, + "children": [], + "parent": { + "href": "escaped_value" + }, + "self": { + "href": "escaped_value" + } + }, + "id": "escaped_value", + "position": "escaped_value", + "text": "escaped_value" + }, + { + "_links": { + "checklist": { + "href": "escaped_value" + }, + "children": [ + { + "href": "escaped_value" + } + ], + "parent": "escaped_value", + "self": { + "href": "escaped_value" + } + }, + "id": "escaped_value", + "position": "escaped_value", + "text": "escaped_value" + } + ] + }, + "_links": { + "items": [ + { + "href": "escaped_value" + }, + { + "href": "escaped_value" + }, + { + "href": "escaped_value" + }, + { + "href": "escaped_value" + }, + { + "href": "escaped_value" + } + ], + "self": { + "href": "escaped_value" + } + }, + "totalItems": "escaped_value" +} diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set checklists__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set checklists__1.json index 16ae186f1b..feed0e6431 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set checklists__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set checklists__1.json @@ -6,6 +6,9 @@ "camp": { "href": "escaped_value" }, + "checklistItems": { + "href": "escaped_value" + }, "self": { "href": "escaped_value" } @@ -18,6 +21,9 @@ "camp": { "href": "escaped_value" }, + "checklistItems": { + "href": "escaped_value" + }, "self": { "href": "escaped_value" } @@ -30,6 +36,9 @@ "camp": { "href": "escaped_value" }, + "checklistItems": { + "href": "escaped_value" + }, "self": { "href": "escaped_value" } @@ -42,6 +51,9 @@ "camp": { "href": "escaped_value" }, + "checklistItems": { + "href": "escaped_value" + }, "self": { "href": "escaped_value" } diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set checklist_items__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set checklist_items__1.json new file mode 100644 index 0000000000..8a41227692 --- /dev/null +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set checklist_items__1.json @@ -0,0 +1,15 @@ +{ + "_links": { + "checklist": { + "href": "escaped_value" + }, + "children": [], + "parent": "escaped_value", + "self": { + "href": "escaped_value" + } + }, + "id": "escaped_value", + "position": "escaped_value", + "text": "escaped_value" +} diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set checklists__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set checklists__1.json index 39e7e3d07f..328e6ab533 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set checklists__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set checklists__1.json @@ -3,6 +3,9 @@ "camp": { "href": "escaped_value" }, + "checklistItems": { + "href": "escaped_value" + }, "self": { "href": "escaped_value" } diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml index 52c7add8a6..70dbc0ebc5 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml @@ -7623,6 +7623,15 @@ components: example: /camps/1a2b3c4d format: iri-reference type: string + checklistItems: + description: 'All ChecklistItems that belong to this Checklist.' + example: '["/checklist_items/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array id: description: 'An internal, unique, randomly generated identifier of this entity.' example: 1a2b3c4d @@ -7636,6 +7645,7 @@ components: type: string required: - camp + - checklistItems - name type: object Checklist-write: @@ -7709,8 +7719,11 @@ components: properties: camp: properties: { data: { properties: { id: { format: iri-reference, type: string }, type: { type: string } }, type: object } } + checklistItems: + properties: { data: { items: { properties: { id: { format: iri-reference, type: string }, type: { type: string } }, type: object }, type: array } } required: - camp + - checklistItems type: object type: type: string @@ -7726,6 +7739,8 @@ components: anyOf: - $ref: '#/components/schemas/Checklist.jsonapi' + - + $ref: '#/components/schemas/Checklist.jsonapi' readOnly: true type: array type: object @@ -7749,6 +7764,15 @@ components: example: /camps/1a2b3c4d format: iri-reference type: string + checklistItems: + description: 'All ChecklistItems that belong to this Checklist.' + example: '["/checklist_items/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array id: description: 'An internal, unique, randomly generated identifier of this entity.' example: 1a2b3c4d @@ -7762,6 +7786,7 @@ components: type: string required: - camp + - checklistItems - name type: object Checklist.jsonhal-write_create: @@ -7834,6 +7859,15 @@ components: example: /camps/1a2b3c4d format: iri-reference type: string + checklistItems: + description: 'All ChecklistItems that belong to this Checklist.' + example: '["/checklist_items/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array id: description: 'An internal, unique, randomly generated identifier of this entity.' example: 1a2b3c4d @@ -7847,6 +7881,7 @@ components: type: string required: - camp + - checklistItems - name type: object Checklist.jsonld-write_create: @@ -7873,8 +7908,408 @@ components: maxLength: 32 type: string required: - - camp - - name + - camp + - name + type: object + ChecklistItem-read: + deprecated: false + description: |- + A ChecklistItem + A Checklist contains a Tree-Structure of ChecklistItems. + properties: + checklist: + description: 'The Checklist this Item belongs to.' + example: /checklists/1a2b3c4d + format: iri-reference + type: string + children: + description: 'All ChecklistItems that are direct children of this ChecklistItem.' + example: '["/checklist_items/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array + id: + description: 'An internal, unique, randomly generated identifier of this entity.' + example: 1a2b3c4d + maxLength: 16 + readOnly: true + type: string + parent: + description: |- + The parent to which ChecklistItem item belongs. Is null in case this ChecklistItem is the + root of a ChecklistItem tree. For non-root ChecklistItems, the parent can be changed, as long + as the new parent is in the same checklist as the old one. + example: /checklist_items/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + position: + default: -1 + description: 'A whole number used for ordering multiple checklist items that are in the same parent.' + example: -1 + type: integer + text: + description: 'The human readable text of the checklist-item.' + example: Pfaditechnick + maxLength: 64 + type: string + required: + - checklist + - children + - position + - text + type: object + ChecklistItem-write: + deprecated: false + description: |- + A ChecklistItem + A Checklist contains a Tree-Structure of ChecklistItems. + properties: + parent: + description: |- + The parent to which ChecklistItem item belongs. Is null in case this ChecklistItem is the + root of a ChecklistItem tree. For non-root ChecklistItems, the parent can be changed, as long + as the new parent is in the same checklist as the old one. + example: /checklist_items/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + position: + default: -1 + description: 'A whole number used for ordering multiple checklist items that are in the same parent.' + example: -1 + type: integer + text: + description: 'The human readable text of the checklist-item.' + example: Pfaditechnick + maxLength: 64 + type: string + required: + - position + - text + type: object + ChecklistItem-write_create: + deprecated: false + description: |- + A ChecklistItem + A Checklist contains a Tree-Structure of ChecklistItems. + properties: + checklist: + description: 'The Checklist this Item belongs to.' + example: /checklists/1a2b3c4d + format: iri-reference + type: string + parent: + description: |- + The parent to which ChecklistItem item belongs. Is null in case this ChecklistItem is the + root of a ChecklistItem tree. For non-root ChecklistItems, the parent can be changed, as long + as the new parent is in the same checklist as the old one. + example: /checklist_items/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + position: + default: -1 + description: 'A whole number used for ordering multiple checklist items that are in the same parent.' + example: -1 + type: integer + text: + description: 'The human readable text of the checklist-item.' + example: Pfaditechnick + maxLength: 64 + type: string + required: + - checklist + - position + - text + type: object + ChecklistItem.jsonapi: + deprecated: false + description: |- + A ChecklistItem + A Checklist contains a Tree-Structure of ChecklistItems. + properties: + data: + properties: + attributes: + properties: + _id: + description: 'An internal, unique, randomly generated identifier of this entity.' + example: 1a2b3c4d + maxLength: 16 + readOnly: true + type: string + position: + default: -1 + description: 'A whole number used for ordering multiple checklist items that are in the same parent.' + example: -1 + type: integer + text: + description: 'The human readable text of the checklist-item.' + example: Pfaditechnick + maxLength: 64 + type: string + required: + - position + - text + type: object + id: + type: string + relationships: + properties: + checklist: + properties: { data: { properties: { id: { format: iri-reference, type: string }, type: { type: string } }, type: object } } + children: + properties: { data: { items: { properties: { id: { format: iri-reference, type: string }, type: { type: string } }, type: object }, type: array } } + parent: + properties: { data: { properties: { id: { format: iri-reference, type: string }, type: { type: string } }, type: object } } + required: + - checklist + - children + type: object + type: + type: string + required: + - id + - type + type: object + included: + description: 'Related resources requested via the "include" query parameter.' + externalDocs: + url: 'https://jsonapi.org/format/#fetching-includes' + items: + anyOf: + - + $ref: '#/components/schemas/ChecklistItem.jsonapi' + - + $ref: '#/components/schemas/ChecklistItem.jsonapi' + - + $ref: '#/components/schemas/ChecklistItem.jsonapi' + readOnly: true + type: array + type: object + ChecklistItem.jsonhal-read: + deprecated: false + description: |- + A ChecklistItem + A Checklist contains a Tree-Structure of ChecklistItems. + properties: + _links: + properties: + self: + properties: + href: + format: iri-reference + type: string + type: object + type: object + checklist: + description: 'The Checklist this Item belongs to.' + example: /checklists/1a2b3c4d + format: iri-reference + type: string + children: + description: 'All ChecklistItems that are direct children of this ChecklistItem.' + example: '["/checklist_items/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array + id: + description: 'An internal, unique, randomly generated identifier of this entity.' + example: 1a2b3c4d + maxLength: 16 + readOnly: true + type: string + parent: + description: |- + The parent to which ChecklistItem item belongs. Is null in case this ChecklistItem is the + root of a ChecklistItem tree. For non-root ChecklistItems, the parent can be changed, as long + as the new parent is in the same checklist as the old one. + example: /checklist_items/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + position: + default: -1 + description: 'A whole number used for ordering multiple checklist items that are in the same parent.' + example: -1 + type: integer + text: + description: 'The human readable text of the checklist-item.' + example: Pfaditechnick + maxLength: 64 + type: string + required: + - checklist + - children + - position + - text + type: object + ChecklistItem.jsonhal-write_create: + deprecated: false + description: |- + A ChecklistItem + A Checklist contains a Tree-Structure of ChecklistItems. + properties: + _links: + properties: + self: + properties: + href: + format: iri-reference + type: string + type: object + type: object + checklist: + description: 'The Checklist this Item belongs to.' + example: /checklists/1a2b3c4d + format: iri-reference + type: string + parent: + description: |- + The parent to which ChecklistItem item belongs. Is null in case this ChecklistItem is the + root of a ChecklistItem tree. For non-root ChecklistItems, the parent can be changed, as long + as the new parent is in the same checklist as the old one. + example: /checklist_items/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + position: + default: -1 + description: 'A whole number used for ordering multiple checklist items that are in the same parent.' + example: -1 + type: integer + text: + description: 'The human readable text of the checklist-item.' + example: Pfaditechnick + maxLength: 64 + type: string + required: + - checklist + - position + - text + type: object + ChecklistItem.jsonld-read: + deprecated: false + description: |- + A ChecklistItem + A Checklist contains a Tree-Structure of ChecklistItems. + properties: + '@context': + oneOf: + - + additionalProperties: true + properties: + '@vocab': + type: string + hydra: + enum: ['http://www.w3.org/ns/hydra/core#'] + type: string + required: + - '@vocab' + - hydra + type: object + - + type: string + readOnly: true + '@id': + readOnly: true + type: string + '@type': + readOnly: true + type: string + checklist: + description: 'The Checklist this Item belongs to.' + example: /checklists/1a2b3c4d + format: iri-reference + type: string + children: + description: 'All ChecklistItems that are direct children of this ChecklistItem.' + example: '["/checklist_items/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array + id: + description: 'An internal, unique, randomly generated identifier of this entity.' + example: 1a2b3c4d + maxLength: 16 + readOnly: true + type: string + parent: + description: |- + The parent to which ChecklistItem item belongs. Is null in case this ChecklistItem is the + root of a ChecklistItem tree. For non-root ChecklistItems, the parent can be changed, as long + as the new parent is in the same checklist as the old one. + example: /checklist_items/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + position: + default: -1 + description: 'A whole number used for ordering multiple checklist items that are in the same parent.' + example: -1 + type: integer + text: + description: 'The human readable text of the checklist-item.' + example: Pfaditechnick + maxLength: 64 + type: string + required: + - checklist + - children + - position + - text + type: object + ChecklistItem.jsonld-write_create: + deprecated: false + description: |- + A ChecklistItem + A Checklist contains a Tree-Structure of ChecklistItems. + properties: + checklist: + description: 'The Checklist this Item belongs to.' + example: /checklists/1a2b3c4d + format: iri-reference + type: string + parent: + description: |- + The parent to which ChecklistItem item belongs. Is null in case this ChecklistItem is the + root of a ChecklistItem tree. For non-root ChecklistItems, the parent can be changed, as long + as the new parent is in the same checklist as the old one. + example: /checklist_items/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + position: + default: -1 + description: 'A whole number used for ordering multiple checklist items that are in the same parent.' + example: -1 + type: integer + text: + description: 'The human readable text of the checklist-item.' + example: Pfaditechnick + maxLength: 64 + type: string + required: + - checklist + - position + - text type: object ColumnLayout-read: deprecated: false @@ -23176,59 +23611,308 @@ paths: type: array style: form responses: - 200: + 200: + content: + application/hal+json: + schema: + properties: + _embedded: { anyOf: [{ properties: { item: { items: { $ref: '#/components/schemas/Checklist.jsonhal-read' }, type: array } }, type: object }, { type: object }] } + _links: { properties: { first: { properties: { href: { format: iri-reference, type: string } }, type: object }, last: { properties: { href: { format: iri-reference, type: string } }, type: object }, next: { properties: { href: { format: iri-reference, type: string } }, type: object }, previous: { properties: { href: { format: iri-reference, type: string } }, type: object }, self: { properties: { href: { format: iri-reference, type: string } }, type: object } }, type: object } + itemsPerPage: { minimum: 0, type: integer } + totalItems: { minimum: 0, type: integer } + required: + - _embedded + - _links + type: object + application/json: + schema: + items: + $ref: '#/components/schemas/Checklist-read' + type: array + application/ld+json: + schema: + properties: + 'hydra:member': { items: { $ref: '#/components/schemas/Checklist.jsonld-read' }, type: array } + 'hydra:search': { properties: { '@type': { type: string }, 'hydra:mapping': { items: { properties: { '@type': { type: string }, property: { type: ['null', string] }, required: { type: boolean }, variable: { type: string } }, type: object }, type: array }, 'hydra:template': { type: string }, 'hydra:variableRepresentation': { type: string } }, type: object } + 'hydra:totalItems': { minimum: 0, type: integer } + 'hydra:view': { example: { '@id': string, 'hydra:first': string, 'hydra:last': string, 'hydra:next': string, 'hydra:previous': string, type: string }, properties: { '@id': { format: iri-reference, type: string }, '@type': { type: string }, 'hydra:first': { format: iri-reference, type: string }, 'hydra:last': { format: iri-reference, type: string }, 'hydra:next': { format: iri-reference, type: string }, 'hydra:previous': { format: iri-reference, type: string } }, type: object } + required: + - 'hydra:member' + type: object + application/vnd.api+json: + schema: + items: + $ref: '#/components/schemas/Checklist.jsonapi' + type: array + text/html: + schema: + items: + $ref: '#/components/schemas/Checklist-read' + type: array + description: 'Checklist collection' + summary: 'Retrieves the collection of Checklist resources.' + tags: + - Checklist + '/camps/{id}': + delete: + deprecated: false + description: 'Removes the Camp resource.' + operationId: api_camps_id_delete + parameters: + - + allowEmptyValue: false + allowReserved: false + deprecated: false + description: 'Camp identifier' + explode: false + in: path + name: id + required: true + schema: + type: string + style: simple + responses: + 204: + description: 'Camp resource deleted' + 404: + description: 'Resource not found' + summary: 'Removes the Camp resource.' + tags: + - Camp + get: + deprecated: false + description: 'Retrieves a Camp resource.' + operationId: api_camps_id_get + parameters: + - + allowEmptyValue: false + allowReserved: false + deprecated: false + description: 'Camp identifier' + explode: false + in: path + name: id + required: true + schema: + type: string + style: simple + responses: + 200: + content: + application/hal+json: + schema: + $ref: '#/components/schemas/Camp.jsonhal-read_Camp.Periods_Period.Days_Camp.CampCollaborations_CampCollaboration.User' + application/json: + schema: + $ref: '#/components/schemas/Camp-read_Camp.Periods_Period.Days_Camp.CampCollaborations_CampCollaboration.User' + application/ld+json: + schema: + $ref: '#/components/schemas/Camp.jsonld-read_Camp.Periods_Period.Days_Camp.CampCollaborations_CampCollaboration.User' + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Camp.jsonapi' + text/html: + schema: + $ref: '#/components/schemas/Camp-read_Camp.Periods_Period.Days_Camp.CampCollaborations_CampCollaboration.User' + description: 'Camp resource' + 404: + description: 'Resource not found' + summary: 'Retrieves a Camp resource.' + tags: + - Camp + patch: + deprecated: false + description: 'Updates the Camp resource.' + operationId: api_camps_id_patch + parameters: + - + allowEmptyValue: false + allowReserved: false + deprecated: false + description: 'Camp identifier' + explode: false + in: path + name: id + required: true + schema: + type: string + style: simple + requestBody: + content: + application/merge-patch+json: + schema: + $ref: '#/components/schemas/Camp-write_update' + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Camp.jsonapi' + description: 'The updated Camp resource' + required: true + responses: + 200: + content: + application/hal+json: + schema: + $ref: '#/components/schemas/Camp.jsonhal-read_Camp.Periods_Period.Days_Camp.CampCollaborations_CampCollaboration.User' + application/json: + schema: + $ref: '#/components/schemas/Camp-read_Camp.Periods_Period.Days_Camp.CampCollaborations_CampCollaboration.User' + application/ld+json: + schema: + $ref: '#/components/schemas/Camp.jsonld-read_Camp.Periods_Period.Days_Camp.CampCollaborations_CampCollaboration.User' + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Camp.jsonapi' + text/html: + schema: + $ref: '#/components/schemas/Camp-read_Camp.Periods_Period.Days_Camp.CampCollaborations_CampCollaboration.User' + description: 'Camp resource updated' + links: [] + 400: + description: 'Invalid input' + 404: + description: 'Resource not found' + 422: + description: 'Unprocessable entity' + summary: 'Updates the Camp resource.' + tags: + - Camp + /categories: + get: + deprecated: false + description: 'Retrieves the collection of Category resources.' + operationId: api_categories_get_collection + parameters: + - + allowEmptyValue: true + allowReserved: false + deprecated: false + description: '' + explode: false + in: query + name: camp + required: false + schema: + type: string + style: form + - + allowEmptyValue: true + allowReserved: false + deprecated: false + description: '' + explode: true + in: query + name: 'camp[]' + required: false + schema: + items: + type: string + type: array + style: form + responses: + 200: + content: + application/hal+json: + schema: + properties: + _embedded: { anyOf: [{ properties: { item: { items: { $ref: '#/components/schemas/Category.jsonhal-read' }, type: array } }, type: object }, { type: object }] } + _links: { properties: { first: { properties: { href: { format: iri-reference, type: string } }, type: object }, last: { properties: { href: { format: iri-reference, type: string } }, type: object }, next: { properties: { href: { format: iri-reference, type: string } }, type: object }, previous: { properties: { href: { format: iri-reference, type: string } }, type: object }, self: { properties: { href: { format: iri-reference, type: string } }, type: object } }, type: object } + itemsPerPage: { minimum: 0, type: integer } + totalItems: { minimum: 0, type: integer } + required: + - _embedded + - _links + type: object + application/json: + schema: + items: + $ref: '#/components/schemas/Category-read' + type: array + application/ld+json: + schema: + properties: + 'hydra:member': { items: { $ref: '#/components/schemas/Category.jsonld-read' }, type: array } + 'hydra:search': { properties: { '@type': { type: string }, 'hydra:mapping': { items: { properties: { '@type': { type: string }, property: { type: ['null', string] }, required: { type: boolean }, variable: { type: string } }, type: object }, type: array }, 'hydra:template': { type: string }, 'hydra:variableRepresentation': { type: string } }, type: object } + 'hydra:totalItems': { minimum: 0, type: integer } + 'hydra:view': { example: { '@id': string, 'hydra:first': string, 'hydra:last': string, 'hydra:next': string, 'hydra:previous': string, type: string }, properties: { '@id': { format: iri-reference, type: string }, '@type': { type: string }, 'hydra:first': { format: iri-reference, type: string }, 'hydra:last': { format: iri-reference, type: string }, 'hydra:next': { format: iri-reference, type: string }, 'hydra:previous': { format: iri-reference, type: string } }, type: object } + required: + - 'hydra:member' + type: object + application/vnd.api+json: + schema: + items: + $ref: '#/components/schemas/Category.jsonapi' + type: array + text/html: + schema: + items: + $ref: '#/components/schemas/Category-read' + type: array + description: 'Category collection' + summary: 'Retrieves the collection of Category resources.' + tags: + - Category + post: + deprecated: false + description: 'Creates a Category resource.' + operationId: api_categories_post + parameters: [] + requestBody: + content: + application/hal+json: + schema: + $ref: '#/components/schemas/Category.jsonhal-write_create' + application/json: + schema: + $ref: '#/components/schemas/Category-write_create' + application/ld+json: + schema: + $ref: '#/components/schemas/Category.jsonld-write_create' + application/vnd.api+json: + schema: + $ref: '#/components/schemas/Category.jsonapi' + text/html: + schema: + $ref: '#/components/schemas/Category-write_create' + description: 'The new Category resource' + required: true + responses: + 201: content: application/hal+json: schema: - properties: - _embedded: { anyOf: [{ properties: { item: { items: { $ref: '#/components/schemas/Checklist.jsonhal-read' }, type: array } }, type: object }, { type: object }] } - _links: { properties: { first: { properties: { href: { format: iri-reference, type: string } }, type: object }, last: { properties: { href: { format: iri-reference, type: string } }, type: object }, next: { properties: { href: { format: iri-reference, type: string } }, type: object }, previous: { properties: { href: { format: iri-reference, type: string } }, type: object }, self: { properties: { href: { format: iri-reference, type: string } }, type: object } }, type: object } - itemsPerPage: { minimum: 0, type: integer } - totalItems: { minimum: 0, type: integer } - required: - - _embedded - - _links - type: object + $ref: '#/components/schemas/Category.jsonhal-read_Category.PreferredContentTypes_Category.ContentNodes' application/json: schema: - items: - $ref: '#/components/schemas/Checklist-read' - type: array + $ref: '#/components/schemas/Category-read_Category.PreferredContentTypes_Category.ContentNodes' application/ld+json: schema: - properties: - 'hydra:member': { items: { $ref: '#/components/schemas/Checklist.jsonld-read' }, type: array } - 'hydra:search': { properties: { '@type': { type: string }, 'hydra:mapping': { items: { properties: { '@type': { type: string }, property: { type: ['null', string] }, required: { type: boolean }, variable: { type: string } }, type: object }, type: array }, 'hydra:template': { type: string }, 'hydra:variableRepresentation': { type: string } }, type: object } - 'hydra:totalItems': { minimum: 0, type: integer } - 'hydra:view': { example: { '@id': string, 'hydra:first': string, 'hydra:last': string, 'hydra:next': string, 'hydra:previous': string, type: string }, properties: { '@id': { format: iri-reference, type: string }, '@type': { type: string }, 'hydra:first': { format: iri-reference, type: string }, 'hydra:last': { format: iri-reference, type: string }, 'hydra:next': { format: iri-reference, type: string }, 'hydra:previous': { format: iri-reference, type: string } }, type: object } - required: - - 'hydra:member' - type: object + $ref: '#/components/schemas/Category.jsonld-read_Category.PreferredContentTypes_Category.ContentNodes' application/vnd.api+json: schema: - items: - $ref: '#/components/schemas/Checklist.jsonapi' - type: array + $ref: '#/components/schemas/Category.jsonapi' text/html: schema: - items: - $ref: '#/components/schemas/Checklist-read' - type: array - description: 'Checklist collection' - summary: 'Retrieves the collection of Checklist resources.' + $ref: '#/components/schemas/Category-read_Category.PreferredContentTypes_Category.ContentNodes' + description: 'Category resource created' + links: [] + 400: + description: 'Invalid input' + 422: + description: 'Unprocessable entity' + summary: 'Creates a Category resource.' tags: - - Checklist - '/camps/{id}': + - Category + '/categories/{id}': delete: deprecated: false - description: 'Removes the Camp resource.' - operationId: api_camps_id_delete + description: 'Removes the Category resource.' + operationId: api_categories_id_delete parameters: - allowEmptyValue: false allowReserved: false deprecated: false - description: 'Camp identifier' + description: 'Category identifier' explode: false in: path name: id @@ -23238,22 +23922,22 @@ paths: style: simple responses: 204: - description: 'Camp resource deleted' + description: 'Category resource deleted' 404: description: 'Resource not found' - summary: 'Removes the Camp resource.' + summary: 'Removes the Category resource.' tags: - - Camp + - Category get: deprecated: false - description: 'Retrieves a Camp resource.' - operationId: api_camps_id_get + description: 'Retrieves a Category resource.' + operationId: api_categories_id_get parameters: - allowEmptyValue: false allowReserved: false deprecated: false - description: 'Camp identifier' + description: 'Category identifier' explode: false in: path name: id @@ -23266,35 +23950,35 @@ paths: content: application/hal+json: schema: - $ref: '#/components/schemas/Camp.jsonhal-read_Camp.Periods_Period.Days_Camp.CampCollaborations_CampCollaboration.User' + $ref: '#/components/schemas/Category.jsonhal-read_Category.PreferredContentTypes_Category.ContentNodes' application/json: schema: - $ref: '#/components/schemas/Camp-read_Camp.Periods_Period.Days_Camp.CampCollaborations_CampCollaboration.User' + $ref: '#/components/schemas/Category-read_Category.PreferredContentTypes_Category.ContentNodes' application/ld+json: schema: - $ref: '#/components/schemas/Camp.jsonld-read_Camp.Periods_Period.Days_Camp.CampCollaborations_CampCollaboration.User' + $ref: '#/components/schemas/Category.jsonld-read_Category.PreferredContentTypes_Category.ContentNodes' application/vnd.api+json: schema: - $ref: '#/components/schemas/Camp.jsonapi' + $ref: '#/components/schemas/Category.jsonapi' text/html: schema: - $ref: '#/components/schemas/Camp-read_Camp.Periods_Period.Days_Camp.CampCollaborations_CampCollaboration.User' - description: 'Camp resource' + $ref: '#/components/schemas/Category-read_Category.PreferredContentTypes_Category.ContentNodes' + description: 'Category resource' 404: description: 'Resource not found' - summary: 'Retrieves a Camp resource.' + summary: 'Retrieves a Category resource.' tags: - - Camp + - Category patch: deprecated: false - description: 'Updates the Camp resource.' - operationId: api_camps_id_patch + description: 'Updates the Category resource.' + operationId: api_categories_id_patch parameters: - allowEmptyValue: false allowReserved: false deprecated: false - description: 'Camp identifier' + description: 'Category identifier' explode: false in: path name: id @@ -23306,31 +23990,31 @@ paths: content: application/merge-patch+json: schema: - $ref: '#/components/schemas/Camp-write_update' + $ref: '#/components/schemas/Category-write_update' application/vnd.api+json: schema: - $ref: '#/components/schemas/Camp.jsonapi' - description: 'The updated Camp resource' + $ref: '#/components/schemas/Category.jsonapi' + description: 'The updated Category resource' required: true responses: 200: content: application/hal+json: schema: - $ref: '#/components/schemas/Camp.jsonhal-read_Camp.Periods_Period.Days_Camp.CampCollaborations_CampCollaboration.User' + $ref: '#/components/schemas/Category.jsonhal-read_Category.PreferredContentTypes_Category.ContentNodes' application/json: schema: - $ref: '#/components/schemas/Camp-read_Camp.Periods_Period.Days_Camp.CampCollaborations_CampCollaboration.User' + $ref: '#/components/schemas/Category-read_Category.PreferredContentTypes_Category.ContentNodes' application/ld+json: schema: - $ref: '#/components/schemas/Camp.jsonld-read_Camp.Periods_Period.Days_Camp.CampCollaborations_CampCollaboration.User' + $ref: '#/components/schemas/Category.jsonld-read_Category.PreferredContentTypes_Category.ContentNodes' application/vnd.api+json: schema: - $ref: '#/components/schemas/Camp.jsonapi' + $ref: '#/components/schemas/Category.jsonapi' text/html: schema: - $ref: '#/components/schemas/Camp-read_Camp.Periods_Period.Days_Camp.CampCollaborations_CampCollaboration.User' - description: 'Camp resource updated' + $ref: '#/components/schemas/Category-read_Category.PreferredContentTypes_Category.ContentNodes' + description: 'Category resource updated' links: [] 400: description: 'Invalid input' @@ -23338,14 +24022,14 @@ paths: description: 'Resource not found' 422: description: 'Unprocessable entity' - summary: 'Updates the Camp resource.' + summary: 'Updates the Category resource.' tags: - - Camp - /categories: + - Category + /checklist_items: get: deprecated: false - description: 'Retrieves the collection of Category resources.' - operationId: api_categories_get_collection + description: 'Retrieves the collection of ChecklistItem resources.' + operationId: api_checklist_items_get_collection parameters: - allowEmptyValue: true @@ -23354,7 +24038,7 @@ paths: description: '' explode: false in: query - name: camp + name: checklist required: false schema: type: string @@ -23366,7 +24050,7 @@ paths: description: '' explode: true in: query - name: 'camp[]' + name: 'checklist[]' required: false schema: items: @@ -23379,7 +24063,7 @@ paths: application/hal+json: schema: properties: - _embedded: { anyOf: [{ properties: { item: { items: { $ref: '#/components/schemas/Category.jsonhal-read' }, type: array } }, type: object }, { type: object }] } + _embedded: { anyOf: [{ properties: { item: { items: { $ref: '#/components/schemas/ChecklistItem.jsonhal-read' }, type: array } }, type: object }, { type: object }] } _links: { properties: { first: { properties: { href: { format: iri-reference, type: string } }, type: object }, last: { properties: { href: { format: iri-reference, type: string } }, type: object }, next: { properties: { href: { format: iri-reference, type: string } }, type: object }, previous: { properties: { href: { format: iri-reference, type: string } }, type: object }, self: { properties: { href: { format: iri-reference, type: string } }, type: object } }, type: object } itemsPerPage: { minimum: 0, type: integer } totalItems: { minimum: 0, type: integer } @@ -23390,12 +24074,12 @@ paths: application/json: schema: items: - $ref: '#/components/schemas/Category-read' + $ref: '#/components/schemas/ChecklistItem-read' type: array application/ld+json: schema: properties: - 'hydra:member': { items: { $ref: '#/components/schemas/Category.jsonld-read' }, type: array } + 'hydra:member': { items: { $ref: '#/components/schemas/ChecklistItem.jsonld-read' }, type: array } 'hydra:search': { properties: { '@type': { type: string }, 'hydra:mapping': { items: { properties: { '@type': { type: string }, property: { type: ['null', string] }, required: { type: boolean }, variable: { type: string } }, type: object }, type: array }, 'hydra:template': { type: string }, 'hydra:variableRepresentation': { type: string } }, type: object } 'hydra:totalItems': { minimum: 0, type: integer } 'hydra:view': { example: { '@id': string, 'hydra:first': string, 'hydra:last': string, 'hydra:next': string, 'hydra:previous': string, type: string }, properties: { '@id': { format: iri-reference, type: string }, '@type': { type: string }, 'hydra:first': { format: iri-reference, type: string }, 'hydra:last': { format: iri-reference, type: string }, 'hydra:next': { format: iri-reference, type: string }, 'hydra:previous': { format: iri-reference, type: string } }, type: object } @@ -23405,79 +24089,80 @@ paths: application/vnd.api+json: schema: items: - $ref: '#/components/schemas/Category.jsonapi' + $ref: '#/components/schemas/ChecklistItem.jsonapi' type: array text/html: schema: items: - $ref: '#/components/schemas/Category-read' + $ref: '#/components/schemas/ChecklistItem-read' type: array - description: 'Category collection' - summary: 'Retrieves the collection of Category resources.' + description: 'ChecklistItem collection' + summary: 'Retrieves the collection of ChecklistItem resources.' tags: - - Category + - ChecklistItem + parameters: [] post: deprecated: false - description: 'Creates a Category resource.' - operationId: api_categories_post + description: 'Creates a ChecklistItem resource.' + operationId: api_checklist_items_post parameters: [] requestBody: content: application/hal+json: schema: - $ref: '#/components/schemas/Category.jsonhal-write_create' + $ref: '#/components/schemas/ChecklistItem.jsonhal-write_create' application/json: schema: - $ref: '#/components/schemas/Category-write_create' + $ref: '#/components/schemas/ChecklistItem-write_create' application/ld+json: schema: - $ref: '#/components/schemas/Category.jsonld-write_create' + $ref: '#/components/schemas/ChecklistItem.jsonld-write_create' application/vnd.api+json: schema: - $ref: '#/components/schemas/Category.jsonapi' + $ref: '#/components/schemas/ChecklistItem.jsonapi' text/html: schema: - $ref: '#/components/schemas/Category-write_create' - description: 'The new Category resource' + $ref: '#/components/schemas/ChecklistItem-write_create' + description: 'The new ChecklistItem resource' required: true responses: 201: content: application/hal+json: schema: - $ref: '#/components/schemas/Category.jsonhal-read_Category.PreferredContentTypes_Category.ContentNodes' + $ref: '#/components/schemas/ChecklistItem.jsonhal-read' application/json: schema: - $ref: '#/components/schemas/Category-read_Category.PreferredContentTypes_Category.ContentNodes' + $ref: '#/components/schemas/ChecklistItem-read' application/ld+json: schema: - $ref: '#/components/schemas/Category.jsonld-read_Category.PreferredContentTypes_Category.ContentNodes' + $ref: '#/components/schemas/ChecklistItem.jsonld-read' application/vnd.api+json: schema: - $ref: '#/components/schemas/Category.jsonapi' + $ref: '#/components/schemas/ChecklistItem.jsonapi' text/html: schema: - $ref: '#/components/schemas/Category-read_Category.PreferredContentTypes_Category.ContentNodes' - description: 'Category resource created' + $ref: '#/components/schemas/ChecklistItem-read' + description: 'ChecklistItem resource created' links: [] 400: description: 'Invalid input' 422: description: 'Unprocessable entity' - summary: 'Creates a Category resource.' + summary: 'Creates a ChecklistItem resource.' tags: - - Category - '/categories/{id}': + - ChecklistItem + '/checklist_items/{id}': delete: deprecated: false - description: 'Removes the Category resource.' - operationId: api_categories_id_delete + description: 'Removes the ChecklistItem resource.' + operationId: api_checklist_items_id_delete parameters: - allowEmptyValue: false allowReserved: false deprecated: false - description: 'Category identifier' + description: 'ChecklistItem identifier' explode: false in: path name: id @@ -23487,22 +24172,22 @@ paths: style: simple responses: 204: - description: 'Category resource deleted' + description: 'ChecklistItem resource deleted' 404: description: 'Resource not found' - summary: 'Removes the Category resource.' + summary: 'Removes the ChecklistItem resource.' tags: - - Category + - ChecklistItem get: deprecated: false - description: 'Retrieves a Category resource.' - operationId: api_categories_id_get + description: 'Retrieves a ChecklistItem resource.' + operationId: api_checklist_items_id_get parameters: - allowEmptyValue: false allowReserved: false deprecated: false - description: 'Category identifier' + description: 'ChecklistItem identifier' explode: false in: path name: id @@ -23515,35 +24200,36 @@ paths: content: application/hal+json: schema: - $ref: '#/components/schemas/Category.jsonhal-read_Category.PreferredContentTypes_Category.ContentNodes' + $ref: '#/components/schemas/ChecklistItem.jsonhal-read' application/json: schema: - $ref: '#/components/schemas/Category-read_Category.PreferredContentTypes_Category.ContentNodes' + $ref: '#/components/schemas/ChecklistItem-read' application/ld+json: schema: - $ref: '#/components/schemas/Category.jsonld-read_Category.PreferredContentTypes_Category.ContentNodes' + $ref: '#/components/schemas/ChecklistItem.jsonld-read' application/vnd.api+json: schema: - $ref: '#/components/schemas/Category.jsonapi' + $ref: '#/components/schemas/ChecklistItem.jsonapi' text/html: schema: - $ref: '#/components/schemas/Category-read_Category.PreferredContentTypes_Category.ContentNodes' - description: 'Category resource' + $ref: '#/components/schemas/ChecklistItem-read' + description: 'ChecklistItem resource' 404: description: 'Resource not found' - summary: 'Retrieves a Category resource.' + summary: 'Retrieves a ChecklistItem resource.' tags: - - Category + - ChecklistItem + parameters: [] patch: deprecated: false - description: 'Updates the Category resource.' - operationId: api_categories_id_patch + description: 'Updates the ChecklistItem resource.' + operationId: api_checklist_items_id_patch parameters: - allowEmptyValue: false allowReserved: false deprecated: false - description: 'Category identifier' + description: 'ChecklistItem identifier' explode: false in: path name: id @@ -23555,31 +24241,31 @@ paths: content: application/merge-patch+json: schema: - $ref: '#/components/schemas/Category-write_update' + $ref: '#/components/schemas/ChecklistItem-write' application/vnd.api+json: schema: - $ref: '#/components/schemas/Category.jsonapi' - description: 'The updated Category resource' + $ref: '#/components/schemas/ChecklistItem.jsonapi' + description: 'The updated ChecklistItem resource' required: true responses: 200: content: application/hal+json: schema: - $ref: '#/components/schemas/Category.jsonhal-read_Category.PreferredContentTypes_Category.ContentNodes' + $ref: '#/components/schemas/ChecklistItem.jsonhal-read' application/json: schema: - $ref: '#/components/schemas/Category-read_Category.PreferredContentTypes_Category.ContentNodes' + $ref: '#/components/schemas/ChecklistItem-read' application/ld+json: schema: - $ref: '#/components/schemas/Category.jsonld-read_Category.PreferredContentTypes_Category.ContentNodes' + $ref: '#/components/schemas/ChecklistItem.jsonld-read' application/vnd.api+json: schema: - $ref: '#/components/schemas/Category.jsonapi' + $ref: '#/components/schemas/ChecklistItem.jsonapi' text/html: schema: - $ref: '#/components/schemas/Category-read_Category.PreferredContentTypes_Category.ContentNodes' - description: 'Category resource updated' + $ref: '#/components/schemas/ChecklistItem-read' + description: 'ChecklistItem resource updated' links: [] 400: description: 'Invalid input' @@ -23587,9 +24273,9 @@ paths: description: 'Resource not found' 422: description: 'Unprocessable entity' - summary: 'Updates the Category resource.' + summary: 'Updates the ChecklistItem resource.' tags: - - Category + - ChecklistItem /checklists: get: deprecated: false @@ -23716,6 +24402,94 @@ paths: summary: 'Creates a Checklist resource.' tags: - Checklist + '/checklists/{checklistId}/checklist_items': + get: + deprecated: false + description: 'Retrieves the collection of ChecklistItem resources.' + operationId: BelongsToChecklist_App\Entity\ChecklistItem_get_collection + parameters: + - + allowEmptyValue: false + allowReserved: false + deprecated: false + description: 'ChecklistItem identifier' + explode: false + in: path + name: checklistId + required: true + schema: + type: string + style: simple + - + allowEmptyValue: true + allowReserved: false + deprecated: false + description: '' + explode: false + in: query + name: checklist + required: false + schema: + type: string + style: form + - + allowEmptyValue: true + allowReserved: false + deprecated: false + description: '' + explode: true + in: query + name: 'checklist[]' + required: false + schema: + items: + type: string + type: array + style: form + responses: + 200: + content: + application/hal+json: + schema: + properties: + _embedded: { anyOf: [{ properties: { item: { items: { $ref: '#/components/schemas/ChecklistItem.jsonhal-read' }, type: array } }, type: object }, { type: object }] } + _links: { properties: { first: { properties: { href: { format: iri-reference, type: string } }, type: object }, last: { properties: { href: { format: iri-reference, type: string } }, type: object }, next: { properties: { href: { format: iri-reference, type: string } }, type: object }, previous: { properties: { href: { format: iri-reference, type: string } }, type: object }, self: { properties: { href: { format: iri-reference, type: string } }, type: object } }, type: object } + itemsPerPage: { minimum: 0, type: integer } + totalItems: { minimum: 0, type: integer } + required: + - _embedded + - _links + type: object + application/json: + schema: + items: + $ref: '#/components/schemas/ChecklistItem-read' + type: array + application/ld+json: + schema: + properties: + 'hydra:member': { items: { $ref: '#/components/schemas/ChecklistItem.jsonld-read' }, type: array } + 'hydra:search': { properties: { '@type': { type: string }, 'hydra:mapping': { items: { properties: { '@type': { type: string }, property: { type: ['null', string] }, required: { type: boolean }, variable: { type: string } }, type: object }, type: array }, 'hydra:template': { type: string }, 'hydra:variableRepresentation': { type: string } }, type: object } + 'hydra:totalItems': { minimum: 0, type: integer } + 'hydra:view': { example: { '@id': string, 'hydra:first': string, 'hydra:last': string, 'hydra:next': string, 'hydra:previous': string, type: string }, properties: { '@id': { format: iri-reference, type: string }, '@type': { type: string }, 'hydra:first': { format: iri-reference, type: string }, 'hydra:last': { format: iri-reference, type: string }, 'hydra:next': { format: iri-reference, type: string }, 'hydra:previous': { format: iri-reference, type: string } }, type: object } + required: + - 'hydra:member' + type: object + application/vnd.api+json: + schema: + items: + $ref: '#/components/schemas/ChecklistItem.jsonapi' + type: array + text/html: + schema: + items: + $ref: '#/components/schemas/ChecklistItem-read' + type: array + description: 'ChecklistItem collection' + summary: 'Retrieves the collection of ChecklistItem resources.' + tags: + - ChecklistItem + parameters: [] '/checklists/{id}': delete: deprecated: false diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testRootEndpointMatchesSnapshot__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testRootEndpointMatchesSnapshot__1.json index 84921e20f9..08bdba78ce 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testRootEndpointMatchesSnapshot__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testRootEndpointMatchesSnapshot__1.json @@ -24,6 +24,10 @@ "href": "\/categories{\/id}{?camp,camp[]}", "templated": true }, + "checklistItems": { + "href": "\/checklist_items{\/id}{?checklist,checklist[]}", + "templated": true + }, "checklists": { "href": "\/checklists{\/id}{?camp,camp[]}", "templated": true diff --git a/api/tests/Api/SnapshotTests/__snapshots__/test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml b/api/tests/Api/SnapshotTests/__snapshots__/test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml index 71b7a0fd66..cffd038675 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml +++ b/api/tests/Api/SnapshotTests/__snapshots__/test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml @@ -12,6 +12,8 @@ /categories/item: 9 /checklists: 6 /checklists/item: 7 +/checklist_items: 6 +/checklist_items/item: 8 /content_types: 6 /content_types/item: 6 /days: 26 From e2cdf141bcd5296a4eb09a0fed0894f11222a743 Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Sat, 15 Jun 2024 23:22:07 +0200 Subject: [PATCH 06/69] add Unittests for ChecklistItem --- .../CreateChecklistItemTest.php | 260 ++++++++++++++++++ .../DeleteChecklistItemTest.php | 87 ++++++ .../ChecklistItems/ListChecklistItemTest.php | 128 +++++++++ .../ChecklistItems/ReadChecklistItemTest.php | 108 ++++++++ .../UpdateChecklistItemTest.php | 220 +++++++++++++++ 5 files changed, 803 insertions(+) create mode 100644 api/tests/Api/ChecklistItems/CreateChecklistItemTest.php create mode 100644 api/tests/Api/ChecklistItems/DeleteChecklistItemTest.php create mode 100644 api/tests/Api/ChecklistItems/ListChecklistItemTest.php create mode 100644 api/tests/Api/ChecklistItems/ReadChecklistItemTest.php create mode 100644 api/tests/Api/ChecklistItems/UpdateChecklistItemTest.php diff --git a/api/tests/Api/ChecklistItems/CreateChecklistItemTest.php b/api/tests/Api/ChecklistItems/CreateChecklistItemTest.php new file mode 100644 index 0000000000..007d8d0970 --- /dev/null +++ b/api/tests/Api/ChecklistItems/CreateChecklistItemTest.php @@ -0,0 +1,260 @@ +request('POST', '/checklist_items', ['json' => $this->getExampleWritePayload()]); + + $this->assertResponseStatusCodeSame(401); + $this->assertJsonContains([ + 'code' => 401, + 'message' => 'JWT Token not found', + ]); + } + + public function testCreateChecklistItemIsNotPossibleForUnrelatedUserBecauseCampIsNotReadable() { + static::createClientWithCredentials(['email' => static::$fixtures['user4unrelated']->getEmail()]) + ->request('POST', '/checklist_items', ['json' => $this->getExampleWritePayload()]) + ; + + $this->assertResponseStatusCodeSame(400); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Item not found for "'.$this->getIriFor('checklist1').'".', + ]); + } + + public function testCreateChecklistItemIsNotPossibleForInactiveCollaboratorBecauseCampIsNotReadable() { + static::createClientWithCredentials(['email' => static::$fixtures['user5inactive']->getEmail()]) + ->request('POST', '/checklist_items', ['json' => $this->getExampleWritePayload()]) + ; + + $this->assertResponseStatusCodeSame(400); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Item not found for "'.$this->getIriFor('checklist1').'".', + ]); + } + + public function testCreateChecklistItemIsDeniedForGuest() { + static::createClientWithCredentials(['email' => static::$fixtures['user3guest']->getEmail()]) + ->request('POST', '/checklist_items', ['json' => $this->getExampleWritePayload()]) + ; + + $this->assertResponseStatusCodeSame(403); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Access Denied.', + ]); + } + + public function testCreateChecklistItemIsAllowedForMember() { + static::createClientWithCredentials(['email' => static::$fixtures['user2member']->getEmail()]) + ->request('POST', '/checklist_items', ['json' => $this->getExampleWritePayload()]) + ; + + $this->assertResponseStatusCodeSame(201); + $this->assertJsonContains($this->getExampleReadPayload(['position' => 5])); + } + + public function testCreateChecklistItemIsAllowedForManager() { + static::createClientWithCredentials()->request('POST', '/checklist_items', ['json' => $this->getExampleWritePayload()]); + + $this->assertResponseStatusCodeSame(201); + $this->assertJsonContains($this->getExampleReadPayload(['position' => 5])); + } + + public function testCreateChecklistItemInCampPrototypeIsDeniedForUnrelatedUser() { + static::createClientWithCredentials()->request('POST', '/checklist_items', ['json' => $this->getExampleWritePayload([ + 'checklist' => $this->getIriFor('checklist1campPrototype'), + ])]); + + $this->assertResponseStatusCodeSame(403); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Access Denied.', + ]); + } + + public function testCreateChecklistItemValidatesMissingChecklist() { + static::createClientWithCredentials()->request('POST', '/checklist_items', ['json' => $this->getExampleWritePayload([], ['checklist'])]); + + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'violations' => [ + [ + 'propertyPath' => 'checklist', + 'message' => 'This value should not be null.', + ], + ], + ]); + } + + public function testCreateChecklistItemValidatesMissingText() { + static::createClientWithCredentials()->request('POST', '/checklist_items', ['json' => $this->getExampleWritePayload([], ['text'])]); + + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'violations' => [ + [ + 'propertyPath' => 'text', + 'message' => 'This value should not be blank.', + ], + ], + ]); + } + + public function testCreateChecklistItemValidatesBlankText() { + static::createClientWithCredentials()->request( + 'POST', + '/checklist_items', + [ + 'json' => $this->getExampleWritePayload( + [ + 'text' => '', + ] + ), + ] + ); + + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'violations' => [ + [ + 'propertyPath' => 'text', + 'message' => 'This value should not be blank.', + ], + ], + ]); + } + + public function testCreateChecklistItemValidatesTooLongText() { + static::createClientWithCredentials()->request( + 'POST', + '/checklist_items', + [ + 'json' => $this->getExampleWritePayload( + [ + 'text' => str_repeat('l', 65), + ] + ), + ] + ); + + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'violations' => [ + [ + 'propertyPath' => 'text', + 'message' => 'This value is too long. It should have 64 characters or less.', + ], + ], + ]); + } + + public function testCreateChecklistItemTrimsText() { + static::createClientWithCredentials()->request( + 'POST', + '/checklist_items', + [ + 'json' => $this->getExampleWritePayload( + [ + 'text' => " \t Ziel 1\t ", + ] + ), + ] + ); + + $this->assertResponseStatusCodeSame(201); + $this->assertJsonContains($this->getExampleReadPayload( + [ + 'text' => 'Ziel 1', + 'position' => 5, + ] + )); + } + + public function testCreateChecklistItemCleansForbiddenCharactersFromText() { + static::createClientWithCredentials()->request( + 'POST', + '/checklist_items', + [ + 'json' => $this->getExampleWritePayload( + [ + 'text' => "\n\tZiel 1", + ] + ), + ] + ); + + $this->assertResponseStatusCodeSame(201); + $this->assertJsonContains($this->getExampleReadPayload( + [ + 'text' => 'Ziel 1', + 'position' => 5, + ] + )); + } + + /** + * @throws RedirectionExceptionInterface + * @throws DecodingExceptionInterface + * @throws ClientExceptionInterface + * @throws TransportExceptionInterface + * @throws ServerExceptionInterface + */ + public function testCreateResponseStructureMatchesReadResponseStructure() { + $client = static::createClientWithCredentials(); + $client->disableReboot(); + $createResponse = $client->request( + 'POST', + '/checklist_items', + [ + 'json' => $this->getExampleWritePayload(), + ] + ); + + $this->assertResponseStatusCodeSame(201); + + $createArray = $createResponse->toArray(); + $newItemLink = $createArray['_links']['self']['href']; + $getItemResponse = $client->request('GET', $newItemLink); + + assertThat($createArray, CompatibleHalResponse::isHalCompatibleWith($getItemResponse->toArray())); + } + + public function getExampleWritePayload($attributes = [], $except = []) { + return $this->getExamplePayload( + ChecklistItem::class, + Post::class, + array_merge([ + 'parent' => null, + 'checklist' => $this->getIriFor('checklist1'), + ], $attributes), + [], + $except + ); + } + + public function getExampleReadPayload($attributes = [], $except = []) { + return $this->getExamplePayload( + ChecklistItem::class, + Get::class, + $attributes, + ['parent', 'checklist'], + $except + ); + } +} diff --git a/api/tests/Api/ChecklistItems/DeleteChecklistItemTest.php b/api/tests/Api/ChecklistItems/DeleteChecklistItemTest.php new file mode 100644 index 0000000000..262ef91457 --- /dev/null +++ b/api/tests/Api/ChecklistItems/DeleteChecklistItemTest.php @@ -0,0 +1,87 @@ +request('DELETE', '/checklist_items/'.$checklistItem->getId()); + $this->assertResponseStatusCodeSame(401); + $this->assertJsonContains([ + 'code' => 401, + 'message' => 'JWT Token not found', + ]); + } + + public function testDeleteChecklistItemIsDeniedForUnrelatedUser() { + $checklistItem = static::getFixture('checklistItem1_1_2_3'); + static::createClientWithCredentials(['email' => static::$fixtures['user4unrelated']->getEmail()]) + ->request('DELETE', '/checklist_items/'.$checklistItem->getId()) + ; + + $this->assertResponseStatusCodeSame(404); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Not Found', + ]); + } + + public function testDeleteChecklistItemIsDeniedForInactiveCollaborator() { + $checklistItem = static::getFixture('checklistItem1_1_2_3'); + static::createClientWithCredentials(['email' => static::$fixtures['user5inactive']->getEmail()]) + ->request('DELETE', '/checklist_items/'.$checklistItem->getId()) + ; + + $this->assertResponseStatusCodeSame(404); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Not Found', + ]); + } + + public function testDeleteChecklistItemIsDeniedForGuest() { + $checklistItem = static::getFixture('checklistItem1_1_2_3'); + static::createClientWithCredentials(['email' => static::$fixtures['user3guest']->getEmail()]) + ->request('DELETE', '/checklist_items/'.$checklistItem->getId()) + ; + + $this->assertResponseStatusCodeSame(403); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Access Denied.', + ]); + } + + public function testDeleteChecklistItemIsAllowedForMember() { + $checklistItem = static::getFixture('checklistItem1_1_2_3'); + static::createClientWithCredentials(['email' => static::$fixtures['user2member']->getEmail()]) + ->request('DELETE', '/checklist_items/'.$checklistItem->getId()) + ; + $this->assertResponseStatusCodeSame(204); + $this->assertNull($this->getEntityManager()->getRepository(ChecklistItem::class)->find($checklistItem->getId())); + } + + public function testDeleteChecklistItemIsAllowedForManager() { + $checklistItem = static::getFixture('checklistItem1_1_2_3'); + static::createClientWithCredentials()->request('DELETE', '/checklist_items/'.$checklistItem->getId()); + $this->assertResponseStatusCodeSame(204); + $this->assertNull($this->getEntityManager()->getRepository(ChecklistItem::class)->find($checklistItem->getId())); + } + + public function testDeleteChecklistItemFromCampPrototypeIsDeniedForUnrelatedUser() { + $checklistItem = static::getFixture('checklistItemPrototype_1_1'); + static::createClientWithCredentials()->request('DELETE', '/checklist_items/'.$checklistItem->getId()); + + $this->assertResponseStatusCodeSame(403); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Access Denied.', + ]); + } +} diff --git a/api/tests/Api/ChecklistItems/ListChecklistItemTest.php b/api/tests/Api/ChecklistItems/ListChecklistItemTest.php new file mode 100644 index 0000000000..cbffa0d0a5 --- /dev/null +++ b/api/tests/Api/ChecklistItems/ListChecklistItemTest.php @@ -0,0 +1,128 @@ +request('GET', '/checklist_items'); + $this->assertResponseStatusCodeSame(401); + $this->assertJsonContains([ + 'code' => 401, + 'message' => 'JWT Token not found', + ]); + } + + public function testListChecklistItemsIsAllowedForLoggedInUserButFiltered() { + // precondition: There is a checklist-item that the user doesn't have access to + $this->assertNotEmpty(static::$fixtures['checklistItemUnrelated_1_1']); + + $response = static::createClientWithCredentials()->request('GET', '/checklist_items'); + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'totalItems' => 5, + '_links' => [ + 'items' => [], + ], + '_embedded' => [ + 'items' => [], + ], + ]); + $this->assertEqualsCanonicalizing([ + ['href' => $this->getIriFor('checklistItem1_1_1')], + ['href' => $this->getIriFor('checklistItem1_1_2')], + ['href' => $this->getIriFor('checklistItem1_1_2_3')], + ['href' => $this->getIriFor('checklistItem2_1_1')], + ['href' => $this->getIriFor('checklistItemPrototype_1_1')], + ], $response->toArray()['_links']['items']); + } + + public function testListChecklistItemsFilteredByChecklistIsAllowedForCollaborator() { + $checklist = static::getFixture('checklist1'); + $response = static::createClientWithCredentials()->request('GET', '/checklist_items?checklist=%2Fchecklists%2F'.$checklist->getId()); + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'totalItems' => 3, + '_links' => [ + 'items' => [], + ], + '_embedded' => [ + 'items' => [], + ], + ]); + $this->assertEqualsCanonicalizing([ + ['href' => $this->getIriFor('checklistItem1_1_1')], + ['href' => $this->getIriFor('checklistItem1_1_2')], + ['href' => $this->getIriFor('checklistItem1_1_2_3')], + ], $response->toArray()['_links']['items']); + } + + public function testListChecklistItemsFilteredByChecklistIsDeniedForUnrelatedUser() { + $checklist = static::getFixture('checklist1'); + $response = static::createClientWithCredentials(['email' => static::$fixtures['user4unrelated']->getEmail()]) + ->request('GET', '/checklist_items?checklist=%2Fchecklists%2F'.$checklist->getId()) + ; + + $this->assertResponseStatusCodeSame(200); + + $this->assertJsonContains(['totalItems' => 0]); + $this->assertArrayNotHasKey('items', $response->toArray()['_links']); + } + + public function testListChecklistItemsFilteredByChecklistIsDeniedForInactiveCollaborator() { + $checklist = static::getFixture('checklist1'); + $response = static::createClientWithCredentials(['email' => static::$fixtures['user5inactive']->getEmail()]) + ->request('GET', '/checklist_items?checklist=%2Fchecklists%2F'.$checklist->getId()) + ; + + $this->assertResponseStatusCodeSame(200); + + $this->assertJsonContains(['totalItems' => 0]); + $this->assertArrayNotHasKey('items', $response->toArray()['_links']); + } + + public function testListChecklistItemsFilteredByChecklistPrototypeIsAllowedForUnrelatedUser() { + $checklist = static::getFixture('checklist1campPrototype'); + $response = static::createClientWithCredentials()->request('GET', '/checklist_items?checklist=%2Fchecklists%2F'.$checklist->getId()); + + $this->assertResponseStatusCodeSame(200); + + $this->assertJsonContains(['totalItems' => 1]); + $this->assertEqualsCanonicalizing([ + ['href' => $this->getIriFor('checklistItemPrototype_1_1')], + ], $response->toArray()['_links']['items']); + } + + public function testListChecklistItemsAsChecklistSubresourceIsAllowedForCollaborator() { + $checklist = static::getFixture('checklist1'); + $response = static::createClientWithCredentials()->request('GET', '/checklists/'.$checklist->getId().'/checklist_items'); + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'totalItems' => 3, + '_links' => [ + 'items' => [], + ], + '_embedded' => [ + 'items' => [], + ], + ]); + $this->assertEqualsCanonicalizing([ + ['href' => $this->getIriFor('checklistItem1_1_1')], + ['href' => $this->getIriFor('checklistItem1_1_2')], + ['href' => $this->getIriFor('checklistItem1_1_2_3')], + ], $response->toArray()['_links']['items']); + } + + public function testListChecklistItemsAsChecklistSubresourceIsDeniedForUnrelatedUser() { + $checklist = static::getFixture('checklist1'); + static::createClientWithCredentials(['email' => static::$fixtures['user4unrelated']->getEmail()]) + ->request('GET', '/checklists/'.$checklist->getId().'/checklist_items') + ; + + $this->assertResponseStatusCodeSame(404); + } +} diff --git a/api/tests/Api/ChecklistItems/ReadChecklistItemTest.php b/api/tests/Api/ChecklistItems/ReadChecklistItemTest.php new file mode 100644 index 0000000000..9e362711a8 --- /dev/null +++ b/api/tests/Api/ChecklistItems/ReadChecklistItemTest.php @@ -0,0 +1,108 @@ +request('GET', '/checklist_items/'.$checklistItem->getId()); + $this->assertResponseStatusCodeSame(401); + $this->assertJsonContains([ + 'code' => 401, + 'message' => 'JWT Token not found', + ]); + } + + public function testGetSingleChecklistItemIsDeniedForUnrelatedUser() { + /** @var ChecklistItem $checklistItem */ + $checklistItem = static::getFixture('checklistItem1_1_1'); + static::createClientWithCredentials(['email' => static::$fixtures['user4unrelated']->getEmail()]) + ->request('GET', '/checklist_items/'.$checklistItem->getId()) + ; + $this->assertResponseStatusCodeSame(404); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Not Found', + ]); + } + + public function testGetSingleChecklistItemIsDeniedForInactiveCollaborator() { + /** @var ChecklistItem $checklistItem */ + $checklistItem = static::getFixture('checklistItem1_1_1'); + static::createClientWithCredentials(['email' => static::$fixtures['user5inactive']->getEmail()]) + ->request('GET', '/checklist_items/'.$checklistItem->getId()) + ; + $this->assertResponseStatusCodeSame(404); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Not Found', + ]); + } + + public function testGetSingleChecklistItemIsAllowedForGuest() { + /** @var ChecklistItem $checklistItem */ + $checklistItem = static::getFixture('checklistItem1_1_1'); + static::createClientWithCredentials(['email' => static::$fixtures['user3guest']->getEmail()]) + ->request('GET', '/checklist_items/'.$checklistItem->getId()) + ; + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'id' => $checklistItem->getId(), + 'text' => $checklistItem->text, + '_links' => [ + 'checklist' => ['href' => $this->getIriFor('checklist1')], + ], + ]); + } + + public function testGetSingleChecklistItemIsAllowedForMember() { + /** @var ChecklistItem $checklistItem */ + $checklistItem = static::getFixture('checklistItem1_1_1'); + static::createClientWithCredentials(['email' => static::$fixtures['user2member']->getEmail()]) + ->request('GET', '/checklist_items/'.$checklistItem->getId()) + ; + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'id' => $checklistItem->getId(), + 'text' => $checklistItem->text, + '_links' => [ + 'checklist' => ['href' => $this->getIriFor('checklist1')], + ], + ]); + } + + public function testGetSingleChecklistItemIsAllowedForManager() { + /** @var ChecklistItem $checklistItem */ + $checklistItem = static::getFixture('checklistItem1_1_1'); + static::createClientWithCredentials()->request('GET', '/checklist_items/'.$checklistItem->getId()); + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'id' => $checklistItem->getId(), + 'text' => $checklistItem->text, + '_links' => [ + 'checklist' => ['href' => $this->getIriFor('checklist1')], + ], + ]); + } + + public function testGetSingleChecklistItemFromCampPrototypeIsAllowedForUnrelatedUser() { + /** @var ChecklistItem $checklistItem */ + $checklistItem = static::getFixture('checklistItemPrototype_1_1'); + static::createClientWithCredentials()->request('GET', '/checklist_items/'.$checklistItem->getId()); + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'id' => $checklistItem->getId(), + 'text' => $checklistItem->text, + '_links' => [ + 'checklist' => ['href' => $this->getIriFor('checklist1campPrototype')], + ], + ]); + } +} diff --git a/api/tests/Api/ChecklistItems/UpdateChecklistItemTest.php b/api/tests/Api/ChecklistItems/UpdateChecklistItemTest.php new file mode 100644 index 0000000000..ca6ceae23a --- /dev/null +++ b/api/tests/Api/ChecklistItems/UpdateChecklistItemTest.php @@ -0,0 +1,220 @@ +request('PATCH', '/checklist_items/'.$checklistItem->getId(), ['json' => [ + 'text' => 'Ziel 2', + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]); + $this->assertResponseStatusCodeSame(401); + $this->assertJsonContains([ + 'code' => 401, + 'message' => 'JWT Token not found', + ]); + } + + public function testPatchChecklistItemIsDeniedForUnrelatedUser() { + $checklistItem = static::getFixture('checklistItem1_1_1'); + static::createClientWithCredentials(['email' => static::$fixtures['user4unrelated']->getEmail()]) + ->request('PATCH', '/checklist_items/'.$checklistItem->getId(), ['json' => [ + 'text' => 'Ziel 2', + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]) + ; + $this->assertResponseStatusCodeSame(404); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Not Found', + ]); + } + + public function testPatchChecklistItemIsDeniedForInactiveCollaborator() { + $checklistItem = static::getFixture('checklistItem1_1_1'); + static::createClientWithCredentials(['email' => static::$fixtures['user5inactive']->getEmail()]) + ->request('PATCH', '/checklist_items/'.$checklistItem->getId(), ['json' => [ + 'text' => 'Ziel 2', + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]) + ; + $this->assertResponseStatusCodeSame(404); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Not Found', + ]); + } + + public function testPatchChecklistItemIsDeniedForGuest() { + $checklistItem = static::getFixture('checklistItem1_1_1'); + static::createClientWithCredentials(['email' => static::$fixtures['user3guest']->getEmail()]) + ->request('PATCH', '/checklist_items/'.$checklistItem->getId(), ['json' => [ + 'text' => 'Ziel 2', + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]) + ; + $this->assertResponseStatusCodeSame(403); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Access Denied.', + ]); + } + + public function testPatchChecklistItemIsAllowedForMember() { + $checklistItem = static::getFixture('checklistItem1_1_1'); + $response = static::createClientWithCredentials(['email' => static::$fixtures['user2member']->getEmail()]) + ->request('PATCH', '/checklist_items/'.$checklistItem->getId(), ['json' => [ + 'text' => 'Ziel 2', + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]) + ; + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'text' => 'Ziel 2', + ]); + } + + public function testPatchChecklistItemIsAllowedForManager() { + $checklistItem = static::getFixture('checklistItem1_1_1'); + $response = static::createClientWithCredentials()->request('PATCH', '/checklist_items/'.$checklistItem->getId(), ['json' => [ + 'text' => 'Ziel 2', + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]); + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + 'text' => 'Ziel 2', + ]); + } + + public function testPatchChecklistItemInCampPrototypeIsDeniedForUnrelatedUser() { + $checklistItem = static::getFixture('checklistItemPrototype_1_1'); + $response = static::createClientWithCredentials()->request('PATCH', '/checklist_items/'.$checklistItem->getId(), ['json' => [ + 'text' => 'Ziel 2', + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]); + $this->assertResponseStatusCodeSame(403); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Access Denied.', + ]); + } + + public function testPatchChecklistItemDisallowsChangingChecklist() { + $checklistItem = static::getFixture('checklistItem1_1_1'); + static::createClientWithCredentials()->request('PATCH', '/checklist_items/'.$checklistItem->getId(), ['json' => [ + 'checklist' => $this->getIriFor('checklistItem2_1_1'), + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]); + + $this->assertResponseStatusCodeSame(400); + $this->assertJsonContains([ + 'detail' => 'Extra attributes are not allowed ("checklist" is unknown).', + ]); + } + + public function testPatchChecklistItemValidatesNullText() { + $checklistItem = static::getFixture('checklistItem1_1_1'); + static::createClientWithCredentials()->request( + 'PATCH', + '/checklist_items/'.$checklistItem->getId(), + [ + 'json' => [ + 'text' => null, + ], + 'headers' => ['Content-Type' => 'application/merge-patch+json'], + ] + ); + + $this->assertResponseStatusCodeSame(400); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'The type of the "text" attribute must be "string", "NULL" given.', + ]); + } + + public function testPatchChecklistItemValidatesBlankText() { + $checklistItem = static::getFixture('checklistItem1_1_1'); + static::createClientWithCredentials()->request( + 'PATCH', + '/checklist_items/'.$checklistItem->getId(), + [ + 'json' => [ + 'text' => ' ', + ], + 'headers' => ['Content-Type' => 'application/merge-patch+json'], + ] + ); + + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'violations' => [ + [ + 'propertyPath' => 'text', + 'message' => 'This value should not be blank.', + ], + ], + ]); + } + + public function testPatchChecklistItemValidatesTooLongText() { + $checklistItem = static::getFixture('checklistItem1_1_1'); + static::createClientWithCredentials()->request( + 'PATCH', + '/checklist_items/'.$checklistItem->getId(), + [ + 'json' => [ + 'text' => str_repeat('l', 65), + ], + 'headers' => ['Content-Type' => 'application/merge-patch+json'], + ] + ); + + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'violations' => [ + [ + 'propertyPath' => 'text', + 'message' => 'This value is too long. It should have 64 characters or less.', + ], + ], + ]); + } + + public function testPatchChecklistItemTrimsText() { + $checklistItem = static::getFixture('checklistItem1_1_1'); + static::createClientWithCredentials()->request( + 'PATCH', + '/checklist_items/'.$checklistItem->getId(), + [ + 'json' => [ + 'text' => " \t Ziel 2\t ", + ], + 'headers' => ['Content-Type' => 'application/merge-patch+json'], ] + ); + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains( + [ + 'text' => 'Ziel 2', + ] + ); + } + + public function testPatchChecklistItemCleansForbiddenCharactersFromText() { + $checklistItem = static::getFixture('checklistItem1_1_1'); + $client = static::createClientWithCredentials(); + $client->disableReboot(); + $client->request( + 'PATCH', + '/checklist_items/'.$checklistItem->getId(), + [ + 'json' => [ + 'text' => "Ziel2\n\t", + ], + 'headers' => ['Content-Type' => 'application/merge-patch+json'], ] + ); + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains( + [ + 'text' => 'Ziel2', + ] + ); + } +} From cc876bbe46a93e97c1bd2634baceb108a5f050a7 Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Sun, 16 Jun 2024 13:58:29 +0200 Subject: [PATCH 07/69] Add ChecklistNode --- api/fixtures/checklistNodes.yml | 15 + api/fixtures/contentTypes.yml | 4 + .../schema/Version20240616104153.php | 34 + .../schema/Version20240616143000.php | 34 + api/src/Entity/ChecklistItem.php | 8 + api/src/Entity/ContentNode/ChecklistNode.php | 108 ++ .../Repository/ChecklistNodeRepository.php | 20 + .../ChecklistNodePersistProcessor.php | 40 + .../ContentNode/ListContentNodesTest.php | 6 +- .../Api/ContentTypes/ListContentTypesTest.php | 8 +- .../SnapshotTests/EndpointPerformanceTest.php | 4 +- .../Api/SnapshotTests/ReadItemFixtureMap.php | 1 + ...Structure with data set activities__1.json | 6 +- ...ta set content_nodechecklist_nodes__1.json | 42 + ...ata set content_nodecolumn_layouts__1.json | 34 +- ...ucture with data set content_nodes__1.json | 50 +- ...ucture with data set content_types__1.json | 16 + ...ta set content_nodechecklist_nodes__1.json | 25 + ...ure with data set schedule_entries__1.json | 6 +- ...est__testOpenApiSpecMatchesSnapshot__1.yml | 1129 +++++++++++++++++ ...t__testRootEndpointMatchesSnapshot__1.json | 4 + e2e/specs/httpCache.cy.js | 2 +- .../responses/content_types_collection.json | 18 +- 23 files changed, 1579 insertions(+), 35 deletions(-) create mode 100644 api/fixtures/checklistNodes.yml create mode 100644 api/migrations/schema/Version20240616104153.php create mode 100644 api/migrations/schema/Version20240616143000.php create mode 100644 api/src/Entity/ContentNode/ChecklistNode.php create mode 100644 api/src/Repository/ChecklistNodeRepository.php create mode 100644 api/src/State/ContentNode/ChecklistNodePersistProcessor.php create mode 100644 api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodechecklist_nodes__1.json create mode 100644 api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set content_nodechecklist_nodes__1.json diff --git a/api/fixtures/checklistNodes.yml b/api/fixtures/checklistNodes.yml new file mode 100644 index 0000000000..9351448280 --- /dev/null +++ b/api/fixtures/checklistNodes.yml @@ -0,0 +1,15 @@ +App\Entity\ContentNode\ChecklistNode: + checklistNode3: + root: '@columnLayout3' + parent: '@columnLayout3' + slot: '1' + position: 1 + instanceName: + contentType: '@contentTypeChecklist' + checklistNodeCampUnrelated: + root: '@columnLayout1campUnrelated' + parent: '@columnLayout1campUnrelated' + slot: '1' + position: 5 + instanceName: + contentType: '@contentTypeChecklist' \ No newline at end of file diff --git a/api/fixtures/contentTypes.yml b/api/fixtures/contentTypes.yml index a620bf2ee9..32d094ec28 100644 --- a/api/fixtures/contentTypes.yml +++ b/api/fixtures/contentTypes.yml @@ -40,3 +40,7 @@ App\Entity\ContentType: active: true entityClass: 'App\Entity\ContentNode\MultiSelect' jsonConfig: { items: [ 'outdoorTechnique', 'security', 'natureAndEnvironment', 'pioneeringTechnique', 'campsiteAndSurroundings', 'preventionAndIntegration' ] } + contentTypeChecklist: + name: 'Checklist' + active: true + entityClass: 'App\Entity\ContentNode\ChecklistNode' diff --git a/api/migrations/schema/Version20240616104153.php b/api/migrations/schema/Version20240616104153.php new file mode 100644 index 0000000000..340d9d16fd --- /dev/null +++ b/api/migrations/schema/Version20240616104153.php @@ -0,0 +1,34 @@ +addSql('CREATE TABLE checklistnode_checklistitem (checklistnode_id VARCHAR(16) NOT NULL, checklistitem_id VARCHAR(16) NOT NULL, PRIMARY KEY(checklistnode_id, checklistitem_id))'); + $this->addSql('CREATE INDEX IDX_5A2B5B31DE6B6F00 ON checklistnode_checklistitem (checklistnode_id)'); + $this->addSql('CREATE INDEX IDX_5A2B5B318A09A289 ON checklistnode_checklistitem (checklistitem_id)'); + $this->addSql('ALTER TABLE checklistnode_checklistitem ADD CONSTRAINT FK_5A2B5B31DE6B6F00 FOREIGN KEY (checklistnode_id) REFERENCES content_node (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE checklistnode_checklistitem ADD CONSTRAINT FK_5A2B5B318A09A289 FOREIGN KEY (checklistitem_id) REFERENCES checklist_item (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE SCHEMA public'); + $this->addSql('ALTER TABLE checklistnode_checklistitem DROP CONSTRAINT FK_5A2B5B31DE6B6F00'); + $this->addSql('ALTER TABLE checklistnode_checklistitem DROP CONSTRAINT FK_5A2B5B318A09A289'); + $this->addSql('DROP TABLE checklistnode_checklistitem'); + } +} diff --git a/api/migrations/schema/Version20240616143000.php b/api/migrations/schema/Version20240616143000.php new file mode 100644 index 0000000000..f18be0dcb8 --- /dev/null +++ b/api/migrations/schema/Version20240616143000.php @@ -0,0 +1,34 @@ +addSql(" + INSERT INTO public.content_type (id, name, active, entityclass, jsonconfig, createtime, updatetime) + VALUES ( + 'a4211c11211c', + 'Checklist', + true, + 'App\\Entity\\ContentNode\\ChecklistNode', + null, + '2024-06-16 14:30:00', + '2024-06-16 14:30:00' + ); + "); + } + + public function down(Schema $schema): void { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('DELETE FROM public.content_type WHERE id IN (\'a4211c11211c\')'); + } +} diff --git a/api/src/Entity/ChecklistItem.php b/api/src/Entity/ChecklistItem.php index aee087b9a6..c6c453806b 100644 --- a/api/src/Entity/ChecklistItem.php +++ b/api/src/Entity/ChecklistItem.php @@ -12,6 +12,7 @@ use ApiPlatform\Metadata\Link; use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Post; +use App\Entity\ContentNode\ChecklistNode; use App\InputFilter; use App\Repository\ChecklistItemRepository; use App\Util\EntityMap; @@ -100,6 +101,12 @@ class ChecklistItem extends BaseEntity implements BelongsToCampInterface, CopyFr #[ORM\OneToMany(targetEntity: ChecklistItem::class, mappedBy: 'parent', cascade: ['persist'])] public Collection $children; + /** + * All ChecklistNodes that have selected this ChecklistItem. + */ + #[ORM\ManyToMany(targetEntity: ChecklistNode::class, mappedBy: 'checklistItems')] + public Collection $checklistNodes; + /** * The human readable text of the checklist-item. */ @@ -125,6 +132,7 @@ class ChecklistItem extends BaseEntity implements BelongsToCampInterface, CopyFr public function __construct() { parent::__construct(); $this->children = new ArrayCollection(); + $this->checklistNodes = new ArrayCollection(); } #[ApiProperty(readable: false)] diff --git a/api/src/Entity/ContentNode/ChecklistNode.php b/api/src/Entity/ContentNode/ChecklistNode.php new file mode 100644 index 0000000000..237296a7b9 --- /dev/null +++ b/api/src/Entity/ContentNode/ChecklistNode.php @@ -0,0 +1,108 @@ + ['write', 'update']], + security: 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)', + validationContext: ['groups' => ['Default', 'update']] + ), + new Delete( + security: '(is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)) and object.parent !== null' + ), + new GetCollection( + security: 'is_authenticated()' + ), + new Post( + processor: ChecklistNodePersistProcessor::class, + denormalizationContext: ['groups' => ['write', 'create']], + securityPostDenormalize: 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)', + validationContext: ['groups' => ['Default', 'create']], + ), + ], + denormalizationContext: ['groups' => ['write']], + normalizationContext: ['groups' => ['read']], + routePrefix: '/content_node' +)] +#[ORM\Entity(repositoryClass: ChecklistNodeRepository::class)] +class ChecklistNode extends ContentNode { + /** + * The content types that are most likely to be useful for planning programme of this category. + */ + #[ApiProperty(example: '["/checklist_items/1a2b3c4d"]')] + #[Groups(['read'])] + #[ORM\ManyToMany(targetEntity: ChecklistItem::class, inversedBy: 'checklistNodes')] + #[ORM\JoinTable(name: 'checklistnode_checklistitem')] + #[ORM\JoinColumn(name: 'checklistnode_id', referencedColumnName: 'id')] + #[ORM\InverseJoinColumn(name: 'checklistitem_id', referencedColumnName: 'id')] + #[ORM\OrderBy(['position' => 'ASC'])] + public Collection $checklistItems; + + #[ApiProperty(example: '["1a2b3c4d"]')] + #[Groups(['write'])] + public ?array $addChecklistItemIds = []; + + #[ApiProperty(example: '["1a2b3c4d"]')] + #[Groups(['write'])] + public ?array $removeChecklistItemIds = []; + + public function __construct() { + parent::__construct(); + $this->checklistItems = new ArrayCollection(); + } + + /** + * @return ChecklistItem[] + */ + public function getChecklistItems(): array { + return $this->checklistItems->getValues(); + } + + public function addChecklistItem(ChecklistItem $checklistItem) { + $this->checklistItems->add($checklistItem); + } + + public function removeChecklistItem(ChecklistItem $checklistItem) { + $this->checklistItems->removeElement($checklistItem); + } + + /** + * @param ChecklistNode $prototype + * @param EntityMap $entityMap + */ + public function copyFromPrototype($prototype, $entityMap): void { + parent::copyFromPrototype($prototype, $entityMap); + + // copy all checklist-items + foreach ($prototype->checklistItems as $itemPrototype) { + /** @var ChecklistItem $itemPrototype */ + /** @var ChecklistItem $checklilstItem */ + $checklilstItem = $entityMap->get($itemPrototype); + $this->addChecklistItem($checklilstItem); + } + } +} diff --git a/api/src/Repository/ChecklistNodeRepository.php b/api/src/Repository/ChecklistNodeRepository.php new file mode 100644 index 0000000000..c6b9bafe84 --- /dev/null +++ b/api/src/Repository/ChecklistNodeRepository.php @@ -0,0 +1,20 @@ + + */ +class ChecklistNodeRepository extends ContentNodeRepository { + public function __construct(EntityManagerInterface $em) { + parent::__construct($em, ChecklistNode::class); + } +} diff --git a/api/src/State/ContentNode/ChecklistNodePersistProcessor.php b/api/src/State/ContentNode/ChecklistNodePersistProcessor.php new file mode 100644 index 0000000000..b138cf7b73 --- /dev/null +++ b/api/src/State/ContentNode/ChecklistNodePersistProcessor.php @@ -0,0 +1,40 @@ + + */ +class ChecklistNodePersistProcessor extends ContentNodePersistProcessor { + public function __construct( + ProcessorInterface $decorated, + private ChecklistItemRepository $checklistItemRepository, + ) { + parent::__construct($decorated); + } + + public function onBefore($data, Operation $operation, array $uriVariables = [], array $context = []): ChecklistNode { + /** @var ChecklistNode $data */ + $data = parent::onBefore($data, $operation, $uriVariables, $context); + + if (null !== $data->addChecklistItemIds) { + foreach ($data->addChecklistItemIds as $checklistItemId) { + $checklistItem = $this->checklistItemRepository->find($checklistItemId); + $data->addChecklistItem($checklistItem); + } + } + if (null !== $data->removeChecklistItemIds) { + foreach ($data->removeChecklistItemIds as $checklistItemId) { + $checklistItem = $this->checklistItemRepository->find($checklistItemId); + $data->removeChecklistItem($checklistItem); + } + } + + return $data; + } +} diff --git a/api/tests/Api/ContentNodes/ContentNode/ListContentNodesTest.php b/api/tests/Api/ContentNodes/ContentNode/ListContentNodesTest.php index 3ea968a731..430a93b593 100644 --- a/api/tests/Api/ContentNodes/ContentNode/ListContentNodesTest.php +++ b/api/tests/Api/ContentNodes/ContentNode/ListContentNodesTest.php @@ -23,7 +23,7 @@ public function testListContentNodesIsAllowedForLoggedInUserButFiltered() { $response = static::createClientWithCredentials()->request('GET', '/content_nodes'); $this->assertResponseStatusCodeSame(200); $this->assertJsonContains([ - 'totalItems' => 21, + 'totalItems' => 22, '_links' => [ 'items' => [], ], @@ -37,6 +37,7 @@ public function testListContentNodesIsAllowedForLoggedInUserButFiltered() { ['href' => $this->getIriFor('columnLayoutChild1')], ['href' => $this->getIriFor('columnLayout2Child1')], ['href' => $this->getIriFor('columnLayout3')], + ['href' => $this->getIriFor('checklistNode3')], ['href' => $this->getIriFor('columnLayout4')], ['href' => $this->getIriFor('columnLayout5')], ['href' => $this->getIriFor('columnLayout1camp2')], @@ -61,7 +62,7 @@ public function testListContentNodesFilteredByPeriodIsAllowedForCollaborator() { $response = static::createClientWithCredentials()->request('GET', '/content_nodes?period=%2Fperiods%2F'.$period->getId()); $this->assertResponseStatusCodeSame(200); $this->assertJsonContains([ - 'totalItems' => 12, + 'totalItems' => 13, '_links' => [ 'items' => [], ], @@ -73,6 +74,7 @@ public function testListContentNodesFilteredByPeriodIsAllowedForCollaborator() { ['href' => $this->getIriFor('columnLayout1')], ['href' => $this->getIriFor('columnLayoutChild1')], ['href' => $this->getIriFor('columnLayout3')], + ['href' => $this->getIriFor('checklistNode3')], ['href' => $this->getIriFor('singleText1')], ['href' => $this->getIriFor('singleText2')], ['href' => $this->getIriFor('safetyConcept1')], diff --git a/api/tests/Api/ContentTypes/ListContentTypesTest.php b/api/tests/Api/ContentTypes/ListContentTypesTest.php index 79cd0bf6ed..c5a58ccee6 100644 --- a/api/tests/Api/ContentTypes/ListContentTypesTest.php +++ b/api/tests/Api/ContentTypes/ListContentTypesTest.php @@ -12,7 +12,7 @@ public function testListContentTypesIsAllowedForAnonymousUser() { $response = static::createBasicClient()->request('GET', '/content_types'); $this->assertResponseStatusCodeSame(200); $this->assertJsonContains([ - 'totalItems' => 10, + 'totalItems' => 11, '_links' => [ 'items' => [], ], @@ -21,14 +21,14 @@ public function testListContentTypesIsAllowedForAnonymousUser() { ], ]); - $this->assertCount(10, $response->toArray()['_links']['items']); + $this->assertCount(11, $response->toArray()['_links']['items']); } public function testListContentTypesIsAllowedForLoggedInUser() { $response = static::createClientWithCredentials()->request('GET', '/content_types'); $this->assertResponseStatusCodeSame(200); $this->assertJsonContains([ - 'totalItems' => 10, + 'totalItems' => 11, '_links' => [ 'items' => [], ], @@ -36,6 +36,6 @@ public function testListContentTypesIsAllowedForLoggedInUser() { 'items' => [], ], ]); - $this->assertCount(10, $response->toArray()['_links']['items']); + $this->assertCount(11, $response->toArray()['_links']['items']); } } diff --git a/api/tests/Api/SnapshotTests/EndpointPerformanceTest.php b/api/tests/Api/SnapshotTests/EndpointPerformanceTest.php index 93cb47f721..1463bb5cd4 100644 --- a/api/tests/Api/SnapshotTests/EndpointPerformanceTest.php +++ b/api/tests/Api/SnapshotTests/EndpointPerformanceTest.php @@ -186,9 +186,11 @@ protected function getSnapshotId(): string { private static function getContentNodeEndpointQueryCountRanges(): array { return [ - '/content_nodes' => [8, 9], + '/content_nodes' => [8, 10], '/content_node/column_layouts' => [6, 6], '/content_node/column_layouts/item' => [10, 10], + '/content_node/checklist_nodes' => [6, 7], + '/content_node/checklist_nodes/item' => [9, 9], '/content_node/material_nodes' => [6, 7], '/content_node/material_nodes/item' => [9, 9], '/content_node/multi_selects' => [6, 7], diff --git a/api/tests/Api/SnapshotTests/ReadItemFixtureMap.php b/api/tests/Api/SnapshotTests/ReadItemFixtureMap.php index a734aa4518..33fa16dfd3 100644 --- a/api/tests/Api/SnapshotTests/ReadItemFixtureMap.php +++ b/api/tests/Api/SnapshotTests/ReadItemFixtureMap.php @@ -13,6 +13,7 @@ public static function get(string $collectionEndpoint, array $fixtures): mixed { '/categories' => $fixtures['category1'], '/checklists' => $fixtures['checklist1'], '/checklist_items' => $fixtures['checklistItem1_1_1'], + '/content_node/checklist_nodes' => $fixtures['checklistNode3'], '/content_node/column_layouts' => $fixtures['columnLayout2'], '/content_node/responsive_layouts' => $fixtures['responsiveLayout1'], '/content_types' => $fixtures['contentTypeSafetyConcept'], diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set activities__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set activities__1.json index eab677ee6d..17f0da395c 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set activities__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set activities__1.json @@ -381,7 +381,11 @@ }, "rootContentNode": { "_links": { - "children": [], + "children": [ + { + "href": "escaped_value" + } + ], "contentType": { "href": "escaped_value" }, diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodechecklist_nodes__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodechecklist_nodes__1.json new file mode 100644 index 0000000000..a657327a12 --- /dev/null +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodechecklist_nodes__1.json @@ -0,0 +1,42 @@ +{ + "_embedded": { + "items": [ + { + "_links": { + "checklist": "escaped_value", + "checklistItems": [], + "children": [], + "contentType": { + "href": "escaped_value" + }, + "parent": { + "href": "escaped_value" + }, + "root": { + "href": "escaped_value" + }, + "self": { + "href": "escaped_value" + } + }, + "contentTypeName": "escaped_value", + "data": "escaped_value", + "id": "escaped_value", + "instanceName": "escaped_value", + "position": "escaped_value", + "slot": "escaped_value" + } + ] + }, + "_links": { + "items": [ + { + "href": "escaped_value" + } + ], + "self": { + "href": "escaped_value" + } + }, + "totalItems": "escaped_value" +} diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodecolumn_layouts__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodecolumn_layouts__1.json index dbdfe83685..2c6362ca64 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodecolumn_layouts__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodecolumn_layouts__1.json @@ -147,7 +147,9 @@ "contentType": { "href": "escaped_value" }, - "parent": "escaped_value", + "parent": { + "href": "escaped_value" + }, "root": { "href": "escaped_value" }, @@ -171,7 +173,17 @@ }, { "_links": { - "children": [], + "children": [ + { + "href": "escaped_value" + }, + { + "href": "escaped_value" + }, + { + "href": "escaped_value" + } + ], "contentType": { "href": "escaped_value" }, @@ -188,6 +200,10 @@ "contentTypeName": "escaped_value", "data": { "columns": [ + { + "slot": "escaped_value", + "width": "escaped_value" + }, { "slot": "escaped_value", "width": "escaped_value" @@ -202,12 +218,6 @@ { "_links": { "children": [ - { - "href": "escaped_value" - }, - { - "href": "escaped_value" - }, { "href": "escaped_value" } @@ -215,9 +225,7 @@ "contentType": { "href": "escaped_value" }, - "parent": { - "href": "escaped_value" - }, + "parent": "escaped_value", "root": { "href": "escaped_value" }, @@ -228,10 +236,6 @@ "contentTypeName": "escaped_value", "data": { "columns": [ - { - "slot": "escaped_value", - "width": "escaped_value" - }, { "slot": "escaped_value", "width": "escaped_value" diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodes__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodes__1.json index 6945297e6c..540f43263f 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodes__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodes__1.json @@ -80,11 +80,15 @@ }, { "_links": { + "checklist": "escaped_value", + "checklistItems": [], "children": [], "contentType": { "href": "escaped_value" }, - "parent": "escaped_value", + "parent": { + "href": "escaped_value" + }, "root": { "href": "escaped_value" }, @@ -93,14 +97,7 @@ } }, "contentTypeName": "escaped_value", - "data": { - "columns": [ - { - "slot": "escaped_value", - "width": "escaped_value" - } - ] - }, + "data": "escaped_value", "id": "escaped_value", "instanceName": "escaped_value", "position": "escaped_value", @@ -644,6 +641,38 @@ "position": "escaped_value", "slot": "escaped_value" }, + { + "_links": { + "children": [ + { + "href": "escaped_value" + } + ], + "contentType": { + "href": "escaped_value" + }, + "parent": "escaped_value", + "root": { + "href": "escaped_value" + }, + "self": { + "href": "escaped_value" + } + }, + "contentTypeName": "escaped_value", + "data": { + "columns": [ + { + "slot": "escaped_value", + "width": "escaped_value" + } + ] + }, + "id": "escaped_value", + "instanceName": "escaped_value", + "position": "escaped_value", + "slot": "escaped_value" + }, { "_links": { "children": [ @@ -740,6 +769,9 @@ { "href": "escaped_value" }, + { + "href": "escaped_value" + }, { "href": "escaped_value" } diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_types__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_types__1.json index d8875812f3..8656a040cf 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_types__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_types__1.json @@ -118,6 +118,19 @@ "id": "escaped_value", "name": "escaped_value" }, + { + "_links": { + "contentNodes": { + "href": "escaped_value" + }, + "self": { + "href": "escaped_value" + } + }, + "active": "escaped_value", + "id": "escaped_value", + "name": "escaped_value" + }, { "_links": { "contentNodes": { @@ -162,6 +175,9 @@ { "href": "escaped_value" }, + { + "href": "escaped_value" + }, { "href": "escaped_value" } diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set content_nodechecklist_nodes__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set content_nodechecklist_nodes__1.json new file mode 100644 index 0000000000..f883ff8e4f --- /dev/null +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set content_nodechecklist_nodes__1.json @@ -0,0 +1,25 @@ +{ + "_links": { + "checklist": "escaped_value", + "checklistItems": [], + "children": [], + "contentType": { + "href": "escaped_value" + }, + "parent": { + "href": "escaped_value" + }, + "root": { + "href": "escaped_value" + }, + "self": { + "href": "escaped_value" + } + }, + "contentTypeName": "escaped_value", + "data": "escaped_value", + "id": "escaped_value", + "instanceName": "escaped_value", + "position": "escaped_value", + "slot": "escaped_value" +} diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set schedule_entries__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set schedule_entries__1.json index 3bc182b966..56715cb3b4 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set schedule_entries__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set schedule_entries__1.json @@ -4,7 +4,11 @@ "_embedded": { "rootContentNode": { "_links": { - "children": [], + "children": [ + { + "href": "escaped_value" + } + ], "contentType": { "href": "escaped_value" }, diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml index 70dbc0ebc5..67a199a93c 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml @@ -8311,6 +8311,846 @@ components: - position - text type: object + ChecklistNode-read: + deprecated: false + description: '' + properties: + checklist: + description: 'The Checklist this Item belongs to.' + example: /checklists/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + checklistItems: + description: 'The content types that are most likely to be useful for planning programme of this category.' + example: '["/checklist_items/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + type: array + children: + description: 'All content nodes that are direct children of this content node.' + example: '["/content_nodes/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array + contentType: + description: |- + Defines the type of this content node. There is a fixed list of types that are implemented + in eCamp. Depending on the type, different content data and different slots may be allowed + in a content node. The content type may not be changed once the content node is created. + example: /content_types/1a2b3c4d + format: iri-reference + type: string + contentTypeName: + description: 'The name of the content type of this content node. Read-only, for convenience.' + example: SafetyConcept + readOnly: true + type: string + data: + description: 'Holds the actual data of the content node.' + example: + text: 'dummy text' + items: + type: string + type: + - array + - 'null' + id: + description: 'An internal, unique, randomly generated identifier of this entity.' + example: 1a2b3c4d + maxLength: 16 + readOnly: true + type: string + instanceName: + description: |- + An optional name for this content node. This is useful when planning e.g. an alternative + version of the programme suited for bad weather, in addition to the normal version. + example: Schlechtwetterprogramm + maxLength: 32 + type: + - 'null' + - string + parent: + description: |- + The parent to which this content node belongs. Is null in case this content node is the + root of a content node tree. For non-root content nodes, the parent can be changed, as long + as the new parent is in the same camp as the old one. + example: /content_nodes/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + position: + default: -1 + description: |- + A whole number used for ordering multiple content nodes that are in the same slot of the + same parent. The API does not guarantee the uniqueness of parent+slot+position. + example: -1 + type: integer + root: + description: |- + The content node that is the root of the content node tree. Refers to itself in case this + content node is the root. + example: /content_nodes/1a2b3c4d + format: iri-reference + readOnly: true + type: + - 'null' + - string + slot: + description: |- + The name of the slot in the parent in which this content node resides. The valid slot names + are defined by the content type of the parent. + example: '1' + maxLength: 32 + type: + - 'null' + - string + required: + - checklistItems + - children + - contentType + - position + type: object + ChecklistNode-write_create: + deprecated: false + description: '' + properties: + addChecklistItemIds: + example: '["1a2b3c4d"]' + items: + type: string + type: + - array + - 'null' + checklist: + description: 'The Checklist this Item belongs to.' + example: /checklists/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + checklistItems: + description: 'The content types that are most likely to be useful for planning programme of this category.' + example: '["/checklist_items/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + type: array + contentType: + description: |- + Defines the type of this content node. There is a fixed list of types that are implemented + in eCamp. Depending on the type, different content data and different slots may be allowed + in a content node. The content type may not be changed once the content node is created. + example: /content_types/1a2b3c4d + format: iri-reference + type: string + data: + description: 'Holds the actual data of the content node.' + example: + text: 'dummy text' + items: + type: string + type: + - array + - 'null' + instanceName: + description: |- + An optional name for this content node. This is useful when planning e.g. an alternative + version of the programme suited for bad weather, in addition to the normal version. + example: Schlechtwetterprogramm + maxLength: 32 + type: + - 'null' + - string + parent: + description: |- + The parent to which this content node belongs. Is null in case this content node is the + root of a content node tree. For non-root content nodes, the parent can be changed, as long + as the new parent is in the same camp as the old one. + example: /content_nodes/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + position: + default: -1 + description: |- + A whole number used for ordering multiple content nodes that are in the same slot of the + same parent. The API does not guarantee the uniqueness of parent+slot+position. + example: -1 + type: integer + removeChecklistItemIds: + example: '["1a2b3c4d"]' + items: + type: string + type: + - array + - 'null' + slot: + description: |- + The name of the slot in the parent in which this content node resides. The valid slot names + are defined by the content type of the parent. + example: '1' + maxLength: 32 + type: + - 'null' + - string + required: + - checklistItems + - contentType + - parent + - position + type: object + ChecklistNode-write_update: + deprecated: false + description: '' + properties: + addChecklistItemIds: + example: '["1a2b3c4d"]' + items: + type: string + type: + - array + - 'null' + checklist: + description: 'The Checklist this Item belongs to.' + example: /checklists/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + checklistItems: + description: 'The content types that are most likely to be useful for planning programme of this category.' + example: '["/checklist_items/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + type: array + data: + description: 'Holds the actual data of the content node.' + example: + text: 'dummy text' + items: + type: string + type: + - array + - 'null' + instanceName: + description: |- + An optional name for this content node. This is useful when planning e.g. an alternative + version of the programme suited for bad weather, in addition to the normal version. + example: Schlechtwetterprogramm + maxLength: 32 + type: + - 'null' + - string + parent: + description: |- + The parent to which this content node belongs. Is null in case this content node is the + root of a content node tree. For non-root content nodes, the parent can be changed, as long + as the new parent is in the same camp as the old one. + example: /content_nodes/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + position: + default: -1 + description: |- + A whole number used for ordering multiple content nodes that are in the same slot of the + same parent. The API does not guarantee the uniqueness of parent+slot+position. + example: -1 + type: integer + removeChecklistItemIds: + example: '["1a2b3c4d"]' + items: + type: string + type: + - array + - 'null' + slot: + description: |- + The name of the slot in the parent in which this content node resides. The valid slot names + are defined by the content type of the parent. + example: '1' + maxLength: 32 + type: + - 'null' + - string + required: + - checklistItems + - position + type: object + ChecklistNode.jsonapi: + deprecated: false + description: '' + properties: + addChecklistItemIds: + example: '["1a2b3c4d"]' + items: + type: string + type: + - array + - 'null' + writeOnly: true + checklist: + description: 'The Checklist this Item belongs to.' + example: /checklists/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + checklistItems: + description: 'The content types that are most likely to be useful for planning programme of this category.' + example: '["/checklist_items/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + type: array + children: + description: 'All content nodes that are direct children of this content node.' + example: '["/content_nodes/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array + contentType: + description: |- + Defines the type of this content node. There is a fixed list of types that are implemented + in eCamp. Depending on the type, different content data and different slots may be allowed + in a content node. The content type may not be changed once the content node is created. + example: /content_types/1a2b3c4d + format: iri-reference + readOnly: true + type: string + contentTypeName: + description: 'The name of the content type of this content node. Read-only, for convenience.' + example: SafetyConcept + readOnly: true + type: string + data: + description: 'Holds the actual data of the content node.' + example: + text: 'dummy text' + items: + type: string + type: + - array + - 'null' + id: + description: 'An internal, unique, randomly generated identifier of this entity.' + example: 1a2b3c4d + maxLength: 16 + readOnly: true + type: string + instanceName: + description: |- + An optional name for this content node. This is useful when planning e.g. an alternative + version of the programme suited for bad weather, in addition to the normal version. + example: Schlechtwetterprogramm + maxLength: 32 + type: + - 'null' + - string + parent: + description: |- + The parent to which this content node belongs. Is null in case this content node is the + root of a content node tree. For non-root content nodes, the parent can be changed, as long + as the new parent is in the same camp as the old one. + example: /content_nodes/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + position: + default: -1 + description: |- + A whole number used for ordering multiple content nodes that are in the same slot of the + same parent. The API does not guarantee the uniqueness of parent+slot+position. + example: -1 + type: integer + removeChecklistItemIds: + example: '["1a2b3c4d"]' + items: + type: string + type: + - array + - 'null' + writeOnly: true + root: + description: |- + The content node that is the root of the content node tree. Refers to itself in case this + content node is the root. + example: /content_nodes/1a2b3c4d + format: iri-reference + readOnly: true + type: + - 'null' + - string + slot: + description: |- + The name of the slot in the parent in which this content node resides. The valid slot names + are defined by the content type of the parent. + example: '1' + maxLength: 32 + type: + - 'null' + - string + required: + - checklistItems + - children + - contentType + - position + type: object + ChecklistNode.jsonhal-read: + deprecated: false + description: '' + properties: + _links: + properties: + self: + properties: + href: + format: iri-reference + type: string + type: object + type: object + checklist: + description: 'The Checklist this Item belongs to.' + example: /checklists/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + checklistItems: + description: 'The content types that are most likely to be useful for planning programme of this category.' + example: '["/checklist_items/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + type: array + children: + description: 'All content nodes that are direct children of this content node.' + example: '["/content_nodes/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array + contentType: + description: |- + Defines the type of this content node. There is a fixed list of types that are implemented + in eCamp. Depending on the type, different content data and different slots may be allowed + in a content node. The content type may not be changed once the content node is created. + example: /content_types/1a2b3c4d + format: iri-reference + type: string + contentTypeName: + description: 'The name of the content type of this content node. Read-only, for convenience.' + example: SafetyConcept + readOnly: true + type: string + data: + description: 'Holds the actual data of the content node.' + example: + text: 'dummy text' + items: + type: string + type: + - array + - 'null' + id: + description: 'An internal, unique, randomly generated identifier of this entity.' + example: 1a2b3c4d + maxLength: 16 + readOnly: true + type: string + instanceName: + description: |- + An optional name for this content node. This is useful when planning e.g. an alternative + version of the programme suited for bad weather, in addition to the normal version. + example: Schlechtwetterprogramm + maxLength: 32 + type: + - 'null' + - string + parent: + description: |- + The parent to which this content node belongs. Is null in case this content node is the + root of a content node tree. For non-root content nodes, the parent can be changed, as long + as the new parent is in the same camp as the old one. + example: /content_nodes/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + position: + default: -1 + description: |- + A whole number used for ordering multiple content nodes that are in the same slot of the + same parent. The API does not guarantee the uniqueness of parent+slot+position. + example: -1 + type: integer + root: + description: |- + The content node that is the root of the content node tree. Refers to itself in case this + content node is the root. + example: /content_nodes/1a2b3c4d + format: iri-reference + readOnly: true + type: + - 'null' + - string + slot: + description: |- + The name of the slot in the parent in which this content node resides. The valid slot names + are defined by the content type of the parent. + example: '1' + maxLength: 32 + type: + - 'null' + - string + required: + - checklistItems + - children + - contentType + - position + type: object + ChecklistNode.jsonhal-write_create: + deprecated: false + description: '' + properties: + _links: + properties: + self: + properties: + href: + format: iri-reference + type: string + type: object + type: object + addChecklistItemIds: + example: '["1a2b3c4d"]' + items: + type: string + type: + - array + - 'null' + checklist: + description: 'The Checklist this Item belongs to.' + example: /checklists/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + checklistItems: + description: 'The content types that are most likely to be useful for planning programme of this category.' + example: '["/checklist_items/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + type: array + contentType: + description: |- + Defines the type of this content node. There is a fixed list of types that are implemented + in eCamp. Depending on the type, different content data and different slots may be allowed + in a content node. The content type may not be changed once the content node is created. + example: /content_types/1a2b3c4d + format: iri-reference + type: string + data: + description: 'Holds the actual data of the content node.' + example: + text: 'dummy text' + items: + type: string + type: + - array + - 'null' + instanceName: + description: |- + An optional name for this content node. This is useful when planning e.g. an alternative + version of the programme suited for bad weather, in addition to the normal version. + example: Schlechtwetterprogramm + maxLength: 32 + type: + - 'null' + - string + parent: + description: |- + The parent to which this content node belongs. Is null in case this content node is the + root of a content node tree. For non-root content nodes, the parent can be changed, as long + as the new parent is in the same camp as the old one. + example: /content_nodes/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + position: + default: -1 + description: |- + A whole number used for ordering multiple content nodes that are in the same slot of the + same parent. The API does not guarantee the uniqueness of parent+slot+position. + example: -1 + type: integer + removeChecklistItemIds: + example: '["1a2b3c4d"]' + items: + type: string + type: + - array + - 'null' + slot: + description: |- + The name of the slot in the parent in which this content node resides. The valid slot names + are defined by the content type of the parent. + example: '1' + maxLength: 32 + type: + - 'null' + - string + required: + - checklistItems + - contentType + - parent + - position + type: object + ChecklistNode.jsonld-read: + deprecated: false + description: '' + properties: + '@context': + oneOf: + - + additionalProperties: true + properties: + '@vocab': + type: string + hydra: + enum: ['http://www.w3.org/ns/hydra/core#'] + type: string + required: + - '@vocab' + - hydra + type: object + - + type: string + readOnly: true + '@id': + readOnly: true + type: string + '@type': + readOnly: true + type: string + checklist: + description: 'The Checklist this Item belongs to.' + example: /checklists/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + checklistItems: + description: 'The content types that are most likely to be useful for planning programme of this category.' + example: '["/checklist_items/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + type: array + children: + description: 'All content nodes that are direct children of this content node.' + example: '["/content_nodes/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + readOnly: true + type: array + contentType: + description: |- + Defines the type of this content node. There is a fixed list of types that are implemented + in eCamp. Depending on the type, different content data and different slots may be allowed + in a content node. The content type may not be changed once the content node is created. + example: /content_types/1a2b3c4d + format: iri-reference + type: string + contentTypeName: + description: 'The name of the content type of this content node. Read-only, for convenience.' + example: SafetyConcept + readOnly: true + type: string + data: + description: 'Holds the actual data of the content node.' + example: + text: 'dummy text' + items: + type: string + type: + - array + - 'null' + id: + description: 'An internal, unique, randomly generated identifier of this entity.' + example: 1a2b3c4d + maxLength: 16 + readOnly: true + type: string + instanceName: + description: |- + An optional name for this content node. This is useful when planning e.g. an alternative + version of the programme suited for bad weather, in addition to the normal version. + example: Schlechtwetterprogramm + maxLength: 32 + type: + - 'null' + - string + parent: + description: |- + The parent to which this content node belongs. Is null in case this content node is the + root of a content node tree. For non-root content nodes, the parent can be changed, as long + as the new parent is in the same camp as the old one. + example: /content_nodes/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + position: + default: -1 + description: |- + A whole number used for ordering multiple content nodes that are in the same slot of the + same parent. The API does not guarantee the uniqueness of parent+slot+position. + example: -1 + type: integer + root: + description: |- + The content node that is the root of the content node tree. Refers to itself in case this + content node is the root. + example: /content_nodes/1a2b3c4d + format: iri-reference + readOnly: true + type: + - 'null' + - string + slot: + description: |- + The name of the slot in the parent in which this content node resides. The valid slot names + are defined by the content type of the parent. + example: '1' + maxLength: 32 + type: + - 'null' + - string + required: + - checklistItems + - children + - contentType + - position + type: object + ChecklistNode.jsonld-write_create: + deprecated: false + description: '' + properties: + addChecklistItemIds: + example: '["1a2b3c4d"]' + items: + type: string + type: + - array + - 'null' + checklist: + description: 'The Checklist this Item belongs to.' + example: /checklists/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + checklistItems: + description: 'The content types that are most likely to be useful for planning programme of this category.' + example: '["/checklist_items/1a2b3c4d"]' + items: + example: 'https://example.com/' + format: iri-reference + type: string + type: array + contentType: + description: |- + Defines the type of this content node. There is a fixed list of types that are implemented + in eCamp. Depending on the type, different content data and different slots may be allowed + in a content node. The content type may not be changed once the content node is created. + example: /content_types/1a2b3c4d + format: iri-reference + type: string + data: + description: 'Holds the actual data of the content node.' + example: + text: 'dummy text' + items: + type: string + type: + - array + - 'null' + instanceName: + description: |- + An optional name for this content node. This is useful when planning e.g. an alternative + version of the programme suited for bad weather, in addition to the normal version. + example: Schlechtwetterprogramm + maxLength: 32 + type: + - 'null' + - string + parent: + description: |- + The parent to which this content node belongs. Is null in case this content node is the + root of a content node tree. For non-root content nodes, the parent can be changed, as long + as the new parent is in the same camp as the old one. + example: /content_nodes/1a2b3c4d + format: iri-reference + type: + - 'null' + - string + position: + default: -1 + description: |- + A whole number used for ordering multiple content nodes that are in the same slot of the + same parent. The API does not guarantee the uniqueness of parent+slot+position. + example: -1 + type: integer + removeChecklistItemIds: + example: '["1a2b3c4d"]' + items: + type: string + type: + - array + - 'null' + slot: + description: |- + The name of the slot in the parent in which this content node resides. The valid slot names + are defined by the content type of the parent. + example: '1' + maxLength: 32 + type: + - 'null' + - string + required: + - checklistItems + - contentType + - parent + - position + type: object ColumnLayout-read: deprecated: false description: '' @@ -24613,6 +25453,295 @@ paths: summary: 'Updates the Checklist resource.' tags: - Checklist + /content_node/checklist_nodes: + get: + deprecated: false + description: 'Retrieves the collection of ChecklistNode resources.' + operationId: api_content_nodechecklist_nodes_get_collection + parameters: + - + allowEmptyValue: true + allowReserved: false + deprecated: false + description: '' + explode: false + in: query + name: contentType + required: false + schema: + type: string + style: form + - + allowEmptyValue: true + allowReserved: false + deprecated: false + description: '' + explode: false + in: query + name: period + required: false + schema: + type: string + style: form + - + allowEmptyValue: true + allowReserved: false + deprecated: false + description: '' + explode: false + in: query + name: root + required: false + schema: + type: string + style: form + - + allowEmptyValue: true + allowReserved: false + deprecated: false + description: '' + explode: true + in: query + name: 'contentType[]' + required: false + schema: + items: + type: string + type: array + style: form + - + allowEmptyValue: true + allowReserved: false + deprecated: false + description: '' + explode: true + in: query + name: 'root[]' + required: false + schema: + items: + type: string + type: array + style: form + responses: + 200: + content: + application/hal+json: + schema: + properties: + _embedded: { anyOf: [{ properties: { item: { items: { $ref: '#/components/schemas/ChecklistNode.jsonhal-read' }, type: array } }, type: object }, { type: object }] } + _links: { properties: { first: { properties: { href: { format: iri-reference, type: string } }, type: object }, last: { properties: { href: { format: iri-reference, type: string } }, type: object }, next: { properties: { href: { format: iri-reference, type: string } }, type: object }, previous: { properties: { href: { format: iri-reference, type: string } }, type: object }, self: { properties: { href: { format: iri-reference, type: string } }, type: object } }, type: object } + itemsPerPage: { minimum: 0, type: integer } + totalItems: { minimum: 0, type: integer } + required: + - _embedded + - _links + type: object + application/json: + schema: + items: + $ref: '#/components/schemas/ChecklistNode-read' + type: array + application/ld+json: + schema: + properties: + 'hydra:member': { items: { $ref: '#/components/schemas/ChecklistNode.jsonld-read' }, type: array } + 'hydra:search': { properties: { '@type': { type: string }, 'hydra:mapping': { items: { properties: { '@type': { type: string }, property: { type: ['null', string] }, required: { type: boolean }, variable: { type: string } }, type: object }, type: array }, 'hydra:template': { type: string }, 'hydra:variableRepresentation': { type: string } }, type: object } + 'hydra:totalItems': { minimum: 0, type: integer } + 'hydra:view': { example: { '@id': string, 'hydra:first': string, 'hydra:last': string, 'hydra:next': string, 'hydra:previous': string, type: string }, properties: { '@id': { format: iri-reference, type: string }, '@type': { type: string }, 'hydra:first': { format: iri-reference, type: string }, 'hydra:last': { format: iri-reference, type: string }, 'hydra:next': { format: iri-reference, type: string }, 'hydra:previous': { format: iri-reference, type: string } }, type: object } + required: + - 'hydra:member' + type: object + application/vnd.api+json: + schema: + items: + $ref: '#/components/schemas/ChecklistNode.jsonapi' + type: array + text/html: + schema: + items: + $ref: '#/components/schemas/ChecklistNode-read' + type: array + description: 'ChecklistNode collection' + summary: 'Retrieves the collection of ChecklistNode resources.' + tags: + - ChecklistNode + parameters: [] + post: + deprecated: false + description: 'Creates a ChecklistNode resource.' + operationId: api_content_nodechecklist_nodes_post + parameters: [] + requestBody: + content: + application/hal+json: + schema: + $ref: '#/components/schemas/ChecklistNode.jsonhal-write_create' + application/json: + schema: + $ref: '#/components/schemas/ChecklistNode-write_create' + application/ld+json: + schema: + $ref: '#/components/schemas/ChecklistNode.jsonld-write_create' + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ChecklistNode.jsonapi' + text/html: + schema: + $ref: '#/components/schemas/ChecklistNode-write_create' + description: 'The new ChecklistNode resource' + required: true + responses: + 201: + content: + application/hal+json: + schema: + $ref: '#/components/schemas/ChecklistNode.jsonhal-read' + application/json: + schema: + $ref: '#/components/schemas/ChecklistNode-read' + application/ld+json: + schema: + $ref: '#/components/schemas/ChecklistNode.jsonld-read' + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ChecklistNode.jsonapi' + text/html: + schema: + $ref: '#/components/schemas/ChecklistNode-read' + description: 'ChecklistNode resource created' + links: [] + 400: + description: 'Invalid input' + 422: + description: 'Unprocessable entity' + summary: 'Creates a ChecklistNode resource.' + tags: + - ChecklistNode + '/content_node/checklist_nodes/{id}': + delete: + deprecated: false + description: 'Removes the ChecklistNode resource.' + operationId: api_content_nodechecklist_nodes_id_delete + parameters: + - + allowEmptyValue: false + allowReserved: false + deprecated: false + description: 'ChecklistNode identifier' + explode: false + in: path + name: id + required: true + schema: + type: string + style: simple + responses: + 204: + description: 'ChecklistNode resource deleted' + 404: + description: 'Resource not found' + summary: 'Removes the ChecklistNode resource.' + tags: + - ChecklistNode + get: + deprecated: false + description: 'Retrieves a ChecklistNode resource.' + operationId: api_content_nodechecklist_nodes_id_get + parameters: + - + allowEmptyValue: false + allowReserved: false + deprecated: false + description: 'ChecklistNode identifier' + explode: false + in: path + name: id + required: true + schema: + type: string + style: simple + responses: + 200: + content: + application/hal+json: + schema: + $ref: '#/components/schemas/ChecklistNode.jsonhal-read' + application/json: + schema: + $ref: '#/components/schemas/ChecklistNode-read' + application/ld+json: + schema: + $ref: '#/components/schemas/ChecklistNode.jsonld-read' + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ChecklistNode.jsonapi' + text/html: + schema: + $ref: '#/components/schemas/ChecklistNode-read' + description: 'ChecklistNode resource' + 404: + description: 'Resource not found' + summary: 'Retrieves a ChecklistNode resource.' + tags: + - ChecklistNode + parameters: [] + patch: + deprecated: false + description: 'Updates the ChecklistNode resource.' + operationId: api_content_nodechecklist_nodes_id_patch + parameters: + - + allowEmptyValue: false + allowReserved: false + deprecated: false + description: 'ChecklistNode identifier' + explode: false + in: path + name: id + required: true + schema: + type: string + style: simple + requestBody: + content: + application/merge-patch+json: + schema: + $ref: '#/components/schemas/ChecklistNode-write_update' + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ChecklistNode.jsonapi' + description: 'The updated ChecklistNode resource' + required: true + responses: + 200: + content: + application/hal+json: + schema: + $ref: '#/components/schemas/ChecklistNode.jsonhal-read' + application/json: + schema: + $ref: '#/components/schemas/ChecklistNode-read' + application/ld+json: + schema: + $ref: '#/components/schemas/ChecklistNode.jsonld-read' + application/vnd.api+json: + schema: + $ref: '#/components/schemas/ChecklistNode.jsonapi' + text/html: + schema: + $ref: '#/components/schemas/ChecklistNode-read' + description: 'ChecklistNode resource updated' + links: [] + 400: + description: 'Invalid input' + 404: + description: 'Resource not found' + 422: + description: 'Unprocessable entity' + summary: 'Updates the ChecklistNode resource.' + tags: + - ChecklistNode /content_node/column_layouts: get: deprecated: false diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testRootEndpointMatchesSnapshot__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testRootEndpointMatchesSnapshot__1.json index 08bdba78ce..040d83054a 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testRootEndpointMatchesSnapshot__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testRootEndpointMatchesSnapshot__1.json @@ -28,6 +28,10 @@ "href": "\/checklist_items{\/id}{?checklist,checklist[]}", "templated": true }, + "checklistNodes": { + "href": "\/content_node\/checklist_nodes{\/id}{?contentType,contentType[],root,root[],period}", + "templated": true + }, "checklists": { "href": "\/checklists{\/id}{?camp,camp[]}", "templated": true diff --git a/e2e/specs/httpCache.cy.js b/e2e/specs/httpCache.cy.js index 4b0fc346be..14a5412ee5 100644 --- a/e2e/specs/httpCache.cy.js +++ b/e2e/specs/httpCache.cy.js @@ -9,7 +9,7 @@ describe('HTTP cache tests', () => { cy.request(Cypress.env('API_ROOT_URL_CACHED') + uri + '.jsonhal').then((response) => { const headers = response.headers expect(headers.xkey).to.eq( - 'c462edd869f3 5e2028c55ee4 a4211c112939 f17470519474 1a0f84e322c8 3ef17bd1df72 4f0c657fecef 44dcc7493c65 cfccaecd4bad 318e064ea0c9 /api/content_types' + 'a4211c11211c c462edd869f3 5e2028c55ee4 a4211c112939 f17470519474 1a0f84e322c8 3ef17bd1df72 4f0c657fecef 44dcc7493c65 cfccaecd4bad 318e064ea0c9 /api/content_types' ) expect(headers['x-cache']).to.eq('MISS') cy.readFile('./specs/responses/content_types_collection.json').then((data) => diff --git a/e2e/specs/responses/content_types_collection.json b/e2e/specs/responses/content_types_collection.json index f209e6a3b5..54ec47fb5c 100644 --- a/e2e/specs/responses/content_types_collection.json +++ b/e2e/specs/responses/content_types_collection.json @@ -4,6 +4,9 @@ "href": "/api/content_types.jsonhal" }, "items": [ + { + "href": "/api/content_types/a4211c11211c" + }, { "href": "/api/content_types/c462edd869f3" }, @@ -36,9 +39,22 @@ } ] }, - "totalItems": 10, + "totalItems": 11, "_embedded": { "items": [ + { + "_links": { + "self": { + "href": "/api/content_types/a4211c11211c" + }, + "contentNodes": { + "href": "/api/content_node/checklist_nodes?contentType=%2Fapi%2Fcontent_types%2Fa4211c11211c" + } + }, + "name": "Checklist", + "active": true, + "id": "a4211c11211c" + }, { "_links": { "self": { From 93ea8748c44f0e67c4e690fdf85952836ac9c79e Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Tue, 18 Jun 2024 20:58:35 +0200 Subject: [PATCH 08/69] Add UnitTests fot checklistNode --- api/fixtures/checklistNodes.yml | 7 ++ api/tests/Api/Activities/ReadActivityTest.php | 2 +- .../ChecklistNode/CreateChecklistNodeTest.php | 35 +++++++ .../ChecklistNode/DeleteChecklistNodeTest.php | 17 ++++ .../ChecklistNode/ListChecklistNodeTest.php | 25 +++++ .../ChecklistNode/ReadChecklistNodeTest.php | 17 ++++ .../ChecklistNode/UpdateChecklistNodeTest.php | 17 ++++ .../ContentNode/ListContentNodesTest.php | 6 +- .../CreateContentNodeTestCase.php | 3 +- .../CreateRootColumnLayoutTest.php | 2 +- .../SnapshotTests/EndpointPerformanceTest.php | 2 +- ...Structure with data set activities__1.json | 3 + ...ta set content_nodechecklist_nodes__1.json | 28 +++++- ...ata set content_nodecolumn_layouts__1.json | 3 + ...ucture with data set content_nodes__1.json | 31 ++++++- ...Structure with data set activities__1.json | 30 ++++++ ...ta set content_nodechecklist_nodes__1.json | 1 - ...est__testOpenApiSpecMatchesSnapshot__1.yml | 93 +------------------ ...manceDidNotChangeForStableEndpoints__1.yml | 2 +- 19 files changed, 221 insertions(+), 103 deletions(-) create mode 100644 api/tests/Api/ContentNodes/ChecklistNode/CreateChecklistNodeTest.php create mode 100644 api/tests/Api/ContentNodes/ChecklistNode/DeleteChecklistNodeTest.php create mode 100644 api/tests/Api/ContentNodes/ChecklistNode/ListChecklistNodeTest.php create mode 100644 api/tests/Api/ContentNodes/ChecklistNode/ReadChecklistNodeTest.php create mode 100644 api/tests/Api/ContentNodes/ChecklistNode/UpdateChecklistNodeTest.php diff --git a/api/fixtures/checklistNodes.yml b/api/fixtures/checklistNodes.yml index 9351448280..eb7ffe74cc 100644 --- a/api/fixtures/checklistNodes.yml +++ b/api/fixtures/checklistNodes.yml @@ -1,4 +1,11 @@ App\Entity\ContentNode\ChecklistNode: + checklistNode1: + root: '@columnLayout1' + parent: '@columnLayout1' + slot: '1' + position: 1 + instanceName: + contentType: '@contentTypeChecklist' checklistNode3: root: '@columnLayout3' parent: '@columnLayout3' diff --git a/api/tests/Api/Activities/ReadActivityTest.php b/api/tests/Api/Activities/ReadActivityTest.php index 2bccea6aa6..61c7394e24 100644 --- a/api/tests/Api/Activities/ReadActivityTest.php +++ b/api/tests/Api/Activities/ReadActivityTest.php @@ -93,7 +93,7 @@ public function testGetSingleActivityIsAllowedForMember() { $this->assertEquals($this->getIriFor($activity->getRootContentNode()), $data['_embedded']['rootContentNode']['_links']['self']['href']); $this->assertEquals($this->getIriFor($activity->getRootContentNode()), $data['_embedded']['rootContentNode']['_links']['root']['href']); $this->assertContains(['href' => $this->getIriFor('responsiveLayout1')], $data['_embedded']['rootContentNode']['_links']['children']); - $this->assertEquals(11, count($data['_embedded']['contentNodes'])); + $this->assertEquals(12, count($data['_embedded']['contentNodes'])); } public function testGetSingleActivityIsAllowedForManager() { diff --git a/api/tests/Api/ContentNodes/ChecklistNode/CreateChecklistNodeTest.php b/api/tests/Api/ContentNodes/ChecklistNode/CreateChecklistNodeTest.php new file mode 100644 index 0000000000..703e19bbe8 --- /dev/null +++ b/api/tests/Api/ContentNodes/ChecklistNode/CreateChecklistNodeTest.php @@ -0,0 +1,35 @@ +endpoint = '/content_node/checklist_nodes'; + $this->entityClass = ChecklistNode::class; + $this->defaultContentType = static::getFixture('contentTypeChecklist'); + } + + /** + * payload set up. + */ + public function getExampleWritePayload($attributes = [], $except = []) { + return parent::getExampleWritePayload( + array_merge( + [ + 'addChecklistItemIds' => null, + 'removeChecklistItemIds' => null, + ], + $attributes + ), + $except + ); + } +} diff --git a/api/tests/Api/ContentNodes/ChecklistNode/DeleteChecklistNodeTest.php b/api/tests/Api/ContentNodes/ChecklistNode/DeleteChecklistNodeTest.php new file mode 100644 index 0000000000..963a52a82b --- /dev/null +++ b/api/tests/Api/ContentNodes/ChecklistNode/DeleteChecklistNodeTest.php @@ -0,0 +1,17 @@ +endpoint = '/content_node/checklist_nodes'; + $this->defaultEntity = static::getFixture('checklistNode3'); + } +} diff --git a/api/tests/Api/ContentNodes/ChecklistNode/ListChecklistNodeTest.php b/api/tests/Api/ContentNodes/ChecklistNode/ListChecklistNodeTest.php new file mode 100644 index 0000000000..723700944e --- /dev/null +++ b/api/tests/Api/ContentNodes/ChecklistNode/ListChecklistNodeTest.php @@ -0,0 +1,25 @@ +endpoint = '/content_node/checklist_nodes'; + + $this->contentNodesCamp1and2 = [ + $this->getIriFor('checklistNode1'), + $this->getIriFor('checklistNode3'), + ]; + + $this->contentNodesCampUnrelated = [ + $this->getIriFor('checklistNodeCampUnrelated'), + ]; + } +} diff --git a/api/tests/Api/ContentNodes/ChecklistNode/ReadChecklistNodeTest.php b/api/tests/Api/ContentNodes/ChecklistNode/ReadChecklistNodeTest.php new file mode 100644 index 0000000000..f68349061a --- /dev/null +++ b/api/tests/Api/ContentNodes/ChecklistNode/ReadChecklistNodeTest.php @@ -0,0 +1,17 @@ +endpoint = '/content_node/checklist_nodes'; + $this->defaultEntity = static::getFixture('checklistNode3'); + } +} diff --git a/api/tests/Api/ContentNodes/ChecklistNode/UpdateChecklistNodeTest.php b/api/tests/Api/ContentNodes/ChecklistNode/UpdateChecklistNodeTest.php new file mode 100644 index 0000000000..182a81d0d5 --- /dev/null +++ b/api/tests/Api/ContentNodes/ChecklistNode/UpdateChecklistNodeTest.php @@ -0,0 +1,17 @@ +endpoint = '/content_node/checklist_nodes'; + $this->defaultEntity = static::getFixture('checklistNode1'); + } +} diff --git a/api/tests/Api/ContentNodes/ContentNode/ListContentNodesTest.php b/api/tests/Api/ContentNodes/ContentNode/ListContentNodesTest.php index 430a93b593..e8ad29383c 100644 --- a/api/tests/Api/ContentNodes/ContentNode/ListContentNodesTest.php +++ b/api/tests/Api/ContentNodes/ContentNode/ListContentNodesTest.php @@ -23,7 +23,7 @@ public function testListContentNodesIsAllowedForLoggedInUserButFiltered() { $response = static::createClientWithCredentials()->request('GET', '/content_nodes'); $this->assertResponseStatusCodeSame(200); $this->assertJsonContains([ - 'totalItems' => 22, + 'totalItems' => 23, '_links' => [ 'items' => [], ], @@ -33,6 +33,7 @@ public function testListContentNodesIsAllowedForLoggedInUserButFiltered() { ]); $this->assertEqualsCanonicalizing([ ['href' => $this->getIriFor('columnLayout1')], + ['href' => $this->getIriFor('checklistNode1')], ['href' => $this->getIriFor('columnLayout2')], ['href' => $this->getIriFor('columnLayoutChild1')], ['href' => $this->getIriFor('columnLayout2Child1')], @@ -62,7 +63,7 @@ public function testListContentNodesFilteredByPeriodIsAllowedForCollaborator() { $response = static::createClientWithCredentials()->request('GET', '/content_nodes?period=%2Fperiods%2F'.$period->getId()); $this->assertResponseStatusCodeSame(200); $this->assertJsonContains([ - 'totalItems' => 13, + 'totalItems' => 14, '_links' => [ 'items' => [], ], @@ -72,6 +73,7 @@ public function testListContentNodesFilteredByPeriodIsAllowedForCollaborator() { ]); $this->assertEqualsCanonicalizing([ ['href' => $this->getIriFor('columnLayout1')], + ['href' => $this->getIriFor('checklistNode1')], ['href' => $this->getIriFor('columnLayoutChild1')], ['href' => $this->getIriFor('columnLayout3')], ['href' => $this->getIriFor('checklistNode3')], diff --git a/api/tests/Api/ContentNodes/CreateContentNodeTestCase.php b/api/tests/Api/ContentNodes/CreateContentNodeTestCase.php index 8fdaa2f327..90c1ba47a8 100644 --- a/api/tests/Api/ContentNodes/CreateContentNodeTestCase.php +++ b/api/tests/Api/ContentNodes/CreateContentNodeTestCase.php @@ -179,11 +179,10 @@ public function testCreatePutsContentNodeAtEndOfSlot() { ], ['position'] )); - $this->assertResponseStatusCodeSame(201); $this->assertJsonContains([ 'slot' => '1', - 'position' => 1, + 'position' => 2, ]); } diff --git a/api/tests/Api/ContentNodes/RootColumnLayout/CreateRootColumnLayoutTest.php b/api/tests/Api/ContentNodes/RootColumnLayout/CreateRootColumnLayoutTest.php index eefa5b64dc..8baf213391 100644 --- a/api/tests/Api/ContentNodes/RootColumnLayout/CreateRootColumnLayoutTest.php +++ b/api/tests/Api/ContentNodes/RootColumnLayout/CreateRootColumnLayoutTest.php @@ -46,7 +46,7 @@ public function testCreateColumnLayoutAllowsMissingPosition() { static::createClientWithCredentials()->request('POST', $this->endpoint, ['json' => $this->getExampleWritePayload([], ['position'])]); $this->assertResponseStatusCodeSame(201); - $this->assertJsonContains(['position' => 1]); + $this->assertJsonContains(['position' => 2]); } public function testCreateColumnLayoutAllowsMissingInstanceName() { diff --git a/api/tests/Api/SnapshotTests/EndpointPerformanceTest.php b/api/tests/Api/SnapshotTests/EndpointPerformanceTest.php index 1463bb5cd4..46e474c2d9 100644 --- a/api/tests/Api/SnapshotTests/EndpointPerformanceTest.php +++ b/api/tests/Api/SnapshotTests/EndpointPerformanceTest.php @@ -186,7 +186,7 @@ protected function getSnapshotId(): string { private static function getContentNodeEndpointQueryCountRanges(): array { return [ - '/content_nodes' => [8, 10], + '/content_nodes' => [8, 11], '/content_node/column_layouts' => [6, 6], '/content_node/column_layouts/item' => [10, 10], '/content_node/checklist_nodes' => [6, 7], diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set activities__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set activities__1.json index 17f0da395c..47bf622d83 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set activities__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set activities__1.json @@ -240,6 +240,9 @@ "rootContentNode": { "_links": { "children": [ + { + "href": "escaped_value" + }, { "href": "escaped_value" } diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodechecklist_nodes__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodechecklist_nodes__1.json index a657327a12..d92c7c8ab7 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodechecklist_nodes__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodechecklist_nodes__1.json @@ -3,7 +3,30 @@ "items": [ { "_links": { - "checklist": "escaped_value", + "checklistItems": [], + "children": [], + "contentType": { + "href": "escaped_value" + }, + "parent": { + "href": "escaped_value" + }, + "root": { + "href": "escaped_value" + }, + "self": { + "href": "escaped_value" + } + }, + "contentTypeName": "escaped_value", + "data": "escaped_value", + "id": "escaped_value", + "instanceName": "escaped_value", + "position": "escaped_value", + "slot": "escaped_value" + }, + { + "_links": { "checklistItems": [], "children": [], "contentType": { @@ -30,6 +53,9 @@ }, "_links": { "items": [ + { + "href": "escaped_value" + }, { "href": "escaped_value" } diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodecolumn_layouts__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodecolumn_layouts__1.json index 2c6362ca64..9e9859e619 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodecolumn_layouts__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodecolumn_layouts__1.json @@ -218,6 +218,9 @@ { "_links": { "children": [ + { + "href": "escaped_value" + }, { "href": "escaped_value" } diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodes__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodes__1.json index 540f43263f..87fb09384c 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodes__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodes__1.json @@ -80,7 +80,30 @@ }, { "_links": { - "checklist": "escaped_value", + "checklistItems": [], + "children": [], + "contentType": { + "href": "escaped_value" + }, + "parent": { + "href": "escaped_value" + }, + "root": { + "href": "escaped_value" + }, + "self": { + "href": "escaped_value" + } + }, + "contentTypeName": "escaped_value", + "data": "escaped_value", + "id": "escaped_value", + "instanceName": "escaped_value", + "position": "escaped_value", + "slot": "escaped_value" + }, + { + "_links": { "checklistItems": [], "children": [], "contentType": { @@ -580,6 +603,9 @@ { "_links": { "children": [ + { + "href": "escaped_value" + }, { "href": "escaped_value" } @@ -772,6 +798,9 @@ { "href": "escaped_value" }, + { + "href": "escaped_value" + }, { "href": "escaped_value" } diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set activities__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set activities__1.json index 9b8c7684dd..81d49812a7 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set activities__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set activities__1.json @@ -123,6 +123,30 @@ "position": "escaped_value", "slot": "escaped_value" }, + { + "_links": { + "checklistItems": [], + "children": [], + "contentType": { + "href": "escaped_value" + }, + "parent": { + "href": "escaped_value" + }, + "root": { + "href": "escaped_value" + }, + "self": { + "href": "escaped_value" + } + }, + "contentTypeName": "escaped_value", + "data": "escaped_value", + "id": "escaped_value", + "instanceName": "escaped_value", + "position": "escaped_value", + "slot": "escaped_value" + }, { "_links": { "children": [], @@ -430,6 +454,9 @@ { "_links": { "children": [ + { + "href": "escaped_value" + }, { "href": "escaped_value" } @@ -464,6 +491,9 @@ "rootContentNode": { "_links": { "children": [ + { + "href": "escaped_value" + }, { "href": "escaped_value" } diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set content_nodechecklist_nodes__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set content_nodechecklist_nodes__1.json index f883ff8e4f..9b0796fa6f 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set content_nodechecklist_nodes__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set content_nodechecklist_nodes__1.json @@ -1,6 +1,5 @@ { "_links": { - "checklist": "escaped_value", "checklistItems": [], "children": [], "contentType": { diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml index 67a199a93c..a58a5d5a5c 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml @@ -8315,13 +8315,6 @@ components: deprecated: false description: '' properties: - checklist: - description: 'The Checklist this Item belongs to.' - example: /checklists/1a2b3c4d - format: iri-reference - type: - - 'null' - - string checklistItems: description: 'The content types that are most likely to be useful for planning programme of this category.' example: '["/checklist_items/1a2b3c4d"]' @@ -8429,21 +8422,6 @@ components: type: - array - 'null' - checklist: - description: 'The Checklist this Item belongs to.' - example: /checklists/1a2b3c4d - format: iri-reference - type: - - 'null' - - string - checklistItems: - description: 'The content types that are most likely to be useful for planning programme of this category.' - example: '["/checklist_items/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string - type: array contentType: description: |- Defines the type of this content node. There is a fixed list of types that are implemented @@ -8504,7 +8482,6 @@ components: - 'null' - string required: - - checklistItems - contentType - parent - position @@ -8520,21 +8497,6 @@ components: type: - array - 'null' - checklist: - description: 'The Checklist this Item belongs to.' - example: /checklists/1a2b3c4d - format: iri-reference - type: - - 'null' - - string - checklistItems: - description: 'The content types that are most likely to be useful for planning programme of this category.' - example: '["/checklist_items/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string - type: array data: description: 'Holds the actual data of the content node.' example: @@ -8587,7 +8549,6 @@ components: - 'null' - string required: - - checklistItems - position type: object ChecklistNode.jsonapi: @@ -8602,13 +8563,6 @@ components: - array - 'null' writeOnly: true - checklist: - description: 'The Checklist this Item belongs to.' - example: /checklists/1a2b3c4d - format: iri-reference - type: - - 'null' - - string checklistItems: description: 'The content types that are most likely to be useful for planning programme of this category.' example: '["/checklist_items/1a2b3c4d"]' @@ -8616,6 +8570,7 @@ components: example: 'https://example.com/' format: iri-reference type: string + readOnly: true type: array children: description: 'All content nodes that are direct children of this content node.' @@ -8727,13 +8682,6 @@ components: type: string type: object type: object - checklist: - description: 'The Checklist this Item belongs to.' - example: /checklists/1a2b3c4d - format: iri-reference - type: - - 'null' - - string checklistItems: description: 'The content types that are most likely to be useful for planning programme of this category.' example: '["/checklist_items/1a2b3c4d"]' @@ -8850,21 +8798,6 @@ components: type: - array - 'null' - checklist: - description: 'The Checklist this Item belongs to.' - example: /checklists/1a2b3c4d - format: iri-reference - type: - - 'null' - - string - checklistItems: - description: 'The content types that are most likely to be useful for planning programme of this category.' - example: '["/checklist_items/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string - type: array contentType: description: |- Defines the type of this content node. There is a fixed list of types that are implemented @@ -8925,7 +8858,6 @@ components: - 'null' - string required: - - checklistItems - contentType - parent - position @@ -8957,13 +8889,6 @@ components: '@type': readOnly: true type: string - checklist: - description: 'The Checklist this Item belongs to.' - example: /checklists/1a2b3c4d - format: iri-reference - type: - - 'null' - - string checklistItems: description: 'The content types that are most likely to be useful for planning programme of this category.' example: '["/checklist_items/1a2b3c4d"]' @@ -9071,21 +8996,6 @@ components: type: - array - 'null' - checklist: - description: 'The Checklist this Item belongs to.' - example: /checklists/1a2b3c4d - format: iri-reference - type: - - 'null' - - string - checklistItems: - description: 'The content types that are most likely to be useful for planning programme of this category.' - example: '["/checklist_items/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string - type: array contentType: description: |- Defines the type of this content node. There is a fixed list of types that are implemented @@ -9146,7 +9056,6 @@ components: - 'null' - string required: - - checklistItems - contentType - parent - position diff --git a/api/tests/Api/SnapshotTests/__snapshots__/test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml b/api/tests/Api/SnapshotTests/__snapshots__/test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml index cffd038675..85260de4e7 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml +++ b/api/tests/Api/SnapshotTests/__snapshots__/test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml @@ -1,5 +1,5 @@ /activities: 21 -/activities/item: 33 +/activities/item: 36 /activity_progress_labels: 6 /activity_progress_labels/item: 7 /activity_responsibles: 6 From 3b67e15e4c04eb817eff9d469e17d0732c604e49 Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Fri, 21 Jun 2024 22:09:27 +0200 Subject: [PATCH 09/69] UnitTest: ChecklistNode add/remove ChecklistItem --- api/fixtures/checklistNodes.yml | 2 + ...16104153.php => Version20240620104153.php} | 2 +- ...16143000.php => Version20240620143000.php} | 2 +- .../schema/Version20240621195713.php | 34 +++++++ api/src/Entity/ContentNode/ChecklistNode.php | 4 +- .../ChecklistNode/UpdateChecklistNodeTest.php | 89 +++++++++++++++++++ ...ta set content_nodechecklist_nodes__1.json | 6 +- ...ucture with data set content_nodes__1.json | 6 +- ...Structure with data set activities__1.json | 6 +- 9 files changed, 144 insertions(+), 7 deletions(-) rename api/migrations/schema/{Version20240616104153.php => Version20240620104153.php} (96%) rename api/migrations/schema/{Version20240616143000.php => Version20240620143000.php} (93%) create mode 100644 api/migrations/schema/Version20240621195713.php diff --git a/api/fixtures/checklistNodes.yml b/api/fixtures/checklistNodes.yml index eb7ffe74cc..a6af5b9eeb 100644 --- a/api/fixtures/checklistNodes.yml +++ b/api/fixtures/checklistNodes.yml @@ -6,6 +6,8 @@ App\Entity\ContentNode\ChecklistNode: position: 1 instanceName: contentType: '@contentTypeChecklist' + checklistItems: + - '@checklistItem1_1_1' checklistNode3: root: '@columnLayout3' parent: '@columnLayout3' diff --git a/api/migrations/schema/Version20240616104153.php b/api/migrations/schema/Version20240620104153.php similarity index 96% rename from api/migrations/schema/Version20240616104153.php rename to api/migrations/schema/Version20240620104153.php index 340d9d16fd..7e0da4b8a2 100644 --- a/api/migrations/schema/Version20240616104153.php +++ b/api/migrations/schema/Version20240620104153.php @@ -10,7 +10,7 @@ /** * Auto-generated Migration: Please modify to your needs! */ -final class Version20240616104153 extends AbstractMigration { +final class Version20240620104153 extends AbstractMigration { public function getDescription(): string { return ''; } diff --git a/api/migrations/schema/Version20240616143000.php b/api/migrations/schema/Version20240620143000.php similarity index 93% rename from api/migrations/schema/Version20240616143000.php rename to api/migrations/schema/Version20240620143000.php index f18be0dcb8..d6c0c34edf 100644 --- a/api/migrations/schema/Version20240616143000.php +++ b/api/migrations/schema/Version20240620143000.php @@ -7,7 +7,7 @@ use Doctrine\DBAL\Schema\Schema; use Doctrine\Migrations\AbstractMigration; -final class Version20240616143000 extends AbstractMigration { +final class Version20240620143000 extends AbstractMigration { public function getDescription(): string { return 'Add ChecklistNode content type'; } diff --git a/api/migrations/schema/Version20240621195713.php b/api/migrations/schema/Version20240621195713.php new file mode 100644 index 0000000000..3dce8330ff --- /dev/null +++ b/api/migrations/schema/Version20240621195713.php @@ -0,0 +1,34 @@ +addSql('ALTER TABLE checklistnode_checklistitem DROP CONSTRAINT FK_5A2B5B31DE6B6F00'); + $this->addSql('ALTER TABLE checklistnode_checklistitem DROP CONSTRAINT FK_5A2B5B318A09A289'); + $this->addSql('ALTER TABLE checklistnode_checklistitem ADD CONSTRAINT FK_5A2B5B31DE6B6F00 FOREIGN KEY (checklistnode_id) REFERENCES content_node (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE checklistnode_checklistitem ADD CONSTRAINT FK_5A2B5B318A09A289 FOREIGN KEY (checklistitem_id) REFERENCES checklist_item (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE SCHEMA public'); + $this->addSql('ALTER TABLE checklistnode_checklistitem DROP CONSTRAINT fk_5a2b5b31de6b6f00'); + $this->addSql('ALTER TABLE checklistnode_checklistitem DROP CONSTRAINT fk_5a2b5b318a09a289'); + $this->addSql('ALTER TABLE checklistnode_checklistitem ADD CONSTRAINT fk_5a2b5b31de6b6f00 FOREIGN KEY (checklistnode_id) REFERENCES content_node (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE checklistnode_checklistitem ADD CONSTRAINT fk_5a2b5b318a09a289 FOREIGN KEY (checklistitem_id) REFERENCES checklist_item (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + } +} diff --git a/api/src/Entity/ContentNode/ChecklistNode.php b/api/src/Entity/ContentNode/ChecklistNode.php index 237296a7b9..36713bfb93 100644 --- a/api/src/Entity/ContentNode/ChecklistNode.php +++ b/api/src/Entity/ContentNode/ChecklistNode.php @@ -57,8 +57,8 @@ class ChecklistNode extends ContentNode { #[Groups(['read'])] #[ORM\ManyToMany(targetEntity: ChecklistItem::class, inversedBy: 'checklistNodes')] #[ORM\JoinTable(name: 'checklistnode_checklistitem')] - #[ORM\JoinColumn(name: 'checklistnode_id', referencedColumnName: 'id')] - #[ORM\InverseJoinColumn(name: 'checklistitem_id', referencedColumnName: 'id')] + #[ORM\JoinColumn(name: 'checklistnode_id', referencedColumnName: 'id', onDelete: 'CASCADE')] + #[ORM\InverseJoinColumn(name: 'checklistitem_id', referencedColumnName: 'id', onDelete: 'CASCADE')] #[ORM\OrderBy(['position' => 'ASC'])] public Collection $checklistItems; diff --git a/api/tests/Api/ContentNodes/ChecklistNode/UpdateChecklistNodeTest.php b/api/tests/Api/ContentNodes/ChecklistNode/UpdateChecklistNodeTest.php index 182a81d0d5..b6c5661558 100644 --- a/api/tests/Api/ContentNodes/ChecklistNode/UpdateChecklistNodeTest.php +++ b/api/tests/Api/ContentNodes/ChecklistNode/UpdateChecklistNodeTest.php @@ -2,6 +2,7 @@ namespace App\Tests\Api\ContentNodes\ChecklistNode; +use App\Entity\ContentNode\ChecklistNode; use App\Tests\Api\ContentNodes\UpdateContentNodeTestCase; /** @@ -14,4 +15,92 @@ public function setUp(): void { $this->endpoint = '/content_node/checklist_nodes'; $this->defaultEntity = static::getFixture('checklistNode1'); } + + public function testAddChecklistItemIsDeniedForGuest() { + $checklistItemId = static::getFixture('checklistItem1_1_2')->getId(); + static::createClientWithCredentials(['email' => static::getFixture('user3guest')->getEmail()]) + ->request('PATCH', $this->endpoint.'/'.$this->defaultEntity->getId(), ['json' => [ + 'addChecklistItemIds' => [$checklistItemId], + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]) + ; + $this->assertResponseStatusCodeSame(403); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Access Denied.', + ]); + } + + public function testAddChecklistItemIsDeniedForMember() { + $checklistItemId = static::getFixture('checklistItem1_1_2')->getId(); + static::createClientWithCredentials(['email' => static::getFixture('user2member')->getEmail()]) + ->request('PATCH', $this->endpoint.'/'.$this->defaultEntity->getId(), ['json' => [ + 'addChecklistItemIds' => [$checklistItemId], + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]) + ; + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + '_links' => [ + 'checklistItems' => [ + 1 => [ + 'href' => '/checklist_items/'.$checklistItemId, + ], + ], + ], + ]); + } + + public function testAddChecklistItemIsDeniedForManager() { + $checklistItemId = static::getFixture('checklistItem1_1_2')->getId(); + static::createClientWithCredentials()->request('PATCH', $this->endpoint.'/'.$this->defaultEntity->getId(), ['json' => [ + 'addChecklistItemIds' => [$checklistItemId], + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]); + + $this->assertResponseStatusCodeSame(200); + $this->assertJsonContains([ + '_links' => [ + 'checklistItems' => [ + 1 => [ + 'href' => '/checklist_items/'.$checklistItemId, + ], + ], + ], + ]); + } + + public function testRemoveChecklistItemIsDeniedForGuest() { + $checklistItemId = static::getFixture('checklistItem1_1_1')->getId(); + static::createClientWithCredentials(['email' => static::getFixture('user3guest')->getEmail()]) + ->request('PATCH', $this->endpoint.'/'.$this->defaultEntity->getId(), ['json' => [ + 'removeChecklistItemIds' => [$checklistItemId], + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]) + ; + $this->assertResponseStatusCodeSame(403); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'Access Denied.', + ]); + } + + public function testRemoveChecklistItemIsDeniedForMember() { + $checklistItem = static::getFixture('checklistItem1_1_1'); + static::createClientWithCredentials(['email' => static::getFixture('user2member')->getEmail()]) + ->request('PATCH', $this->endpoint.'/'.$this->defaultEntity->getId(), ['json' => [ + 'removeChecklistItemIds' => [$checklistItem->getId()], + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]) + ; + $this->assertResponseStatusCodeSame(200); + $checklistNode = $this->getEntityManager()->getRepository(ChecklistNode::class)->find($this->defaultEntity->getId()); + $this->assertFalse(in_array($checklistItem, $checklistNode->getChecklistItems())); + } + + public function testRemoveChecklistItemIsDeniedForManager() { + $checklistItem = static::getFixture('checklistItem1_1_1'); + static::createClientWithCredentials()->request('PATCH', $this->endpoint.'/'.$this->defaultEntity->getId(), ['json' => [ + 'removeChecklistItemIds' => [$checklistItem->getId()], + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]); + + $this->assertResponseStatusCodeSame(200); + $checklistNode = $this->getEntityManager()->getRepository(ChecklistNode::class)->find($this->defaultEntity->getId()); + $this->assertFalse(in_array($checklistItem, $checklistNode->getChecklistItems())); + } } diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodechecklist_nodes__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodechecklist_nodes__1.json index d92c7c8ab7..20693aaa9d 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodechecklist_nodes__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodechecklist_nodes__1.json @@ -27,7 +27,11 @@ }, { "_links": { - "checklistItems": [], + "checklistItems": [ + { + "href": "escaped_value" + } + ], "children": [], "contentType": { "href": "escaped_value" diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodes__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodes__1.json index 87fb09384c..2088e60717 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodes__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetCollectionMatchesStructure with data set content_nodes__1.json @@ -104,7 +104,11 @@ }, { "_links": { - "checklistItems": [], + "checklistItems": [ + { + "href": "escaped_value" + } + ], "children": [], "contentType": { "href": "escaped_value" diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set activities__1.json b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set activities__1.json index 81d49812a7..df948bb2cf 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set activities__1.json +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testGetItemMatchesStructure with data set activities__1.json @@ -125,7 +125,11 @@ }, { "_links": { - "checklistItems": [], + "checklistItems": [ + { + "href": "escaped_value" + } + ], "children": [], "contentType": { "href": "escaped_value" From 8151ebca8855da43d07023af6e1e4f56e8e89ba9 Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Sat, 22 Jun 2024 14:42:51 +0200 Subject: [PATCH 10/69] unify AssertNoLoop-Validators --- api/src/Entity/ChecklistItem.php | 8 +++- api/src/Entity/ContentNode.php | 8 +++- api/src/Entity/HasParentInterface.php | 7 +++ .../{ContentNode => }/AssertNoLoop.php | 2 +- .../AssertNoLoopValidator.php | 8 ++-- .../Validator/ChecklistItem/AssertNoLoop.php | 10 ---- .../ChecklistItem/AssertNoLoopValidator.php | 46 ------------------- .../AssertNoLoopValidatorTest.php | 6 +-- 8 files changed, 27 insertions(+), 68 deletions(-) create mode 100644 api/src/Entity/HasParentInterface.php rename api/src/Validator/{ContentNode => }/AssertNoLoop.php (83%) rename api/src/Validator/{ContentNode => }/AssertNoLoopValidator.php (88%) delete mode 100644 api/src/Validator/ChecklistItem/AssertNoLoop.php delete mode 100644 api/src/Validator/ChecklistItem/AssertNoLoopValidator.php rename api/tests/Validator/{ContentNode => }/AssertNoLoopValidatorTest.php (95%) diff --git a/api/src/Entity/ChecklistItem.php b/api/src/Entity/ChecklistItem.php index c6c453806b..f9a42a65c0 100644 --- a/api/src/Entity/ChecklistItem.php +++ b/api/src/Entity/ChecklistItem.php @@ -16,8 +16,8 @@ use App\InputFilter; use App\Repository\ChecklistItemRepository; use App\Util\EntityMap; +use App\Validator\AssertNoLoop; use App\Validator\ChecklistItem\AssertBelongsToChecklist; -use App\Validator\ChecklistItem\AssertNoLoop; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -67,7 +67,7 @@ )] #[ApiFilter(filterClass: SearchFilter::class, properties: ['checklist'])] #[ORM\Entity(repositoryClass: ChecklistItemRepository::class)] -class ChecklistItem extends BaseEntity implements BelongsToCampInterface, CopyFromPrototypeInterface { +class ChecklistItem extends BaseEntity implements BelongsToCampInterface, CopyFromPrototypeInterface, HasParentInterface { public const CHECKLIST_SUBRESOURCE_URI_TEMPLATE = '/checklists/{checklistId}/checklist_items.{_format}'; /** @@ -140,6 +140,10 @@ public function getCamp(): ?Camp { return $this->checklist?->getCamp(); } + public function getParent(): ?HasParentInterface { + return $this->parent; + } + /** * @return ChecklistItem[] */ diff --git a/api/src/Entity/ContentNode.php b/api/src/Entity/ContentNode.php index 0b29d17753..7c40ff24d4 100644 --- a/api/src/Entity/ContentNode.php +++ b/api/src/Entity/ContentNode.php @@ -14,9 +14,9 @@ use App\Util\ClassInfoTrait; use App\Util\EntityMap; use App\Util\JsonMergePatch; +use App\Validator\AssertNoLoop; use App\Validator\ContentNode\AssertAttachedToRoot; use App\Validator\ContentNode\AssertContentTypeCompatible; -use App\Validator\ContentNode\AssertNoLoop; use App\Validator\ContentNode\AssertNoRootChange; use App\Validator\ContentNode\AssertSlotSupportedByParent; use Doctrine\Common\Collections\ArrayCollection; @@ -49,7 +49,7 @@ #[ORM\InheritanceType('SINGLE_TABLE')] #[ORM\DiscriminatorColumn(name: 'strategy', type: 'string')] #[ORM\UniqueConstraint(name: 'contentnode_parentid_slot_position_unique', columns: ['parentid', 'slot', 'position'])] -abstract class ContentNode extends BaseEntity implements BelongsToContentNodeTreeInterface, CopyFromPrototypeInterface { +abstract class ContentNode extends BaseEntity implements BelongsToContentNodeTreeInterface, CopyFromPrototypeInterface, HasParentInterface { use ClassInfoTrait; /** @@ -180,6 +180,10 @@ public function getRoot(): ?ColumnLayout { return $this->root; } + public function getParent(): ?HasParentInterface { + return $this->parent; + } + /** * Holds the actual data of the content node. */ diff --git a/api/src/Entity/HasParentInterface.php b/api/src/Entity/HasParentInterface.php new file mode 100644 index 0000000000..87ec5c2d00 --- /dev/null +++ b/api/src/Entity/HasParentInterface.php @@ -0,0 +1,7 @@ +context->getObject(); - /** @var ContentNode $parent */ + /** @var HasParentInterface $parent */ $parent = $value; // $seen keeps track of all parents that we have visited. This is for a safety @@ -36,7 +36,7 @@ public function validate($value, Constraint $constraint): void { } $seen[] = $parent->getId(); - $parent = $parent->parent; + $parent = $parent->getParent(); } } } diff --git a/api/src/Validator/ChecklistItem/AssertNoLoop.php b/api/src/Validator/ChecklistItem/AssertNoLoop.php deleted file mode 100644 index f60e2bba67..0000000000 --- a/api/src/Validator/ChecklistItem/AssertNoLoop.php +++ /dev/null @@ -1,10 +0,0 @@ -context->getObject(); - if (!$object instanceof ChecklistItem) { - throw new UnexpectedValueException($object, ChecklistItem::class); - } - - /** @var ChecklistItem $parent */ - $parent = $value; - - // $seen keeps track of all parents that we have visited. This is for a safety - // bailout mechanism to avoid an infinite loop in case there is flawed data in the DB - $seen = []; - - while (null !== $parent && !in_array($parent->getId(), $seen)) { - if ($parent->getId() === $object->getId()) { - $this->context->buildViolation($constraint->message) - ->addViolation() - ; - - return; - } - - $seen[] = $parent->getId(); - $parent = $parent->parent; - } - } -} diff --git a/api/tests/Validator/ContentNode/AssertNoLoopValidatorTest.php b/api/tests/Validator/AssertNoLoopValidatorTest.php similarity index 95% rename from api/tests/Validator/ContentNode/AssertNoLoopValidatorTest.php rename to api/tests/Validator/AssertNoLoopValidatorTest.php index ead7803414..527f4bfb94 100644 --- a/api/tests/Validator/ContentNode/AssertNoLoopValidatorTest.php +++ b/api/tests/Validator/AssertNoLoopValidatorTest.php @@ -1,10 +1,10 @@ Date: Tue, 9 Jul 2024 19:26:00 +0200 Subject: [PATCH 11/69] fixes according to review --- api/fixtures/checklistItems.yml | 3 --- api/migrations/schema/Version20240620143000.php | 2 +- api/src/Entity/Checklist.php | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/api/fixtures/checklistItems.yml b/api/fixtures/checklistItems.yml index 3892d00a43..ffe2553f24 100644 --- a/api/fixtures/checklistItems.yml +++ b/api/fixtures/checklistItems.yml @@ -9,9 +9,6 @@ App\Entity\ChecklistItem: checklist: '@checklist1' parent: '@checklistItem1_1_2' text: 'Camp1_List1_Item2_Item3' -# checklist2WithNoItems: -# checklist: '@checklist2WithNoItems' -# text: 'Camp1_List2_Item1' checklistItem2_1_1: checklist: '@checklist1camp2' text: 'Camp2_List1_Item1' diff --git a/api/migrations/schema/Version20240620143000.php b/api/migrations/schema/Version20240620143000.php index d6c0c34edf..1d61764ed0 100644 --- a/api/migrations/schema/Version20240620143000.php +++ b/api/migrations/schema/Version20240620143000.php @@ -29,6 +29,6 @@ public function up(Schema $schema): void { public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs - $this->addSql('DELETE FROM public.content_type WHERE id IN (\'a4211c11211c\')'); + $this->addSql("DELETE FROM public.content_type WHERE id IN ('a4211c11211c')"); } } diff --git a/api/src/Entity/Checklist.php b/api/src/Entity/Checklist.php index 9a5ba7fd2c..9703f5d30a 100644 --- a/api/src/Entity/Checklist.php +++ b/api/src/Entity/Checklist.php @@ -102,7 +102,7 @@ class Checklist extends BaseEntity implements BelongsToCampInterface, CopyFromPr #[Assert\NotBlank] #[Assert\Length(max: 32)] #[ORM\Column(type: 'text')] - public ?string $name = null; + public string $name; public function __construct() { parent::__construct(); From 0cee81e5833f9e776e8b1c731bce7ccfacfb2405 Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Tue, 9 Jul 2024 19:32:18 +0200 Subject: [PATCH 12/69] fixes according to review --- .../schema/Version20240620104153.php | 6 ++-- .../schema/Version20240621195713.php | 34 ------------------- api/src/Entity/ChecklistItem.php | 2 ++ .../ChecklistNodePersistProcessor.php | 10 ++++-- .../CreateChecklistItemTest.php | 8 ++--- .../ChecklistNode/CreateChecklistNodeTest.php | 10 ++---- 6 files changed, 20 insertions(+), 50 deletions(-) delete mode 100644 api/migrations/schema/Version20240621195713.php diff --git a/api/migrations/schema/Version20240620104153.php b/api/migrations/schema/Version20240620104153.php index 7e0da4b8a2..82cfd58b19 100644 --- a/api/migrations/schema/Version20240620104153.php +++ b/api/migrations/schema/Version20240620104153.php @@ -17,16 +17,18 @@ public function getDescription(): string { public function up(Schema $schema): void { // this up() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE UNIQUE INDEX checklistitem_checklistid_parentid_position_unique ON checklist_item (checklistid, parentid, position)'); $this->addSql('CREATE TABLE checklistnode_checklistitem (checklistnode_id VARCHAR(16) NOT NULL, checklistitem_id VARCHAR(16) NOT NULL, PRIMARY KEY(checklistnode_id, checklistitem_id))'); $this->addSql('CREATE INDEX IDX_5A2B5B31DE6B6F00 ON checklistnode_checklistitem (checklistnode_id)'); $this->addSql('CREATE INDEX IDX_5A2B5B318A09A289 ON checklistnode_checklistitem (checklistitem_id)'); - $this->addSql('ALTER TABLE checklistnode_checklistitem ADD CONSTRAINT FK_5A2B5B31DE6B6F00 FOREIGN KEY (checklistnode_id) REFERENCES content_node (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE checklistnode_checklistitem ADD CONSTRAINT FK_5A2B5B318A09A289 FOREIGN KEY (checklistitem_id) REFERENCES checklist_item (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE checklistnode_checklistitem ADD CONSTRAINT FK_5A2B5B31DE6B6F00 FOREIGN KEY (checklistnode_id) REFERENCES content_node (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE checklistnode_checklistitem ADD CONSTRAINT FK_5A2B5B318A09A289 FOREIGN KEY (checklistitem_id) REFERENCES checklist_item (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); } public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs $this->addSql('CREATE SCHEMA public'); + $this->addSql('DROP INDEX checklistitem_checklistid_parentid_position_unique'); $this->addSql('ALTER TABLE checklistnode_checklistitem DROP CONSTRAINT FK_5A2B5B31DE6B6F00'); $this->addSql('ALTER TABLE checklistnode_checklistitem DROP CONSTRAINT FK_5A2B5B318A09A289'); $this->addSql('DROP TABLE checklistnode_checklistitem'); diff --git a/api/migrations/schema/Version20240621195713.php b/api/migrations/schema/Version20240621195713.php deleted file mode 100644 index 3dce8330ff..0000000000 --- a/api/migrations/schema/Version20240621195713.php +++ /dev/null @@ -1,34 +0,0 @@ -addSql('ALTER TABLE checklistnode_checklistitem DROP CONSTRAINT FK_5A2B5B31DE6B6F00'); - $this->addSql('ALTER TABLE checklistnode_checklistitem DROP CONSTRAINT FK_5A2B5B318A09A289'); - $this->addSql('ALTER TABLE checklistnode_checklistitem ADD CONSTRAINT FK_5A2B5B31DE6B6F00 FOREIGN KEY (checklistnode_id) REFERENCES content_node (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE checklistnode_checklistitem ADD CONSTRAINT FK_5A2B5B318A09A289 FOREIGN KEY (checklistitem_id) REFERENCES checklist_item (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); - } - - public function down(Schema $schema): void { - // this down() migration is auto-generated, please modify it to your needs - $this->addSql('CREATE SCHEMA public'); - $this->addSql('ALTER TABLE checklistnode_checklistitem DROP CONSTRAINT fk_5a2b5b31de6b6f00'); - $this->addSql('ALTER TABLE checklistnode_checklistitem DROP CONSTRAINT fk_5a2b5b318a09a289'); - $this->addSql('ALTER TABLE checklistnode_checklistitem ADD CONSTRAINT fk_5a2b5b31de6b6f00 FOREIGN KEY (checklistnode_id) REFERENCES content_node (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); - $this->addSql('ALTER TABLE checklistnode_checklistitem ADD CONSTRAINT fk_5a2b5b318a09a289 FOREIGN KEY (checklistitem_id) REFERENCES checklist_item (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); - } -} diff --git a/api/src/Entity/ChecklistItem.php b/api/src/Entity/ChecklistItem.php index f9a42a65c0..2b726bf253 100644 --- a/api/src/Entity/ChecklistItem.php +++ b/api/src/Entity/ChecklistItem.php @@ -67,6 +67,7 @@ )] #[ApiFilter(filterClass: SearchFilter::class, properties: ['checklist'])] #[ORM\Entity(repositoryClass: ChecklistItemRepository::class)] +#[ORM\UniqueConstraint(name: 'checklistitem_checklistid_parentid_position_unique', columns: ['checklistid', 'parentid', 'position'])] class ChecklistItem extends BaseEntity implements BelongsToCampInterface, CopyFromPrototypeInterface, HasParentInterface { public const CHECKLIST_SUBRESOURCE_URI_TEMPLATE = '/checklists/{checklistId}/checklist_items.{_format}'; @@ -74,6 +75,7 @@ class ChecklistItem extends BaseEntity implements BelongsToCampInterface, CopyFr * The Checklist this Item belongs to. */ #[ApiProperty(example: '/checklists/1a2b3c4d')] + #[Gedmo\SortableGroup] #[Groups(['read', 'create'])] #[ORM\ManyToOne(targetEntity: Checklist::class, inversedBy: 'checklistItems')] #[ORM\JoinColumn(nullable: false, onDelete: 'cascade')] diff --git a/api/src/State/ContentNode/ChecklistNodePersistProcessor.php b/api/src/State/ContentNode/ChecklistNodePersistProcessor.php index b138cf7b73..bdbe6a9f34 100644 --- a/api/src/State/ContentNode/ChecklistNodePersistProcessor.php +++ b/api/src/State/ContentNode/ChecklistNodePersistProcessor.php @@ -25,13 +25,19 @@ public function onBefore($data, Operation $operation, array $uriVariables = [], if (null !== $data->addChecklistItemIds) { foreach ($data->addChecklistItemIds as $checklistItemId) { $checklistItem = $this->checklistItemRepository->find($checklistItemId); - $data->addChecklistItem($checklistItem); + if (null != $checklistItem) { + // if a checklistItem does not exists, do not add it + $data->addChecklistItem($checklistItem); + } } } if (null !== $data->removeChecklistItemIds) { foreach ($data->removeChecklistItemIds as $checklistItemId) { $checklistItem = $this->checklistItemRepository->find($checklistItemId); - $data->removeChecklistItem($checklistItem); + if (null != $checklistItem) { + // if a checklistItem no longer exists, it does not have to be removed + $data->removeChecklistItem($checklistItem); + } } } diff --git a/api/tests/Api/ChecklistItems/CreateChecklistItemTest.php b/api/tests/Api/ChecklistItems/CreateChecklistItemTest.php index 007d8d0970..6aa37d9489 100644 --- a/api/tests/Api/ChecklistItems/CreateChecklistItemTest.php +++ b/api/tests/Api/ChecklistItems/CreateChecklistItemTest.php @@ -66,14 +66,14 @@ public function testCreateChecklistItemIsAllowedForMember() { ; $this->assertResponseStatusCodeSame(201); - $this->assertJsonContains($this->getExampleReadPayload(['position' => 5])); + $this->assertJsonContains($this->getExampleReadPayload(['position' => 2])); } public function testCreateChecklistItemIsAllowedForManager() { static::createClientWithCredentials()->request('POST', '/checklist_items', ['json' => $this->getExampleWritePayload()]); $this->assertResponseStatusCodeSame(201); - $this->assertJsonContains($this->getExampleReadPayload(['position' => 5])); + $this->assertJsonContains($this->getExampleReadPayload(['position' => 2])); } public function testCreateChecklistItemInCampPrototypeIsDeniedForUnrelatedUser() { @@ -181,7 +181,7 @@ public function testCreateChecklistItemTrimsText() { $this->assertJsonContains($this->getExampleReadPayload( [ 'text' => 'Ziel 1', - 'position' => 5, + 'position' => 2, ] )); } @@ -203,7 +203,7 @@ public function testCreateChecklistItemCleansForbiddenCharactersFromText() { $this->assertJsonContains($this->getExampleReadPayload( [ 'text' => 'Ziel 1', - 'position' => 5, + 'position' => 2, ] )); } diff --git a/api/tests/Api/ContentNodes/ChecklistNode/CreateChecklistNodeTest.php b/api/tests/Api/ContentNodes/ChecklistNode/CreateChecklistNodeTest.php index 703e19bbe8..8d0fd4d8f8 100644 --- a/api/tests/Api/ContentNodes/ChecklistNode/CreateChecklistNodeTest.php +++ b/api/tests/Api/ContentNodes/ChecklistNode/CreateChecklistNodeTest.php @@ -22,14 +22,8 @@ public function setUp(): void { */ public function getExampleWritePayload($attributes = [], $except = []) { return parent::getExampleWritePayload( - array_merge( - [ - 'addChecklistItemIds' => null, - 'removeChecklistItemIds' => null, - ], - $attributes - ), - $except + $attributes, + array_merge(['addChecklistItemIds', 'removeChecklistItemIds'], $except) ); } } From 2297d5f9616cf903554c00233d33a09fb4e21202 Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Sat, 13 Jul 2024 16:36:45 +0200 Subject: [PATCH 13/69] ChecklistItem text length = 256 --- api/src/Entity/ChecklistItem.php | 2 +- .../ChecklistItems/CreateChecklistItemTest.php | 4 ++-- .../ChecklistItems/UpdateChecklistItemTest.php | 4 ++-- ...otTest__testOpenApiSpecMatchesSnapshot__1.yml | 16 ++++++++-------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/api/src/Entity/ChecklistItem.php b/api/src/Entity/ChecklistItem.php index 2b726bf253..9cbec270c1 100644 --- a/api/src/Entity/ChecklistItem.php +++ b/api/src/Entity/ChecklistItem.php @@ -117,7 +117,7 @@ class ChecklistItem extends BaseEntity implements BelongsToCampInterface, CopyFr #[InputFilter\Trim] #[InputFilter\CleanText] #[Assert\NotBlank] - #[Assert\Length(max: 64)] + #[Assert\Length(max: 256)] #[ORM\Column(type: 'text')] public ?string $text = null; diff --git a/api/tests/Api/ChecklistItems/CreateChecklistItemTest.php b/api/tests/Api/ChecklistItems/CreateChecklistItemTest.php index 6aa37d9489..6381cc0999 100644 --- a/api/tests/Api/ChecklistItems/CreateChecklistItemTest.php +++ b/api/tests/Api/ChecklistItems/CreateChecklistItemTest.php @@ -147,7 +147,7 @@ public function testCreateChecklistItemValidatesTooLongText() { [ 'json' => $this->getExampleWritePayload( [ - 'text' => str_repeat('l', 65), + 'text' => str_repeat('l', 257), ] ), ] @@ -158,7 +158,7 @@ public function testCreateChecklistItemValidatesTooLongText() { 'violations' => [ [ 'propertyPath' => 'text', - 'message' => 'This value is too long. It should have 64 characters or less.', + 'message' => 'This value is too long. It should have 256 characters or less.', ], ], ]); diff --git a/api/tests/Api/ChecklistItems/UpdateChecklistItemTest.php b/api/tests/Api/ChecklistItems/UpdateChecklistItemTest.php index ca6ceae23a..0152401f68 100644 --- a/api/tests/Api/ChecklistItems/UpdateChecklistItemTest.php +++ b/api/tests/Api/ChecklistItems/UpdateChecklistItemTest.php @@ -161,7 +161,7 @@ public function testPatchChecklistItemValidatesTooLongText() { '/checklist_items/'.$checklistItem->getId(), [ 'json' => [ - 'text' => str_repeat('l', 65), + 'text' => str_repeat('l', 257), ], 'headers' => ['Content-Type' => 'application/merge-patch+json'], ] @@ -172,7 +172,7 @@ public function testPatchChecklistItemValidatesTooLongText() { 'violations' => [ [ 'propertyPath' => 'text', - 'message' => 'This value is too long. It should have 64 characters or less.', + 'message' => 'This value is too long. It should have 256 characters or less.', ], ], ]); diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml index a58a5d5a5c..26a4f2af89 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml @@ -7955,7 +7955,7 @@ components: text: description: 'The human readable text of the checklist-item.' example: Pfaditechnick - maxLength: 64 + maxLength: 256 type: string required: - checklist @@ -7987,7 +7987,7 @@ components: text: description: 'The human readable text of the checklist-item.' example: Pfaditechnick - maxLength: 64 + maxLength: 256 type: string required: - position @@ -8022,7 +8022,7 @@ components: text: description: 'The human readable text of the checklist-item.' example: Pfaditechnick - maxLength: 64 + maxLength: 256 type: string required: - checklist @@ -8053,7 +8053,7 @@ components: text: description: 'The human readable text of the checklist-item.' example: Pfaditechnick - maxLength: 64 + maxLength: 256 type: string required: - position @@ -8147,7 +8147,7 @@ components: text: description: 'The human readable text of the checklist-item.' example: Pfaditechnick - maxLength: 64 + maxLength: 256 type: string required: - checklist @@ -8193,7 +8193,7 @@ components: text: description: 'The human readable text of the checklist-item.' example: Pfaditechnick - maxLength: 64 + maxLength: 256 type: string required: - checklist @@ -8267,7 +8267,7 @@ components: text: description: 'The human readable text of the checklist-item.' example: Pfaditechnick - maxLength: 64 + maxLength: 256 type: string required: - checklist @@ -8304,7 +8304,7 @@ components: text: description: 'The human readable text of the checklist-item.' example: Pfaditechnick - maxLength: 64 + maxLength: 256 type: string required: - checklist From e8d58d04d7e15467a3f45587c35b810859a06e68 Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Mon, 15 Jul 2024 18:25:41 +0200 Subject: [PATCH 14/69] fix unittest-names --- .../ChecklistNode/UpdateChecklistNodeTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/tests/Api/ContentNodes/ChecklistNode/UpdateChecklistNodeTest.php b/api/tests/Api/ContentNodes/ChecklistNode/UpdateChecklistNodeTest.php index b6c5661558..a2cd67de89 100644 --- a/api/tests/Api/ContentNodes/ChecklistNode/UpdateChecklistNodeTest.php +++ b/api/tests/Api/ContentNodes/ChecklistNode/UpdateChecklistNodeTest.php @@ -30,7 +30,7 @@ public function testAddChecklistItemIsDeniedForGuest() { ]); } - public function testAddChecklistItemIsDeniedForMember() { + public function testAddChecklistItemForMember() { $checklistItemId = static::getFixture('checklistItem1_1_2')->getId(); static::createClientWithCredentials(['email' => static::getFixture('user2member')->getEmail()]) ->request('PATCH', $this->endpoint.'/'.$this->defaultEntity->getId(), ['json' => [ @@ -49,7 +49,7 @@ public function testAddChecklistItemIsDeniedForMember() { ]); } - public function testAddChecklistItemIsDeniedForManager() { + public function testAddChecklistItemForManager() { $checklistItemId = static::getFixture('checklistItem1_1_2')->getId(); static::createClientWithCredentials()->request('PATCH', $this->endpoint.'/'.$this->defaultEntity->getId(), ['json' => [ 'addChecklistItemIds' => [$checklistItemId], @@ -81,7 +81,7 @@ public function testRemoveChecklistItemIsDeniedForGuest() { ]); } - public function testRemoveChecklistItemIsDeniedForMember() { + public function testRemoveChecklistItemForMember() { $checklistItem = static::getFixture('checklistItem1_1_1'); static::createClientWithCredentials(['email' => static::getFixture('user2member')->getEmail()]) ->request('PATCH', $this->endpoint.'/'.$this->defaultEntity->getId(), ['json' => [ @@ -93,7 +93,7 @@ public function testRemoveChecklistItemIsDeniedForMember() { $this->assertFalse(in_array($checklistItem, $checklistNode->getChecklistItems())); } - public function testRemoveChecklistItemIsDeniedForManager() { + public function testRemoveChecklistItemForManager() { $checklistItem = static::getFixture('checklistItem1_1_1'); static::createClientWithCredentials()->request('PATCH', $this->endpoint.'/'.$this->defaultEntity->getId(), ['json' => [ 'removeChecklistItemIds' => [$checklistItem->getId()], From 09c4000abe9acddb8ce583c170a962fdb7da114b Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Sun, 21 Jul 2024 18:00:34 +0200 Subject: [PATCH 15/69] fix performance-unittests --- .../performance_test/checklistItems.yml | 2 +- ...est__testOpenApiSpecMatchesSnapshot__1.yml | 5 ----- ...manceDidNotChangeForStableEndpoints__1.yml | 20 +++++++++++-------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/api/fixtures/performance_test/checklistItems.yml b/api/fixtures/performance_test/checklistItems.yml index ea01fe011d..623cc12099 100644 --- a/api/fixtures/performance_test/checklistItems.yml +++ b/api/fixtures/performance_test/checklistItems.yml @@ -6,5 +6,5 @@ App\Entity\ChecklistItem: checklist: '@additional_checklist2_' text: 'Item_' additional_checklistItem_camp1_{1..12}: - camp: '@additional_checklist_camp1_1' + checklist: '@additional_checklist_camp1_1' text: 'Item_' diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml index 26a4f2af89..3a3bc5d0bf 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml @@ -24849,7 +24849,6 @@ paths: summary: 'Retrieves the collection of ChecklistItem resources.' tags: - ChecklistItem - parameters: [] post: deprecated: false description: 'Creates a ChecklistItem resource.' @@ -24968,7 +24967,6 @@ paths: summary: 'Retrieves a ChecklistItem resource.' tags: - ChecklistItem - parameters: [] patch: deprecated: false description: 'Updates the ChecklistItem resource.' @@ -25238,7 +25236,6 @@ paths: summary: 'Retrieves the collection of ChecklistItem resources.' tags: - ChecklistItem - parameters: [] '/checklists/{id}': delete: deprecated: false @@ -25475,7 +25472,6 @@ paths: summary: 'Retrieves the collection of ChecklistNode resources.' tags: - ChecklistNode - parameters: [] post: deprecated: false description: 'Creates a ChecklistNode resource.' @@ -25594,7 +25590,6 @@ paths: summary: 'Retrieves a ChecklistNode resource.' tags: - ChecklistNode - parameters: [] patch: deprecated: false description: 'Updates the ChecklistNode resource.' diff --git a/api/tests/Api/SnapshotTests/__snapshots__/performance_test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml b/api/tests/Api/SnapshotTests/__snapshots__/performance_test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml index b8edfa35ed..fdc9790ac3 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/performance_test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml +++ b/api/tests/Api/SnapshotTests/__snapshots__/performance_test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml @@ -1,15 +1,19 @@ /activities: 221 -/activities/item: 233 +/activities/item: 236 /activity_progress_labels: 6 /activity_progress_labels/item: 7 /activity_responsibles: 6 /activity_responsibles/item: 8 -/camps: 36 -/camps/item: 31 -/camp_collaborations: 22 -/camp_collaborations/item: 24 +/camps: 39 +/camps/item: 32 +/camp_collaborations: 25 +/camp_collaborations/item: 25 /categories: 11 /categories/item: 9 +/checklists: 6 +/checklists/item: 7 +/checklist_items: 6 +/checklist_items/item: 8 /content_types: 6 /content_types/item: 6 /days: 26 @@ -21,7 +25,7 @@ /material_lists: 6 /material_lists/item: 7 /periods: 6 -/periods/item: 27 +/periods/item: 28 /profiles: 6 /profiles/item: 6 /schedule_entries: 23 @@ -30,8 +34,8 @@ '/activities?camp=': 213 '/activity_progress_labels?camp=': 6 '/activity_responsibles?activity.camp=': 6 -'/camp_collaborations?camp=': 12 -'/camp_collaborations?activityResponsibles.activity=': 24 +'/camp_collaborations?camp=': 13 +'/camp_collaborations?activityResponsibles.activity=': 25 '/categories?camp=': 9 '/content_types?categories=': 6 '/day_responsibles?day.period=': 6 From ac9fa3228e1e324cbdb31b5074d1ac1e3b68814c Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Tue, 6 Aug 2024 22:57:28 +0200 Subject: [PATCH 16/69] changes according to review --- api/src/Entity/Camp.php | 2 +- api/src/Entity/Checklist.php | 5 +- api/src/Entity/ChecklistItem.php | 11 +- api/src/Entity/ContentNode/ChecklistNode.php | 2 +- ...t.php => AssertBelongsToSameChecklist.php} | 2 +- ...AssertBelongsToSameChecklistValidator.php} | 6 +- .../ListCampCollaborationsTest.php | 2 +- .../ReadCampCollaborationTest.php | 2 +- ...est__testOpenApiSpecMatchesSnapshot__1.yml | 147 ++++++------------ ...manceDidNotChangeForStableEndpoints__1.yml | 14 +- ...manceDidNotChangeForStableEndpoints__1.yml | 14 +- 11 files changed, 79 insertions(+), 128 deletions(-) rename api/src/Validator/ChecklistItem/{AssertBelongsToChecklist.php => AssertBelongsToSameChecklist.php} (75%) rename api/src/Validator/ChecklistItem/{AssertBelongsToChecklistValidator.php => AssertBelongsToSameChecklistValidator.php} (87%) diff --git a/api/src/Entity/Camp.php b/api/src/Entity/Camp.php index 88a895869c..35295e7956 100644 --- a/api/src/Entity/Camp.php +++ b/api/src/Entity/Camp.php @@ -140,7 +140,7 @@ class Camp extends BaseEntity implements BelongsToCampInterface, CopyFromPrototy * List of all Checklists of this Camp. * Each Checklist is a List of ChecklistItems. */ - #[ApiProperty(writable: false, example: '["/checklists/1a2b3c4d"]')] + #[ApiProperty(writable: false, uriTemplate: Checklist::CAMP_SUBRESOURCE_URI_TEMPLATE)] #[Groups(['read'])] #[ORM\OneToMany(targetEntity: Checklist::class, mappedBy: 'camp', orphanRemoval: true, cascade: ['persist'])] public Collection $checklists; diff --git a/api/src/Entity/Checklist.php b/api/src/Entity/Checklist.php index 9703f5d30a..336177e806 100644 --- a/api/src/Entity/Checklist.php +++ b/api/src/Entity/Checklist.php @@ -48,7 +48,6 @@ securityPostDenormalize: 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)' ), new GetCollection( - name: 'BelongsToCamp_App\Entity\Checklist_get_collection', uriTemplate: self::CAMP_SUBRESOURCE_URI_TEMPLATE, uriVariables: [ 'campId' => new Link( @@ -66,7 +65,7 @@ #[ApiFilter(filterClass: SearchFilter::class, properties: ['camp'])] #[ORM\Entity(repositoryClass: ChecklistRepository::class)] class Checklist extends BaseEntity implements BelongsToCampInterface, CopyFromPrototypeInterface { - public const CAMP_SUBRESOURCE_URI_TEMPLATE = '/camps/{campId}/checklists.{_format}'; + public const CAMP_SUBRESOURCE_URI_TEMPLATE = '/camps/{campId}/checklists{._format}'; /** * The camp this checklist belongs to. @@ -87,7 +86,7 @@ class Checklist extends BaseEntity implements BelongsToCampInterface, CopyFromPr /** * All ChecklistItems that belong to this Checklist. */ - #[ApiProperty(writable: false, example: '["/checklist_items/1a2b3c4d"]')] + #[ApiProperty(writable: false, uriTemplate: ChecklistItem::CHECKLIST_SUBRESOURCE_URI_TEMPLATE)] #[Groups(['read'])] #[ORM\OneToMany(targetEntity: ChecklistItem::class, mappedBy: 'checklist', cascade: ['persist'])] public Collection $checklistItems; diff --git a/api/src/Entity/ChecklistItem.php b/api/src/Entity/ChecklistItem.php index 9cbec270c1..9317985251 100644 --- a/api/src/Entity/ChecklistItem.php +++ b/api/src/Entity/ChecklistItem.php @@ -17,7 +17,7 @@ use App\Repository\ChecklistItemRepository; use App\Util\EntityMap; use App\Validator\AssertNoLoop; -use App\Validator\ChecklistItem\AssertBelongsToChecklist; +use App\Validator\ChecklistItem\AssertBelongsToSameChecklist; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -38,9 +38,7 @@ security: 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)' ), new Delete( - security: 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)', - validate: true, - validationContext: ['groups' => ['delete']] + security: 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)' ), new GetCollection( security: 'is_authenticated()' @@ -50,7 +48,6 @@ securityPostDenormalize: 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)' ), new GetCollection( - name: 'BelongsToChecklist_App\Entity\ChecklistItem_get_collection', uriTemplate: self::CHECKLIST_SUBRESOURCE_URI_TEMPLATE, uriVariables: [ 'checklistId' => new Link( @@ -69,7 +66,7 @@ #[ORM\Entity(repositoryClass: ChecklistItemRepository::class)] #[ORM\UniqueConstraint(name: 'checklistitem_checklistid_parentid_position_unique', columns: ['checklistid', 'parentid', 'position'])] class ChecklistItem extends BaseEntity implements BelongsToCampInterface, CopyFromPrototypeInterface, HasParentInterface { - public const CHECKLIST_SUBRESOURCE_URI_TEMPLATE = '/checklists/{checklistId}/checklist_items.{_format}'; + public const CHECKLIST_SUBRESOURCE_URI_TEMPLATE = '/checklists/{checklistId}/checklist_items{._format}'; /** * The Checklist this Item belongs to. @@ -86,7 +83,7 @@ class ChecklistItem extends BaseEntity implements BelongsToCampInterface, CopyFr * root of a ChecklistItem tree. For non-root ChecklistItems, the parent can be changed, as long * as the new parent is in the same checklist as the old one. */ - #[AssertBelongsToChecklist(groups: ['update'])] + #[AssertBelongsToSameChecklist(groups: ['update'])] #[AssertNoLoop(groups: ['update'])] #[ApiProperty(example: '/checklist_items/1a2b3c4d')] #[Gedmo\SortableGroup] diff --git a/api/src/Entity/ContentNode/ChecklistNode.php b/api/src/Entity/ContentNode/ChecklistNode.php index 36713bfb93..433be7ec36 100644 --- a/api/src/Entity/ContentNode/ChecklistNode.php +++ b/api/src/Entity/ContentNode/ChecklistNode.php @@ -51,7 +51,7 @@ #[ORM\Entity(repositoryClass: ChecklistNodeRepository::class)] class ChecklistNode extends ContentNode { /** - * The content types that are most likely to be useful for planning programme of this category. + * List of selected ChecklistItems. */ #[ApiProperty(example: '["/checklist_items/1a2b3c4d"]')] #[Groups(['read'])] diff --git a/api/src/Validator/ChecklistItem/AssertBelongsToChecklist.php b/api/src/Validator/ChecklistItem/AssertBelongsToSameChecklist.php similarity index 75% rename from api/src/Validator/ChecklistItem/AssertBelongsToChecklist.php rename to api/src/Validator/ChecklistItem/AssertBelongsToSameChecklist.php index ceb67ccc17..a70685628d 100644 --- a/api/src/Validator/ChecklistItem/AssertBelongsToChecklist.php +++ b/api/src/Validator/ChecklistItem/AssertBelongsToSameChecklist.php @@ -5,6 +5,6 @@ use Symfony\Component\Validator\Constraint; #[\Attribute] -class AssertBelongsToChecklist extends Constraint { +class AssertBelongsToSameChecklist extends Constraint { public string $message = 'Must belong to the same checklist.'; } diff --git a/api/src/Validator/ChecklistItem/AssertBelongsToChecklistValidator.php b/api/src/Validator/ChecklistItem/AssertBelongsToSameChecklistValidator.php similarity index 87% rename from api/src/Validator/ChecklistItem/AssertBelongsToChecklistValidator.php rename to api/src/Validator/ChecklistItem/AssertBelongsToSameChecklistValidator.php index 01aaa2fb76..7ad21d1670 100644 --- a/api/src/Validator/ChecklistItem/AssertBelongsToChecklistValidator.php +++ b/api/src/Validator/ChecklistItem/AssertBelongsToSameChecklistValidator.php @@ -9,12 +9,12 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException; use Symfony\Component\Validator\Exception\UnexpectedValueException; -class AssertBelongsToChecklistValidator extends ConstraintValidator { +class AssertBelongsToSameChecklistValidator extends ConstraintValidator { public function __construct(public RequestStack $requestStack) {} public function validate($value, Constraint $constraint): void { - if (!$constraint instanceof AssertBelongsToChecklist) { - throw new UnexpectedTypeException($constraint, AssertBelongsToChecklist::class); + if (!$constraint instanceof AssertBelongsToSameChecklist) { + throw new UnexpectedTypeException($constraint, AssertBelongsToSameChecklist::class); } if (null === $value || '' === $value) { diff --git a/api/tests/Api/CampCollaborations/ListCampCollaborationsTest.php b/api/tests/Api/CampCollaborations/ListCampCollaborationsTest.php index 8ce744e353..06975241fe 100644 --- a/api/tests/Api/CampCollaborations/ListCampCollaborationsTest.php +++ b/api/tests/Api/CampCollaborations/ListCampCollaborationsTest.php @@ -114,6 +114,6 @@ public function testSqlQueryCount() { $client->enableProfiler(); $client->request('GET', '/camp_collaborations'); - $this->assertSqlQueryCount($client, 25); + $this->assertSqlQueryCount($client, 22); } } diff --git a/api/tests/Api/CampCollaborations/ReadCampCollaborationTest.php b/api/tests/Api/CampCollaborations/ReadCampCollaborationTest.php index 8c9eaf027f..a9916e6211 100644 --- a/api/tests/Api/CampCollaborations/ReadCampCollaborationTest.php +++ b/api/tests/Api/CampCollaborations/ReadCampCollaborationTest.php @@ -126,6 +126,6 @@ public function testSqlQueryCount() { $client->enableProfiler(); $client->request('GET', '/camp_collaborations/'.$campCollaboration->getId()); - $this->assertSqlQueryCount($client, 15); + $this->assertSqlQueryCount($client, 14); } } diff --git a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml index 3a3bc5d0bf..c3eec18fe1 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml +++ b/api/tests/Api/SnapshotTests/__snapshots__/ResponseSnapshotTest__testOpenApiSpecMatchesSnapshot__1.yml @@ -2335,13 +2335,10 @@ components: type: string checklists: description: 'List of all Checklists of this Camp.' - example: '["/checklists/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string + example: 'https://example.com/' + format: iri-reference readOnly: true - type: array + type: string coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -2538,13 +2535,10 @@ components: type: string checklists: description: 'List of all Checklists of this Camp.' - example: '["/checklists/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string + example: 'https://example.com/' + format: iri-reference readOnly: true - type: array + type: string coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -2730,13 +2724,10 @@ components: type: string checklists: description: 'List of all Checklists of this Camp.' - example: '["/checklists/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string + example: 'https://example.com/' + format: iri-reference readOnly: true - type: array + type: string coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -2929,13 +2920,10 @@ components: type: string checklists: description: 'List of all Checklists of this Camp.' - example: '["/checklists/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string + example: 'https://example.com/' + format: iri-reference readOnly: true - type: array + type: string coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -3540,13 +3528,10 @@ components: type: string checklists: description: 'List of all Checklists of this Camp.' - example: '["/checklists/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string + example: 'https://example.com/' + format: iri-reference readOnly: true - type: array + type: string coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -3752,13 +3737,10 @@ components: type: string checklists: description: 'List of all Checklists of this Camp.' - example: '["/checklists/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string + example: 'https://example.com/' + format: iri-reference readOnly: true - type: array + type: string coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -3953,13 +3935,10 @@ components: type: string checklists: description: 'List of all Checklists of this Camp.' - example: '["/checklists/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string + example: 'https://example.com/' + format: iri-reference readOnly: true - type: array + type: string coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -4161,13 +4140,10 @@ components: type: string checklists: description: 'List of all Checklists of this Camp.' - example: '["/checklists/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string + example: 'https://example.com/' + format: iri-reference readOnly: true - type: array + type: string coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -4516,13 +4492,10 @@ components: type: string checklists: description: 'List of all Checklists of this Camp.' - example: '["/checklists/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string + example: 'https://example.com/' + format: iri-reference readOnly: true - type: array + type: string coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -4742,13 +4715,10 @@ components: type: string checklists: description: 'List of all Checklists of this Camp.' - example: '["/checklists/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string + example: 'https://example.com/' + format: iri-reference readOnly: true - type: array + type: string coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -4957,13 +4927,10 @@ components: type: string checklists: description: 'List of all Checklists of this Camp.' - example: '["/checklists/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string + example: 'https://example.com/' + format: iri-reference readOnly: true - type: array + type: string coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -5179,13 +5146,10 @@ components: type: string checklists: description: 'List of all Checklists of this Camp.' - example: '["/checklists/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string + example: 'https://example.com/' + format: iri-reference readOnly: true - type: array + type: string coachName: description: 'The name of the Y+S coach who is in charge of the camp.' example: 'Albert Anderegg' @@ -7625,13 +7589,10 @@ components: type: string checklistItems: description: 'All ChecklistItems that belong to this Checklist.' - example: '["/checklist_items/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string + example: 'https://example.com/' + format: iri-reference readOnly: true - type: array + type: string id: description: 'An internal, unique, randomly generated identifier of this entity.' example: 1a2b3c4d @@ -7766,13 +7727,10 @@ components: type: string checklistItems: description: 'All ChecklistItems that belong to this Checklist.' - example: '["/checklist_items/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string + example: 'https://example.com/' + format: iri-reference readOnly: true - type: array + type: string id: description: 'An internal, unique, randomly generated identifier of this entity.' example: 1a2b3c4d @@ -7861,13 +7819,10 @@ components: type: string checklistItems: description: 'All ChecklistItems that belong to this Checklist.' - example: '["/checklist_items/1a2b3c4d"]' - items: - example: 'https://example.com/' - format: iri-reference - type: string + example: 'https://example.com/' + format: iri-reference readOnly: true - type: array + type: string id: description: 'An internal, unique, randomly generated identifier of this entity.' example: 1a2b3c4d @@ -8316,7 +8271,7 @@ components: description: '' properties: checklistItems: - description: 'The content types that are most likely to be useful for planning programme of this category.' + description: 'List of selected ChecklistItems.' example: '["/checklist_items/1a2b3c4d"]' items: example: 'https://example.com/' @@ -8564,7 +8519,7 @@ components: - 'null' writeOnly: true checklistItems: - description: 'The content types that are most likely to be useful for planning programme of this category.' + description: 'List of selected ChecklistItems.' example: '["/checklist_items/1a2b3c4d"]' items: example: 'https://example.com/' @@ -8683,7 +8638,7 @@ components: type: object type: object checklistItems: - description: 'The content types that are most likely to be useful for planning programme of this category.' + description: 'List of selected ChecklistItems.' example: '["/checklist_items/1a2b3c4d"]' items: example: 'https://example.com/' @@ -8890,7 +8845,7 @@ components: readOnly: true type: string checklistItems: - description: 'The content types that are most likely to be useful for planning programme of this category.' + description: 'List of selected ChecklistItems.' example: '["/checklist_items/1a2b3c4d"]' items: example: 'https://example.com/' @@ -24319,7 +24274,7 @@ paths: get: deprecated: false description: 'Retrieves the collection of Checklist resources.' - operationId: BelongsToCamp_App\Entity\Checklist_get_collection + operationId: api_camps_campIdchecklists_get_collection parameters: - allowEmptyValue: false @@ -25153,7 +25108,7 @@ paths: get: deprecated: false description: 'Retrieves the collection of ChecklistItem resources.' - operationId: BelongsToChecklist_App\Entity\ChecklistItem_get_collection + operationId: api_checklists_checklistIdchecklist_items_get_collection parameters: - allowEmptyValue: false diff --git a/api/tests/Api/SnapshotTests/__snapshots__/performance_test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml b/api/tests/Api/SnapshotTests/__snapshots__/performance_test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml index fdc9790ac3..00d3d68b59 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/performance_test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml +++ b/api/tests/Api/SnapshotTests/__snapshots__/performance_test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml @@ -4,10 +4,10 @@ /activity_progress_labels/item: 7 /activity_responsibles: 6 /activity_responsibles/item: 8 -/camps: 39 -/camps/item: 32 -/camp_collaborations: 25 -/camp_collaborations/item: 25 +/camps: 36 +/camps/item: 31 +/camp_collaborations: 22 +/camp_collaborations/item: 24 /categories: 11 /categories/item: 9 /checklists: 6 @@ -25,7 +25,7 @@ /material_lists: 6 /material_lists/item: 7 /periods: 6 -/periods/item: 28 +/periods/item: 27 /profiles: 6 /profiles/item: 6 /schedule_entries: 23 @@ -34,8 +34,8 @@ '/activities?camp=': 213 '/activity_progress_labels?camp=': 6 '/activity_responsibles?activity.camp=': 6 -'/camp_collaborations?camp=': 13 -'/camp_collaborations?activityResponsibles.activity=': 25 +'/camp_collaborations?camp=': 12 +'/camp_collaborations?activityResponsibles.activity=': 24 '/categories?camp=': 9 '/content_types?categories=': 6 '/day_responsibles?day.period=': 6 diff --git a/api/tests/Api/SnapshotTests/__snapshots__/test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml b/api/tests/Api/SnapshotTests/__snapshots__/test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml index 85260de4e7..31e42033f3 100644 --- a/api/tests/Api/SnapshotTests/__snapshots__/test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml +++ b/api/tests/Api/SnapshotTests/__snapshots__/test_EndpointPerformanceTest__testPerformanceDidNotChangeForStableEndpoints__1.yml @@ -4,10 +4,10 @@ /activity_progress_labels/item: 7 /activity_responsibles: 6 /activity_responsibles/item: 8 -/camps: 29 -/camps/item: 22 -/camp_collaborations: 25 -/camp_collaborations/item: 15 +/camps: 26 +/camps/item: 21 +/camp_collaborations: 22 +/camp_collaborations/item: 14 /categories: 11 /categories/item: 9 /checklists: 6 @@ -25,7 +25,7 @@ /material_lists: 6 /material_lists/item: 7 /periods: 6 -/periods/item: 18 +/periods/item: 17 /profiles: 6 /profiles/item: 6 /schedule_entries: 23 @@ -34,8 +34,8 @@ '/activities?camp=': 13 '/activity_progress_labels?camp=': 6 '/activity_responsibles?activity.camp=': 6 -'/camp_collaborations?camp=': 13 -'/camp_collaborations?activityResponsibles.activity=': 15 +'/camp_collaborations?camp=': 12 +'/camp_collaborations?activityResponsibles.activity=': 14 '/categories?camp=': 9 '/content_types?categories=': 6 '/day_responsibles?day.period=': 6 From bdd8b35a717b7d71c6b4fd7b48033117e353e7c8 Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Thu, 8 Aug 2024 19:42:36 +0200 Subject: [PATCH 17/69] UnitTest ChecklistNode can only contain ChecklistItems of the same camp --- api/src/Entity/ContentNode/ChecklistNode.php | 2 + .../ChecklistItem/AssertBelongsToSameCamp.php | 10 ++++ .../AssertBelongsToSameCampValidator.php | 55 +++++++++++++++++++ .../ChecklistNode/UpdateChecklistNodeTest.php | 14 +++++ 4 files changed, 81 insertions(+) create mode 100644 api/src/Validator/ChecklistItem/AssertBelongsToSameCamp.php create mode 100644 api/src/Validator/ChecklistItem/AssertBelongsToSameCampValidator.php diff --git a/api/src/Entity/ContentNode/ChecklistNode.php b/api/src/Entity/ContentNode/ChecklistNode.php index 433be7ec36..2f6dcc8c39 100644 --- a/api/src/Entity/ContentNode/ChecklistNode.php +++ b/api/src/Entity/ContentNode/ChecklistNode.php @@ -15,6 +15,7 @@ use App\Repository\ChecklistNodeRepository; use App\State\ContentNode\ChecklistNodePersistProcessor; use App\Util\EntityMap; +use App\Validator\ChecklistItem\AssertBelongsToSameCamp; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -62,6 +63,7 @@ class ChecklistNode extends ContentNode { #[ORM\OrderBy(['position' => 'ASC'])] public Collection $checklistItems; + #[AssertBelongsToSameCamp(groups: ['update'])] #[ApiProperty(example: '["1a2b3c4d"]')] #[Groups(['write'])] public ?array $addChecklistItemIds = []; diff --git a/api/src/Validator/ChecklistItem/AssertBelongsToSameCamp.php b/api/src/Validator/ChecklistItem/AssertBelongsToSameCamp.php new file mode 100644 index 0000000000..e27bffc8d6 --- /dev/null +++ b/api/src/Validator/ChecklistItem/AssertBelongsToSameCamp.php @@ -0,0 +1,10 @@ +context->getObject(); + if (!$object instanceof ChecklistNode) { + throw new UnexpectedValueException($object, ChecklistNode::class); + } + + $camp = $this->getCampFromInterface($object, $this->em); + + foreach($value as $checklistItemId) { + /** @var ChecklistItem $checklistItem */ + $checklistItem = $this->checklistItemRepository->find($checklistItemId); + + if ($camp != $checklistItem?->getCamp()) { + $this->context->buildViolation($constraint->message) + ->addViolation(); + } + } + } +} diff --git a/api/tests/Api/ContentNodes/ChecklistNode/UpdateChecklistNodeTest.php b/api/tests/Api/ContentNodes/ChecklistNode/UpdateChecklistNodeTest.php index a2cd67de89..679348df60 100644 --- a/api/tests/Api/ContentNodes/ChecklistNode/UpdateChecklistNodeTest.php +++ b/api/tests/Api/ContentNodes/ChecklistNode/UpdateChecklistNodeTest.php @@ -103,4 +103,18 @@ public function testRemoveChecklistItemForManager() { $checklistNode = $this->getEntityManager()->getRepository(ChecklistNode::class)->find($this->defaultEntity->getId()); $this->assertFalse(in_array($checklistItem, $checklistNode->getChecklistItems())); } + + public function testAddChecklistItemOfOtherCampIsDenied() { + $checklistItemId = static::getFixture('checklistItem2_1_1')->getId(); + static::createClientWithCredentials(['email' => static::getFixture('user2member')->getEmail()]) + ->request('PATCH', $this->endpoint.'/'.$this->defaultEntity->getId(), ['json' => [ + 'addChecklistItemIds' => [$checklistItemId], + ], 'headers' => ['Content-Type' => 'application/merge-patch+json']]) + ; + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'addChecklistItemIds: Must belong to the same camp.', + ]); + } } From 46b5519dec4a493ce5d0a6c07dd5f37c3a59d240 Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Thu, 8 Aug 2024 19:45:10 +0200 Subject: [PATCH 18/69] changes according to review --- api/src/Entity/Checklist.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/api/src/Entity/Checklist.php b/api/src/Entity/Checklist.php index 336177e806..1746c30021 100644 --- a/api/src/Entity/Checklist.php +++ b/api/src/Entity/Checklist.php @@ -35,9 +35,7 @@ security: 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)' ), new Delete( - security: 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)', - validate: true, - validationContext: ['groups' => ['delete']] + security: 'is_granted("CAMP_MEMBER", object) or is_granted("CAMP_MANAGER", object)' ), new GetCollection( security: 'is_authenticated()' From 630b9abacb8bba6e04f12e34f9b4db9da2cc1fff Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Thu, 8 Aug 2024 20:10:57 +0200 Subject: [PATCH 19/69] UnitTest ChecklistItem NoParentLoop --- api/src/Entity/ChecklistItem.php | 4 ++-- .../UpdateChecklistItemTest.php | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/api/src/Entity/ChecklistItem.php b/api/src/Entity/ChecklistItem.php index 9317985251..4a414832b5 100644 --- a/api/src/Entity/ChecklistItem.php +++ b/api/src/Entity/ChecklistItem.php @@ -83,8 +83,8 @@ class ChecklistItem extends BaseEntity implements BelongsToCampInterface, CopyFr * root of a ChecklistItem tree. For non-root ChecklistItems, the parent can be changed, as long * as the new parent is in the same checklist as the old one. */ - #[AssertBelongsToSameChecklist(groups: ['update'])] - #[AssertNoLoop(groups: ['update'])] + #[AssertBelongsToSameChecklist] + #[AssertNoLoop] #[ApiProperty(example: '/checklist_items/1a2b3c4d')] #[Gedmo\SortableGroup] #[Groups(['read', 'write'])] diff --git a/api/tests/Api/ChecklistItems/UpdateChecklistItemTest.php b/api/tests/Api/ChecklistItems/UpdateChecklistItemTest.php index 0152401f68..5237deb0bb 100644 --- a/api/tests/Api/ChecklistItems/UpdateChecklistItemTest.php +++ b/api/tests/Api/ChecklistItems/UpdateChecklistItemTest.php @@ -110,6 +110,28 @@ public function testPatchChecklistItemDisallowsChangingChecklist() { ]); } + public function testPatchhChecklistItemValidatesNoParentLoop() { + $checklistItemParent = static::getFixture('checklistItem1_1_2'); + $checklistItemChild = static::getFixture('checklistItem1_1_2_3'); + + static::createClientWithCredentials()->request( + 'PATCH', + '/checklist_items/'.$checklistItemParent->getId(), + [ + 'json' => [ + 'parent' => '/checklist_items/'.$checklistItemChild->getId(), + ], + 'headers' => ['Content-Type' => 'application/merge-patch+json'], + ] + ); + + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'parent: Must not form a loop of parent-child relations.', + ]); + } + public function testPatchChecklistItemValidatesNullText() { $checklistItem = static::getFixture('checklistItem1_1_1'); static::createClientWithCredentials()->request( From 5cf86d54d80c2016d44cef5032fa17f25e07f759 Mon Sep 17 00:00:00 2001 From: Pirmin Mattmann Date: Thu, 8 Aug 2024 20:14:43 +0200 Subject: [PATCH 20/69] cs-fix; phpstan --- .../AssertBelongsToSameCampValidator.php | 11 ++++++----- .../Api/ChecklistItems/UpdateChecklistItemTest.php | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/api/src/Validator/ChecklistItem/AssertBelongsToSameCampValidator.php b/api/src/Validator/ChecklistItem/AssertBelongsToSameCampValidator.php index 7716448fa7..373471ef3b 100644 --- a/api/src/Validator/ChecklistItem/AssertBelongsToSameCampValidator.php +++ b/api/src/Validator/ChecklistItem/AssertBelongsToSameCampValidator.php @@ -15,9 +15,9 @@ class AssertBelongsToSameCampValidator extends ConstraintValidator { use GetCampFromContentNodeTrait; - + public function __construct( - public RequestStack $requestStack, + public RequestStack $requestStack, private EntityManagerInterface $em, private ChecklistItemRepository $checklistItemRepository, ) {} @@ -42,13 +42,14 @@ public function validate($value, Constraint $constraint): void { $camp = $this->getCampFromInterface($object, $this->em); - foreach($value as $checklistItemId) { - /** @var ChecklistItem $checklistItem */ + foreach ($value as $checklistItemId) { + /** @var ?ChecklistItem $checklistItem */ $checklistItem = $this->checklistItemRepository->find($checklistItemId); if ($camp != $checklistItem?->getCamp()) { $this->context->buildViolation($constraint->message) - ->addViolation(); + ->addViolation() + ; } } } diff --git a/api/tests/Api/ChecklistItems/UpdateChecklistItemTest.php b/api/tests/Api/ChecklistItems/UpdateChecklistItemTest.php index 5237deb0bb..24462d3c0e 100644 --- a/api/tests/Api/ChecklistItems/UpdateChecklistItemTest.php +++ b/api/tests/Api/ChecklistItems/UpdateChecklistItemTest.php @@ -124,7 +124,7 @@ public function testPatchhChecklistItemValidatesNoParentLoop() { 'headers' => ['Content-Type' => 'application/merge-patch+json'], ] ); - + $this->assertResponseStatusCodeSame(422); $this->assertJsonContains([ 'title' => 'An error occurred', From 15187f03f3efa50d05dc9550f1fd7cd79c242392 Mon Sep 17 00:00:00 2001 From: Manuel Meister Date: Sun, 30 Jun 2024 19:12:15 +0200 Subject: [PATCH 21/69] Add checklist to frontend admin --- common/locales/de.json | 12 ++ common/locales/en.json | 12 ++ common/locales/fr.json | 11 + .../components/checklist/ChecklistCreate.vue | 83 ++++++++ .../components/checklist/ChecklistItem.vue | 94 ++++++++ .../checklist/ChecklistItemCreate.vue | 82 +++++++ .../checklist/ChecklistItemEdit.vue | 69 ++++++ .../checklist/SortableChecklist.vue | 201 ++++++++++++++++++ frontend/src/locales/de.json | 15 ++ frontend/src/locales/en.json | 15 ++ frontend/src/router.js | 61 ++++++ frontend/src/views/admin/Checklists.vue | 56 +++++ frontend/src/views/admin/SideBarAdmin.vue | 5 + frontend/src/views/checklist/Checklist.vue | 55 +++++ .../src/views/checklist/SideBarChecklist.vue | 29 +++ 15 files changed, 800 insertions(+) create mode 100644 frontend/src/components/checklist/ChecklistCreate.vue create mode 100644 frontend/src/components/checklist/ChecklistItem.vue create mode 100644 frontend/src/components/checklist/ChecklistItemCreate.vue create mode 100644 frontend/src/components/checklist/ChecklistItemEdit.vue create mode 100644 frontend/src/components/checklist/SortableChecklist.vue create mode 100644 frontend/src/views/admin/Checklists.vue create mode 100644 frontend/src/views/checklist/Checklist.vue create mode 100644 frontend/src/views/checklist/SideBarChecklist.vue diff --git a/common/locales/de.json b/common/locales/de.json index c8f3f1d83f..5995eceffb 100644 --- a/common/locales/de.json +++ b/common/locales/de.json @@ -169,6 +169,18 @@ "-": "keine Nummerierung" } }, + "checklist": { + "fields": { + "name": "Name" + }, + "name": "Checkliste | Checklisten" + }, + "checklistItem": { + "fields": { + "text": "Text" + }, + "name": "Checklisteneintrag" + }, "contentType": { "name": "Inhalttyp | Inhalttypen" }, diff --git a/common/locales/en.json b/common/locales/en.json index 1093dd758c..1b918ccd64 100644 --- a/common/locales/en.json +++ b/common/locales/en.json @@ -176,6 +176,18 @@ "-": "no numbering" } }, + "checklist": { + "fields": { + "name": "Name" + }, + "name": "Checklist | Checklists" + }, + "checklistItem": { + "fields": { + "text": "Text" + }, + "name": "Checklist entry" + }, "contentType": { "name": "Contenttype | Contenttypes" }, diff --git a/common/locales/fr.json b/common/locales/fr.json index db1a1a74a4..96f2ba8fdb 100644 --- a/common/locales/fr.json +++ b/common/locales/fr.json @@ -157,6 +157,17 @@ "i": "i, ii, iii - chiffres romains minuscules" } }, + "checklist": { + "fields": { + "name": "Nom" + }, + "name": "Check-list | Check-lists" + }, + "checklistItem": { + "fields": { + "text": "Text" + } + }, "contentType": { "name": "Type de contenu | Types de contenu" }, diff --git a/frontend/src/components/checklist/ChecklistCreate.vue b/frontend/src/components/checklist/ChecklistCreate.vue new file mode 100644 index 0000000000..4a59225efb --- /dev/null +++ b/frontend/src/components/checklist/ChecklistCreate.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/frontend/src/components/checklist/ChecklistItem.vue b/frontend/src/components/checklist/ChecklistItem.vue new file mode 100644 index 0000000000..47596d52e4 --- /dev/null +++ b/frontend/src/components/checklist/ChecklistItem.vue @@ -0,0 +1,94 @@ + + + + + diff --git a/frontend/src/components/checklist/ChecklistItemCreate.vue b/frontend/src/components/checklist/ChecklistItemCreate.vue new file mode 100644 index 0000000000..444f357d23 --- /dev/null +++ b/frontend/src/components/checklist/ChecklistItemCreate.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/frontend/src/components/checklist/ChecklistItemEdit.vue b/frontend/src/components/checklist/ChecklistItemEdit.vue new file mode 100644 index 0000000000..5d00317ffd --- /dev/null +++ b/frontend/src/components/checklist/ChecklistItemEdit.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/frontend/src/components/checklist/SortableChecklist.vue b/frontend/src/components/checklist/SortableChecklist.vue new file mode 100644 index 0000000000..55ad6ccc17 --- /dev/null +++ b/frontend/src/components/checklist/SortableChecklist.vue @@ -0,0 +1,201 @@ + + + + + diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 15e660cce8..5ae5147bb9 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -193,6 +193,21 @@ "title": "Kategorie kopieren & einfügen" } }, + "checklist": { + "checklistCreate": { + "title": "Checkliste erstellen" + }, + "checklistItemCreate": { + "add": "Checklisteneintrag erstellen", + "title": "Checklisteneintrag hinzufügen" + }, + "checklistItemEdit": { + "title": "Checklisteneintrag bearbeiten" + }, + "sortableChecklist": { + "add": "Zu \"{parent}\" hinzufügen" + } + }, "collaborator": { "collaboratorCreate": { "invite": "Einladung verschicken", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 01ac2616c3..da2cd59d19 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -193,6 +193,21 @@ "title": "Copy & paste category" } }, + "checklist": { + "checklistCreate": { + "title": "Create checklist" + }, + "checklistItemCreate": { + "add": "Create checklist entry", + "title": "Add checklist entry" + }, + "checklistItemEdit": { + "title": "Edit checklist entry" + }, + "sortableChecklist": { + "add": "Add to \"{parent}\"" + } + }, "collaborator": { "collaboratorCreate": { "invite": "Send invitation", diff --git a/frontend/src/router.js b/frontend/src/router.js index 650a54777a..ae931cea5d 100644 --- a/frontend/src/router.js +++ b/frontend/src/router.js @@ -338,6 +338,24 @@ export default new Router({ }), }, }, + { + name: 'admin/checklists/checklist', + path: '/camps/:campId/:campTitle?/admin/checklist/:checklistId/:checklistName?', + components: { + navigation: NavigationCamp, + default: () => import('./views/checklist/Checklist.vue'), + aside: () => import('./views/checklist/SideBarChecklist.vue'), + }, + beforeEnter: all([requireAuth, requireCamp, requireChecklist]), + props: { + navigation: (route) => ({ camp: campFromRoute(route) }), + aside: (route) => ({ camp: campFromRoute(route) }), + default: (route) => ({ + camp: campFromRoute(route), + checklist: checklistFromRoute(route), + }), + }, + }, { path: '/camps/:campId/:campTitle?/admin', components: { @@ -384,6 +402,12 @@ export default new Router({ component: () => import('./views/admin/Print.vue'), props: (route) => ({ camp: campFromRoute(route) }), }, + { + path: 'checklists', + name: 'admin/checklists', + component: () => import('./views/admin/Checklists.vue'), + props: (route) => ({ camp: campFromRoute(route) }), + }, { path: 'materiallists', name: 'camp/material', @@ -567,6 +591,25 @@ async function requireMaterialList(to, from, next) { } } +async function requireChecklist(to, from, next) { + const checklist = await checklistFromRoute(to) + if (checklist === undefined) { + next({ + name: 'PageNotFound', + params: [to.fullPath, ''], + replace: true, + }) + } else { + await checklist._meta.load + .then(() => { + next() + }) + .catch(() => { + next(campRoute(campFromRoute(to))) + }) + } +} + export function campFromRoute(route) { return apiStore.get().camps({ id: route.params.campId }) } @@ -593,6 +636,10 @@ export function materialListFromRoute(route) { return apiStore.get().materialLists({ id: route.params.materialId }) } +export function checklistFromRoute(route) { + return apiStore.get().checklists({ id: route.params.checklistId }) +} + function getContentLayout(route) { switch (route.name) { case 'camp/period/program': @@ -722,6 +769,20 @@ export function categoryRoute(camp, category, query = {}) { } } +export function checklistRoute(camp, checklist, query = {}) { + if (camp._meta.loading || checklist._meta.loading) return {} + return { + name: 'admin/checklists/checklist', + params: { + campId: camp.id, + campTitle: slugify(camp.title), + checklistId: checklist.id, + checklistName: slugify(checklist.name), + }, + query, + } +} + async function firstFuturePeriod(route) { const periods = await apiStore.get().camps({ id: route.params.campId }).periods()._meta .load diff --git a/frontend/src/views/admin/Checklists.vue b/frontend/src/views/admin/Checklists.vue new file mode 100644 index 0000000000..4bba314b0c --- /dev/null +++ b/frontend/src/views/admin/Checklists.vue @@ -0,0 +1,56 @@ + + + diff --git a/frontend/src/views/admin/SideBarAdmin.vue b/frontend/src/views/admin/SideBarAdmin.vue index 2d1abd7e4a..76a4074130 100644 --- a/frontend/src/views/admin/SideBarAdmin.vue +++ b/frontend/src/views/admin/SideBarAdmin.vue @@ -17,6 +17,11 @@ :title="$tc('views.admin.sideBarAdmin.itemCollaborators')" icon="mdi-account-group-outline" /> + + + + + + + + + + + + diff --git a/frontend/src/views/checklist/SideBarChecklist.vue b/frontend/src/views/checklist/SideBarChecklist.vue new file mode 100644 index 0000000000..dc4fa7f6c7 --- /dev/null +++ b/frontend/src/views/checklist/SideBarChecklist.vue @@ -0,0 +1,29 @@ + + + From c4ef98ddfb1944d2a0f39baf2a6a6d3492b047a9 Mon Sep 17 00:00:00 2001 From: Manuel Meister Date: Fri, 5 Jul 2024 21:20:26 +0200 Subject: [PATCH 22/69] Create checklist contentnode --- common/locales/de.json | 4 + .../src/components/activity/ContentNode.vue | 2 + .../components/activity/content/Checklist.vue | 219 ++++++++++++++++++ .../content/checklist/ChecklistItem.vue | 60 +++++ .../checklist/SortableChecklist.vue | 21 +- ...listItem.vue => SortableChecklistItem.vue} | 28 +-- frontend/src/locales/de.json | 3 + frontend/src/locales/en.json | 3 + frontend/src/views/admin/SideBarAdmin.vue | 2 +- 9 files changed, 317 insertions(+), 25 deletions(-) create mode 100644 frontend/src/components/activity/content/Checklist.vue create mode 100644 frontend/src/components/activity/content/checklist/ChecklistItem.vue rename frontend/src/components/checklist/{ChecklistItem.vue => SortableChecklistItem.vue} (70%) diff --git a/common/locales/de.json b/common/locales/de.json index 5995eceffb..e3f8c07f0c 100644 --- a/common/locales/de.json +++ b/common/locales/de.json @@ -7,6 +7,10 @@ } }, "contentNode": { + "checklist": { + "icon": "mdi-clipboard-list-outline", + "name": "Checkliste" + }, "columnLayout": { "entity": { "column": { diff --git a/frontend/src/components/activity/ContentNode.vue b/frontend/src/components/activity/ContentNode.vue index 4f152eb231..be53044258 100644 --- a/frontend/src/components/activity/ContentNode.vue +++ b/frontend/src/components/activity/ContentNode.vue @@ -23,6 +23,7 @@ import LearningTopics from './content/LearningTopics.vue' import SafetyConcept from './content/SafetyConcept.vue' import Storyboard from './content/Storyboard.vue' import Storycontext from './content/Storycontext.vue' +import Checklist from './content/Checklist.vue' const contentNodeComponents = { ColumnLayout, @@ -35,6 +36,7 @@ const contentNodeComponents = { SafetyConcept, Storyboard, Storycontext, + Checklist, } export default { diff --git a/frontend/src/components/activity/content/Checklist.vue b/frontend/src/components/activity/content/Checklist.vue new file mode 100644 index 0000000000..074286c895 --- /dev/null +++ b/frontend/src/components/activity/content/Checklist.vue @@ -0,0 +1,219 @@ + + + + + diff --git a/frontend/src/components/activity/content/checklist/ChecklistItem.vue b/frontend/src/components/activity/content/checklist/ChecklistItem.vue new file mode 100644 index 0000000000..8800e15cae --- /dev/null +++ b/frontend/src/components/activity/content/checklist/ChecklistItem.vue @@ -0,0 +1,60 @@ + + + + + diff --git a/frontend/src/components/checklist/SortableChecklist.vue b/frontend/src/components/checklist/SortableChecklist.vue index 55ad6ccc17..aa72a2e498 100644 --- a/frontend/src/components/checklist/SortableChecklist.vue +++ b/frontend/src/components/checklist/SortableChecklist.vue @@ -3,7 +3,7 @@ - -
-

{{ checklist.name }}

-
    - -
+
+ + + +

+ {{ checklist.name }} + + ({{ + selectionContentNode.filter( + (item) => + checkedItems.includes(item.id) && + item.checklist()._meta.self === checklist?._meta?.self + ).length + }} + selected) + +

+
+ +
    + +
+
+
+
@@ -104,35 +122,58 @@ export default { } }, computed: { + campChecklistItems() { + return this.api.get().checklistItems().items + }, selectionContentNode() { - return this.api - .get() - .checklistItems() - .items.filter((item) => - this.contentNode - .checklistItems() - .items.some(({ _meta }) => _meta.self === item._meta.self) - ) + return this.campChecklistItems.filter((item) => + this.contentNode + .checklistItems() + .items.some(({ _meta }) => _meta.self === item._meta.self) + ) }, serverSelection() { return this.selectionContentNode.map((item) => item.id) }, + allChecklists() { + return this.camp.checklists().items.map((checklist) => ({ + checklist, + items: this.campChecklistItems + .filter((item) => item.checklist()._meta.self === checklist?._meta.self) + .map((item) => ({ + item, + parents: this.itemsLoaded ? this.getParents(item) : [], + })) + .sort((a, b) => { + const aparents = [ + ...a.parents.map(({ position }) => position), + a.item.position, + -1, + ] + const bparents = [ + ...b.parents.map(({ position }) => position), + b.item.position, + -1, + ] + for (let i = 0; i < Math.min(aparents.length, bparents.length); i++) { + if (aparents[i] !== bparents[i]) { + return aparents[i] - bparents[i] + } + } + return 0 + }), + })) + }, activeChecklists() { - return this.camp - .checklists() - .items.filter(({ _meta }) => + return this.allChecklists + .filter(({ checklist }) => this.contentNode .checklistItems() - .items.some((item) => _meta.self === item?.checklist()._meta.self) + .items.some((item) => checklist._meta.self === item?.checklist()._meta.self) ) - .map((checklist) => ({ + .map(({ checklist, items }) => ({ checklist, - items: this.selectionContentNode - .filter((item) => item.checklist()._meta.self === checklist._meta.self) - .map((item) => ({ - item, - parents: this.itemsLoaded ? this.getParents(item) : [], - })), + items: items.filter(({ item }) => this.checkedItems.includes(item.id)), })) }, }, diff --git a/frontend/src/components/checklist/ChecklistItemCreate.vue b/frontend/src/components/checklist/ChecklistItemCreate.vue index 444f357d23..d8cf07b42e 100644 --- a/frontend/src/components/checklist/ChecklistItemCreate.vue +++ b/frontend/src/components/checklist/ChecklistItemCreate.vue @@ -24,6 +24,7 @@ type="text" path="text" vee-rules="required" + autofocus /> diff --git a/frontend/src/components/checklist/ChecklistItemEdit.vue b/frontend/src/components/checklist/ChecklistItemEdit.vue index 5d00317ffd..4bf61d5488 100644 --- a/frontend/src/components/checklist/ChecklistItemEdit.vue +++ b/frontend/src/components/checklist/ChecklistItemEdit.vue @@ -20,6 +20,7 @@ type="text" path="text" vee-rules="required" + autofocus /> diff --git a/frontend/src/components/checklist/SortableChecklist.vue b/frontend/src/components/checklist/SortableChecklist.vue index aa72a2e498..5af2d61bef 100644 --- a/frontend/src/components/checklist/SortableChecklist.vue +++ b/frontend/src/components/checklist/SortableChecklist.vue @@ -147,8 +147,7 @@ export default { // patch content node location await this.api .patch(event.item.dataset.href, { - position: - event.newDraggableIndex + (event.from === event.to || !parent ? 1 : 0), + position: event.newDraggableIndex, parent, }) .catch((e) => { diff --git a/frontend/src/views/checklist/Checklist.vue b/frontend/src/views/checklist/Checklist.vue index 15dee209fd..ad3c60da07 100644 --- a/frontend/src/views/checklist/Checklist.vue +++ b/frontend/src/views/checklist/Checklist.vue @@ -2,6 +2,7 @@ Date: Sat, 17 Aug 2024 21:13:41 +0200 Subject: [PATCH 24/69] Refactor story page to summary page --- common/locales/de.json | 10 +- common/locales/en.json | 10 +- common/locales/fr.json | 10 +- common/locales/it.json | 10 +- .../components/print/PrintConfigurator.vue | 9 +- .../print/__tests__/repairPrintConfig.spec.js | 67 +- .../components/print/config/StoryConfig.vue | 58 - .../components/print/config/SummaryConfig.vue | 95 ++ frontend/src/locales/de.json | 8 +- frontend/src/locales/en.json | 6 +- frontend/src/locales/fr.json | 4 +- frontend/src/locales/it.json | 4 +- frontend/src/locales/rm.json | 2 +- pdf/src/CampPrint.vue | 4 +- pdf/src/campPrint/story/StoryPeriod.vue | 35 - .../{story/Story.vue => summary/Summary.vue} | 14 +- .../StoryDay.vue => summary/SummaryDay.vue} | 43 +- pdf/src/campPrint/summary/SummaryPeriod.vue | 59 + .../tableOfContents/TableOfContents.vue | 4 +- .../entry/{Story.vue => Summary.vue} | 11 +- .../story_overview.spec.json.snap | 1187 +---------------- .../Toc/{TocStory.vue => TocSummary.vue} | 8 +- .../config/{Story.vue => Summary.vue} | 6 +- print/components/config/Toc.vue | 19 +- .../StoryDay.vue => summary/SummaryDay.vue} | 43 +- .../SummaryPeriod.vue} | 29 +- 26 files changed, 366 insertions(+), 1389 deletions(-) delete mode 100644 frontend/src/components/print/config/StoryConfig.vue create mode 100644 frontend/src/components/print/config/SummaryConfig.vue delete mode 100644 pdf/src/campPrint/story/StoryPeriod.vue rename pdf/src/campPrint/{story/Story.vue => summary/Summary.vue} (59%) rename pdf/src/campPrint/{story/StoryDay.vue => summary/SummaryDay.vue} (62%) create mode 100644 pdf/src/campPrint/summary/SummaryPeriod.vue rename pdf/src/campPrint/tableOfContents/entry/{Story.vue => Summary.vue} (56%) rename print/components/Toc/{TocStory.vue => TocSummary.vue} (78%) rename print/components/config/{Story.vue => Summary.vue} (87%) rename print/components/{story/StoryDay.vue => summary/SummaryDay.vue} (62%) rename print/components/{story/StoryPeriod.vue => summary/SummaryPeriod.vue} (55%) diff --git a/common/locales/de.json b/common/locales/de.json index c8f3f1d83f..43b551bf2f 100644 --- a/common/locales/de.json +++ b/common/locales/de.json @@ -1,8 +1,8 @@ { "components": { - "story": { - "storyDay": { - "noStory": "Die Blöcke an diesem Tag enthalten keinen roten Faden." + "summary": { + "summaryDay": { + "noContent": "Die Blöcke an diesem Tag enthalten keine '{contentType}' Inhalte." } } }, @@ -259,8 +259,8 @@ "program": { "title": "Detailprogramm" }, - "story": { - "title": "Roter Faden" + "summary": { + "title": "Zusammenfassung" }, "toc": { "title": "Inhaltsverzeichnis" diff --git a/common/locales/en.json b/common/locales/en.json index 1093dd758c..0b70e3a5f1 100644 --- a/common/locales/en.json +++ b/common/locales/en.json @@ -1,8 +1,8 @@ { "components": { - "story": { - "storyDay": { - "noStory": "The activities on this day do not contain any story content." + "summary": { + "summaryDay": { + "noContent": "The activities on this day do not contain any {contentType} content." } } }, @@ -266,8 +266,8 @@ "program": { "title": "Program" }, - "story": { - "title": "Storyline" + "summary": { + "title": "Summary" }, "toc": { "title": "Table of contents" diff --git a/common/locales/fr.json b/common/locales/fr.json index db1a1a74a4..da17239695 100644 --- a/common/locales/fr.json +++ b/common/locales/fr.json @@ -1,8 +1,8 @@ { "components": { - "story": { - "storyDay": { - "noStory": "Aucun file rouge trouvé ce jour-là..." + "summary": { + "summaryDay": { + "noContent": "Aucun {contentType} trouvé ce jour-là..." } } }, @@ -246,8 +246,8 @@ "program": { "title": "Programme" }, - "story": { - "title": "Histoire" + "summary": { + "title": "Résumé" }, "toc": { "title": "Table des matières" diff --git a/common/locales/it.json b/common/locales/it.json index f7ea5a4054..797f08c72e 100644 --- a/common/locales/it.json +++ b/common/locales/it.json @@ -1,8 +1,8 @@ { "components": { - "story": { - "storyDay": { - "noStory": "Nessun contenuto di storia trovato in questo giorno..." + "summary": { + "summaryDay": { + "noContent": "Nessun contenuto '{contentType}' trovato in questo giorno..." } } }, @@ -230,8 +230,8 @@ "program": { "title": "Programma" }, - "story": { - "title": "Trama" + "summary": { + "title": "Sommario" }, "toc": { "title": "Indice dei contenuti" diff --git a/frontend/src/components/print/PrintConfigurator.vue b/frontend/src/components/print/PrintConfigurator.vue index 60863f5764..8fe30f790b 100644 --- a/frontend/src/components/print/PrintConfigurator.vue +++ b/frontend/src/components/print/PrintConfigurator.vue @@ -100,7 +100,7 @@ import PrintPreviewNuxt from './print-nuxt/PrintPreviewNuxt.vue' import Draggable from 'vuedraggable' import CoverConfig from './config/CoverConfig.vue' import PicassoConfig from './config/PicassoConfig.vue' -import StoryConfig from './config/StoryConfig.vue' +import SummaryConfig from './config/SummaryConfig.vue' import ProgramConfig from './config/ProgramConfig.vue' import ActivityConfig from './config/ActivityConfig.vue' import TocConfig from './config/TocConfig.vue' @@ -125,7 +125,7 @@ export default { PrintPreviewNuxt, CoverConfig, PicassoConfig, - StoryConfig, + SummaryConfig, ProgramConfig, ActivityConfig, TocConfig, @@ -141,7 +141,7 @@ export default { contentComponents: { Cover: CoverConfig, Picasso: PicassoConfig, - Story: StoryConfig, + Summary: SummaryConfig, Program: ProgramConfig, Activity: ActivityConfig, Toc: TocConfig, @@ -205,9 +205,10 @@ export default { this.camp.periods().items.forEach((period) => { contents.push({ - type: 'Story', + type: 'Summary', options: { periods: [period._meta.self], + contentType: 'Storycontext', }, }) contents.push({ diff --git a/frontend/src/components/print/__tests__/repairPrintConfig.spec.js b/frontend/src/components/print/__tests__/repairPrintConfig.spec.js index 54c598658b..92e27a4cbf 100644 --- a/frontend/src/components/print/__tests__/repairPrintConfig.spec.js +++ b/frontend/src/components/print/__tests__/repairPrintConfig.spec.js @@ -3,7 +3,7 @@ import PicassoConfig from '../config/PicassoConfig.vue' import ActivityConfig from '../config/ActivityConfig.vue' import CoverConfig from '../config/CoverConfig.vue' import ProgramConfig from '../config/ProgramConfig.vue' -import StoryConfig from '../config/StoryConfig.vue' +import SummaryConfig from '../config/SummaryConfig.vue' import TocConfig from '../config/TocConfig.vue' describe('repairConfig', () => { @@ -25,7 +25,7 @@ describe('repairConfig', () => { CoverConfig, PicassoConfig, ProgramConfig, - StoryConfig, + SummaryConfig, TocConfig, ].map((component) => [component.name.replace(/Config$/, ''), component.repairConfig]) ) @@ -817,14 +817,14 @@ describe('repairConfig', () => { }) }) - describe('story', () => { + describe('summary', () => { test('adds missing options', async () => { // given const config = { camp: '/camps/1a2b3c4d', contents: [ { - type: 'Story', + type: 'Summary', }, ], documentName: 'test camp', @@ -839,8 +839,8 @@ describe('repairConfig', () => { camp: '/camps/1a2b3c4d', contents: [ { - type: 'Story', - options: { periods: [] }, + type: 'Summary', + options: { periods: [], contentType: 'Storycontext' }, }, ], documentName: 'test camp', @@ -854,8 +854,8 @@ describe('repairConfig', () => { camp: '/camps/1a2b3c4d', contents: [ { - type: 'Story', - options: { periods: [] }, + type: 'Summary', + options: { periods: [], contentType: 'Storycontext' }, }, ], documentName: 'test camp', @@ -870,8 +870,8 @@ describe('repairConfig', () => { camp: '/camps/1a2b3c4d', contents: [ { - type: 'Story', - options: { periods: [] }, + type: 'Summary', + options: { periods: [], contentType: 'Storycontext' }, }, ], documentName: 'test camp', @@ -885,9 +885,10 @@ describe('repairConfig', () => { camp: '/camps/1a2b3c4d', contents: [ { - type: 'Story', + type: 'Summary', options: { periods: ['/periods/11112222', '/periods/1a2b3c4d'], + contentType: 'Storycontext', }, }, ], @@ -903,8 +904,48 @@ describe('repairConfig', () => { camp: '/camps/1a2b3c4d', contents: [ { - type: 'Story', - options: { periods: ['/periods/1a2b3c4d'] }, + type: 'Summary', + options: { + periods: ['/periods/1a2b3c4d'], + contentType: 'Storycontext', + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('uses known contentType', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Summary', + options: { + periods: ['/periods/1a2b3c4d'], + contentType: 'Storyboard', + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'Summary', + options: { + periods: ['/periods/1a2b3c4d'], + contentType: 'Storycontext', + }, }, ], documentName: 'test camp', diff --git a/frontend/src/components/print/config/StoryConfig.vue b/frontend/src/components/print/config/StoryConfig.vue deleted file mode 100644 index 6576b5cc6c..0000000000 --- a/frontend/src/components/print/config/StoryConfig.vue +++ /dev/null @@ -1,58 +0,0 @@ - - - diff --git a/frontend/src/components/print/config/SummaryConfig.vue b/frontend/src/components/print/config/SummaryConfig.vue new file mode 100644 index 0000000000..637bbb4eb9 --- /dev/null +++ b/frontend/src/components/print/config/SummaryConfig.vue @@ -0,0 +1,95 @@ + + + diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 4a33fba56d..4e5cf98a0c 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -316,7 +316,9 @@ "dayOverview": "Tagesübersicht", "periods": "Lagerabschnitt(e)" }, - "storyConfig": { + "summaryConfig": { + "contentType": "Blockinhalt", + "instanceNameFilter": "Instanznamenfilter", "periods": "Lagerabschnitt(e)" } }, @@ -353,7 +355,7 @@ "Cover": "Titelseite", "Picasso": "Grobprogramm", "Program": "Detailprogramm", - "Story": "Roter Faden", + "Summary": "Zusammenfassung", "Toc": "Inhaltsverzeichnis" } }, @@ -575,8 +577,8 @@ "loginCallback": { "loginInProgress": "Du wirst eingeloggt" }, - "or": "oder mit", "notActivated": "Nicht aktiviert?", + "or": "oder mit", "password": "Passwort", "passwordForgotten": "Passwort vergessen?", "provider": { diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 21d2cf0f4f..04cb16264a 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -316,7 +316,9 @@ "dayOverview": "print day overview", "periods": "Period(s)" }, - "storyConfig": { + "summaryConfig": { + "contentType": "Content type", + "instanceNameFilter": "Instancename filter", "periods": "Period(s)" } }, @@ -353,7 +355,7 @@ "Cover": "Cover page", "Picasso": "Picasso", "Program": "Program", - "Story": "Story summary", + "Summary": "Summary", "Toc": "Table of contents" } }, diff --git a/frontend/src/locales/fr.json b/frontend/src/locales/fr.json index 996d2aa0be..1756cff692 100644 --- a/frontend/src/locales/fr.json +++ b/frontend/src/locales/fr.json @@ -296,7 +296,7 @@ "dayOverview": "Aperçu des jours", "periods": "Période(s) du camp" }, - "storyConfig": { + "summaryConfig": { "periods": "Période(s) du camp" } }, @@ -333,7 +333,7 @@ "Cover": "Page de couverture", "Picasso": "Picasso", "Program": "Programme", - "Story": "Histoire", + "Summary": "Résumé", "Toc": "Table des matières" } }, diff --git a/frontend/src/locales/it.json b/frontend/src/locales/it.json index db1a87d3a6..a2ae3aa9c7 100644 --- a/frontend/src/locales/it.json +++ b/frontend/src/locales/it.json @@ -288,7 +288,7 @@ "dayOverview": "Panoramica della giornata di stampa", "periods": "Sezione/i portante/i" }, - "storyConfig": { + "summaryConfig": { "periods": "Sezione/i portante/i" } }, @@ -325,7 +325,7 @@ "Cover": "Pagina di copertina", "Picasso": "Picasso", "Program": "Programma", - "Story": "Riassunto della storia", + "Story": "Riassunto", "Toc": "Indice dei contenuti" } }, diff --git a/frontend/src/locales/rm.json b/frontend/src/locales/rm.json index d50c5de283..160011891a 100644 --- a/frontend/src/locales/rm.json +++ b/frontend/src/locales/rm.json @@ -289,7 +289,7 @@ "Cover": "Pagina da titel", "Picasso": "Program general", "Program": "Program en detagl", - "Story": "Fil cotschen", + "Summary": "Riassunto", "Toc": "Tavla da cuntegn" } }, diff --git a/pdf/src/CampPrint.vue b/pdf/src/CampPrint.vue index 6e35c5c6fc..9694149b29 100644 --- a/pdf/src/CampPrint.vue +++ b/pdf/src/CampPrint.vue @@ -22,7 +22,7 @@ import InterDisplayBoldItalic from '@/assets/fonts/Inter/InterDisplay-BoldItalic import Cover from '@/campPrint/cover/Cover.vue' import TableOfContents from '@/campPrint/tableOfContents/TableOfContents.vue' import Picasso from '@/campPrint/picasso/Picasso.vue' -import Story from '@/campPrint/story/Story.vue' +import Summary from '@/campPrint/summary/Summary.vue' import Program from '@/campPrint/program/Program.vue' import Activity from '@/campPrint/activity/Activity.vue' import { wordHyphenation } from '@react-pdf/textkit' @@ -43,7 +43,7 @@ export default { Picasso, Program, Activity, - Story, + Summary, } }, }, diff --git a/pdf/src/campPrint/story/StoryPeriod.vue b/pdf/src/campPrint/story/StoryPeriod.vue deleted file mode 100644 index 5389c95f91..0000000000 --- a/pdf/src/campPrint/story/StoryPeriod.vue +++ /dev/null @@ -1,35 +0,0 @@ - - - -.story-period-title { - font-size: 10pt; - font-weight: bold; - text-align: center; -} - diff --git a/pdf/src/campPrint/story/Story.vue b/pdf/src/campPrint/summary/Summary.vue similarity index 59% rename from pdf/src/campPrint/story/Story.vue rename to pdf/src/campPrint/summary/Summary.vue index 30573dce91..13298f604f 100644 --- a/pdf/src/campPrint/story/Story.vue +++ b/pdf/src/campPrint/summary/Summary.vue @@ -1,15 +1,21 @@ -.story-day-title-container { +.summary-day-title-container { display: flex; flex-direction: row; justify-content: space-between; @@ -86,15 +95,15 @@ export default { padding-bottom: 2pt; margin-bottom: 1pt; } -.story-day-title { +.summary-day-title { font-size: 14; font-weight: semibold; margin: 10pt 0 3pt; } -.story-day-date { +.summary-day-date { font-size: 11pt; } -.story-chapter-title { +.summary-chapter-title { display: flex; flex-direction: row; align-items: center; diff --git a/pdf/src/campPrint/summary/SummaryPeriod.vue b/pdf/src/campPrint/summary/SummaryPeriod.vue new file mode 100644 index 0000000000..405643279c --- /dev/null +++ b/pdf/src/campPrint/summary/SummaryPeriod.vue @@ -0,0 +1,59 @@ + + + +.summary-period-title { + font-size: 10pt; + font-weight: bold; + text-align: center; +} + diff --git a/pdf/src/campPrint/tableOfContents/TableOfContents.vue b/pdf/src/campPrint/tableOfContents/TableOfContents.vue index cbe37ffab3..17a852a3cd 100644 --- a/pdf/src/campPrint/tableOfContents/TableOfContents.vue +++ b/pdf/src/campPrint/tableOfContents/TableOfContents.vue @@ -23,7 +23,7 @@ import Toc from './entry/Toc.vue' import Picasso from './entry/Picasso.vue' import Program from './entry/Program.vue' import Activity from './entry/Activity.vue' -import Story from './entry/Story.vue' +import Summary from './entry/Summary.vue' export default { name: 'Cover', @@ -40,7 +40,7 @@ export default { Picasso, Program, Activity, - Story, + Summary, } }, }, diff --git a/pdf/src/campPrint/tableOfContents/entry/Story.vue b/pdf/src/campPrint/tableOfContents/entry/Summary.vue similarity index 56% rename from pdf/src/campPrint/tableOfContents/entry/Story.vue rename to pdf/src/campPrint/tableOfContents/entry/Summary.vue index a205af4c87..9898ae563b 100644 --- a/pdf/src/campPrint/tableOfContents/entry/Story.vue +++ b/pdf/src/campPrint/tableOfContents/entry/Summary.vue @@ -1,13 +1,20 @@ diff --git a/print/components/story/StoryPeriod.vue b/print/components/summary/SummaryPeriod.vue similarity index 55% rename from print/components/story/StoryPeriod.vue rename to print/components/summary/SummaryPeriod.vue index 0f8f65f0be..0064d6932c 100644 --- a/print/components/story/StoryPeriod.vue +++ b/print/components/summary/SummaryPeriod.vue @@ -4,21 +4,28 @@ :id="`content_${index}_period_${period.id}`" class="tw-text-center tw-font-semibold tw-mb-6" > - {{ $t('print.story.title') }}: {{ period.description }} + {{ $t('print.summary.title') }} + {{ $t(`contentNode.${camelCase(contentType)}.name`) + }}: + {{ period.description }} -
diff --git a/pdf/src/campPrint/tableOfContents/entry/Summary.vue b/pdf/src/campPrint/tableOfContents/entry/Summary.vue index 3c8094d96b..b2476a5f13 100644 --- a/pdf/src/campPrint/tableOfContents/entry/Summary.vue +++ b/pdf/src/campPrint/tableOfContents/entry/Summary.vue @@ -15,7 +15,6 @@ import camelCase from 'lodash/camelCase.js' export default { name: 'Summary', - methods: { camelCase }, extends: PdfComponent, props: { entry: { type: Object, required: true }, @@ -25,6 +24,7 @@ export default { return this.entry.options.periods.map((periodUri) => this.api.get(periodUri)) }, }, + methods: { camelCase }, } From 84bfa7447762877075285c1f72af41c7be5daf66 Mon Sep 17 00:00:00 2001 From: Manuel Meister Date: Sun, 25 Aug 2024 10:47:15 +0200 Subject: [PATCH 28/69] Change instanceNameFilter translation --- frontend/src/locales/de.json | 2 +- frontend/src/locales/en.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 4e5cf98a0c..6a82acbf29 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -318,7 +318,7 @@ }, "summaryConfig": { "contentType": "Blockinhalt", - "instanceNameFilter": "Instanznamenfilter", + "instanceNameFilter": "Nach Bausteintitel filtern", "periods": "Lagerabschnitt(e)" } }, diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 04cb16264a..d62acf2a59 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -318,7 +318,7 @@ }, "summaryConfig": { "contentType": "Content type", - "instanceNameFilter": "Instancename filter", + "instanceNameFilter": "Block title filter", "periods": "Period(s)" } }, From f19208d648e070547bf17fd71fa18408fcf29c1e Mon Sep 17 00:00:00 2001 From: Manuel Meister Date: Tue, 27 Aug 2024 22:19:11 +0200 Subject: [PATCH 29/69] Add feature toggle for checklist --- .github/workflows/reusable-dev-deployment.yml | 1 + .helm/deploy-to-cluster.sh | 1 + .../ecamp3/templates/frontend_configmap.yaml | 1 + .helm/ecamp3/values.yaml | 3 +- .../activity/ButtonNestedContentNodeAdd.vue | 9 ++- frontend/src/environment.js | 1 + frontend/src/router.js | 58 +++++++++++-------- frontend/src/views/admin/SideBarAdmin.vue | 7 +++ 8 files changed, 55 insertions(+), 26 deletions(-) diff --git a/.github/workflows/reusable-dev-deployment.yml b/.github/workflows/reusable-dev-deployment.yml index d0f3ae3abd..456513e1e1 100644 --- a/.github/workflows/reusable-dev-deployment.yml +++ b/.github/workflows/reusable-dev-deployment.yml @@ -130,6 +130,7 @@ jobs: --set recaptcha.secret='${{ secrets.RECAPTCHA_SECRET }}' \ --set frontend.loginInfoTextKey=${{ vars.LOGIN_INFO_TEXT_KEY }} \ --set featureToggle.developer=true + --set featureToggle.checklist=true - name: Finish the GitHub deployment uses: bobheadxi/deployments@v1.5.0 diff --git a/.helm/deploy-to-cluster.sh b/.helm/deploy-to-cluster.sh index fcf7c17def..4702dbe0ed 100755 --- a/.helm/deploy-to-cluster.sh +++ b/.helm/deploy-to-cluster.sh @@ -64,6 +64,7 @@ for i in 1; do values="$values --set deploymentTime=$(date -u +%s)" values="$values --set deployedVersion=\"$(git rev-parse --short HEAD)\"" values="$values --set featureToggle.developer=true" + values="$values --set featureToggle.checklist=true" if [ -n "$BACKUP_SCHEDULE" ]; then values="$values --set postgresql.backup.schedule=$BACKUP_SCHEDULE" diff --git a/.helm/ecamp3/templates/frontend_configmap.yaml b/.helm/ecamp3/templates/frontend_configmap.yaml index 4e18b26ed7..d58504aa32 100644 --- a/.helm/ecamp3/templates/frontend_configmap.yaml +++ b/.helm/ecamp3/templates/frontend_configmap.yaml @@ -29,6 +29,7 @@ data: RECAPTCHA_SITE_KEY: null, {{- end }} FEATURE_DEVELOPER: {{ .Values.featureToggle.developer | default false }}, + FEATURE_CHECKLIST: {{ .Values.featureToggle.checklist | default false }}, LOGIN_INFO_TEXT_KEY: '{{ .Values.frontend.loginInfoTextKey }}', } deployedVersion: {{ .Values.deployedVersion | quote }} diff --git a/.helm/ecamp3/values.yaml b/.helm/ecamp3/values.yaml index e60ab9fcb2..3a11d75bd9 100644 --- a/.helm/ecamp3/values.yaml +++ b/.helm/ecamp3/values.yaml @@ -15,6 +15,7 @@ helpLink: # 'https://ecamp3.ch/faq' # enable/disable feature across the complete deployment featureToggle: developer: false # enables various tools/features foreseen for development deployments (language switcher, form controls view, performance measurement view, etc.) + checklist: false # enables various tools/features foreseen for development deployments (language switcher, form controls view, performance measurement view, etc.) api: subpath: "/api" @@ -251,7 +252,7 @@ apiCache: requests: cpu: 10m memory: 20Mi - + autoscaling: enabled: false minReplicas: 1 diff --git a/frontend/src/components/activity/ButtonNestedContentNodeAdd.vue b/frontend/src/components/activity/ButtonNestedContentNodeAdd.vue index 6fb3ef9535..9013c978aa 100644 --- a/frontend/src/components/activity/ButtonNestedContentNodeAdd.vue +++ b/frontend/src/components/activity/ButtonNestedContentNodeAdd.vue @@ -60,6 +60,7 @@ From eed6fde6781128006e580a66be79c875e74d6b50 Mon Sep 17 00:00:00 2001 From: Manuel Meister Date: Sun, 1 Sep 2024 21:28:04 +0200 Subject: [PATCH 30/69] Separate story & safetyconsiderations from summary --- common/locales/de.json | 10 +- common/locales/en.json | 10 +- common/locales/fr.json | 10 +- common/locales/it.json | 10 +- frontend/eslint.config.mjs | 2 +- .../components/print/PrintConfigurator.vue | 7 +- .../print/__tests__/repairPrintConfig.spec.js | 161 +++++++++- .../components/print/config/PicassoConfig.vue | 2 +- .../components/print/config/ProgramConfig.vue | 2 +- .../config/SafetyConsiderationsConfig.vue | 44 +++ .../components/print/config/StoryConfig.vue | 44 +++ .../components/print/config/SummaryConfig.vue | 65 +--- frontend/src/locales/de.json | 11 +- frontend/src/locales/en.json | 14 +- frontend/src/locales/fr.json | 12 +- frontend/src/locales/it.json | 12 +- frontend/src/locales/rm.json | 11 +- pdf/eslint.config.mjs | 2 +- pdf/src/CampPrint.vue | 6 +- .../{Summary.vue => SafetyConsiderations.vue} | 5 +- pdf/src/campPrint/summary/Story.vue | 29 ++ pdf/src/campPrint/summary/SummaryDay.vue | 11 +- pdf/src/campPrint/summary/SummaryPeriod.vue | 21 +- .../tableOfContents/TableOfContents.vue | 6 +- .../entry/SafetyConsiderations.vue | 16 + .../campPrint/tableOfContents/entry/Story.vue | 13 + .../tableOfContents/entry/Summary.vue | 15 - .../story_overview.spec.json.snap | 278 +++++++++++++++++- ...ummary.vue => TocSafetyConsiderations.vue} | 10 +- print/components/Toc/TocStory.vue | 38 +++ .../{Summary.vue => SafetyConsiderations.vue} | 3 +- print/components/config/Story.vue | 40 +++ print/components/summary/SummaryDay.vue | 10 +- print/components/summary/SummaryPeriod.vue | 6 +- print/eslint.config.mjs | 2 +- 35 files changed, 735 insertions(+), 203 deletions(-) create mode 100644 frontend/src/components/print/config/SafetyConsiderationsConfig.vue create mode 100644 frontend/src/components/print/config/StoryConfig.vue rename pdf/src/campPrint/summary/{Summary.vue => SafetyConsiderations.vue} (84%) create mode 100644 pdf/src/campPrint/summary/Story.vue create mode 100644 pdf/src/campPrint/tableOfContents/entry/SafetyConsiderations.vue create mode 100644 pdf/src/campPrint/tableOfContents/entry/Story.vue rename print/components/Toc/{TocSummary.vue => TocSafetyConsiderations.vue} (75%) create mode 100644 print/components/Toc/TocStory.vue rename print/components/config/{Summary.vue => SafetyConsiderations.vue} (91%) create mode 100644 print/components/config/Story.vue diff --git a/common/locales/de.json b/common/locales/de.json index 476879bd51..2f2afc70a8 100644 --- a/common/locales/de.json +++ b/common/locales/de.json @@ -244,6 +244,9 @@ "shortScheduleEntryDescription": "Tag\u202f{dayNumber} {startTime}" }, "print": { + "config": { + "periods": "Lagerabschnitt(e)" + }, "cover": { "title": "Titelseite" }, @@ -260,7 +263,12 @@ "title": "Detailprogramm" }, "summary": { - "title": "Zusammenfassung" + "safetyConsiderations": { + "title": "Sicherheitsüberlegungen" + }, + "storycontext": { + "title": "Roter Faden" + } }, "toc": { "title": "Inhaltsverzeichnis" diff --git a/common/locales/en.json b/common/locales/en.json index 9b68b8d6b0..2f33b5a304 100644 --- a/common/locales/en.json +++ b/common/locales/en.json @@ -251,6 +251,9 @@ "shortScheduleEntryDescription": "day {dayNumber} {startTime}" }, "print": { + "config": { + "periods": "Period(s)" + }, "cover": { "title": "Cover page" }, @@ -267,7 +270,12 @@ "title": "Program" }, "summary": { - "title": "Summary" + "safetyConsiderations": { + "title": "Safety considerations" + }, + "storycontext": { + "title": "Story" + } }, "toc": { "title": "Table of contents" diff --git a/common/locales/fr.json b/common/locales/fr.json index a0916342f8..893e313ad2 100644 --- a/common/locales/fr.json +++ b/common/locales/fr.json @@ -231,6 +231,9 @@ } }, "print": { + "config": { + "periods": "Période(s) du camp" + }, "cover": { "title": "Page de couverture" }, @@ -247,7 +250,12 @@ "title": "Programme" }, "summary": { - "title": "Résumé" + "safetyConsiderations": { + "title": "Considérations de sécurité" + }, + "storycontext": { + "title": "Histoire" + } }, "toc": { "title": "Table des matières" diff --git a/common/locales/it.json b/common/locales/it.json index 312e58304c..ea6c611789 100644 --- a/common/locales/it.json +++ b/common/locales/it.json @@ -221,6 +221,9 @@ } }, "print": { + "config": { + "periods": "Sezione/i portante/i" + }, "cover": { "title": "Pagina di copertina" }, @@ -231,7 +234,12 @@ "title": "Programma" }, "summary": { - "title": "Sommario" + "safetyConsiderations": { + "title": "Considerazioni sulla sicurezza" + }, + "storycontext": { + "title": "Storia" + } }, "toc": { "title": "Indice dei contenuti" diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index cd3bfc8a0f..437b437b7f 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -82,7 +82,7 @@ export default [ 'error', { ignoreKeysRegex: - '^(global|entity|contentNode\\.[a-z][a-zA-Z]+|print\\.(global|activity|cover|picasso|program|story|toc))\\..+', + '^(global|entity|contentNode\\.[a-z][a-zA-Z]+|print\\.(global|activity|cover|picasso|program|config|summary|toc))\\..+', translationKeyPropRegex: '[a-zA-Z0-9]-i18n-key$', }, ], diff --git a/frontend/src/components/print/PrintConfigurator.vue b/frontend/src/components/print/PrintConfigurator.vue index 13efbe1b13..bc4091fc53 100644 --- a/frontend/src/components/print/PrintConfigurator.vue +++ b/frontend/src/components/print/PrintConfigurator.vue @@ -112,6 +112,8 @@ import { getEnv } from '@/environment.js' import cloneDeep from 'lodash/cloneDeep' import VueI18n from '../../plugins/i18n/index.js' import repairConfig from './repairPrintConfig.js' +import StoryConfig from '@/components/print/config/StoryConfig.vue' +import SafetyConsiderationsConfig from '@/components/print/config/SafetyConsiderationsConfig.vue' import campShortTitle from '@/common/helpers/campShortTitle.js' export default { @@ -142,7 +144,8 @@ export default { contentComponents: { Cover: CoverConfig, Picasso: PicassoConfig, - Summary: SummaryConfig, + Story: StoryConfig, + SafetyConsiderations: SafetyConsiderationsConfig, Program: ProgramConfig, Activity: ActivityConfig, Toc: TocConfig, @@ -206,7 +209,7 @@ export default { this.camp.periods().items.forEach((period) => { contents.push({ - type: 'Summary', + type: 'Story', options: { periods: [period._meta.self], contentType: 'Storycontext', diff --git a/frontend/src/components/print/__tests__/repairPrintConfig.spec.js b/frontend/src/components/print/__tests__/repairPrintConfig.spec.js index 06fbfa1499..c78b3f84a6 100644 --- a/frontend/src/components/print/__tests__/repairPrintConfig.spec.js +++ b/frontend/src/components/print/__tests__/repairPrintConfig.spec.js @@ -3,7 +3,8 @@ import PicassoConfig from '../config/PicassoConfig.vue' import ActivityConfig from '../config/ActivityConfig.vue' import CoverConfig from '../config/CoverConfig.vue' import ProgramConfig from '../config/ProgramConfig.vue' -import SummaryConfig from '../config/SummaryConfig.vue' +import StoryConfig from '../config/StoryConfig.vue' +import SafetyConsiderationsConfig from '../config/SafetyConsiderationsConfig.vue' import TocConfig from '../config/TocConfig.vue' describe('repairConfig', () => { @@ -25,7 +26,8 @@ describe('repairConfig', () => { CoverConfig, PicassoConfig, ProgramConfig, - SummaryConfig, + SafetyConsiderationsConfig, + StoryConfig, TocConfig, ].map((component) => [component.name.replace(/Config$/, ''), component.repairConfig]) ) @@ -817,14 +819,14 @@ describe('repairConfig', () => { }) }) - describe('summary', () => { + describe('story', () => { test('adds missing options', async () => { // given const config = { camp: '/camps/1a2b3c4d', contents: [ { - type: 'Summary', + type: 'Story', }, ], documentName: 'test camp', @@ -839,7 +841,7 @@ describe('repairConfig', () => { camp: '/camps/1a2b3c4d', contents: [ { - type: 'Summary', + type: 'Story', options: { periods: [], contentType: 'Storycontext' }, }, ], @@ -854,7 +856,7 @@ describe('repairConfig', () => { camp: '/camps/1a2b3c4d', contents: [ { - type: 'Summary', + type: 'Story', options: { periods: [], contentType: 'Storycontext' }, }, ], @@ -870,7 +872,7 @@ describe('repairConfig', () => { camp: '/camps/1a2b3c4d', contents: [ { - type: 'Summary', + type: 'Story', options: { periods: [], contentType: 'Storycontext' }, }, ], @@ -885,7 +887,7 @@ describe('repairConfig', () => { camp: '/camps/1a2b3c4d', contents: [ { - type: 'Summary', + type: 'Story', options: { periods: ['/periods/11112222', '/periods/1a2b3c4d'], contentType: 'Storycontext', @@ -904,7 +906,7 @@ describe('repairConfig', () => { camp: '/camps/1a2b3c4d', contents: [ { - type: 'Summary', + type: 'Story', options: { periods: ['/periods/1a2b3c4d'], contentType: 'Storycontext', @@ -922,7 +924,7 @@ describe('repairConfig', () => { camp: '/camps/1a2b3c4d', contents: [ { - type: 'Summary', + type: 'Story', options: { periods: ['/periods/1a2b3c4d'], contentType: 'Storyboard', @@ -941,7 +943,7 @@ describe('repairConfig', () => { camp: '/camps/1a2b3c4d', contents: [ { - type: 'Summary', + type: 'Story', options: { periods: ['/periods/1a2b3c4d'], contentType: 'Storycontext', @@ -954,6 +956,143 @@ describe('repairConfig', () => { }) }) + describe('safetyConsiderations', () => { + test('adds missing options', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'SafetyConsiderations', + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'SafetyConsiderations', + options: { periods: [], contentType: 'SafetyConsiderations' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('allows empty periods', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'SafetyConsiderations', + options: { periods: [], contentType: 'SafetyConsiderations' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'SafetyConsiderations', + options: { periods: [], contentType: 'SafetyConsiderations' }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('filters out unknown periods', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'SafetyConsiderations', + options: { + periods: ['/periods/11112222', '/periods/1a2b3c4d'], + contentType: 'SafetyConsiderations', + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'SafetyConsiderations', + options: { + periods: ['/periods/1a2b3c4d'], + contentType: 'SafetyConsiderations', + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + + test('uses known contentType', async () => { + // given + const config = { + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'SafetyConsiderations', + options: { + periods: ['/periods/1a2b3c4d'], + contentType: 'Storyboard', + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + } + + // when + const result = repairConfig(config, ...args) + + // then + expect(result).toEqual({ + camp: '/camps/1a2b3c4d', + contents: [ + { + type: 'SafetyConsiderations', + options: { + periods: ['/periods/1a2b3c4d'], + contentType: 'SafetyConsiderations', + }, + }, + ], + documentName: 'test camp', + language: 'en-GB', + }) + }) + }) + describe('toc', () => { test('leaves config alone', async () => { // given diff --git a/frontend/src/components/print/config/PicassoConfig.vue b/frontend/src/components/print/config/PicassoConfig.vue index 49e767cc05..9f49c0961e 100644 --- a/frontend/src/components/print/config/PicassoConfig.vue +++ b/frontend/src/components/print/config/PicassoConfig.vue @@ -2,7 +2,7 @@
+
+ +
+ + + diff --git a/frontend/src/components/print/config/StoryConfig.vue b/frontend/src/components/print/config/StoryConfig.vue new file mode 100644 index 0000000000..74af6dc76a --- /dev/null +++ b/frontend/src/components/print/config/StoryConfig.vue @@ -0,0 +1,44 @@ + + + diff --git a/frontend/src/components/print/config/SummaryConfig.vue b/frontend/src/components/print/config/SummaryConfig.vue index 8b612479a2..a445f76439 100644 --- a/frontend/src/components/print/config/SummaryConfig.vue +++ b/frontend/src/components/print/config/SummaryConfig.vue @@ -1,40 +1,5 @@ - - diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 951979a910..f2395d1b3f 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -314,13 +314,7 @@ "periods": "Lagerabschnitt(e)" }, "programConfig": { - "dayOverview": "Tagesübersicht", - "periods": "Lagerabschnitt(e)" - }, - "summaryConfig": { - "contentType": "Blockinhalt", - "instanceNameFilter": "Nach Bausteintitel filtern", - "periods": "Lagerabschnitt(e)" + "dayOverview": "Tagesübersicht" } }, "documents": { @@ -356,7 +350,8 @@ "Cover": "Titelseite", "Picasso": "Grobprogramm", "Program": "Detailprogramm", - "Summary": "Zusammenfassung", + "SafetyConsiderations": "Sicherheits­überlegungen", + "Story": "Roter Faden", "Toc": "Inhaltsverzeichnis" } }, diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 43dc10437f..27f7c52dc0 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -309,17 +309,10 @@ "activity": "Activity" }, "picassoConfig": { - "orientation": "Page layout", - "periods": "Period(s)" + "orientation": "Page layout" }, "programConfig": { - "dayOverview": "print day overview", - "periods": "Period(s)" - }, - "summaryConfig": { - "contentType": "Content type", - "instanceNameFilter": "Block title filter", - "periods": "Period(s)" + "dayOverview": "print day overview" } }, "documents": { @@ -355,7 +348,8 @@ "Cover": "Cover page", "Picasso": "Picasso", "Program": "Program", - "Summary": "Summary", + "SafetyConsiderations": "Safety considerations", + "Story": "Story", "Toc": "Table of contents" } }, diff --git a/frontend/src/locales/fr.json b/frontend/src/locales/fr.json index c55d8a1942..afeb1d59d1 100644 --- a/frontend/src/locales/fr.json +++ b/frontend/src/locales/fr.json @@ -289,15 +289,10 @@ "activity": "Activité" }, "picassoConfig": { - "orientation": "Mise en page", - "periods": "Période(s) du camp" + "orientation": "Mise en page" }, "programConfig": { - "dayOverview": "Aperçu des jours", - "periods": "Période(s) du camp" - }, - "summaryConfig": { - "periods": "Période(s) du camp" + "dayOverview": "Aperçu des jours" } }, "documents": { @@ -333,7 +328,8 @@ "Cover": "Page de couverture", "Picasso": "Picasso", "Program": "Programme", - "Summary": "Résumé", + "SafetyConsiderations": "Considérations de sécurité", + "Story": "Histoire", "Toc": "Table des matières" } }, diff --git a/frontend/src/locales/it.json b/frontend/src/locales/it.json index 75edc0756c..e994a0db59 100644 --- a/frontend/src/locales/it.json +++ b/frontend/src/locales/it.json @@ -281,15 +281,10 @@ "activity": "Attività" }, "picassoConfig": { - "orientation": "Layout della pagina", - "periods": "Sezione/i portante/i" + "orientation": "Layout della pagina" }, "programConfig": { - "dayOverview": "Panoramica della giornata di stampa", - "periods": "Sezione/i portante/i" - }, - "summaryConfig": { - "periods": "Sezione/i portante/i" + "dayOverview": "Panoramica della giornata di stampa" } }, "documents": { @@ -325,7 +320,8 @@ "Cover": "Pagina di copertina", "Picasso": "Picasso", "Program": "Programma", - "Story": "Riassunto", + "SafetyConsiderations": "Considerazioni sulla sicurezza", + "Story": "Riassunto della storia", "Toc": "Indice dei contenuti" } }, diff --git a/frontend/src/locales/rm.json b/frontend/src/locales/rm.json index b86b9c01d4..489707cbe2 100644 --- a/frontend/src/locales/rm.json +++ b/frontend/src/locales/rm.json @@ -245,15 +245,10 @@ "activity": "Activitad" }, "picassoConfig": { - "orientation": "Layout da la pagina", - "periods": "Part(s) dal champ" + "orientation": "Layout da la pagina" }, "programConfig": { - "dayOverview": "Survista dal di", - "periods": "Part(s) dal champ" - }, - "storyConfig": { - "periods": "Part(s) dal champ" + "dayOverview": "Survista dal di" } }, "documents": { @@ -289,7 +284,7 @@ "Cover": "Pagina da titel", "Picasso": "Program general", "Program": "Program en detagl", - "Summary": "Riassunto", + "Story": "Fil cotschen", "Toc": "Tavla da cuntegn" } }, diff --git a/pdf/eslint.config.mjs b/pdf/eslint.config.mjs index 18ac6c8697..8e152813d3 100644 --- a/pdf/eslint.config.mjs +++ b/pdf/eslint.config.mjs @@ -77,7 +77,7 @@ export default [ 'error', { ignoreKeysRegex: - '^(global|entity|contentNode\\.[a-z][a-zA-Z]+|print\\.(global|activity|cover|picasso|program|summary|toc))\\..+', + '^(global|entity|contentNode\\.[a-z][a-zA-Z]+|print\\.(global|activity|cover|picasso|program|config|summary|toc))\\..+', translationKeyPropRegex: '[a-zA-Z0-9]-i18n-key$', }, ], diff --git a/pdf/src/CampPrint.vue b/pdf/src/CampPrint.vue index 4184345836..20a440438a 100644 --- a/pdf/src/CampPrint.vue +++ b/pdf/src/CampPrint.vue @@ -23,7 +23,8 @@ import InterDisplayBoldItalic from '@/assets/fonts/Inter/InterDisplay-BoldItalic import Cover from '@/campPrint/cover/Cover.vue' import TableOfContents from '@/campPrint/tableOfContents/TableOfContents.vue' import Picasso from '@/campPrint/picasso/Picasso.vue' -import Summary from '@/campPrint/summary/Summary.vue' +import Story from './campPrint/summary/Story.vue' +import SafetyConsiderations from './campPrint/summary/SafetyConsiderations.vue' import Program from '@/campPrint/program/Program.vue' import Activity from '@/campPrint/activity/Activity.vue' import { wordHyphenation } from '@react-pdf/textkit' @@ -44,7 +45,8 @@ export default { Picasso, Program, Activity, - Summary, + Story, + SafetyConsiderations, } }, }, diff --git a/pdf/src/campPrint/summary/Summary.vue b/pdf/src/campPrint/summary/SafetyConsiderations.vue similarity index 84% rename from pdf/src/campPrint/summary/Summary.vue rename to pdf/src/campPrint/summary/SafetyConsiderations.vue index 0bda2da5a2..ff329c87ef 100644 --- a/pdf/src/campPrint/summary/Summary.vue +++ b/pdf/src/campPrint/summary/SafetyConsiderations.vue @@ -5,7 +5,6 @@ :id="id" :period="period" :content-type="content.options.contentType" - :instance-name-filter="content.options.instanceNameFilter ?? ''" /> @@ -14,7 +13,7 @@ import PdfComponent from '@/PdfComponent.js' import SummaryPeriod from './SummaryPeriod.vue' export default { - name: 'Summary', + name: 'SafetyConsiderations', components: { SummaryPeriod }, extends: PdfComponent, props: { @@ -28,5 +27,3 @@ export default { }, } - - diff --git a/pdf/src/campPrint/summary/Story.vue b/pdf/src/campPrint/summary/Story.vue new file mode 100644 index 0000000000..1c061eebf1 --- /dev/null +++ b/pdf/src/campPrint/summary/Story.vue @@ -0,0 +1,29 @@ + + diff --git a/pdf/src/campPrint/summary/SummaryDay.vue b/pdf/src/campPrint/summary/SummaryDay.vue index 5a474ce976..cfa4179f3e 100644 --- a/pdf/src/campPrint/summary/SummaryDay.vue +++ b/pdf/src/campPrint/summary/SummaryDay.vue @@ -26,7 +26,6 @@ import { dateLong } from '../../../common/helpers/dateHelperUTCFormatted.js' import CategoryLabel from '../CategoryLabel.vue' import RichText from '../RichText.vue' import { isEmptyHtml } from '../helpers.js' -import camelCase from 'lodash/camelCase.js' export default { name: 'SummaryDay', @@ -36,7 +35,6 @@ export default { period: { type: Object, required: true }, day: { type: Object, required: true }, contentType: { type: String, required: true }, - instanceNameFilter: { type: String, default: '' }, }, computed: { date() { @@ -57,14 +55,7 @@ export default { contentNode.contentTypeName === this.contentType && contentNode.root()._meta.self === scheduleEntry.activity().rootContentNode()._meta.self && - !isEmptyHtml(contentNode.data.html) && - (!this.instanceNameFilter || - contentNode.instanceName - ?.toLowerCase() - .includes(this.instanceNameFilter.toLowerCase()) || - this.$tc(`contentNode.${camelCase(this.contentType)}.name`) - .toLowerCase() - .includes(this.instanceNameFilter.toLowerCase())) + !isEmptyHtml(contentNode.data.html) ) .map((chapter) => ({ ...chapter, diff --git a/pdf/src/campPrint/summary/SummaryPeriod.vue b/pdf/src/campPrint/summary/SummaryPeriod.vue index d2ccc394f7..7c655f69ff 100644 --- a/pdf/src/campPrint/summary/SummaryPeriod.vue +++ b/pdf/src/campPrint/summary/SummaryPeriod.vue @@ -1,20 +1,9 @@ diff --git a/pdf/src/campPrint/tableOfContents/entry/Story.vue b/pdf/src/campPrint/tableOfContents/entry/Story.vue new file mode 100644 index 0000000000..32e02e7711 --- /dev/null +++ b/pdf/src/campPrint/tableOfContents/entry/Story.vue @@ -0,0 +1,13 @@ + + diff --git a/pdf/src/campPrint/tableOfContents/entry/Summary.vue b/pdf/src/campPrint/tableOfContents/entry/Summary.vue index b2476a5f13..58ef06ec95 100644 --- a/pdf/src/campPrint/tableOfContents/entry/Summary.vue +++ b/pdf/src/campPrint/tableOfContents/entry/Summary.vue @@ -1,17 +1,5 @@ - - - diff --git a/pdf/src/renderer/__tests__/__snapshots__/story_overview.spec.json.snap b/pdf/src/renderer/__tests__/__snapshots__/story_overview.spec.json.snap index ffcc77a4fd..67ccc1d63e 100644 --- a/pdf/src/renderer/__tests__/__snapshots__/story_overview.spec.json.snap +++ b/pdf/src/renderer/__tests__/__snapshots__/story_overview.spec.json.snap @@ -1,6 +1,282 @@ { "box": {}, - "children": [], + "children": [ + { + "box": {}, + "children": [ + { + "box": {}, + "children": [ + { + "parent": [Circular], + "type": "TEXT_INSTANCE", + "value": "print.summary..title: Hauptlager", + }, + ], + "parent": [Circular], + "props": { + "bookmark": { + "fit": true, + "title": "print.summary..title: Hauptlager", + }, + "class": "summary-period-title", + "id": "entry-0-16b2fcffdd8e", + }, + "style": { + "fontSize": "10pt", + "fontWeight": "bold", + "textAlign": "center", + }, + "type": "TEXT", + }, + { + "box": {}, + "children": [ + { + "box": {}, + "children": [ + { + "parent": [Circular], + "type": "TEXT_INSTANCE", + "value": "Day 1", + }, + ], + "parent": [Circular], + "props": { + "class": "summary-day-title", + }, + "style": { + "fontSize": "14", + "fontWeight": "semibold", + "margin": "10pt 0 3pt", + }, + "type": "TEXT", + }, + { + "box": {}, + "children": [ + { + "parent": [Circular], + "type": "TEXT_INSTANCE", + "value": "Fr 05/10/2024", + }, + ], + "parent": [Circular], + "props": { + "class": "summary-day-date", + }, + "style": { + "fontSize": "11pt", + }, + "type": "TEXT", + }, + ], + "parent": [Circular], + "props": { + "class": "summary-day-title-container", + "id": "entry-0-16b2fcffdd8e-f036e9302f67", + }, + "style": { + "alignItems": "baseline", + "borderBottom": "2pt solid #aaaaaa", + "display": "flex", + "flexDirection": "row", + "justifyContent": "space-between", + "marginBottom": "1pt", + "paddingBottom": "2pt", + }, + "type": "VIEW", + }, + { + "box": {}, + "children": [ + { + "box": {}, + "children": [ + { + "parent": [Circular], + "type": "TEXT_INSTANCE", + "value": "Day 2", + }, + ], + "parent": [Circular], + "props": { + "class": "summary-day-title", + }, + "style": { + "fontSize": "14", + "fontWeight": "semibold", + "margin": "10pt 0 3pt", + }, + "type": "TEXT", + }, + { + "box": {}, + "children": [ + { + "parent": [Circular], + "type": "TEXT_INSTANCE", + "value": "Sa 05/11/2024", + }, + ], + "parent": [Circular], + "props": { + "class": "summary-day-date", + }, + "style": { + "fontSize": "11pt", + }, + "type": "TEXT", + }, + ], + "parent": [Circular], + "props": { + "class": "summary-day-title-container", + "id": "entry-0-16b2fcffdd8e-f036e9302f68", + }, + "style": { + "alignItems": "baseline", + "borderBottom": "2pt solid #aaaaaa", + "display": "flex", + "flexDirection": "row", + "justifyContent": "space-between", + "marginBottom": "1pt", + "paddingBottom": "2pt", + }, + "type": "VIEW", + }, + { + "box": {}, + "children": [ + { + "box": {}, + "children": [ + { + "parent": [Circular], + "type": "TEXT_INSTANCE", + "value": "Day 3", + }, + ], + "parent": [Circular], + "props": { + "class": "summary-day-title", + }, + "style": { + "fontSize": "14", + "fontWeight": "semibold", + "margin": "10pt 0 3pt", + }, + "type": "TEXT", + }, + { + "box": {}, + "children": [ + { + "parent": [Circular], + "type": "TEXT_INSTANCE", + "value": "Su 05/12/2024", + }, + ], + "parent": [Circular], + "props": { + "class": "summary-day-date", + }, + "style": { + "fontSize": "11pt", + }, + "type": "TEXT", + }, + ], + "parent": [Circular], + "props": { + "class": "summary-day-title-container", + "id": "entry-0-16b2fcffdd8e-f036e9302f69", + }, + "style": { + "alignItems": "baseline", + "borderBottom": "2pt solid #aaaaaa", + "display": "flex", + "flexDirection": "row", + "justifyContent": "space-between", + "marginBottom": "1pt", + "paddingBottom": "2pt", + }, + "type": "VIEW", + }, + { + "box": {}, + "children": [ + { + "box": {}, + "children": [ + { + "parent": [Circular], + "type": "TEXT_INSTANCE", + "value": "Day 4", + }, + ], + "parent": [Circular], + "props": { + "class": "summary-day-title", + }, + "style": { + "fontSize": "14", + "fontWeight": "semibold", + "margin": "10pt 0 3pt", + }, + "type": "TEXT", + }, + { + "box": {}, + "children": [ + { + "parent": [Circular], + "type": "TEXT_INSTANCE", + "value": "Mo 05/13/2024", + }, + ], + "parent": [Circular], + "props": { + "class": "summary-day-date", + }, + "style": { + "fontSize": "11pt", + }, + "type": "TEXT", + }, + ], + "parent": [Circular], + "props": { + "class": "summary-day-title-container", + "id": "entry-0-16b2fcffdd8e-f036e9302f70", + }, + "style": { + "alignItems": "baseline", + "borderBottom": "2pt solid #aaaaaa", + "display": "flex", + "flexDirection": "row", + "justifyContent": "space-between", + "marginBottom": "1pt", + "paddingBottom": "2pt", + }, + "type": "VIEW", + }, + ], + "parent": [Circular], + "props": { + "class": "page", + "id": "entry-0", + }, + "style": { + "display": "flex", + "flexDirection": "column", + "fontFamily": "InterDisplay", + "fontSize": "12", + "padding": "30", + }, + "type": "PAGE", + }, + ], "parent": null, "props": { "locale": "de", diff --git a/print/components/Toc/TocSummary.vue b/print/components/Toc/TocSafetyConsiderations.vue similarity index 75% rename from print/components/Toc/TocSummary.vue rename to print/components/Toc/TocSafetyConsiderations.vue index 11df4f7583..ffb8d2db2d 100644 --- a/print/components/Toc/TocSummary.vue +++ b/print/components/Toc/TocSafetyConsiderations.vue @@ -1,11 +1,7 @@ diff --git a/print/components/config/Summary.vue b/print/components/config/SafetyConsiderations.vue similarity index 91% rename from print/components/config/Summary.vue rename to print/components/config/SafetyConsiderations.vue index 706c34fd38..21e73d94a5 100644 --- a/print/components/config/Summary.vue +++ b/print/components/config/SafetyConsiderations.vue @@ -8,7 +8,6 @@ :camp="camp" :index="index" :content-type="options.contentType" - :instance-name-filter="options.instanceNameFilter" />
@@ -24,7 +23,7 @@ const props = defineProps({ const { $api } = useNuxtApp() const { data: periods, error } = await useAsyncData( - `config/Summary-${props.index}`, + `config/SafetyConsiderations-${props.index}`, async () => { await Promise.all([ $api.get().contentTypes().$loadItems(), diff --git a/print/components/config/Story.vue b/print/components/config/Story.vue new file mode 100644 index 0000000000..1ae5362484 --- /dev/null +++ b/print/components/config/Story.vue @@ -0,0 +1,40 @@ + + + diff --git a/print/components/summary/SummaryDay.vue b/print/components/summary/SummaryDay.vue index bb5d8e86d6..56415d0643 100644 --- a/print/components/summary/SummaryDay.vue +++ b/print/components/summary/SummaryDay.vue @@ -69,7 +69,6 @@ export default { index: { type: Number, required: true }, allContentNodes: { type: Array, required: true }, contentType: { type: String, required: true }, - instanceNameFilter: { type: String, default: '' }, }, computed: { // returns scheduleEntries of current day without the need for an additional API call @@ -89,14 +88,7 @@ export default { (contentNode) => contentNode.root()._meta.self === scheduleEntry.activity().rootContentNode()._meta.self && - !isEmptyHtml(contentNode.data.html) && - (!this.instanceNameFilter || - contentNode.instanceName - ?.toLowerCase() - .includes(this.instanceNameFilter.toLowerCase()) || - this.$t(`contentNode.${camelCase(this.contentType)}.name`) - .toLowerCase() - .includes(this.instanceNameFilter.toLowerCase())) + !isEmptyHtml(contentNode.data.html) ), })) }, diff --git a/print/components/summary/SummaryPeriod.vue b/print/components/summary/SummaryPeriod.vue index 57916d2e62..4cd139679a 100644 --- a/print/components/summary/SummaryPeriod.vue +++ b/print/components/summary/SummaryPeriod.vue @@ -4,9 +4,7 @@ :id="`content_${index}_period_${period.id}`" class="tw-text-center tw-font-semibold tw-mb-6" > - {{ $t('print.summary.title') }} - {{ $t(`contentNode.${camelCase(contentType)}.name`) - }}: + {{ $t('print.summary.' + camelCase(contentType) + '.title') }}: {{ period.description }} @@ -18,7 +16,6 @@ :day="day" :all-content-nodes="data.contentNodes" :content-type="contentType" - :instance-name-filter="instanceNameFilter" /> @@ -34,7 +31,6 @@ const props = defineProps({ }, index: { type: Number, required: true }, contentType: { type: String, default: 'Storycontext' }, - instanceNameFilter: { type: String, default: '' }, }) const { $api } = useNuxtApp() diff --git a/print/eslint.config.mjs b/print/eslint.config.mjs index 3910e7e665..1c9ab4141a 100644 --- a/print/eslint.config.mjs +++ b/print/eslint.config.mjs @@ -55,7 +55,7 @@ export default [ 'error', { ignoreKeysRegex: - '^(global|entity|contentNode\\.[a-z][a-zA-Z]+|print\\.(global|activity|cover|picasso|program|summary|toc))\\..+', + '^(global|entity|contentNode\\.[a-z][a-zA-Z]+|print\\.(global|activity|cover|picasso|program|config|summary|toc))\\..+', translationKeyPropRegex: '[a-zA-Z0-9]-i18n-key$', }, ], From 65201787794fd3bb5bff482b070e866ba43f91fb Mon Sep 17 00:00:00 2001 From: Manuel Meister Date: Tue, 3 Sep 2024 20:54:48 +0200 Subject: [PATCH 31/69] Fix requested changes --- pdf/src/CampPrint.vue | 4 ++-- print/components/config/Story.vue | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pdf/src/CampPrint.vue b/pdf/src/CampPrint.vue index 20a440438a..fbca30e02f 100644 --- a/pdf/src/CampPrint.vue +++ b/pdf/src/CampPrint.vue @@ -23,8 +23,8 @@ import InterDisplayBoldItalic from '@/assets/fonts/Inter/InterDisplay-BoldItalic import Cover from '@/campPrint/cover/Cover.vue' import TableOfContents from '@/campPrint/tableOfContents/TableOfContents.vue' import Picasso from '@/campPrint/picasso/Picasso.vue' -import Story from './campPrint/summary/Story.vue' -import SafetyConsiderations from './campPrint/summary/SafetyConsiderations.vue' +import Story from '@/campPrint/summary/Story.vue' +import SafetyConsiderations from '@/campPrint/summary/SafetyConsiderations.vue' import Program from '@/campPrint/program/Program.vue' import Activity from '@/campPrint/activity/Activity.vue' import { wordHyphenation } from '@react-pdf/textkit' diff --git a/print/components/config/Story.vue b/print/components/config/Story.vue index 1ae5362484..d952c22570 100644 --- a/print/components/config/Story.vue +++ b/print/components/config/Story.vue @@ -23,7 +23,7 @@ const props = defineProps({ const { $api } = useNuxtApp() const { data: periods, error } = await useAsyncData( - `config/Story -${props.index}`, + `config/Story-${props.index}`, async () => { await Promise.all([ $api.get().contentTypes().$loadItems(), From 2ab872c2bb2f4c7043c43ba28fa3c124b539fec6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 15:55:51 +0000 Subject: [PATCH 32/69] fix(deps): update sentry-javascript monorepo to v8.30.0 --- frontend/package-lock.json | 114 +++++++++++++------------- frontend/package.json | 4 +- print/package-lock.json | 161 +++++++++++++++---------------------- print/package.json | 2 +- 4 files changed, 126 insertions(+), 155 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 4173e42a9a..2a8cfc9542 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -14,8 +14,8 @@ "@react-pdf/pdfkit": "3.1.10", "@react-pdf/primitives": "3.1.1", "@react-pdf/render": "3.4.4", - "@sentry/browser": "8.29.0", - "@sentry/vue": "8.29.0", + "@sentry/browser": "8.30.0", + "@sentry/vue": "8.30.0", "@tiptap/extension-bold": "2.6.6", "@tiptap/extension-bubble-menu": "2.6.6", "@tiptap/extension-bullet-list": "2.6.6", @@ -3270,58 +3270,58 @@ ] }, "node_modules/@sentry-internal/browser-utils": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.29.0.tgz", - "integrity": "sha512-6HpyQkaqPvK6Lnigjlarq/LDYgXT2OBNf24RK7z0ipJSxSIpmtelfzHbnwWYnypNDXfTDdPm97fZEenQHryYJA==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.30.0.tgz", + "integrity": "sha512-pwX+awNWaxSOAsBLVLqc1+Hw+Fm1Nci9mbKFA6Ed5YzCG049PnBVQwugpmx2dcyyCqJpORhcIqb9jHdCkYmCiA==", "license": "MIT", "dependencies": { - "@sentry/core": "8.29.0", - "@sentry/types": "8.29.0", - "@sentry/utils": "8.29.0" + "@sentry/core": "8.30.0", + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/feedback": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.29.0.tgz", - "integrity": "sha512-yAL5YMEFk4XaeVRUGEguydahRzaQrNPAaWRv6k+XRzCv9CGBhxb14KXQc9X/penlauMFcDfgelCPKcTqcf6wDw==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.30.0.tgz", + "integrity": "sha512-ParFRxQY6helxkwUDmro77Wc5uSIC6rZos88jYMrYwFmoTJaNWf4lDzPyECfdSiSYyzSMZk4dorSUN85Ul7DCg==", "license": "MIT", "dependencies": { - "@sentry/core": "8.29.0", - "@sentry/types": "8.29.0", - "@sentry/utils": "8.29.0" + "@sentry/core": "8.30.0", + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/replay": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.29.0.tgz", - "integrity": "sha512-Xgv/eYucsm7GaGKms2ClQ02NpD07MxjoTjp1/vYZm0H4Q08dVphVZrQp7hL1oX/VD9mb5SFyyKuuIRqIu7S8RA==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.30.0.tgz", + "integrity": "sha512-/KFre+BrovPCiovgAu5N1ErJtkDVzkJA5hV3Jw011AlxRWxrmPwu6+9sV9/rn3tqYAGyq6IggYqeIOHhLh1Ihg==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "8.29.0", - "@sentry/core": "8.29.0", - "@sentry/types": "8.29.0", - "@sentry/utils": "8.29.0" + "@sentry-internal/browser-utils": "8.30.0", + "@sentry/core": "8.30.0", + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/replay-canvas": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.29.0.tgz", - "integrity": "sha512-W2YbZRvp2lYC50V51fNLcnoIiK1Km4vSc+v6SL7c//lv2qpyumoUAAIDKY+14s8Lgt1RsR6rfZhfheD4O/6WSQ==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.30.0.tgz", + "integrity": "sha512-y/QqcvchhtMlVA6eOZicIfTxtZarazQZJuFW0018ynPxBTiuuWSxMCLqduulXUYsFejfD8/eKHb3BpCIFdDYjg==", "license": "MIT", "dependencies": { - "@sentry-internal/replay": "8.29.0", - "@sentry/core": "8.29.0", - "@sentry/types": "8.29.0", - "@sentry/utils": "8.29.0" + "@sentry-internal/replay": "8.30.0", + "@sentry/core": "8.30.0", + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0" }, "engines": { "node": ">=14.18" @@ -3338,18 +3338,18 @@ } }, "node_modules/@sentry/browser": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.29.0.tgz", - "integrity": "sha512-aKTy4H/3RI0q9LIeepesjWGlGNeh4HGFfwQjzHME8gcWCQ5LSlzYX4U+hu2yp7r1Jfd9MUTFfOuuLih2HGLGsQ==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.30.0.tgz", + "integrity": "sha512-M+tKqawH9S3CqlAIcqdZcHbcsNQkEa9MrPqPCYvXco3C4LRpNizJP2XwBiGQY2yK+fOSvbaWpPtlI938/wuRZQ==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "8.29.0", - "@sentry-internal/feedback": "8.29.0", - "@sentry-internal/replay": "8.29.0", - "@sentry-internal/replay-canvas": "8.29.0", - "@sentry/core": "8.29.0", - "@sentry/types": "8.29.0", - "@sentry/utils": "8.29.0" + "@sentry-internal/browser-utils": "8.30.0", + "@sentry-internal/feedback": "8.30.0", + "@sentry-internal/replay": "8.30.0", + "@sentry-internal/replay-canvas": "8.30.0", + "@sentry/core": "8.30.0", + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0" }, "engines": { "node": ">=14.18" @@ -3528,34 +3528,34 @@ } }, "node_modules/@sentry/core": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.29.0.tgz", - "integrity": "sha512-scMbZaJ0Ov8NPgWn86EdjhyTLrhvRVbTxjg0imJAvhIvRbblH3xyqye/17Qnk2fOp8TNDOl7TBZHi0NCFQ5HUw==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.30.0.tgz", + "integrity": "sha512-CJ/FuWLw0QEKGKXGL/nm9eaOdajEcmPekLuHAuOCxID7N07R9l9laz3vFbAkUZ97GGDv3sYrJZgywfY3Moropg==", "license": "MIT", "dependencies": { - "@sentry/types": "8.29.0", - "@sentry/utils": "8.29.0" + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry/types": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.29.0.tgz", - "integrity": "sha512-j4gX3ctzgD4xVWllXAhm6M+kHFEvrFoUPFq60X/pgkjsWCocGuhtNfB0rW43ICG8hCnlz8IYl7O7b8V8qY7SPg==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.30.0.tgz", + "integrity": "sha512-kgWW2BCjBmVlSQRG32GonHEVyeDbys74xf9mLPvynwHTgw3+NUlNAlEdu05xnb2ow4bCTHfbkS5G1zRgyv5k4Q==", "license": "MIT", "engines": { "node": ">=14.18" } }, "node_modules/@sentry/utils": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.29.0.tgz", - "integrity": "sha512-nb93/m3SjQChQJFqJj3oNW3Rz/12yrT7jypTCire3c2hpYWG2uR5n8VY9UUMTA6HLNvdom6tckK7p3bXGXlF0w==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.30.0.tgz", + "integrity": "sha512-wZxU2HWlzsnu8214Xy7S7cRIuD6h8Z5DnnkojJfX0i0NLooepZQk2824el1Q13AakLb7/S8CHSHXOMnCtoSduw==", "license": "MIT", "dependencies": { - "@sentry/types": "8.29.0" + "@sentry/types": "8.30.0" }, "engines": { "node": ">=14.18" @@ -3576,15 +3576,15 @@ } }, "node_modules/@sentry/vue": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@sentry/vue/-/vue-8.29.0.tgz", - "integrity": "sha512-LvS9SbQxwmjPwRNOfj189XKGDxebUyIxHRNtxPMSO1LEWIkhDK1WC88bZCdFUf59t4vaAgel6UdGVbWkB+eOwA==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry/vue/-/vue-8.30.0.tgz", + "integrity": "sha512-0mGQXZGYgpVhmcaYmMLN4oUhaRcQ2ZoXFkoYR58wL6QAuvLR/80Ey5K7FuoLeGIaPHESm1uCqEqgv8y5a5Nx+w==", "license": "MIT", "dependencies": { - "@sentry/browser": "8.29.0", - "@sentry/core": "8.29.0", - "@sentry/types": "8.29.0", - "@sentry/utils": "8.29.0" + "@sentry/browser": "8.30.0", + "@sentry/core": "8.30.0", + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0" }, "engines": { "node": ">=14.18" diff --git a/frontend/package.json b/frontend/package.json index 2c974fa0a9..0382aa177d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -26,8 +26,8 @@ "@react-pdf/pdfkit": "3.1.10", "@react-pdf/primitives": "3.1.1", "@react-pdf/render": "3.4.4", - "@sentry/browser": "8.29.0", - "@sentry/vue": "8.29.0", + "@sentry/browser": "8.30.0", + "@sentry/vue": "8.30.0", "@tiptap/extension-bold": "2.6.6", "@tiptap/extension-bubble-menu": "2.6.6", "@tiptap/extension-bullet-list": "2.6.6", diff --git a/print/package-lock.json b/print/package-lock.json index 2309f3320f..d7b40271a4 100644 --- a/print/package-lock.json +++ b/print/package-lock.json @@ -8,7 +8,7 @@ "dependencies": { "@jamescoyle/vue-icon": "0.1.2", "@mdi/js": "7.4.47", - "@sentry/node": "8.29.0", + "@sentry/node": "8.30.0", "axios": "1.7.7", "colorjs.io": "0.5.2", "dayjs": "1.11.13", @@ -3011,6 +3011,22 @@ "@opentelemetry/api": "^1.3.0" } }, + "node_modules/@opentelemetry/instrumentation-kafkajs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.3.0.tgz", + "integrity": "sha512-UnkZueYK1ise8FXQeKlpBd7YYUtC7mM8J0wzUSccEfc/G8UqHQqAzIyYCUOUPUKp8GsjLnWOOK/3hJc4owb7Jg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, "node_modules/@opentelemetry/instrumentation-koa": { "version": "0.43.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.43.0.tgz", @@ -3148,6 +3164,22 @@ "@opentelemetry/api": "^1.3.0" } }, + "node_modules/@opentelemetry/instrumentation-undici": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.6.0.tgz", + "integrity": "sha512-ABJBhm5OdhGmbh0S/fOTE4N69IZ00CsHC5ijMYfzbw3E5NwLgpQk5xsljaECrJ8wz1SfXbO03FiSuu5AyRAkvQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.53.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.7.0" + } + }, "node_modules/@opentelemetry/redis-common": { "version": "0.36.2", "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz", @@ -4164,22 +4196,22 @@ ] }, "node_modules/@sentry/core": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.29.0.tgz", - "integrity": "sha512-scMbZaJ0Ov8NPgWn86EdjhyTLrhvRVbTxjg0imJAvhIvRbblH3xyqye/17Qnk2fOp8TNDOl7TBZHi0NCFQ5HUw==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.30.0.tgz", + "integrity": "sha512-CJ/FuWLw0QEKGKXGL/nm9eaOdajEcmPekLuHAuOCxID7N07R9l9laz3vFbAkUZ97GGDv3sYrJZgywfY3Moropg==", "license": "MIT", "dependencies": { - "@sentry/types": "8.29.0", - "@sentry/utils": "8.29.0" + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry/node": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-8.29.0.tgz", - "integrity": "sha512-RCKpWR6DUWmlxtms10MRXwJZRrFt1a2P38FjwEEahcdcK1R6wB8GPf0GO4JnJAiw6oeM0MERSqLIcSLT8+FxtA==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-8.30.0.tgz", + "integrity": "sha512-Tog0Ag7sU3lNj4cPUZy1KRJXyYXZlWiwlk34KYNNxAk0vDiK6W0bF8mvS+aaUukgb7FO5A0eu9l+VApdBJOr3Q==", "license": "MIT", "dependencies": { "@opentelemetry/api": "^1.9.0", @@ -4195,6 +4227,7 @@ "@opentelemetry/instrumentation-hapi": "0.41.0", "@opentelemetry/instrumentation-http": "0.53.0", "@opentelemetry/instrumentation-ioredis": "0.43.0", + "@opentelemetry/instrumentation-kafkajs": "0.3.0", "@opentelemetry/instrumentation-koa": "0.43.0", "@opentelemetry/instrumentation-mongodb": "0.47.0", "@opentelemetry/instrumentation-mongoose": "0.42.0", @@ -4203,32 +4236,30 @@ "@opentelemetry/instrumentation-nestjs-core": "0.40.0", "@opentelemetry/instrumentation-pg": "0.44.0", "@opentelemetry/instrumentation-redis-4": "0.42.0", - "@opentelemetry/resources": "^1.25.1", - "@opentelemetry/sdk-trace-base": "^1.25.1", - "@opentelemetry/semantic-conventions": "^1.25.1", + "@opentelemetry/instrumentation-undici": "0.6.0", + "@opentelemetry/resources": "^1.26.0", + "@opentelemetry/sdk-trace-base": "^1.26.0", + "@opentelemetry/semantic-conventions": "^1.27.0", "@prisma/instrumentation": "5.19.1", - "@sentry/core": "8.29.0", - "@sentry/opentelemetry": "8.29.0", - "@sentry/types": "8.29.0", - "@sentry/utils": "8.29.0", + "@sentry/core": "8.30.0", + "@sentry/opentelemetry": "8.30.0", + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0", "import-in-the-middle": "^1.11.0" }, "engines": { "node": ">=14.18" - }, - "optionalDependencies": { - "opentelemetry-instrumentation-fetch-node": "1.2.3" } }, "node_modules/@sentry/opentelemetry": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-8.29.0.tgz", - "integrity": "sha512-MtfjDMUuKFYlyw9hZohp9xnphz+6QosyHb2zCV3e/fANoA53FDxmg/Co7haMohUCiOwwJPytUmSQQaP0nyL2Uw==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-8.30.0.tgz", + "integrity": "sha512-6mCIP2zvxAiEsNEoF8kv+UUD4XGWSKJU6RY5BF1U26HLitXv1fNPtzaTR96Ehv9h0zktjLfqfpVUZ7DGkdBvLA==", "license": "MIT", "dependencies": { - "@sentry/core": "8.29.0", - "@sentry/types": "8.29.0", - "@sentry/utils": "8.29.0" + "@sentry/core": "8.30.0", + "@sentry/types": "8.30.0", + "@sentry/utils": "8.30.0" }, "engines": { "node": ">=14.18" @@ -4236,27 +4267,27 @@ "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/core": "^1.25.1", - "@opentelemetry/instrumentation": "^0.52.1", - "@opentelemetry/sdk-trace-base": "^1.25.1", - "@opentelemetry/semantic-conventions": "^1.25.1" + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/sdk-trace-base": "^1.26.0", + "@opentelemetry/semantic-conventions": "^1.27.0" } }, "node_modules/@sentry/types": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.29.0.tgz", - "integrity": "sha512-j4gX3ctzgD4xVWllXAhm6M+kHFEvrFoUPFq60X/pgkjsWCocGuhtNfB0rW43ICG8hCnlz8IYl7O7b8V8qY7SPg==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.30.0.tgz", + "integrity": "sha512-kgWW2BCjBmVlSQRG32GonHEVyeDbys74xf9mLPvynwHTgw3+NUlNAlEdu05xnb2ow4bCTHfbkS5G1zRgyv5k4Q==", "license": "MIT", "engines": { "node": ">=14.18" } }, "node_modules/@sentry/utils": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.29.0.tgz", - "integrity": "sha512-nb93/m3SjQChQJFqJj3oNW3Rz/12yrT7jypTCire3c2hpYWG2uR5n8VY9UUMTA6HLNvdom6tckK7p3bXGXlF0w==", + "version": "8.30.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.30.0.tgz", + "integrity": "sha512-wZxU2HWlzsnu8214Xy7S7cRIuD6h8Z5DnnkojJfX0i0NLooepZQk2824el1Q13AakLb7/S8CHSHXOMnCtoSduw==", "license": "MIT", "dependencies": { - "@sentry/types": "8.29.0" + "@sentry/types": "8.30.0" }, "engines": { "node": ">=14.18" @@ -5336,16 +5367,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "license": "MIT", - "optional": true, - "peerDependencies": { - "acorn": "^8" - } - }, "node_modules/acorn-import-attributes": { "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", @@ -12614,56 +12635,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/opentelemetry-instrumentation-fetch-node": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/opentelemetry-instrumentation-fetch-node/-/opentelemetry-instrumentation-fetch-node-1.2.3.tgz", - "integrity": "sha512-Qb11T7KvoCevMaSeuamcLsAD+pZnavkhDnlVL0kRozfhl42dKG5Q3anUklAFKJZjY3twLR+BnRa6DlwwkIE/+A==", - "license": "MIT", - "optional": true, - "dependencies": { - "@opentelemetry/instrumentation": "^0.46.0", - "@opentelemetry/semantic-conventions": "^1.17.0" - }, - "engines": { - "node": ">18.0.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.6.0" - } - }, - "node_modules/opentelemetry-instrumentation-fetch-node/node_modules/@opentelemetry/instrumentation": { - "version": "0.46.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.46.0.tgz", - "integrity": "sha512-a9TijXZZbk0vI5TGLZl+0kxyFfrXHhX6Svtz7Pp2/VBlCSKrazuULEyoJQrOknJyFWNMEmbbJgOciHCCpQcisw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@types/shimmer": "^1.0.2", - "import-in-the-middle": "1.7.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/opentelemetry-instrumentation-fetch-node/node_modules/import-in-the-middle": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.7.1.tgz", - "integrity": "sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "acorn": "^8.8.2", - "acorn-import-assertions": "^1.9.0", - "cjs-module-lexer": "^1.2.2", - "module-details-from-path": "^1.0.3" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", diff --git a/print/package.json b/print/package.json index 96c470a939..41ffad877a 100644 --- a/print/package.json +++ b/print/package.json @@ -17,7 +17,7 @@ "dependencies": { "@jamescoyle/vue-icon": "0.1.2", "@mdi/js": "7.4.47", - "@sentry/node": "8.29.0", + "@sentry/node": "8.30.0", "axios": "1.7.7", "colorjs.io": "0.5.2", "dayjs": "1.11.13", From e67715902618ef8f14b2b3c235e39faf154be875 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 20:17:28 +0000 Subject: [PATCH 33/69] chore(deps): update amazon/aws-cli docker tag to v2.17.48 --- .ops/aws-setup/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ops/aws-setup/docker-compose.yml b/.ops/aws-setup/docker-compose.yml index fdbd1edb48..a7f40800ad 100644 --- a/.ops/aws-setup/docker-compose.yml +++ b/.ops/aws-setup/docker-compose.yml @@ -13,7 +13,7 @@ services: - AWS_DEFAULT_REGION=eu-west-3 aws-cli: - image: amazon/aws-cli:2.17.47 + image: amazon/aws-cli:2.17.48 container_name: 'ecamp3-aws-cli' volumes: - ./.aws:/root/.aws:delegated From fb79e555872113a6528a7d9cabc33de9510d9b09 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 00:10:11 +0000 Subject: [PATCH 34/69] chore(deps): update dependency @nuxtjs/i18n to v8.5.3 --- print/package-lock.json | 97 ++++++++++++++++++++++++++++++++++++----- print/package.json | 2 +- 2 files changed, 87 insertions(+), 12 deletions(-) diff --git a/print/package-lock.json b/print/package-lock.json index f70022d91b..126a3fcd10 100644 --- a/print/package-lock.json +++ b/print/package-lock.json @@ -26,7 +26,7 @@ "@eslint/js": "9.9.1", "@nuxt/eslint": "0.5.6", "@nuxt/eslint-config": "0.5.6", - "@nuxtjs/i18n": "8.5.2", + "@nuxtjs/i18n": "8.5.3", "@nuxtjs/tailwindcss": "6.12.1", "@tailwindcss/typography": "0.5.15", "@typescript-eslint/eslint-plugin": "8.5.0", @@ -2732,9 +2732,9 @@ } }, "node_modules/@nuxtjs/i18n": { - "version": "8.5.2", - "resolved": "https://registry.npmjs.org/@nuxtjs/i18n/-/i18n-8.5.2.tgz", - "integrity": "sha512-x5AZAd2sfvL3cYfpwCMQn7DyiwWCTPZSciiMWcfWQunin1V5toyzQRKjztvA6lh2iVOyeZF9bJpCkHG+UkOlkA==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@nuxtjs/i18n/-/i18n-8.5.3.tgz", + "integrity": "sha512-owSqQtBzi6NYer1yFOpQxnZzRWg+85cXWvlweN+yKYN6hdacLtOpN/hZn3FiXXc5OKDNStTyi+QoVpb0OH4n7w==", "dev": true, "license": "MIT", "dependencies": { @@ -2743,9 +2743,9 @@ "@intlify/unplugin-vue-i18n": "^3.0.1", "@intlify/utils": "^0.12.0", "@miyaneee/rollup-plugin-json5": "^1.2.0", - "@nuxt/kit": "^3.12.4", + "@nuxt/kit": "^3.13.1", "@rollup/plugin-yaml": "^4.1.2", - "@vue/compiler-sfc": "^3.4.37", + "@vue/compiler-sfc": "^3.5.4", "debug": "^4.3.5", "defu": "^6.1.2", "estree-walker": "^3.0.3", @@ -2759,12 +2759,87 @@ "ufo": "^1.3.1", "unplugin": "^1.10.1", "vue-i18n": "^9.9.0", - "vue-router": "^4.4.0" + "vue-router": "^4.4.4" }, "engines": { "node": "^14.16.0 || >=16.11.0" } }, + "node_modules/@nuxtjs/i18n/node_modules/@vue/compiler-core": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.4.tgz", + "integrity": "sha512-oNwn+BAt3n9dK9uAYvI+XGlutwuTq/wfj4xCBaZCqwwVIGtD7D6ViihEbyYZrDHIHTDE3Q6oL3/hqmAyFEy9DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.4", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@nuxtjs/i18n/node_modules/@vue/compiler-core/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nuxtjs/i18n/node_modules/@vue/compiler-dom": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.4.tgz", + "integrity": "sha512-yP9RRs4BDLOLfldn6ah+AGCNovGjMbL9uHvhDHf5wan4dAHLnFGOkqtfE7PPe4HTXIqE7l/NILdYw53bo1C8jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.4", + "@vue/shared": "3.5.4" + } + }, + "node_modules/@nuxtjs/i18n/node_modules/@vue/compiler-sfc": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.4.tgz", + "integrity": "sha512-P+yiPhL+NYH7m0ZgCq7AQR2q7OIE+mpAEgtkqEeH9oHSdIRvUO+4X6MPvblJIWcoe4YC5a2Gdf/RsoyP8FFiPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/compiler-core": "3.5.4", + "@vue/compiler-dom": "3.5.4", + "@vue/compiler-ssr": "3.5.4", + "@vue/shared": "3.5.4", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.11", + "postcss": "^8.4.44", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@nuxtjs/i18n/node_modules/@vue/compiler-sfc/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nuxtjs/i18n/node_modules/@vue/compiler-ssr": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.4.tgz", + "integrity": "sha512-acESdTXsxPnYr2C4Blv0ggx5zIFMgOzZmYU2UgvIff9POdRGbRNBHRyzHAnizcItvpgerSKQbllUc9USp3V7eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.4", + "@vue/shared": "3.5.4" + } + }, + "node_modules/@nuxtjs/i18n/node_modules/@vue/shared": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.4.tgz", + "integrity": "sha512-L2MCDD8l7yC62Te5UUyPVpmexhL9ipVnYRw9CsWfm/BGRL5FwDX4a25bcJ/OJSD3+Hx+k/a8LDKcG2AFdJV3BA==", + "dev": true, + "license": "MIT" + }, "node_modules/@nuxtjs/tailwindcss": { "version": "6.12.1", "resolved": "https://registry.npmjs.org/@nuxtjs/tailwindcss/-/tailwindcss-6.12.1.tgz", @@ -17556,13 +17631,13 @@ } }, "node_modules/vue-router": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.4.3.tgz", - "integrity": "sha512-sv6wmNKx2j3aqJQDMxLFzs/u/mjA9Z5LCgy6BE0f7yFWMjrPLnS/sPNn8ARY/FXw6byV18EFutn5lTO6+UsV5A==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.4.4.tgz", + "integrity": "sha512-3MlnDqwRwZwCQVbtVfpsU+nrNymNjnXSsQtXName5925NVC1+326VVfYH9vSrA0N13teGEo8z5x7gbRnGjCDiQ==", "dev": true, "license": "MIT", "dependencies": { - "@vue/devtools-api": "^6.6.3" + "@vue/devtools-api": "^6.6.4" }, "funding": { "url": "https://github.com/sponsors/posva" diff --git a/print/package.json b/print/package.json index 8f4bd37fce..105a1ff076 100644 --- a/print/package.json +++ b/print/package.json @@ -35,7 +35,7 @@ "@eslint/js": "9.9.1", "@nuxt/eslint": "0.5.6", "@nuxt/eslint-config": "0.5.6", - "@nuxtjs/i18n": "8.5.2", + "@nuxtjs/i18n": "8.5.3", "@nuxtjs/tailwindcss": "6.12.1", "@tailwindcss/typography": "0.5.15", "@typescript-eslint/eslint-plugin": "8.5.0", From a5351e29f0826d18475a74343f407bfc23450dea Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 09:33:09 +0000 Subject: [PATCH 35/69] chore(deps): update dependency @nuxt/eslint to v0.5.7 --- print/package-lock.json | 115 ++++++++++++++++++++++++++++++++++++---- print/package.json | 2 +- 2 files changed, 107 insertions(+), 10 deletions(-) diff --git a/print/package-lock.json b/print/package-lock.json index 126a3fcd10..7805b7568d 100644 --- a/print/package-lock.json +++ b/print/package-lock.json @@ -24,7 +24,7 @@ "@eslint/compat": "1.1.1", "@eslint/eslintrc": "3.1.0", "@eslint/js": "9.9.1", - "@nuxt/eslint": "0.5.6", + "@nuxt/eslint": "0.5.7", "@nuxt/eslint-config": "0.5.6", "@nuxtjs/i18n": "8.5.3", "@nuxtjs/tailwindcss": "6.12.1", @@ -2060,20 +2060,20 @@ } }, "node_modules/@nuxt/eslint": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@nuxt/eslint/-/eslint-0.5.6.tgz", - "integrity": "sha512-kW9+vyFBSSCYY1oaHhtMZPoZUlD2fLh1j6t/giCw6M/IiPWsMs2Hfzm/hqrfP/XNw9pvvtATAxRB9eF76IStwA==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@nuxt/eslint/-/eslint-0.5.7.tgz", + "integrity": "sha512-t2GoH8BIfDVysZ5Y9kPBTnT9rcUSJcXTeY5Fa93//qmHJba3kIpoETy3qJe/v75R1giGgIPO+Iydt6uXZ2jjJQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint/config-inspector": "^0.5.4", - "@nuxt/devtools-kit": "^1.4.1", - "@nuxt/eslint-config": "0.5.6", - "@nuxt/eslint-plugin": "0.5.6", + "@nuxt/devtools-kit": "^1.4.2", + "@nuxt/eslint-config": "0.5.7", + "@nuxt/eslint-plugin": "0.5.7", "@nuxt/kit": "^3.13.1", "chokidar": "^3.6.0", - "eslint-flat-config-utils": "^0.3.1", - "eslint-typegen": "^0.3.1", + "eslint-flat-config-utils": "^0.4.0", + "eslint-typegen": "^0.3.2", "find-up": "^7.0.0", "get-port-please": "^3.1.2", "mlly": "^1.7.1", @@ -2153,6 +2153,103 @@ "eslint": "^8.57.0 || ^9.0.0" } }, + "node_modules/@nuxt/eslint/node_modules/@eslint/js": { + "version": "9.10.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz", + "integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@nuxt/eslint/node_modules/@nuxt/devtools-kit": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@nuxt/devtools-kit/-/devtools-kit-1.4.2.tgz", + "integrity": "sha512-8a5PhVnC7E94318/sHbNSe9mI2MlsQ8+pJLGs2Hh1OJyidB9SWe6hoFc8q4K9VOtXak9uCFVb5V2JGXS1q+1aA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nuxt/kit": "^3.13.1", + "@nuxt/schema": "^3.13.1", + "execa": "^7.2.0" + }, + "peerDependencies": { + "vite": "*" + } + }, + "node_modules/@nuxt/eslint/node_modules/@nuxt/eslint-config": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@nuxt/eslint-config/-/eslint-config-0.5.7.tgz", + "integrity": "sha512-B+snO9NS9+v2657Z84tMbW3hLxjauIUkk2m4vnYjb9xfAFdoQwK07q6aaf7LzvagmVFmQiclT9LbJMvlRqzmsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint/js": "^9.10.0", + "@nuxt/eslint-plugin": "0.5.7", + "@stylistic/eslint-plugin": "^2.8.0", + "@typescript-eslint/eslint-plugin": "^8.5.0", + "@typescript-eslint/parser": "^8.5.0", + "eslint-config-flat-gitignore": "^0.3.0", + "eslint-flat-config-utils": "^0.4.0", + "eslint-plugin-import-x": "^4.2.1", + "eslint-plugin-jsdoc": "^50.2.2", + "eslint-plugin-regexp": "^2.6.0", + "eslint-plugin-unicorn": "^55.0.0", + "eslint-plugin-vue": "^9.28.0", + "globals": "^15.9.0", + "local-pkg": "^0.5.0", + "pathe": "^1.1.2", + "vue-eslint-parser": "^9.4.3" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/@nuxt/eslint/node_modules/@nuxt/eslint-config/node_modules/eslint-config-flat-gitignore": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-flat-gitignore/-/eslint-config-flat-gitignore-0.3.0.tgz", + "integrity": "sha512-0Ndxo4qGhcewjTzw52TK06Mc00aDtHNTdeeW2JfONgDcLkRO/n/BteMRzNVpLQYxdCC/dFEilfM9fjjpGIJ9Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint/compat": "^1.1.1", + "find-up-simple": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "eslint": "^9.5.0" + } + }, + "node_modules/@nuxt/eslint/node_modules/@nuxt/eslint-plugin": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@nuxt/eslint-plugin/-/eslint-plugin-0.5.7.tgz", + "integrity": "sha512-vYQYs/L87g2pBIoTmkk2mgYBqePTQDnhk87nGqsosKbfQ80xj9kkN3dsVb6BDQFk0zik4THWpXmnfjkvsjm/eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "^8.5.0", + "@typescript-eslint/utils": "^8.5.0" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/@nuxt/eslint/node_modules/eslint-flat-config-utils": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/eslint-flat-config-utils/-/eslint-flat-config-utils-0.4.0.tgz", + "integrity": "sha512-kfd5kQZC+BMO0YwTol6zxjKX1zAsk8JfSAopbKjKqmENTJcew+yBejuvccAg37cvOrN0Mh+DVbeyznuNWEjt4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@nuxt/kit": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.13.1.tgz", diff --git a/print/package.json b/print/package.json index 105a1ff076..129810dace 100644 --- a/print/package.json +++ b/print/package.json @@ -33,7 +33,7 @@ "@eslint/compat": "1.1.1", "@eslint/eslintrc": "3.1.0", "@eslint/js": "9.9.1", - "@nuxt/eslint": "0.5.6", + "@nuxt/eslint": "0.5.7", "@nuxt/eslint-config": "0.5.6", "@nuxtjs/i18n": "8.5.3", "@nuxtjs/tailwindcss": "6.12.1", From 89f89c42739f48f8b51b1297617ddb5ac042c981 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 09:33:21 +0000 Subject: [PATCH 36/69] chore(deps): update dependency @nuxt/eslint-config to v0.5.7 --- print/package-lock.json | 102 ++++++++++++++++++++++++++++++++++++---- print/package.json | 2 +- 2 files changed, 93 insertions(+), 11 deletions(-) diff --git a/print/package-lock.json b/print/package-lock.json index 126a3fcd10..075be875f7 100644 --- a/print/package-lock.json +++ b/print/package-lock.json @@ -25,7 +25,7 @@ "@eslint/eslintrc": "3.1.0", "@eslint/js": "9.9.1", "@nuxt/eslint": "0.5.6", - "@nuxt/eslint-config": "0.5.6", + "@nuxt/eslint-config": "0.5.7", "@nuxtjs/i18n": "8.5.3", "@nuxtjs/tailwindcss": "6.12.1", "@tailwindcss/typography": "0.5.15", @@ -2095,19 +2095,19 @@ } }, "node_modules/@nuxt/eslint-config": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@nuxt/eslint-config/-/eslint-config-0.5.6.tgz", - "integrity": "sha512-2kse94xvLW9SeENOAkGaksfff7vwRWsekbDsRjVoW2h3/95wRHWSenObUbGaW6Jr3D0o7DzyEIsaOvnWHZXvDg==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@nuxt/eslint-config/-/eslint-config-0.5.7.tgz", + "integrity": "sha512-B+snO9NS9+v2657Z84tMbW3hLxjauIUkk2m4vnYjb9xfAFdoQwK07q6aaf7LzvagmVFmQiclT9LbJMvlRqzmsA==", "dev": true, "license": "MIT", "dependencies": { - "@eslint/js": "^9.9.1", - "@nuxt/eslint-plugin": "0.5.6", - "@stylistic/eslint-plugin": "^2.7.2", - "@typescript-eslint/eslint-plugin": "^8.4.0", - "@typescript-eslint/parser": "^8.4.0", + "@eslint/js": "^9.10.0", + "@nuxt/eslint-plugin": "0.5.7", + "@stylistic/eslint-plugin": "^2.8.0", + "@typescript-eslint/eslint-plugin": "^8.5.0", + "@typescript-eslint/parser": "^8.5.0", "eslint-config-flat-gitignore": "^0.3.0", - "eslint-flat-config-utils": "^0.3.1", + "eslint-flat-config-utils": "^0.4.0", "eslint-plugin-import-x": "^4.2.1", "eslint-plugin-jsdoc": "^50.2.2", "eslint-plugin-regexp": "^2.6.0", @@ -2122,6 +2122,30 @@ "eslint": "^8.57.0 || ^9.0.0" } }, + "node_modules/@nuxt/eslint-config/node_modules/@eslint/js": { + "version": "9.10.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz", + "integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@nuxt/eslint-config/node_modules/@nuxt/eslint-plugin": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@nuxt/eslint-plugin/-/eslint-plugin-0.5.7.tgz", + "integrity": "sha512-vYQYs/L87g2pBIoTmkk2mgYBqePTQDnhk87nGqsosKbfQ80xj9kkN3dsVb6BDQFk0zik4THWpXmnfjkvsjm/eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "^8.5.0", + "@typescript-eslint/utils": "^8.5.0" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, "node_modules/@nuxt/eslint-config/node_modules/eslint-config-flat-gitignore": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/eslint-config-flat-gitignore/-/eslint-config-flat-gitignore-0.3.0.tgz", @@ -2139,6 +2163,19 @@ "eslint": "^9.5.0" } }, + "node_modules/@nuxt/eslint-config/node_modules/eslint-flat-config-utils": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/eslint-flat-config-utils/-/eslint-flat-config-utils-0.4.0.tgz", + "integrity": "sha512-kfd5kQZC+BMO0YwTol6zxjKX1zAsk8JfSAopbKjKqmENTJcew+yBejuvccAg37cvOrN0Mh+DVbeyznuNWEjt4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@nuxt/eslint-plugin": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/@nuxt/eslint-plugin/-/eslint-plugin-0.5.6.tgz", @@ -2153,6 +2190,51 @@ "eslint": "^8.57.0 || ^9.0.0" } }, + "node_modules/@nuxt/eslint/node_modules/@nuxt/eslint-config": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@nuxt/eslint-config/-/eslint-config-0.5.6.tgz", + "integrity": "sha512-2kse94xvLW9SeENOAkGaksfff7vwRWsekbDsRjVoW2h3/95wRHWSenObUbGaW6Jr3D0o7DzyEIsaOvnWHZXvDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint/js": "^9.9.1", + "@nuxt/eslint-plugin": "0.5.6", + "@stylistic/eslint-plugin": "^2.7.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "eslint-config-flat-gitignore": "^0.3.0", + "eslint-flat-config-utils": "^0.3.1", + "eslint-plugin-import-x": "^4.2.1", + "eslint-plugin-jsdoc": "^50.2.2", + "eslint-plugin-regexp": "^2.6.0", + "eslint-plugin-unicorn": "^55.0.0", + "eslint-plugin-vue": "^9.28.0", + "globals": "^15.9.0", + "local-pkg": "^0.5.0", + "pathe": "^1.1.2", + "vue-eslint-parser": "^9.4.3" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/@nuxt/eslint/node_modules/@nuxt/eslint-config/node_modules/eslint-config-flat-gitignore": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-flat-gitignore/-/eslint-config-flat-gitignore-0.3.0.tgz", + "integrity": "sha512-0Ndxo4qGhcewjTzw52TK06Mc00aDtHNTdeeW2JfONgDcLkRO/n/BteMRzNVpLQYxdCC/dFEilfM9fjjpGIJ9Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint/compat": "^1.1.1", + "find-up-simple": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "eslint": "^9.5.0" + } + }, "node_modules/@nuxt/kit": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.13.1.tgz", diff --git a/print/package.json b/print/package.json index 105a1ff076..e03615f5e7 100644 --- a/print/package.json +++ b/print/package.json @@ -34,7 +34,7 @@ "@eslint/eslintrc": "3.1.0", "@eslint/js": "9.9.1", "@nuxt/eslint": "0.5.6", - "@nuxt/eslint-config": "0.5.6", + "@nuxt/eslint-config": "0.5.7", "@nuxtjs/i18n": "8.5.3", "@nuxtjs/tailwindcss": "6.12.1", "@tailwindcss/typography": "0.5.15", From 81a6f006f1435e55cfcd2d03e59638a21b55b7ff Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 12:08:18 +0000 Subject: [PATCH 37/69] chore(deps): update dependency vite to v5.4.4 --- frontend/package-lock.json | 8 +-- frontend/package.json | 2 +- pdf/package-lock.json | 8 +-- pdf/package.json | 2 +- print/package-lock.json | 102 ++++--------------------------------- print/package.json | 2 +- 6 files changed, 21 insertions(+), 103 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 4173e42a9a..1cd42fd58b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -102,7 +102,7 @@ "prettier": "3.3.3", "sass": "1.32.13", "unplugin-vue-components": "0.27.4", - "vite": "5.4.3", + "vite": "5.4.4", "vite-plugin-comlink": "5.0.1", "vite-plugin-vue2-svg": "0.4.0", "vitest": "2.0.5", @@ -11900,9 +11900,9 @@ } }, "node_modules/vite": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.3.tgz", - "integrity": "sha512-IH+nl64eq9lJjFqU+/yrRnrHPVTlgy42/+IzbOdaFDVlyLgI/wDlf+FCobXLX1cT0X5+7LMyH1mIy2xJdLfo8Q==", + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.4.tgz", + "integrity": "sha512-RHFCkULitycHVTtelJ6jQLd+KSAAzOgEYorV32R2q++M6COBjKJR6BxqClwp5sf0XaBDjVMuJ9wnNfyAJwjMkA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/frontend/package.json b/frontend/package.json index 2c974fa0a9..38acb8d639 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -114,7 +114,7 @@ "prettier": "3.3.3", "sass": "1.32.13", "unplugin-vue-components": "0.27.4", - "vite": "5.4.3", + "vite": "5.4.4", "vite-plugin-comlink": "5.0.1", "vite-plugin-vue2-svg": "0.4.0", "vitest": "2.0.5", diff --git a/pdf/package-lock.json b/pdf/package-lock.json index e6e40a961f..6027046a9e 100644 --- a/pdf/package-lock.json +++ b/pdf/package-lock.json @@ -36,7 +36,7 @@ "jsdom": "25.0.0", "prettier": "3.3.3", "url-template": "3.1.1", - "vite": "5.4.3", + "vite": "5.4.4", "vitest": "2.0.5" }, "peerDependencies": { @@ -7716,9 +7716,9 @@ "license": "MIT" }, "node_modules/vite": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.3.tgz", - "integrity": "sha512-IH+nl64eq9lJjFqU+/yrRnrHPVTlgy42/+IzbOdaFDVlyLgI/wDlf+FCobXLX1cT0X5+7LMyH1mIy2xJdLfo8Q==", + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.4.tgz", + "integrity": "sha512-RHFCkULitycHVTtelJ6jQLd+KSAAzOgEYorV32R2q++M6COBjKJR6BxqClwp5sf0XaBDjVMuJ9wnNfyAJwjMkA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/pdf/package.json b/pdf/package.json index 519aea4bc8..3960a199e1 100644 --- a/pdf/package.json +++ b/pdf/package.json @@ -56,7 +56,7 @@ "jsdom": "25.0.0", "prettier": "3.3.3", "url-template": "3.1.1", - "vite": "5.4.3", + "vite": "5.4.4", "vitest": "2.0.5" } } diff --git a/print/package-lock.json b/print/package-lock.json index 075be875f7..126a3fcd10 100644 --- a/print/package-lock.json +++ b/print/package-lock.json @@ -25,7 +25,7 @@ "@eslint/eslintrc": "3.1.0", "@eslint/js": "9.9.1", "@nuxt/eslint": "0.5.6", - "@nuxt/eslint-config": "0.5.7", + "@nuxt/eslint-config": "0.5.6", "@nuxtjs/i18n": "8.5.3", "@nuxtjs/tailwindcss": "6.12.1", "@tailwindcss/typography": "0.5.15", @@ -2095,19 +2095,19 @@ } }, "node_modules/@nuxt/eslint-config": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@nuxt/eslint-config/-/eslint-config-0.5.7.tgz", - "integrity": "sha512-B+snO9NS9+v2657Z84tMbW3hLxjauIUkk2m4vnYjb9xfAFdoQwK07q6aaf7LzvagmVFmQiclT9LbJMvlRqzmsA==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@nuxt/eslint-config/-/eslint-config-0.5.6.tgz", + "integrity": "sha512-2kse94xvLW9SeENOAkGaksfff7vwRWsekbDsRjVoW2h3/95wRHWSenObUbGaW6Jr3D0o7DzyEIsaOvnWHZXvDg==", "dev": true, "license": "MIT", "dependencies": { - "@eslint/js": "^9.10.0", - "@nuxt/eslint-plugin": "0.5.7", - "@stylistic/eslint-plugin": "^2.8.0", - "@typescript-eslint/eslint-plugin": "^8.5.0", - "@typescript-eslint/parser": "^8.5.0", + "@eslint/js": "^9.9.1", + "@nuxt/eslint-plugin": "0.5.6", + "@stylistic/eslint-plugin": "^2.7.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", "eslint-config-flat-gitignore": "^0.3.0", - "eslint-flat-config-utils": "^0.4.0", + "eslint-flat-config-utils": "^0.3.1", "eslint-plugin-import-x": "^4.2.1", "eslint-plugin-jsdoc": "^50.2.2", "eslint-plugin-regexp": "^2.6.0", @@ -2122,30 +2122,6 @@ "eslint": "^8.57.0 || ^9.0.0" } }, - "node_modules/@nuxt/eslint-config/node_modules/@eslint/js": { - "version": "9.10.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz", - "integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@nuxt/eslint-config/node_modules/@nuxt/eslint-plugin": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@nuxt/eslint-plugin/-/eslint-plugin-0.5.7.tgz", - "integrity": "sha512-vYQYs/L87g2pBIoTmkk2mgYBqePTQDnhk87nGqsosKbfQ80xj9kkN3dsVb6BDQFk0zik4THWpXmnfjkvsjm/eg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "^8.5.0", - "@typescript-eslint/utils": "^8.5.0" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - } - }, "node_modules/@nuxt/eslint-config/node_modules/eslint-config-flat-gitignore": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/eslint-config-flat-gitignore/-/eslint-config-flat-gitignore-0.3.0.tgz", @@ -2163,19 +2139,6 @@ "eslint": "^9.5.0" } }, - "node_modules/@nuxt/eslint-config/node_modules/eslint-flat-config-utils": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/eslint-flat-config-utils/-/eslint-flat-config-utils-0.4.0.tgz", - "integrity": "sha512-kfd5kQZC+BMO0YwTol6zxjKX1zAsk8JfSAopbKjKqmENTJcew+yBejuvccAg37cvOrN0Mh+DVbeyznuNWEjt4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "pathe": "^1.1.2" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/@nuxt/eslint-plugin": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/@nuxt/eslint-plugin/-/eslint-plugin-0.5.6.tgz", @@ -2190,51 +2153,6 @@ "eslint": "^8.57.0 || ^9.0.0" } }, - "node_modules/@nuxt/eslint/node_modules/@nuxt/eslint-config": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@nuxt/eslint-config/-/eslint-config-0.5.6.tgz", - "integrity": "sha512-2kse94xvLW9SeENOAkGaksfff7vwRWsekbDsRjVoW2h3/95wRHWSenObUbGaW6Jr3D0o7DzyEIsaOvnWHZXvDg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint/js": "^9.9.1", - "@nuxt/eslint-plugin": "0.5.6", - "@stylistic/eslint-plugin": "^2.7.2", - "@typescript-eslint/eslint-plugin": "^8.4.0", - "@typescript-eslint/parser": "^8.4.0", - "eslint-config-flat-gitignore": "^0.3.0", - "eslint-flat-config-utils": "^0.3.1", - "eslint-plugin-import-x": "^4.2.1", - "eslint-plugin-jsdoc": "^50.2.2", - "eslint-plugin-regexp": "^2.6.0", - "eslint-plugin-unicorn": "^55.0.0", - "eslint-plugin-vue": "^9.28.0", - "globals": "^15.9.0", - "local-pkg": "^0.5.0", - "pathe": "^1.1.2", - "vue-eslint-parser": "^9.4.3" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - } - }, - "node_modules/@nuxt/eslint/node_modules/@nuxt/eslint-config/node_modules/eslint-config-flat-gitignore": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-flat-gitignore/-/eslint-config-flat-gitignore-0.3.0.tgz", - "integrity": "sha512-0Ndxo4qGhcewjTzw52TK06Mc00aDtHNTdeeW2JfONgDcLkRO/n/BteMRzNVpLQYxdCC/dFEilfM9fjjpGIJ9Og==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint/compat": "^1.1.1", - "find-up-simple": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "eslint": "^9.5.0" - } - }, "node_modules/@nuxt/kit": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.13.1.tgz", diff --git a/print/package.json b/print/package.json index e03615f5e7..105a1ff076 100644 --- a/print/package.json +++ b/print/package.json @@ -34,7 +34,7 @@ "@eslint/eslintrc": "3.1.0", "@eslint/js": "9.9.1", "@nuxt/eslint": "0.5.6", - "@nuxt/eslint-config": "0.5.7", + "@nuxt/eslint-config": "0.5.6", "@nuxtjs/i18n": "8.5.3", "@nuxtjs/tailwindcss": "6.12.1", "@tailwindcss/typography": "0.5.15", From c14562bf52eafa7e0d7f1c3a5a4a513680d75e97 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 12:13:17 +0000 Subject: [PATCH 38/69] chore(deps): update dependency @nuxt/eslint-config to v0.5.7 --- print/package-lock.json | 124 +++++++++------------------------------- print/package.json | 2 +- 2 files changed, 27 insertions(+), 99 deletions(-) diff --git a/print/package-lock.json b/print/package-lock.json index 7805b7568d..0b3cda8a7e 100644 --- a/print/package-lock.json +++ b/print/package-lock.json @@ -25,7 +25,7 @@ "@eslint/eslintrc": "3.1.0", "@eslint/js": "9.9.1", "@nuxt/eslint": "0.5.7", - "@nuxt/eslint-config": "0.5.6", + "@nuxt/eslint-config": "0.5.7", "@nuxtjs/i18n": "8.5.3", "@nuxtjs/tailwindcss": "6.12.1", "@tailwindcss/typography": "0.5.15", @@ -2095,90 +2095,6 @@ } }, "node_modules/@nuxt/eslint-config": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@nuxt/eslint-config/-/eslint-config-0.5.6.tgz", - "integrity": "sha512-2kse94xvLW9SeENOAkGaksfff7vwRWsekbDsRjVoW2h3/95wRHWSenObUbGaW6Jr3D0o7DzyEIsaOvnWHZXvDg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint/js": "^9.9.1", - "@nuxt/eslint-plugin": "0.5.6", - "@stylistic/eslint-plugin": "^2.7.2", - "@typescript-eslint/eslint-plugin": "^8.4.0", - "@typescript-eslint/parser": "^8.4.0", - "eslint-config-flat-gitignore": "^0.3.0", - "eslint-flat-config-utils": "^0.3.1", - "eslint-plugin-import-x": "^4.2.1", - "eslint-plugin-jsdoc": "^50.2.2", - "eslint-plugin-regexp": "^2.6.0", - "eslint-plugin-unicorn": "^55.0.0", - "eslint-plugin-vue": "^9.28.0", - "globals": "^15.9.0", - "local-pkg": "^0.5.0", - "pathe": "^1.1.2", - "vue-eslint-parser": "^9.4.3" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - } - }, - "node_modules/@nuxt/eslint-config/node_modules/eslint-config-flat-gitignore": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-flat-gitignore/-/eslint-config-flat-gitignore-0.3.0.tgz", - "integrity": "sha512-0Ndxo4qGhcewjTzw52TK06Mc00aDtHNTdeeW2JfONgDcLkRO/n/BteMRzNVpLQYxdCC/dFEilfM9fjjpGIJ9Og==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint/compat": "^1.1.1", - "find-up-simple": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "eslint": "^9.5.0" - } - }, - "node_modules/@nuxt/eslint-plugin": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@nuxt/eslint-plugin/-/eslint-plugin-0.5.6.tgz", - "integrity": "sha512-WgTcC4pGjbd8NCZpTYOOWnUWEncYV/rWJFeL5gyCXT+t36qkmWESrPLQ2NqBNaFLhoz6b/BFuOvMPVKg/q1T9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "^8.4.0", - "@typescript-eslint/utils": "^8.4.0" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - } - }, - "node_modules/@nuxt/eslint/node_modules/@eslint/js": { - "version": "9.10.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz", - "integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@nuxt/eslint/node_modules/@nuxt/devtools-kit": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@nuxt/devtools-kit/-/devtools-kit-1.4.2.tgz", - "integrity": "sha512-8a5PhVnC7E94318/sHbNSe9mI2MlsQ8+pJLGs2Hh1OJyidB9SWe6hoFc8q4K9VOtXak9uCFVb5V2JGXS1q+1aA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nuxt/kit": "^3.13.1", - "@nuxt/schema": "^3.13.1", - "execa": "^7.2.0" - }, - "peerDependencies": { - "vite": "*" - } - }, - "node_modules/@nuxt/eslint/node_modules/@nuxt/eslint-config": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@nuxt/eslint-config/-/eslint-config-0.5.7.tgz", "integrity": "sha512-B+snO9NS9+v2657Z84tMbW3hLxjauIUkk2m4vnYjb9xfAFdoQwK07q6aaf7LzvagmVFmQiclT9LbJMvlRqzmsA==", @@ -2206,7 +2122,17 @@ "eslint": "^8.57.0 || ^9.0.0" } }, - "node_modules/@nuxt/eslint/node_modules/@nuxt/eslint-config/node_modules/eslint-config-flat-gitignore": { + "node_modules/@nuxt/eslint-config/node_modules/@eslint/js": { + "version": "9.10.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz", + "integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@nuxt/eslint-config/node_modules/eslint-config-flat-gitignore": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/eslint-config-flat-gitignore/-/eslint-config-flat-gitignore-0.3.0.tgz", "integrity": "sha512-0Ndxo4qGhcewjTzw52TK06Mc00aDtHNTdeeW2JfONgDcLkRO/n/BteMRzNVpLQYxdCC/dFEilfM9fjjpGIJ9Og==", @@ -2223,7 +2149,7 @@ "eslint": "^9.5.0" } }, - "node_modules/@nuxt/eslint/node_modules/@nuxt/eslint-plugin": { + "node_modules/@nuxt/eslint-plugin": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@nuxt/eslint-plugin/-/eslint-plugin-0.5.7.tgz", "integrity": "sha512-vYQYs/L87g2pBIoTmkk2mgYBqePTQDnhk87nGqsosKbfQ80xj9kkN3dsVb6BDQFk0zik4THWpXmnfjkvsjm/eg==", @@ -2237,17 +2163,19 @@ "eslint": "^8.57.0 || ^9.0.0" } }, - "node_modules/@nuxt/eslint/node_modules/eslint-flat-config-utils": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/eslint-flat-config-utils/-/eslint-flat-config-utils-0.4.0.tgz", - "integrity": "sha512-kfd5kQZC+BMO0YwTol6zxjKX1zAsk8JfSAopbKjKqmENTJcew+yBejuvccAg37cvOrN0Mh+DVbeyznuNWEjt4A==", + "node_modules/@nuxt/eslint/node_modules/@nuxt/devtools-kit": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@nuxt/devtools-kit/-/devtools-kit-1.4.2.tgz", + "integrity": "sha512-8a5PhVnC7E94318/sHbNSe9mI2MlsQ8+pJLGs2Hh1OJyidB9SWe6hoFc8q4K9VOtXak9uCFVb5V2JGXS1q+1aA==", "dev": true, "license": "MIT", "dependencies": { - "pathe": "^1.1.2" + "@nuxt/kit": "^3.13.1", + "@nuxt/schema": "^3.13.1", + "execa": "^7.2.0" }, - "funding": { - "url": "https://github.com/sponsors/antfu" + "peerDependencies": { + "vite": "*" } }, "node_modules/@nuxt/kit": { @@ -4536,6 +4464,7 @@ "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -7866,13 +7795,12 @@ } }, "node_modules/eslint-flat-config-utils": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/eslint-flat-config-utils/-/eslint-flat-config-utils-0.3.1.tgz", - "integrity": "sha512-eFT3EaoJN1hlN97xw4FIEX//h0TiFUobgl2l5uLkIwhVN9ahGq95Pbs+i1/B5UACA78LO3rco3JzuvxLdTUOPA==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/eslint-flat-config-utils/-/eslint-flat-config-utils-0.4.0.tgz", + "integrity": "sha512-kfd5kQZC+BMO0YwTol6zxjKX1zAsk8JfSAopbKjKqmENTJcew+yBejuvccAg37cvOrN0Mh+DVbeyznuNWEjt4A==", "dev": true, "license": "MIT", "dependencies": { - "@types/eslint": "^9.6.0", "pathe": "^1.1.2" }, "funding": { diff --git a/print/package.json b/print/package.json index 129810dace..f4f19cee35 100644 --- a/print/package.json +++ b/print/package.json @@ -34,7 +34,7 @@ "@eslint/eslintrc": "3.1.0", "@eslint/js": "9.9.1", "@nuxt/eslint": "0.5.7", - "@nuxt/eslint-config": "0.5.6", + "@nuxt/eslint-config": "0.5.7", "@nuxtjs/i18n": "8.5.3", "@nuxtjs/tailwindcss": "6.12.1", "@tailwindcss/typography": "0.5.15", From c5b748786ee71dc342c436f94bf6830431025456 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:33:16 +0000 Subject: [PATCH 39/69] chore(deps): update dependency vite-plugin-eslint2 to v4.4.1 --- print/package-lock.json | 14 +++++++++----- print/package.json | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/print/package-lock.json b/print/package-lock.json index 0b3cda8a7e..5078e96837 100644 --- a/print/package-lock.json +++ b/print/package-lock.json @@ -47,7 +47,7 @@ "nuxt": "3.13.1", "prettier": "3.3.3", "sass": "1.69.4", - "vite-plugin-eslint2": "4.4.0", + "vite-plugin-eslint2": "4.4.1", "vite-svg-loader": "5.1.0", "vitest": "2.0.5", "vue": "3.5.3" @@ -4464,6 +4464,7 @@ "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "dev": true, "license": "MIT", + "optional": true, "peer": true, "dependencies": { "@types/estree": "*", @@ -17247,15 +17248,15 @@ } }, "node_modules/vite-plugin-eslint2": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/vite-plugin-eslint2/-/vite-plugin-eslint2-4.4.0.tgz", - "integrity": "sha512-xy5G4Gj18ke1bO5OS0zgyunkPvPy/vSLJFTyMpGmKGKTlYuuhPad3Xy1PWLuqRMoWnuCoFMf2ST1EGhz89uqrA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/vite-plugin-eslint2/-/vite-plugin-eslint2-4.4.1.tgz", + "integrity": "sha512-z0Eu/d+VeeVNrnFG8QqQbGlWxrXi8JQvO79OVWX4t6nBHUWxCBHLqev1CYQDPzd+50vs9e2MHaBhcNpNE7D1bQ==", "dev": true, "license": "MIT", "dependencies": { "@rollup/pluginutils": "^5.1.0", "chokidar": "^3.6.0", - "debug": "^4.3.4" + "debug": "^4.3.7" }, "engines": { "node": ">=18" @@ -17267,6 +17268,9 @@ "vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" }, "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, "rollup": { "optional": true } diff --git a/print/package.json b/print/package.json index f4f19cee35..9afb019d2c 100644 --- a/print/package.json +++ b/print/package.json @@ -56,7 +56,7 @@ "nuxt": "3.13.1", "prettier": "3.3.3", "sass": "1.69.4", - "vite-plugin-eslint2": "4.4.0", + "vite-plugin-eslint2": "4.4.1", "vite-svg-loader": "5.1.0", "vitest": "2.0.5", "vue": "3.5.3" From f5e05f8e55f06a3511a2398021511c1ede343de2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:54:24 +0000 Subject: [PATCH 40/69] chore(deps): update docker/dockerfile docker tag to v1.10 --- api/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/Dockerfile b/api/Dockerfile index aebbdc1627..9052915aec 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -1,4 +1,4 @@ -#syntax=docker/dockerfile:1.9 +#syntax=docker/dockerfile:1.10 # Adapted from https://github.com/api-platform/api-platform/blob/fa1c5808305d7cadbf7b8392e0fddb6e80fb2092/api/Dockerfile From b2c73b15e955dab31fe6fc60f4a48f1c57ef1290 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 22:16:07 +0000 Subject: [PATCH 41/69] chore(deps): update amazon/aws-cli docker tag to v2.17.49 --- .ops/aws-setup/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ops/aws-setup/docker-compose.yml b/.ops/aws-setup/docker-compose.yml index a7f40800ad..2f3d83cba8 100644 --- a/.ops/aws-setup/docker-compose.yml +++ b/.ops/aws-setup/docker-compose.yml @@ -13,7 +13,7 @@ services: - AWS_DEFAULT_REGION=eu-west-3 aws-cli: - image: amazon/aws-cli:2.17.48 + image: amazon/aws-cli:2.17.49 container_name: 'ecamp3-aws-cli' volumes: - ./.aws:/root/.aws:delegated From 31507921f898e3926b1ad5d848be6f910e4155d6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 12 Sep 2024 01:25:15 +0000 Subject: [PATCH 42/69] chore(deps): update pulumi/pulumi-nodejs docker tag to v3.132.0 --- .ops/aws-setup/docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ops/aws-setup/docker-compose.yml b/.ops/aws-setup/docker-compose.yml index 2f3d83cba8..a4cc5bf7bd 100644 --- a/.ops/aws-setup/docker-compose.yml +++ b/.ops/aws-setup/docker-compose.yml @@ -1,6 +1,6 @@ services: aws-setup: - image: pulumi/pulumi-nodejs:3.131.0 + image: pulumi/pulumi-nodejs:3.132.0 container_name: 'ecamp3-aws-setup' volumes: - ../../.prettierrc:/.prettierrc:delegated @@ -13,7 +13,7 @@ services: - AWS_DEFAULT_REGION=eu-west-3 aws-cli: - image: amazon/aws-cli:2.17.49 + image: amazon/aws-cli:2.17.48 container_name: 'ecamp3-aws-cli' volumes: - ./.aws:/root/.aws:delegated From 616ee84afc7ab302fecbd5bda3abcae7e2b042bd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 12 Sep 2024 01:25:33 +0000 Subject: [PATCH 43/69] fix(deps): update dependency @pulumi/pulumi to v3.132.0 --- .ops/aws-setup/docker-compose.yml | 2 +- .ops/aws-setup/package-lock.json | 8 ++++---- .ops/aws-setup/package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.ops/aws-setup/docker-compose.yml b/.ops/aws-setup/docker-compose.yml index 2f3d83cba8..a7f40800ad 100644 --- a/.ops/aws-setup/docker-compose.yml +++ b/.ops/aws-setup/docker-compose.yml @@ -13,7 +13,7 @@ services: - AWS_DEFAULT_REGION=eu-west-3 aws-cli: - image: amazon/aws-cli:2.17.49 + image: amazon/aws-cli:2.17.48 container_name: 'ecamp3-aws-cli' volumes: - ./.aws:/root/.aws:delegated diff --git a/.ops/aws-setup/package-lock.json b/.ops/aws-setup/package-lock.json index 17a90cf614..c30e136955 100644 --- a/.ops/aws-setup/package-lock.json +++ b/.ops/aws-setup/package-lock.json @@ -8,7 +8,7 @@ "dependencies": { "@pulumi/aws": "6.51.0", "@pulumi/awsx": "2.14.0", - "@pulumi/pulumi": "3.131.0" + "@pulumi/pulumi": "3.132.0" }, "devDependencies": { "@babel/eslint-parser": "7.25.1", @@ -2074,9 +2074,9 @@ } }, "node_modules/@pulumi/pulumi": { - "version": "3.131.0", - "resolved": "https://registry.npmjs.org/@pulumi/pulumi/-/pulumi-3.131.0.tgz", - "integrity": "sha512-QNtQeav3dkU0mRdMe2TVvkBmIGkBevVvbD7/bt0fJlGoX/onzv5tysqi1GWCkXsq0FKtBtGYNpVD6wH0cqMN6g==", + "version": "3.132.0", + "resolved": "https://registry.npmjs.org/@pulumi/pulumi/-/pulumi-3.132.0.tgz", + "integrity": "sha512-ntsEo17gALvRdkfKMFrf7EEWrfPHPuRHG/96ziVSItYHofwMLtMk2f7BoRqOSYq3B08wHRkz6J15IUrT9l9wuQ==", "license": "Apache-2.0", "dependencies": { "@grpc/grpc-js": "^1.10.1", diff --git a/.ops/aws-setup/package.json b/.ops/aws-setup/package.json index 1b148233f2..eddfa90735 100644 --- a/.ops/aws-setup/package.json +++ b/.ops/aws-setup/package.json @@ -10,7 +10,7 @@ "lint:check:prettier": "prettier --check --ignore-path .prettierignore **/*.{json,md,mjs,ts}" }, "dependencies": { - "@pulumi/pulumi": "3.131.0", + "@pulumi/pulumi": "3.132.0", "@pulumi/aws": "6.51.0", "@pulumi/awsx": "2.14.0" }, From b1154ca33d8937d69ed932dade0842124f749f00 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 12 Sep 2024 10:19:53 +0000 Subject: [PATCH 44/69] fix(deps): update dependency @pulumi/aws to v6.51.1 --- .ops/aws-setup/package-lock.json | 8 ++++---- .ops/aws-setup/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.ops/aws-setup/package-lock.json b/.ops/aws-setup/package-lock.json index c30e136955..3e8a71d146 100644 --- a/.ops/aws-setup/package-lock.json +++ b/.ops/aws-setup/package-lock.json @@ -6,7 +6,7 @@ "": { "name": "ecamp-core", "dependencies": { - "@pulumi/aws": "6.51.0", + "@pulumi/aws": "6.51.1", "@pulumi/awsx": "2.14.0", "@pulumi/pulumi": "3.132.0" }, @@ -2026,9 +2026,9 @@ "license": "BSD-3-Clause" }, "node_modules/@pulumi/aws": { - "version": "6.51.0", - "resolved": "https://registry.npmjs.org/@pulumi/aws/-/aws-6.51.0.tgz", - "integrity": "sha512-t2aduFqp8CVZ5axGbBGwKZUjMb8y3YC1iVLgaW5wh/eHW2AYEgz9u+weqkte5c43v16QIfV15bXBy6j/fkVQOg==", + "version": "6.51.1", + "resolved": "https://registry.npmjs.org/@pulumi/aws/-/aws-6.51.1.tgz", + "integrity": "sha512-rsOcRkt5/yDUs8e1QohowNEwM1OHf0eRyD/vp2n0w6TBoKZUzPpIwPic8LF3ysWfa2GmB2ylxQ+lSQ5813Ut0w==", "license": "Apache-2.0", "dependencies": { "@pulumi/pulumi": "^3.0.0", diff --git a/.ops/aws-setup/package.json b/.ops/aws-setup/package.json index eddfa90735..3a41ab64e0 100644 --- a/.ops/aws-setup/package.json +++ b/.ops/aws-setup/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "@pulumi/pulumi": "3.132.0", - "@pulumi/aws": "6.51.0", + "@pulumi/aws": "6.51.1", "@pulumi/awsx": "2.14.0" }, "devDependencies": { From 35adecf22647f392c4e3cb6c2194bc619a619e7d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 12 Sep 2024 16:35:28 +0000 Subject: [PATCH 45/69] chore(deps): update vitest monorepo to v2.1.0 --- frontend/package-lock.json | 179 +++++++++++++-------- frontend/package.json | 4 +- pdf/package-lock.json | 307 +++++++++++++------------------------ pdf/package.json | 4 +- print/package-lock.json | 209 ++++++++++++------------- print/package.json | 4 +- 6 files changed, 318 insertions(+), 389 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 006d8965e5..205f405383 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -80,7 +80,7 @@ "@testing-library/user-event": "14.5.2", "@testing-library/vue": "5.9.0", "@vitejs/plugin-vue2": "2.3.1", - "@vitest/coverage-v8": "2.0.5", + "@vitest/coverage-v8": "2.1.0", "@vue/babel-preset-app": "5.0.8", "@vue/eslint-config-prettier": "9.0.0", "@vue/test-utils": "1.3.6", @@ -105,7 +105,7 @@ "vite": "5.4.4", "vite-plugin-comlink": "5.0.1", "vite-plugin-vue2-svg": "0.4.0", - "vitest": "2.0.5", + "vitest": "2.1.0", "vitest-canvas-mock": "0.3.3", "vue-template-compiler": "2.7.15" } @@ -4273,20 +4273,20 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.0.5.tgz", - "integrity": "sha512-qeFcySCg5FLO2bHHSa0tAZAOnAUbp4L6/A5JDuj9+bt53JREl8hpLjLHEWF0e/gWc8INVpJaqA7+Ene2rclpZg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.0.tgz", + "integrity": "sha512-yqCkr2nrV4o58VcVMxTVkS6Ggxzy7pmSD8JbTbhbH5PsQfUIES1QT716VUzo33wf2lX9EcWYdT3Vl2MMmjR59g==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", "@bcoe/v8-coverage": "^0.2.3", - "debug": "^4.3.5", + "debug": "^4.3.6", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-lib-source-maps": "^5.0.6", "istanbul-reports": "^3.1.7", - "magic-string": "^0.30.10", + "magic-string": "^0.30.11", "magicast": "^0.3.4", "std-env": "^3.7.0", "test-exclude": "^7.0.1", @@ -4296,7 +4296,13 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "2.0.5" + "@vitest/browser": "2.1.0", + "vitest": "2.1.0" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } } }, "node_modules/@vitest/coverage-v8/node_modules/magic-string": { @@ -4310,14 +4316,14 @@ } }, "node_modules/@vitest/expect": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.0.5.tgz", - "integrity": "sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.0.tgz", + "integrity": "sha512-N3/xR4fSu0+6sVZETEtPT1orUs2+Y477JOXTcU3xKuu3uBlsgbD7/7Mz2LZ1Jr1XjwilEWlrIgSCj4N1+5ZmsQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.0.5", - "@vitest/utils": "2.0.5", + "@vitest/spy": "2.1.0", + "@vitest/utils": "2.1.0", "chai": "^5.1.1", "tinyrainbow": "^1.2.0" }, @@ -4325,10 +4331,58 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/mocker": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.0.tgz", + "integrity": "sha512-ZxENovUqhzl+QiOFpagiHUNUuZ1qPd5yYTCYHomGIZOFArzn4mgX2oxZmiAItJWAaXHG6bbpb/DpSPhlk5DgtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "^2.1.0-beta.1", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.11" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/spy": "2.1.0", + "msw": "^2.3.5", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/mocker/node_modules/magic-string": { + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, "node_modules/@vitest/pretty-format": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.0.5.tgz", - "integrity": "sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.0.tgz", + "integrity": "sha512-7sxf2F3DNYatgmzXXcTh6cq+/fxwB47RIQqZJFoSH883wnVAoccSRT6g+dTKemUBo8Q5N4OYYj1EBXLuRKvp3Q==", "dev": true, "license": "MIT", "dependencies": { @@ -4339,13 +4393,13 @@ } }, "node_modules/@vitest/runner": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.0.5.tgz", - "integrity": "sha512-TfRfZa6Bkk9ky4tW0z20WKXFEwwvWhRY+84CnSEtq4+3ZvDlJyY32oNTJtM7AW9ihW90tX/1Q78cb6FjoAs+ig==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.0.tgz", + "integrity": "sha512-D9+ZiB8MbMt7qWDRJc4CRNNUlne/8E1X7dcKhZVAbcOKG58MGGYVDqAq19xlhNfMFZsW0bpVKgztBwks38Ko0w==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.0.5", + "@vitest/utils": "2.1.0", "pathe": "^1.1.2" }, "funding": { @@ -4353,14 +4407,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.0.5.tgz", - "integrity": "sha512-SgCPUeDFLaM0mIUHfaArq8fD2WbaXG/zVXjRupthYfYGzc8ztbFbu6dUNOblBG7XLMR1kEhS/DNnfCZ2IhdDew==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.0.tgz", + "integrity": "sha512-x69CygGMzt9VCO283K2/FYQ+nBrOj66OTKpsPykjCR4Ac3lLV+m85hj9reaIGmjBSsKzVvbxWmjWE3kF5ha3uQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.0.5", - "magic-string": "^0.30.10", + "@vitest/pretty-format": "2.1.0", + "magic-string": "^0.30.11", "pathe": "^1.1.2" }, "funding": { @@ -4378,9 +4432,9 @@ } }, "node_modules/@vitest/spy": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.0.5.tgz", - "integrity": "sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.0.tgz", + "integrity": "sha512-IXX5NkbdgTYTog3F14i2LgnBc+20YmkXMx0IWai84mcxySUDRgm0ihbOfR4L0EVRBDFG85GjmQQEZNNKVVpkZw==", "dev": true, "license": "MIT", "dependencies": { @@ -4391,14 +4445,13 @@ } }, "node_modules/@vitest/utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.0.5.tgz", - "integrity": "sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.0.tgz", + "integrity": "sha512-rreyfVe0PuNqJfKYUwfPDfi6rrp0VSu0Wgvp5WBqJonP+4NvXHk48X6oBam1Lj47Hy6jbJtnMj3OcRdrkTP0tA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.0.5", - "estree-walker": "^3.0.3", + "@vitest/pretty-format": "2.1.0", "loupe": "^3.1.1", "tinyrainbow": "^1.2.0" }, @@ -4406,16 +4459,6 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/utils/node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, "node_modules/@vue/babel-helper-vue-jsx-merge-props": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.4.0.tgz", @@ -11411,6 +11454,13 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyexec": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz", + "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", + "dev": true, + "license": "MIT" + }, "node_modules/tinypool": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", @@ -11974,16 +12024,15 @@ } }, "node_modules/vite-node": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.0.5.tgz", - "integrity": "sha512-LdsW4pxj0Ot69FAoXZ1yTnA9bjGohr2yNBU7QKRxpz8ITSkhuDl6h3zS/tvgz4qrNjeRnvrWeXQ8ZF7Um4W00Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.0.tgz", + "integrity": "sha512-+ybYqBVUjYyIscoLzMWodus2enQDZOpGhcU6HdOVD6n8WZdk12w1GFL3mbnxLs7hPtRtqs1Wo5YF6/Tsr6fmhg==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", - "debug": "^4.3.5", + "debug": "^4.3.6", "pathe": "^1.1.2", - "tinyrainbow": "^1.2.0", "vite": "^5.0.0" }, "bin": { @@ -12037,30 +12086,30 @@ } }, "node_modules/vitest": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.0.5.tgz", - "integrity": "sha512-8GUxONfauuIdeSl5f9GTgVEpg5BTOlplET4WEDaeY2QBiN8wSm68vxN/tb5z405OwppfoCavnwXafiaYBC/xOA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.0.tgz", + "integrity": "sha512-XuuEeyNkqbfr0FtAvd9vFbInSSNY1ykCQTYQ0sj9wPy4hx+1gR7gqVNdW0AX2wrrM1wWlN5fnJDjF9xG6mYRSQ==", "dev": true, "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.3.0", - "@vitest/expect": "2.0.5", - "@vitest/pretty-format": "^2.0.5", - "@vitest/runner": "2.0.5", - "@vitest/snapshot": "2.0.5", - "@vitest/spy": "2.0.5", - "@vitest/utils": "2.0.5", + "@vitest/expect": "2.1.0", + "@vitest/mocker": "2.1.0", + "@vitest/pretty-format": "^2.1.0", + "@vitest/runner": "2.1.0", + "@vitest/snapshot": "2.1.0", + "@vitest/spy": "2.1.0", + "@vitest/utils": "2.1.0", "chai": "^5.1.1", - "debug": "^4.3.5", - "execa": "^8.0.1", - "magic-string": "^0.30.10", + "debug": "^4.3.6", + "magic-string": "^0.30.11", "pathe": "^1.1.2", "std-env": "^3.7.0", - "tinybench": "^2.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.0", "tinypool": "^1.0.0", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "2.0.5", + "vite-node": "2.1.0", "why-is-node-running": "^2.3.0" }, "bin": { @@ -12075,8 +12124,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.0.5", - "@vitest/ui": "2.0.5", + "@vitest/browser": "2.1.0", + "@vitest/ui": "2.1.0", "happy-dom": "*", "jsdom": "*" }, diff --git a/frontend/package.json b/frontend/package.json index 6ff6facaca..aece11a95f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -92,7 +92,7 @@ "@testing-library/user-event": "14.5.2", "@testing-library/vue": "5.9.0", "@vitejs/plugin-vue2": "2.3.1", - "@vitest/coverage-v8": "2.0.5", + "@vitest/coverage-v8": "2.1.0", "@vue/babel-preset-app": "5.0.8", "@vue/eslint-config-prettier": "9.0.0", "@vue/test-utils": "1.3.6", @@ -117,7 +117,7 @@ "vite": "5.4.4", "vite-plugin-comlink": "5.0.1", "vite-plugin-vue2-svg": "0.4.0", - "vitest": "2.0.5", + "vitest": "2.1.0", "vitest-canvas-mock": "0.3.3", "vue-template-compiler": "2.7.15" }, diff --git a/pdf/package-lock.json b/pdf/package-lock.json index 6027046a9e..2369ad000b 100644 --- a/pdf/package-lock.json +++ b/pdf/package-lock.json @@ -18,7 +18,7 @@ "@intlify/core": "^9.10.2", "@rushstack/eslint-patch": "1.10.4", "@vitejs/plugin-vue": "5.1.3", - "@vitest/coverage-v8": "2.0.5", + "@vitest/coverage-v8": "2.1.0", "@vue/babel-preset-app": "5.0.8", "@vue/compiler-dom": "3.5.3", "@vue/compiler-sfc": "3.5.3", @@ -37,7 +37,7 @@ "prettier": "3.3.3", "url-template": "3.1.1", "vite": "5.4.4", - "vitest": "2.0.5" + "vitest": "2.1.0" }, "peerDependencies": { "@react-pdf/font": "2.5.1", @@ -3155,20 +3155,20 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.0.5.tgz", - "integrity": "sha512-qeFcySCg5FLO2bHHSa0tAZAOnAUbp4L6/A5JDuj9+bt53JREl8hpLjLHEWF0e/gWc8INVpJaqA7+Ene2rclpZg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.0.tgz", + "integrity": "sha512-yqCkr2nrV4o58VcVMxTVkS6Ggxzy7pmSD8JbTbhbH5PsQfUIES1QT716VUzo33wf2lX9EcWYdT3Vl2MMmjR59g==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", "@bcoe/v8-coverage": "^0.2.3", - "debug": "^4.3.5", + "debug": "^4.3.6", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-lib-source-maps": "^5.0.6", "istanbul-reports": "^3.1.7", - "magic-string": "^0.30.10", + "magic-string": "^0.30.11", "magicast": "^0.3.4", "std-env": "^3.7.0", "test-exclude": "^7.0.1", @@ -3178,18 +3178,24 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "2.0.5" + "@vitest/browser": "2.1.0", + "vitest": "2.1.0" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } } }, "node_modules/@vitest/expect": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.0.5.tgz", - "integrity": "sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.0.tgz", + "integrity": "sha512-N3/xR4fSu0+6sVZETEtPT1orUs2+Y477JOXTcU3xKuu3uBlsgbD7/7Mz2LZ1Jr1XjwilEWlrIgSCj4N1+5ZmsQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.0.5", - "@vitest/utils": "2.0.5", + "@vitest/spy": "2.1.0", + "@vitest/utils": "2.1.0", "chai": "^5.1.1", "tinyrainbow": "^1.2.0" }, @@ -3197,10 +3203,48 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/mocker": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.0.tgz", + "integrity": "sha512-ZxENovUqhzl+QiOFpagiHUNUuZ1qPd5yYTCYHomGIZOFArzn4mgX2oxZmiAItJWAaXHG6bbpb/DpSPhlk5DgtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "^2.1.0-beta.1", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.11" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/spy": "2.1.0", + "msw": "^2.3.5", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/@vitest/pretty-format": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.0.5.tgz", - "integrity": "sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.0.tgz", + "integrity": "sha512-7sxf2F3DNYatgmzXXcTh6cq+/fxwB47RIQqZJFoSH883wnVAoccSRT6g+dTKemUBo8Q5N4OYYj1EBXLuRKvp3Q==", "dev": true, "license": "MIT", "dependencies": { @@ -3211,13 +3255,13 @@ } }, "node_modules/@vitest/runner": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.0.5.tgz", - "integrity": "sha512-TfRfZa6Bkk9ky4tW0z20WKXFEwwvWhRY+84CnSEtq4+3ZvDlJyY32oNTJtM7AW9ihW90tX/1Q78cb6FjoAs+ig==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.0.tgz", + "integrity": "sha512-D9+ZiB8MbMt7qWDRJc4CRNNUlne/8E1X7dcKhZVAbcOKG58MGGYVDqAq19xlhNfMFZsW0bpVKgztBwks38Ko0w==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.0.5", + "@vitest/utils": "2.1.0", "pathe": "^1.1.2" }, "funding": { @@ -3225,14 +3269,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.0.5.tgz", - "integrity": "sha512-SgCPUeDFLaM0mIUHfaArq8fD2WbaXG/zVXjRupthYfYGzc8ztbFbu6dUNOblBG7XLMR1kEhS/DNnfCZ2IhdDew==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.0.tgz", + "integrity": "sha512-x69CygGMzt9VCO283K2/FYQ+nBrOj66OTKpsPykjCR4Ac3lLV+m85hj9reaIGmjBSsKzVvbxWmjWE3kF5ha3uQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.0.5", - "magic-string": "^0.30.10", + "@vitest/pretty-format": "2.1.0", + "magic-string": "^0.30.11", "pathe": "^1.1.2" }, "funding": { @@ -3240,9 +3284,9 @@ } }, "node_modules/@vitest/spy": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.0.5.tgz", - "integrity": "sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.0.tgz", + "integrity": "sha512-IXX5NkbdgTYTog3F14i2LgnBc+20YmkXMx0IWai84mcxySUDRgm0ihbOfR4L0EVRBDFG85GjmQQEZNNKVVpkZw==", "dev": true, "license": "MIT", "dependencies": { @@ -3253,14 +3297,13 @@ } }, "node_modules/@vitest/utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.0.5.tgz", - "integrity": "sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.0.tgz", + "integrity": "sha512-rreyfVe0PuNqJfKYUwfPDfi6rrp0VSu0Wgvp5WBqJonP+4NvXHk48X6oBam1Lj47Hy6jbJtnMj3OcRdrkTP0tA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.0.5", - "estree-walker": "^3.0.3", + "@vitest/pretty-format": "2.1.0", "loupe": "^3.1.1", "tinyrainbow": "^1.2.0" }, @@ -3268,16 +3311,6 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/utils/node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, "node_modules/@vue/babel-helper-vue-jsx-merge-props": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.4.0.tgz", @@ -5064,30 +5097,6 @@ "node": ">=0.10.0" } }, - "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -5299,19 +5308,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -5570,16 +5566,6 @@ "node": ">= 14" } }, - "node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=16.17.0" - } - }, "node_modules/hyphen": { "version": "1.10.4", "resolved": "https://registry.npmjs.org/hyphen/-/hyphen-1.10.4.tgz", @@ -5735,19 +5721,6 @@ "dev": true, "license": "MIT" }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-url": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", @@ -6160,13 +6133,6 @@ "license": "MIT", "peer": true }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -6190,19 +6156,6 @@ "node": ">= 0.6" } }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -6338,35 +6291,6 @@ "svg-arc-to-cubic-bezier": "^3.0.0" } }, - "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -6426,22 +6350,6 @@ "wrappy": "1" } }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -7312,19 +7220,6 @@ "node": ">=8" } }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -7463,6 +7358,13 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyexec": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz", + "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", + "dev": true, + "license": "MIT" + }, "node_modules/tinypool": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", @@ -7791,16 +7693,15 @@ } }, "node_modules/vite-node": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.0.5.tgz", - "integrity": "sha512-LdsW4pxj0Ot69FAoXZ1yTnA9bjGohr2yNBU7QKRxpz8ITSkhuDl6h3zS/tvgz4qrNjeRnvrWeXQ8ZF7Um4W00Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.0.tgz", + "integrity": "sha512-+ybYqBVUjYyIscoLzMWodus2enQDZOpGhcU6HdOVD6n8WZdk12w1GFL3mbnxLs7hPtRtqs1Wo5YF6/Tsr6fmhg==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", - "debug": "^4.3.5", + "debug": "^4.3.6", "pathe": "^1.1.2", - "tinyrainbow": "^1.2.0", "vite": "^5.0.0" }, "bin": { @@ -7814,30 +7715,30 @@ } }, "node_modules/vitest": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.0.5.tgz", - "integrity": "sha512-8GUxONfauuIdeSl5f9GTgVEpg5BTOlplET4WEDaeY2QBiN8wSm68vxN/tb5z405OwppfoCavnwXafiaYBC/xOA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.0.tgz", + "integrity": "sha512-XuuEeyNkqbfr0FtAvd9vFbInSSNY1ykCQTYQ0sj9wPy4hx+1gR7gqVNdW0AX2wrrM1wWlN5fnJDjF9xG6mYRSQ==", "dev": true, "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.3.0", - "@vitest/expect": "2.0.5", - "@vitest/pretty-format": "^2.0.5", - "@vitest/runner": "2.0.5", - "@vitest/snapshot": "2.0.5", - "@vitest/spy": "2.0.5", - "@vitest/utils": "2.0.5", + "@vitest/expect": "2.1.0", + "@vitest/mocker": "2.1.0", + "@vitest/pretty-format": "^2.1.0", + "@vitest/runner": "2.1.0", + "@vitest/snapshot": "2.1.0", + "@vitest/spy": "2.1.0", + "@vitest/utils": "2.1.0", "chai": "^5.1.1", - "debug": "^4.3.5", - "execa": "^8.0.1", - "magic-string": "^0.30.10", + "debug": "^4.3.6", + "magic-string": "^0.30.11", "pathe": "^1.1.2", "std-env": "^3.7.0", - "tinybench": "^2.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.0", "tinypool": "^1.0.0", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "2.0.5", + "vite-node": "2.1.0", "why-is-node-running": "^2.3.0" }, "bin": { @@ -7852,8 +7753,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.0.5", - "@vitest/ui": "2.0.5", + "@vitest/browser": "2.1.0", + "@vitest/ui": "2.1.0", "happy-dom": "*", "jsdom": "*" }, diff --git a/pdf/package.json b/pdf/package.json index 3960a199e1..533220ae4d 100644 --- a/pdf/package.json +++ b/pdf/package.json @@ -38,7 +38,7 @@ "@intlify/core": "^9.10.2", "@rushstack/eslint-patch": "1.10.4", "@vitejs/plugin-vue": "5.1.3", - "@vitest/coverage-v8": "2.0.5", + "@vitest/coverage-v8": "2.1.0", "@vue/babel-preset-app": "5.0.8", "@vue/compiler-dom": "3.5.3", "@vue/compiler-sfc": "3.5.3", @@ -57,6 +57,6 @@ "prettier": "3.3.3", "url-template": "3.1.1", "vite": "5.4.4", - "vitest": "2.0.5" + "vitest": "2.1.0" } } diff --git a/print/package-lock.json b/print/package-lock.json index 670fde2c9b..8309b7578a 100644 --- a/print/package-lock.json +++ b/print/package-lock.json @@ -30,7 +30,7 @@ "@nuxtjs/tailwindcss": "6.12.1", "@tailwindcss/typography": "0.5.15", "@typescript-eslint/eslint-plugin": "8.5.0", - "@vitest/coverage-v8": "2.0.5", + "@vitest/coverage-v8": "2.1.0", "@vue/compiler-dom": "3.5.3", "@vue/compiler-sfc": "3.5.3", "@vue/runtime-dom": "3.5.3", @@ -49,7 +49,7 @@ "sass": "1.69.4", "vite-plugin-eslint2": "4.4.1", "vite-svg-loader": "5.1.0", - "vitest": "2.0.5", + "vitest": "2.1.0", "vue": "3.5.3" } }, @@ -5025,20 +5025,20 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.0.5.tgz", - "integrity": "sha512-qeFcySCg5FLO2bHHSa0tAZAOnAUbp4L6/A5JDuj9+bt53JREl8hpLjLHEWF0e/gWc8INVpJaqA7+Ene2rclpZg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.0.tgz", + "integrity": "sha512-yqCkr2nrV4o58VcVMxTVkS6Ggxzy7pmSD8JbTbhbH5PsQfUIES1QT716VUzo33wf2lX9EcWYdT3Vl2MMmjR59g==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", "@bcoe/v8-coverage": "^0.2.3", - "debug": "^4.3.5", + "debug": "^4.3.6", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-lib-source-maps": "^5.0.6", "istanbul-reports": "^3.1.7", - "magic-string": "^0.30.10", + "magic-string": "^0.30.11", "magicast": "^0.3.4", "std-env": "^3.7.0", "test-exclude": "^7.0.1", @@ -5048,18 +5048,24 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "2.0.5" + "@vitest/browser": "2.1.0", + "vitest": "2.1.0" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } } }, "node_modules/@vitest/expect": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.0.5.tgz", - "integrity": "sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.0.tgz", + "integrity": "sha512-N3/xR4fSu0+6sVZETEtPT1orUs2+Y477JOXTcU3xKuu3uBlsgbD7/7Mz2LZ1Jr1XjwilEWlrIgSCj4N1+5ZmsQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.0.5", - "@vitest/utils": "2.0.5", + "@vitest/spy": "2.1.0", + "@vitest/utils": "2.1.0", "chai": "^5.1.1", "tinyrainbow": "^1.2.0" }, @@ -5067,10 +5073,38 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/mocker": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.0.tgz", + "integrity": "sha512-ZxENovUqhzl+QiOFpagiHUNUuZ1qPd5yYTCYHomGIZOFArzn4mgX2oxZmiAItJWAaXHG6bbpb/DpSPhlk5DgtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "^2.1.0-beta.1", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.11" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/spy": "2.1.0", + "msw": "^2.3.5", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, "node_modules/@vitest/pretty-format": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.0.5.tgz", - "integrity": "sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.0.tgz", + "integrity": "sha512-7sxf2F3DNYatgmzXXcTh6cq+/fxwB47RIQqZJFoSH883wnVAoccSRT6g+dTKemUBo8Q5N4OYYj1EBXLuRKvp3Q==", "dev": true, "license": "MIT", "dependencies": { @@ -5081,13 +5115,13 @@ } }, "node_modules/@vitest/runner": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.0.5.tgz", - "integrity": "sha512-TfRfZa6Bkk9ky4tW0z20WKXFEwwvWhRY+84CnSEtq4+3ZvDlJyY32oNTJtM7AW9ihW90tX/1Q78cb6FjoAs+ig==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.0.tgz", + "integrity": "sha512-D9+ZiB8MbMt7qWDRJc4CRNNUlne/8E1X7dcKhZVAbcOKG58MGGYVDqAq19xlhNfMFZsW0bpVKgztBwks38Ko0w==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.0.5", + "@vitest/utils": "2.1.0", "pathe": "^1.1.2" }, "funding": { @@ -5095,14 +5129,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.0.5.tgz", - "integrity": "sha512-SgCPUeDFLaM0mIUHfaArq8fD2WbaXG/zVXjRupthYfYGzc8ztbFbu6dUNOblBG7XLMR1kEhS/DNnfCZ2IhdDew==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.0.tgz", + "integrity": "sha512-x69CygGMzt9VCO283K2/FYQ+nBrOj66OTKpsPykjCR4Ac3lLV+m85hj9reaIGmjBSsKzVvbxWmjWE3kF5ha3uQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.0.5", - "magic-string": "^0.30.10", + "@vitest/pretty-format": "2.1.0", + "magic-string": "^0.30.11", "pathe": "^1.1.2" }, "funding": { @@ -5110,9 +5144,9 @@ } }, "node_modules/@vitest/spy": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.0.5.tgz", - "integrity": "sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.0.tgz", + "integrity": "sha512-IXX5NkbdgTYTog3F14i2LgnBc+20YmkXMx0IWai84mcxySUDRgm0ihbOfR4L0EVRBDFG85GjmQQEZNNKVVpkZw==", "dev": true, "license": "MIT", "dependencies": { @@ -5123,14 +5157,13 @@ } }, "node_modules/@vitest/utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.0.5.tgz", - "integrity": "sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.0.tgz", + "integrity": "sha512-rreyfVe0PuNqJfKYUwfPDfi6rrp0VSu0Wgvp5WBqJonP+4NvXHk48X6oBam1Lj47Hy6jbJtnMj3OcRdrkTP0tA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.0.5", - "estree-walker": "^3.0.3", + "@vitest/pretty-format": "2.1.0", "loupe": "^3.1.1", "tinyrainbow": "^1.2.0" }, @@ -16295,6 +16328,13 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyexec": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz", + "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", + "dev": true, + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.5.tgz", @@ -17106,16 +17146,15 @@ } }, "node_modules/vite-node": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.0.5.tgz", - "integrity": "sha512-LdsW4pxj0Ot69FAoXZ1yTnA9bjGohr2yNBU7QKRxpz8ITSkhuDl6h3zS/tvgz4qrNjeRnvrWeXQ8ZF7Um4W00Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.0.tgz", + "integrity": "sha512-+ybYqBVUjYyIscoLzMWodus2enQDZOpGhcU6HdOVD6n8WZdk12w1GFL3mbnxLs7hPtRtqs1Wo5YF6/Tsr6fmhg==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", - "debug": "^4.3.5", + "debug": "^4.3.6", "pathe": "^1.1.2", - "tinyrainbow": "^1.2.0", "vite": "^5.0.0" }, "bin": { @@ -17314,30 +17353,30 @@ } }, "node_modules/vitest": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.0.5.tgz", - "integrity": "sha512-8GUxONfauuIdeSl5f9GTgVEpg5BTOlplET4WEDaeY2QBiN8wSm68vxN/tb5z405OwppfoCavnwXafiaYBC/xOA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.0.tgz", + "integrity": "sha512-XuuEeyNkqbfr0FtAvd9vFbInSSNY1ykCQTYQ0sj9wPy4hx+1gR7gqVNdW0AX2wrrM1wWlN5fnJDjF9xG6mYRSQ==", "dev": true, "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.3.0", - "@vitest/expect": "2.0.5", - "@vitest/pretty-format": "^2.0.5", - "@vitest/runner": "2.0.5", - "@vitest/snapshot": "2.0.5", - "@vitest/spy": "2.0.5", - "@vitest/utils": "2.0.5", + "@vitest/expect": "2.1.0", + "@vitest/mocker": "2.1.0", + "@vitest/pretty-format": "^2.1.0", + "@vitest/runner": "2.1.0", + "@vitest/snapshot": "2.1.0", + "@vitest/spy": "2.1.0", + "@vitest/utils": "2.1.0", "chai": "^5.1.1", - "debug": "^4.3.5", - "execa": "^8.0.1", - "magic-string": "^0.30.10", + "debug": "^4.3.6", + "magic-string": "^0.30.11", "pathe": "^1.1.2", "std-env": "^3.7.0", - "tinybench": "^2.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.0", "tinypool": "^1.0.0", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "2.0.5", + "vite-node": "2.1.0", "why-is-node-running": "^2.3.0" }, "bin": { @@ -17352,8 +17391,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.0.5", - "@vitest/ui": "2.0.5", + "@vitest/browser": "2.1.0", + "@vitest/ui": "2.1.0", "happy-dom": "*", "jsdom": "*" }, @@ -17378,66 +17417,6 @@ } } }, - "node_modules/vitest/node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/vitest/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/vitest/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/vscode-jsonrpc": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", diff --git a/print/package.json b/print/package.json index 0200a1c123..07930a8e2d 100644 --- a/print/package.json +++ b/print/package.json @@ -39,7 +39,7 @@ "@nuxtjs/tailwindcss": "6.12.1", "@tailwindcss/typography": "0.5.15", "@typescript-eslint/eslint-plugin": "8.5.0", - "@vitest/coverage-v8": "2.0.5", + "@vitest/coverage-v8": "2.1.0", "@vue/compiler-dom": "3.5.3", "@vue/compiler-sfc": "3.5.3", "@vue/runtime-dom": "3.5.3", @@ -58,7 +58,7 @@ "sass": "1.69.4", "vite-plugin-eslint2": "4.4.1", "vite-svg-loader": "5.1.0", - "vitest": "2.0.5", + "vitest": "2.1.0", "vue": "3.5.3" } } From a8303d90364251f4887b4a0d4436ac8e3f50b8c5 Mon Sep 17 00:00:00 2001 From: Manuel Meister Date: Thu, 12 Sep 2024 21:09:50 +0200 Subject: [PATCH 46/69] Combine contentType filter --- .../activity/ButtonNestedContentNodeAdd.vue | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/activity/ButtonNestedContentNodeAdd.vue b/frontend/src/components/activity/ButtonNestedContentNodeAdd.vue index 9013c978aa..2cc05ed505 100644 --- a/frontend/src/components/activity/ButtonNestedContentNodeAdd.vue +++ b/frontend/src/components/activity/ButtonNestedContentNodeAdd.vue @@ -83,7 +83,7 @@ export default { return [] } return this.preferredContentTypes() - .items.filter((ct) => this.showResponsiveLayout(ct) && this.showChecklistNode(ct)) + .items.filter(this.filterContentType) .sort(this.sortContentTypeByTranslatedName) }, nonpreferredContentTypesItems() { @@ -95,7 +95,7 @@ export default { .contentTypes() .items.filter( (ct) => - this.showResponsiveLayout(ct) && + this.filterContentType(ct) && !this.preferredContentTypes() .items.map((ct) => ct.id) .includes(ct.id) @@ -116,13 +116,15 @@ export default { contentTypeIconKey(contentType) { return 'contentNode.' + camelCase(contentType.name) + '.icon' }, - showResponsiveLayout(contentType) { - return ( - contentType.name !== 'ResponsiveLayout' || this.parentContentNode.parent === null - ) - }, - showChecklistNode(contentType) { - return contentType.name === 'Checklist' ? this.featureChecklistEnabled : true + filterContentType(contentType) { + switch(contentType.name) { + case 'ResponsiveLayout': + return this.parentContentNode.parent === null + case 'Checklist': + return this.featureChecklistEnabled + default: + return true + } }, sortContentTypeByTranslatedName(ct1, ct2) { const ct1name = this.$i18n.tc(this.contentTypeNameKey(ct1)) From 45057f52d6e280794d855d78dc30a4b9e6ad0694 Mon Sep 17 00:00:00 2001 From: Manuel Meister Date: Thu, 12 Sep 2024 21:10:36 +0200 Subject: [PATCH 47/69] Fix description of checklist featureToggle --- .helm/ecamp3/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.helm/ecamp3/values.yaml b/.helm/ecamp3/values.yaml index 3a11d75bd9..504272c251 100644 --- a/.helm/ecamp3/values.yaml +++ b/.helm/ecamp3/values.yaml @@ -15,7 +15,7 @@ helpLink: # 'https://ecamp3.ch/faq' # enable/disable feature across the complete deployment featureToggle: developer: false # enables various tools/features foreseen for development deployments (language switcher, form controls view, performance measurement view, etc.) - checklist: false # enables various tools/features foreseen for development deployments (language switcher, form controls view, performance measurement view, etc.) + checklist: false # enables checklist feature in frontend api: subpath: "/api" From 7f36f96d5b444d0bcffc6c05a75a5de73461ab65 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2024 20:42:00 +0000 Subject: [PATCH 48/69] chore(deps): update dependency eslint to v9 --- .ops/aws-setup/package-lock.json | 316 ++++++++----------------------- .ops/aws-setup/package.json | 2 +- e2e/package-lock.json | 313 ++++++++---------------------- e2e/package.json | 2 +- frontend/package-lock.json | 264 ++++++++------------------ frontend/package.json | 2 +- pdf/package-lock.json | 310 ++++++++---------------------- pdf/package.json | 2 +- print/package-lock.json | 200 ++++++------------- print/package.json | 2 +- 10 files changed, 368 insertions(+), 1045 deletions(-) diff --git a/.ops/aws-setup/package-lock.json b/.ops/aws-setup/package-lock.json index 3e8a71d146..5b96af896b 100644 --- a/.ops/aws-setup/package-lock.json +++ b/.ops/aws-setup/package-lock.json @@ -16,7 +16,7 @@ "@eslint/eslintrc": "3.1.0", "@eslint/js": "9.9.1", "@types/node": "20.16.5", - "eslint": "8.57.0", + "eslint": "9.9.1", "eslint-config-prettier": "9.1.0", "eslint-plugin-n": "17.10.2", "eslint-plugin-prettier": "5.2.1", @@ -1055,6 +1055,21 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", @@ -1102,6 +1117,16 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@grpc/grpc-js": { "version": "1.11.2", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.11.2.tgz", @@ -1133,22 +1158,6 @@ "node": ">=6" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -1163,13 +1172,19 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", "dev": true, - "license": "BSD-3-Clause" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@isaacs/cliui": { "version": "8.0.2", @@ -2958,13 +2973,6 @@ "integrity": "sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA==", "license": "MIT" }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true, - "license": "ISC" - }, "node_modules/abbrev": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", @@ -3693,19 +3701,6 @@ "semver": "bin/semver" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -3816,42 +3811,38 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz", + "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.9.1", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -3865,10 +3856,18 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-compat-utils": { @@ -4071,40 +4070,6 @@ "node": ">=10" } }, - "node_modules/eslint/node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -4172,9 +4137,9 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -4182,38 +4147,20 @@ "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -4229,22 +4176,6 @@ "node": ">=4.0" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -4491,16 +4422,16 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/find-up": { @@ -4521,18 +4452,17 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { @@ -4591,13 +4521,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -4790,13 +4713,6 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -5055,18 +4971,6 @@ "node": ">=8" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -6150,16 +6054,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -6645,45 +6539,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -7201,19 +7056,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", diff --git a/.ops/aws-setup/package.json b/.ops/aws-setup/package.json index 3a41ab64e0..14842ba3db 100644 --- a/.ops/aws-setup/package.json +++ b/.ops/aws-setup/package.json @@ -20,7 +20,7 @@ "@eslint/eslintrc": "3.1.0", "@eslint/js": "9.9.1", "@types/node": "20.16.5", - "eslint": "8.57.0", + "eslint": "9.9.1", "eslint-config-prettier": "9.1.0", "eslint-plugin-n": "17.10.2", "eslint-plugin-prettier": "5.2.1", diff --git a/e2e/package-lock.json b/e2e/package-lock.json index 9e8bdd0c2f..e0e267b8d5 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -11,7 +11,7 @@ "@eslint/eslintrc": "3.1.0", "@eslint/js": "9.9.1", "cypress": "13.13.2", - "eslint": "8.57.0", + "eslint": "9.9.1", "eslint-config-prettier": "9.1.0", "eslint-plugin-cypress": "3.5.0", "eslint-plugin-prettier": "5.2.1", @@ -452,6 +452,21 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", @@ -499,20 +514,14 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, "engines": { - "node": ">=10.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -529,13 +538,19 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", "dev": true, - "license": "BSD-3-Clause" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", @@ -692,13 +707,6 @@ "@types/node": "*" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true, - "license": "ISC" - }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", @@ -1533,19 +1541,6 @@ "node": ">=0.4.0" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -1641,42 +1636,38 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz", + "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.9.1", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -1690,10 +1681,18 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-prettier": { @@ -1806,40 +1805,6 @@ "node": ">=10" } }, - "node_modules/eslint/node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -1907,9 +1872,9 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -1917,38 +1882,20 @@ "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -1964,22 +1911,6 @@ "node": ">=4.0" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2003,19 +1934,6 @@ "node": ">=8" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/espree": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", @@ -2260,16 +2178,16 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/find-up": { @@ -2290,18 +2208,17 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { @@ -2352,13 +2269,6 @@ "node": ">=10" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -2436,28 +2346,6 @@ "assert-plus": "^1.0.0" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -2520,13 +2408,6 @@ "dev": true, "license": "ISC" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -2683,25 +2564,6 @@ "node": ">=8" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, "node_modules/ini": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", @@ -3476,16 +3338,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -3728,23 +3580,6 @@ "dev": true, "license": "MIT" }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", diff --git a/e2e/package.json b/e2e/package.json index dbd59acb1c..c7475e9699 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -17,7 +17,7 @@ "@eslint/eslintrc": "3.1.0", "@eslint/js": "9.9.1", "cypress": "13.13.2", - "eslint": "8.57.0", + "eslint": "9.9.1", "eslint-config-prettier": "9.1.0", "eslint-plugin-cypress": "3.5.0", "eslint-plugin-prettier": "5.2.1", diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 205f405383..2b79af9ae8 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -86,7 +86,7 @@ "@vue/test-utils": "1.3.6", "autoprefixer": "10.4.20", "babel-plugin-require-context-hook": "1.0.0", - "eslint": "8.57.0", + "eslint": "9.9.1", "eslint-config-prettier": "9.1.0", "eslint-plugin-local-rules": "3.0.2", "eslint-plugin-n": "17.10.2", @@ -2474,6 +2474,21 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", @@ -2521,20 +2536,14 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, "engines": { - "node": ">=10.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -2551,13 +2560,19 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", "dev": true, - "license": "BSD-3-Clause" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@intlify/core": { "version": "9.14.0", @@ -4251,13 +4266,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true, - "license": "ISC" - }, "node_modules/@vitejs/plugin-vue2": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue2/-/plugin-vue2-2.3.1.tgz", @@ -6160,19 +6168,6 @@ "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==", "license": "MIT" }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dom-accessibility-api": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", @@ -6492,42 +6487,38 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz", + "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.9.1", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -6541,10 +6532,18 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-compat-utils": { @@ -6833,40 +6832,6 @@ "node": ">=10" } }, - "node_modules/eslint/node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -6934,9 +6899,9 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -6944,38 +6909,20 @@ "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -6991,22 +6938,6 @@ "node": ">=4.0" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -7255,16 +7186,16 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/file-saver": { @@ -7304,18 +7235,17 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { @@ -7632,13 +7562,6 @@ "dev": true, "license": "ISC" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, "node_modules/hal-json-normalizer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hal-json-normalizer/-/hal-json-normalizer-4.2.0.tgz", @@ -10645,45 +10568,6 @@ "dev": true, "license": "MIT" }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/rollup": { "version": "4.21.2", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index aece11a95f..70088f0d75 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -98,7 +98,7 @@ "@vue/test-utils": "1.3.6", "autoprefixer": "10.4.20", "babel-plugin-require-context-hook": "1.0.0", - "eslint": "8.57.0", + "eslint": "9.9.1", "eslint-config-prettier": "9.1.0", "eslint-plugin-local-rules": "3.0.2", "eslint-plugin-n": "17.10.2", diff --git a/pdf/package-lock.json b/pdf/package-lock.json index 2369ad000b..796a2b99a8 100644 --- a/pdf/package-lock.json +++ b/pdf/package-lock.json @@ -29,7 +29,7 @@ "@vue/test-utils": "2.4.6", "css": "3.0.0", "dayjs": "1.11.13", - "eslint": "8.57.0", + "eslint": "9.9.1", "eslint-plugin-local-rules": "3.0.2", "eslint-plugin-vue": "9.28.0", "globals": "15.9.0", @@ -2400,6 +2400,21 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", @@ -2447,20 +2462,14 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, "engines": { - "node": ">=10.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -2477,13 +2486,19 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", "dev": true, - "license": "BSD-3-Clause" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@intlify/core": { "version": "9.14.0", @@ -3133,13 +3148,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true, - "license": "ISC" - }, "node_modules/@vitejs/plugin-vue": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.1.3.tgz", @@ -4426,19 +4434,6 @@ "license": "MIT", "peer": true }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -4614,42 +4609,38 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz", + "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.9.1", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -4663,10 +4654,18 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-prettier": { @@ -4796,40 +4795,6 @@ "node": ">=10" } }, - "node_modules/eslint/node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -4897,9 +4862,9 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -4907,38 +4872,20 @@ "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -4954,22 +4901,6 @@ "node": ">=4.0" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -5135,16 +5066,16 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/find-up": { @@ -5165,18 +5096,17 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { @@ -5236,13 +5166,6 @@ "node": ">= 6" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -5394,13 +5317,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -5623,18 +5539,6 @@ "node": ">=0.8.19" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -6340,16 +6244,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -6457,16 +6351,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -6822,45 +6706,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/rollup": { "version": "4.21.2", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.2.tgz", @@ -8164,13 +8009,6 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, "node_modules/ws": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", diff --git a/pdf/package.json b/pdf/package.json index 533220ae4d..6d93e9ac1f 100644 --- a/pdf/package.json +++ b/pdf/package.json @@ -49,7 +49,7 @@ "@vue/test-utils": "2.4.6", "css": "3.0.0", "dayjs": "1.11.13", - "eslint": "8.57.0", + "eslint": "9.9.1", "eslint-plugin-local-rules": "3.0.2", "eslint-plugin-vue": "9.28.0", "globals": "15.9.0", diff --git a/print/package-lock.json b/print/package-lock.json index 8309b7578a..3aa8ae320c 100644 --- a/print/package-lock.json +++ b/print/package-lock.json @@ -37,7 +37,7 @@ "@vue/server-renderer": "3.5.3", "@vue/shared": "3.5.3", "@vue/test-utils": "2.4.6", - "eslint": "8.57.0", + "eslint": "9.9.1", "eslint-config-prettier": "9.1.0", "eslint-plugin-local-rules": "3.0.2", "eslint-plugin-prettier": "5.2.1", @@ -1372,22 +1372,6 @@ "node": ">=14" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -1402,13 +1386,19 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", "dev": true, - "license": "BSD-3-Clause" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@intlify/bundle-utils": { "version": "7.5.1", @@ -4829,13 +4819,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true, - "license": "ISC" - }, "node_modules/@unhead/dom": { "version": "1.11.2", "resolved": "https://registry.npmjs.org/@unhead/dom/-/dom-1.11.2.tgz", @@ -7765,42 +7748,38 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz", + "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.9.1", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -7814,10 +7793,18 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-compat-utils": { @@ -8195,38 +8182,19 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/eslint/node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true, - "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/eslint/node_modules/@nodelib/fs.scandir": { @@ -8267,32 +8235,18 @@ "node": ">= 8" } }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "node_modules/eslint/node_modules/eslint-scope": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -8328,22 +8282,6 @@ "node": ">=10.13.0" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -8402,19 +8340,6 @@ "node": ">=8" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -8734,16 +8659,16 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/file-uri-to-path": { @@ -8798,18 +8723,17 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { diff --git a/print/package.json b/print/package.json index 07930a8e2d..e272cfebb2 100644 --- a/print/package.json +++ b/print/package.json @@ -46,7 +46,7 @@ "@vue/server-renderer": "3.5.3", "@vue/shared": "3.5.3", "@vue/test-utils": "2.4.6", - "eslint": "8.57.0", + "eslint": "9.9.1", "eslint-config-prettier": "9.1.0", "eslint-plugin-local-rules": "3.0.2", "eslint-plugin-prettier": "5.2.1", From 2571625d3420ba31d2929d51d5a78ce8b2f33788 Mon Sep 17 00:00:00 2001 From: BacLuc Date: Tue, 27 Aug 2024 21:33:28 +0200 Subject: [PATCH 49/69] frontend: fix lint after update to eslint 9 --- .../activity/content/columnLayout/calculateNextSlotName.js | 2 +- frontend/src/components/form/base/EColorField.vue | 4 ++-- frontend/src/components/form/base/EColorPicker.vue | 2 +- frontend/src/components/form/tiptap/AutoLinkDecoration.js | 2 +- frontend/src/plugins/store/preferences.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/activity/content/columnLayout/calculateNextSlotName.js b/frontend/src/components/activity/content/columnLayout/calculateNextSlotName.js index a07b20b795..89624c8e82 100644 --- a/frontend/src/components/activity/content/columnLayout/calculateNextSlotName.js +++ b/frontend/src/components/activity/content/columnLayout/calculateNextSlotName.js @@ -2,7 +2,7 @@ import cloneDeep from 'lodash/cloneDeep' export function calculateNextSlotName(slotNames) { let i = 0 - // eslint-disable-next-line no-constant-condition + while (true) { if (!slotNames.includes((++i).toString())) return i.toString() } diff --git a/frontend/src/components/form/base/EColorField.vue b/frontend/src/components/form/base/EColorField.vue index 143776a19e..30ccabd7d3 100644 --- a/frontend/src/components/form/base/EColorField.vue +++ b/frontend/src/components/form/base/EColorField.vue @@ -84,7 +84,7 @@ export default { serialize(value) { try { return serialize(value, { format: 'hex', collapse: false }).toUpperCase() - } catch (e) { + } catch { return null } }, @@ -95,7 +95,7 @@ export default { deserialize(value) { try { return !value ? null : reactive(parse(value, { space: 'srgb', format: 'hex' })) - } catch (e) { + } catch { return null } }, diff --git a/frontend/src/components/form/base/EColorPicker.vue b/frontend/src/components/form/base/EColorPicker.vue index bdb649070d..96056a9de9 100644 --- a/frontend/src/components/form/base/EColorPicker.vue +++ b/frontend/src/components/form/base/EColorPicker.vue @@ -145,7 +145,7 @@ export default { return this.value && this.value !== '#NANNAN' ? contrastColor(this.value) : 'black' - } catch (error) { + } catch { return 'black' } }, diff --git a/frontend/src/components/form/tiptap/AutoLinkDecoration.js b/frontend/src/components/form/tiptap/AutoLinkDecoration.js index 4fb8720df9..667ba03a75 100644 --- a/frontend/src/components/form/tiptap/AutoLinkDecoration.js +++ b/frontend/src/components/form/tiptap/AutoLinkDecoration.js @@ -24,7 +24,7 @@ export const AutoLinkDecoration = Extension.create({ let link try { link = new URL(url) - } catch (_) { + } catch { /* It can't be parsed as an url */ } if (!link.host.includes('.') && !link.port) { diff --git a/frontend/src/plugins/store/preferences.js b/frontend/src/plugins/store/preferences.js index 94f00399f5..f9559d9a80 100644 --- a/frontend/src/plugins/store/preferences.js +++ b/frontend/src/plugins/store/preferences.js @@ -13,7 +13,7 @@ export function loadFromLocalStorage(localStorage = window.localStorage) { ) values[uri] ||= {} values[uri][identifier] = JSON.parse(localStorage[key]) - } catch (error) { + } catch { // Just ignore this key and continue with the others } }) From 046ebd73d4ddc40c2cb1e0a625f5710d9543e473 Mon Sep 17 00:00:00 2001 From: BacLuc Date: Tue, 27 Aug 2024 21:33:44 +0200 Subject: [PATCH 50/69] frontend: fix tests after update of eslint --- .../__tests__/matchingTranslationKeys.spec.js | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/common/eslint-local-rules/__tests__/matchingTranslationKeys.spec.js b/common/eslint-local-rules/__tests__/matchingTranslationKeys.spec.js index ad1029aa77..42b5c3c59f 100644 --- a/common/eslint-local-rules/__tests__/matchingTranslationKeys.spec.js +++ b/common/eslint-local-rules/__tests__/matchingTranslationKeys.spec.js @@ -4,26 +4,29 @@ import path from 'path' import fs from 'fs' import utils from 'eslint-plugin-vue/lib/utils/index.js' import { describe, it } from 'vitest' +import localRules from 'eslint-plugin-local-rules' +import globals from 'globals' +import eslintParser from 'vue-eslint-parser' RuleTester.describe = describe RuleTester.it = it const ruleTester = new RuleTester({ - parser: require.resolve('vue-eslint-parser'), - root: true, - env: { - node: true, + plugins: { + 'local-rules': localRules, }, - extends: [ - 'plugin:vue/recommended', - 'eslint:recommended', - 'plugin:prettier/recommended', - '@vue/eslint-config-prettier', - ], - parserOptions: { - parser: '@babel/eslint-parser', + + languageOptions: { + parser: eslintParser, + globals: { + ...globals.node, + ...globals.jest, + }, + + parserOptions: { + parser: '@babel/eslint-parser', + }, }, - plugins: ['eslint-plugin-local-rules'], }) const ruleInstance = rule(path, utils, fs) From 66e7a44278a802de2e6fa63c9421d1c57437c6e3 Mon Sep 17 00:00:00 2001 From: BacLuc Date: Wed, 28 Aug 2024 22:33:41 +0200 Subject: [PATCH 51/69] matchingTranslationKeys.spec.js: use double quotes in 'allows correct key with arguments' Else the test runner will complain that this is a duplicate test of allows correct key with single quotes. --- .../__tests__/matchingTranslationKeys.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/eslint-local-rules/__tests__/matchingTranslationKeys.spec.js b/common/eslint-local-rules/__tests__/matchingTranslationKeys.spec.js index 42b5c3c59f..342c3c9405 100644 --- a/common/eslint-local-rules/__tests__/matchingTranslationKeys.spec.js +++ b/common/eslint-local-rules/__tests__/matchingTranslationKeys.spec.js @@ -125,7 +125,7 @@ ruleTester.run('local-rules/matching-translation-keys', ruleInstance, { }, { name: 'allows correct key with arguments', - code: '$tc(\'components.hello.world\', 0, { test: "foo" })', + code: '$tc("components.hello.world", 0, { test: "foo" })', options: options, filename: '/src/components/hello.js', }, From 2489ccb798a11b25967973b2fa1fc3bd10b082b2 Mon Sep 17 00:00:00 2001 From: BacLuc Date: Wed, 28 Aug 2024 22:34:11 +0200 Subject: [PATCH 52/69] frontend: ignore data directory in .prettierignore --- frontend/.prettierignore | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/.prettierignore b/frontend/.prettierignore index e33c23a197..de2f837688 100644 --- a/frontend/.prettierignore +++ b/frontend/.prettierignore @@ -1,5 +1,6 @@ src/common/locales/ src/locales/ +/data /dist .vscode /public/twemoji From 46651ece449c033f786ea77d4e73e478adf723dd Mon Sep 17 00:00:00 2001 From: Manuel Meister Date: Thu, 12 Sep 2024 22:29:20 +0200 Subject: [PATCH 53/69] Add content if empty --- .../components/activity/content/Checklist.vue | 45 ++++++++++++------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/frontend/src/components/activity/content/Checklist.vue b/frontend/src/components/activity/content/Checklist.vue index 03bc49e8e9..05c029e26d 100644 --- a/frontend/src/components/activity/content/Checklist.vue +++ b/frontend/src/components/activity/content/Checklist.vue @@ -8,20 +8,21 @@ >