From e832539c3829887184742aea52a2165f356d1c9a Mon Sep 17 00:00:00 2001 From: jekuaitk Date: Thu, 1 Oct 2026 14:35:23 +0200 Subject: [PATCH] 8381: Remove strategy and plans term --- CHANGELOG.md | 3 ++ assets/app.js | 4 +-- migrations/Version20261001080000.php | 38 +++++++++++++++++++++++ src/Controller/ProjectController.php | 2 -- src/DataFixtures/AppFixtures.php | 5 --- src/Entity/Project.php | 41 +------------------------ src/Enum/Vocabulary.php | 1 - src/Form/ProjectType.php | 6 ---- src/Repository/ProjectRepository.php | 3 +- templates/project/_form.html.twig | 1 - templates/project/show.html.twig | 3 -- tests/Repository/TermRepositoryTest.php | 6 ++-- tests/Unit/Entity/ProjectTest.php | 19 ------------ tests/Unit/Entity/TermTest.php | 8 ++--- translations/messages.da.yaml | 4 +-- translations/messages.en.yaml | 4 +-- 16 files changed, 54 insertions(+), 94 deletions(-) create mode 100644 migrations/Version20261001080000.php diff --git a/CHANGELOG.md b/CHANGELOG.md index d397b7c..f39e881 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +* [PR-45](https://github.com/itk-dev/itk-projects/pull/45) + Remove the "Strategies and plans" field. Update Summary help text to now ask + for strategy and plans. * [PR-33](https://github.com/itk-dev/itk-projects/pull/33) Let a project be anchored in several departments, picked with a searchable multiselect. diff --git a/assets/app.js b/assets/app.js index 4b9e80e..f1eb66a 100644 --- a/assets/app.js +++ b/assets/app.js @@ -103,8 +103,8 @@ function initCreatableSelect(selector, poolKey, transform) { }); } -// Free-tagging term fields (strategies, tags) capitalise new -// entries; partners keep the typed name as-is. +// Free-tagging term fields (tags) capitalise new entries; partners keep +// the typed name as-is. function initTermSelect() { initCreatableSelect("[data-term-select]", "termPool", capitalize); } diff --git a/migrations/Version20261001080000.php b/migrations/Version20261001080000.php new file mode 100644 index 0000000..48711c3 --- /dev/null +++ b/migrations/Version20261001080000.php @@ -0,0 +1,38 @@ +addSql('ALTER TABLE project_strategy DROP FOREIGN KEY `FK_2908CE36166D1F9C`'); + $this->addSql('ALTER TABLE project_strategy DROP FOREIGN KEY `FK_2908CE36E2C35FC`'); + $this->addSql('DROP TABLE project_strategy'); + // The Vocabulary enum no longer has a strategy case, so leftover rows + // would fail to hydrate. + $this->addSql("DELETE FROM term WHERE vocabulary = 'strategy'"); + } + + public function down(Schema $schema): void + { + // Recreates the empty join table only; the deleted terms are not restored. + $this->addSql('CREATE TABLE project_strategy (project_id BINARY(16) NOT NULL, term_id BINARY(16) NOT NULL, INDEX IDX_2908CE36166D1F9C (project_id), INDEX IDX_2908CE36E2C35FC (term_id), PRIMARY KEY (project_id, term_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_general_ci` ENGINE = InnoDB COMMENT = \'\' '); + $this->addSql('ALTER TABLE project_strategy ADD CONSTRAINT `FK_2908CE36166D1F9C` FOREIGN KEY (project_id) REFERENCES project (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE project_strategy ADD CONSTRAINT `FK_2908CE36E2C35FC` FOREIGN KEY (term_id) REFERENCES term (id) ON DELETE CASCADE'); + } +} diff --git a/src/Controller/ProjectController.php b/src/Controller/ProjectController.php index 1d5e1db..aab7991 100644 --- a/src/Controller/ProjectController.php +++ b/src/Controller/ProjectController.php @@ -75,7 +75,6 @@ public function export(Request $request, ProjectRepository $projects, Translator $translator->trans('project.endorsement_author'), $translator->trans('project.budget'), $translator->trans('project.funding'), - $translator->trans('project.strategies'), $translator->trans('project.tags'), $translator->trans('project.time_period_start'), $translator->trans('project.time_period_end'), @@ -99,7 +98,6 @@ public function export(Request $request, ProjectRepository $projects, Translator $translate($row->getEndorsementAuthor()), $row->getBudget(), implode(', ', array_map($translate, $row->getFunding())), - $names($row->getStrategies()), $names($row->getTags()), $row->getTimePeriodStart()?->format('Y-m-d'), $row->getTimePeriodEnd()?->format('Y-m-d'), diff --git a/src/DataFixtures/AppFixtures.php b/src/DataFixtures/AppFixtures.php index f982053..4b5d523 100644 --- a/src/DataFixtures/AppFixtures.php +++ b/src/DataFixtures/AppFixtures.php @@ -23,7 +23,6 @@ class AppFixtures extends Fixture { private const array TAGS = ['Bæredygtighed', 'Borgerinddragelse', 'Innovation', 'Sundhed', 'Klima', 'Mobilitet', 'Data', 'Tryghed', 'Læring', 'Fællesskab']; - private const array STRATEGIES = ['Klimaplan 2030', 'Erhvervsplan', 'Børn- og ungepolitik', 'Mobilitetsplan', 'Digitaliseringsstrategi', 'Sundhedspolitik']; private const array DEPARTMENTS = ['ITK Development', 'CFIA', 'Aarhus CityLab', 'Stab', 'OS2', 'AI Lab', 'IOT Lab', 'GTM', 'Fut Lab']; private const array PARTNERS = ['Aarhus Universitet', 'VIA University College', 'Alexandra Instituttet', 'Teknologisk Institut', 'Region Midtjylland', 'Erhverv Aarhus', 'Danmarks Tekniske Universitet', 'Aarhus Vand', 'AffaldVarme Aarhus', 'Dansk Industri']; private const array AREAS = ['Klima og miljø', 'Mobilitet', 'Velfærd', 'Kultur og fritid', 'Uddannelse', 'Erhverv', 'Digitalisering', 'Byudvikling']; @@ -59,7 +58,6 @@ public function load(ObjectManager $manager): void $users = [$admin, $editor]; $tags = $this->makeTerms($manager, self::TAGS, Vocabulary::Tag); - $strategies = $this->makeTerms($manager, self::STRATEGIES, Vocabulary::Strategy); $departments = []; foreach (self::DEPARTMENTS as $name) { @@ -169,9 +167,6 @@ public function load(ObjectManager $manager): void foreach (\array_slice($this->shuffleCopy($tags), 0, mt_rand(1, 4)) as $term) { $project->addTag($term); } - foreach (\array_slice($this->shuffleCopy($strategies), 0, mt_rand(0, 2)) as $term) { - $project->addStrategy($term); - } foreach (\array_slice($this->shuffleCopy($contacts), 0, mt_rand(1, 3)) as $contact) { $project->addContact($contact); } diff --git a/src/Entity/Project.php b/src/Entity/Project.php index 73476b4..3804909 100644 --- a/src/Entity/Project.php +++ b/src/Entity/Project.php @@ -49,7 +49,7 @@ class Project extends AbstractEntity #[ORM\JoinColumn(onDelete: 'SET NULL')] private ?Area $area = null; - /** A few lines summing up the project's purpose and content. */ + /** A few lines summing up the project's purpose, content, strategy and plans. */ #[ORM\Column(type: Types::TEXT, nullable: true)] private ?string $summary = null; @@ -57,11 +57,6 @@ class Project extends AbstractEntity #[ORM\Column(type: Types::TEXT, nullable: true)] private ?string $description = null; - /** @var Collection */ - #[ORM\ManyToMany(targetEntity: Term::class, cascade: ['persist'])] - #[ORM\JoinTable(name: 'project_strategy')] - private Collection $strategies; - #[ORM\Column(length: 32, nullable: true, enumType: ProjectType::class)] private ?ProjectType $projectType = null; @@ -133,7 +128,6 @@ public function __construct() { parent::__construct(); $this->organizationalAnchoring = new ArrayCollection(); - $this->strategies = new ArrayCollection(); $this->contacts = new ArrayCollection(); $this->partners = new ArrayCollection(); $this->tags = new ArrayCollection(); @@ -199,39 +193,6 @@ public function setDescription(?string $description): static return $this; } - /** @return Collection */ - public function getStrategies(): Collection - { - return $this->strategies; - } - - public function addStrategy(Term $term): static - { - if (!$this->strategies->contains($term)) { - $this->strategies->add($term); - } - - return $this; - } - - public function removeStrategy(Term $term): static - { - $this->strategies->removeElement($term); - - return $this; - } - - /** @param iterable $terms */ - public function setStrategies(iterable $terms): static - { - $this->strategies->clear(); - foreach ($terms as $term) { - $this->addStrategy($term); - } - - return $this; - } - public function getProjectType(): ?ProjectType { return $this->projectType; diff --git a/src/Enum/Vocabulary.php b/src/Enum/Vocabulary.php index adcef26..4238416 100644 --- a/src/Enum/Vocabulary.php +++ b/src/Enum/Vocabulary.php @@ -11,7 +11,6 @@ enum Vocabulary: string implements TranslatableEnum { case Tag = 'tag'; - case Strategy = 'strategy'; public function labelKey(): string { diff --git a/src/Form/ProjectType.php b/src/Form/ProjectType.php index 149c2ea..a956aa4 100644 --- a/src/Form/ProjectType.php +++ b/src/Form/ProjectType.php @@ -66,12 +66,6 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'attr' => ['rows' => 8], 'help' => 'project.description_help', ]) - ->add('strategies', TermsTextType::class, [ - 'label' => 'project.strategies', - 'vocabulary' => Vocabulary::Strategy, - 'required' => false, - 'help' => 'project.terms_help', - ]) ->add('projectType', EnumType::class, [ 'label' => 'project.project_type', 'class' => ProjectTypeEnum::class, diff --git a/src/Repository/ProjectRepository.php b/src/Repository/ProjectRepository.php index 1181091..195522f 100644 --- a/src/Repository/ProjectRepository.php +++ b/src/Repository/ProjectRepository.php @@ -50,7 +50,6 @@ public function search(ProjectFilter $filter): QueryBuilder // paginator's count stays correct. sprintf('i.id IN (SELECT icrt.id FROM %s icrt JOIN icrt.createdBy cb WHERE LOWER(cb.name) LIKE :q)', Project::class), sprintf('i.id IN (SELECT itag.id FROM %s itag JOIN itag.tags tg WHERE LOWER(tg.name) LIKE :q)', Project::class), - sprintf('i.id IN (SELECT istr.id FROM %s istr JOIN istr.strategies st WHERE LOWER(st.name) LIKE :q)', Project::class), sprintf('i.id IN (SELECT icon.id FROM %s icon JOIN icon.contacts co WHERE LOWER(co.name) LIKE :q)', Project::class), sprintf('i.id IN (SELECT ipar.id FROM %s ipar JOIN ipar.partners pa WHERE LOWER(pa.name) LIKE :q)', Project::class), // Department and area are related entities searched by their stored @@ -147,7 +146,7 @@ public function findForExport(ProjectFilter $filter): array return []; } - foreach (['organizationalAnchoring', 'strategies', 'tags', 'contacts', 'partners'] as $association) { + foreach (['organizationalAnchoring', 'tags', 'contacts', 'partners'] as $association) { $this->createQueryBuilder('i') ->addSelect('rel') ->leftJoin('i.'.$association, 'rel') diff --git a/templates/project/_form.html.twig b/templates/project/_form.html.twig index 495f8bb..607d9a7 100644 --- a/templates/project/_form.html.twig +++ b/templates/project/_form.html.twig @@ -62,7 +62,6 @@ {{ form_row(form.organizationalAnchoring) }} {{ form_row(form.statusAdditional) }} - {{ form_row(form.strategies) }} {{ form_row(form.tags) }} diff --git a/templates/project/show.html.twig b/templates/project/show.html.twig index 8b56a0c..279c2c7 100644 --- a/templates/project/show.html.twig +++ b/templates/project/show.html.twig @@ -123,9 +123,6 @@ {% else %}—{% endif %} -
{{ 'project.strategies'|trans }}
-
{{ h.term_list(project.strategies) }}
-
{{ 'project.tags'|trans }}
{{ h.term_list(project.tags) }}
diff --git a/tests/Repository/TermRepositoryTest.php b/tests/Repository/TermRepositoryTest.php index 5475281..76afb50 100644 --- a/tests/Repository/TermRepositoryTest.php +++ b/tests/Repository/TermRepositoryTest.php @@ -42,16 +42,16 @@ public function testFindOrCreateBuildsANewUnflushedTerm(): void { $name = 'BrandNewTag-'.uniqid(); - $term = $this->repository->findOrCreate($name, Vocabulary::Strategy); + $term = $this->repository->findOrCreate($name, Vocabulary::Tag); self::assertSame($name, $term->getName()); - self::assertSame(Vocabulary::Strategy, $term->getVocabulary()); + self::assertSame(Vocabulary::Tag, $term->getVocabulary()); self::assertCount(0, $this->repository->findBy(['name' => $name]), 'A freshly created term is not yet flushed to the database.'); } public function testFindOrCreateCapitalisesANewTerm(): void { - $term = $this->repository->findOrCreate('grøn omstilling '.uniqid(), Vocabulary::Strategy); + $term = $this->repository->findOrCreate('grøn omstilling '.uniqid(), Vocabulary::Tag); self::assertSame('G', mb_substr((string) $term->getName(), 0, 1)); } diff --git a/tests/Unit/Entity/ProjectTest.php b/tests/Unit/Entity/ProjectTest.php index 2a80fce..450b977 100644 --- a/tests/Unit/Entity/ProjectTest.php +++ b/tests/Unit/Entity/ProjectTest.php @@ -28,7 +28,6 @@ public function testDefaults(): void self::assertSame([], $project->getFunding()); self::assertSame([], $project->getLinks()); self::assertCount(0, $project->getOrganizationalAnchoring()); - self::assertCount(0, $project->getStrategies()); self::assertCount(0, $project->getTags()); self::assertCount(0, $project->getContacts()); self::assertCount(0, $project->getPartners()); @@ -157,24 +156,6 @@ public function testOrganizationalAnchoringCollection(): void self::assertCount(0, $project->getOrganizationalAnchoring()); } - public function testStrategyCollection(): void - { - $project = new Project(); - $term = new Term(Vocabulary::Strategy); - - $project->addStrategy($term); - $project->addStrategy($term); - self::assertCount(1, $project->getStrategies()); - - $project->removeStrategy($term); - self::assertCount(0, $project->getStrategies()); - - $project->setStrategies([new Term(Vocabulary::Strategy), new Term(Vocabulary::Strategy)]); - self::assertCount(2, $project->getStrategies()); - $project->setStrategies([]); - self::assertCount(0, $project->getStrategies()); - } - public function testTagCollection(): void { $project = new Project(); diff --git a/tests/Unit/Entity/TermTest.php b/tests/Unit/Entity/TermTest.php index aebd6b6..1936938 100644 --- a/tests/Unit/Entity/TermTest.php +++ b/tests/Unit/Entity/TermTest.php @@ -24,11 +24,11 @@ public function testDefaultVocabularyIsTag(): void public function testAccessors(): void { - $term = (new Term(Vocabulary::Strategy))->setName('Klimaplan 2030'); + $term = (new Term(Vocabulary::Tag))->setName('Klima'); - self::assertSame('Klimaplan 2030', $term->getName()); - self::assertSame(Vocabulary::Strategy, $term->getVocabulary()); - self::assertSame('Klimaplan 2030', (string) $term); + self::assertSame('Klima', $term->getName()); + self::assertSame(Vocabulary::Tag, $term->getVocabulary()); + self::assertSame('Klima', (string) $term); $term->setVocabulary(Vocabulary::Tag); self::assertSame(Vocabulary::Tag, $term->getVocabulary()); diff --git a/translations/messages.da.yaml b/translations/messages.da.yaml index ab9483b..4687dfc 100644 --- a/translations/messages.da.yaml +++ b/translations/messages.da.yaml @@ -169,10 +169,9 @@ project: area: Område area_help: Det tematiske område projektet hører under. summary: Opsummering - summary_help: Kort opsummering af formål og indhold. + summary_help: Kort opsummering af formål, indhold, strategi og planer. description: Beskrivelse description_help: Hvorfor vi gør det, og hvad projektet har ophæng i. - strategies: Strategier og planer project_type: Projektets karakter project_type_help: Projektets karakter, fx projekt eller drift. status: Status @@ -390,4 +389,3 @@ enum: external_partner: Ekstern partner vocabulary: tag: Tag - strategy: Strategi diff --git a/translations/messages.en.yaml b/translations/messages.en.yaml index dade48e..bfc68a7 100644 --- a/translations/messages.en.yaml +++ b/translations/messages.en.yaml @@ -169,10 +169,9 @@ project: area: Area area_help: The thematic area the project belongs to. summary: Summary - summary_help: A brief summary of the purpose and content. + summary_help: A brief summary of the purpose, content, strategy and plans. description: Description description_help: Why we are doing it, and what the project is anchored in. - strategies: Strategies and plans project_type: Type of project project_type_help: The nature of the project, e.g. project or operation. status: Status @@ -390,4 +389,3 @@ enum: external_partner: External partner vocabulary: tag: Tag - strategy: Strategy