diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b16e19..2a729ba 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-42](https://github.com/itk-dev/itk-projects/pull/42) Describe what ITK counts as a project: a callout on the create page, a "What counts as a project?" dialog on the project list, and a tour step. diff --git a/assets/app.js b/assets/app.js index 4d83cea..a9e2c6b 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 25b1d4e..9db106c 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 9812f0b..5d1755e 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']; @@ -60,7 +59,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) { @@ -181,9 +179,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 73adbb2..8396a4d 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; - /** * What kind of thing the project is ("Projekt", "Drift", …). A project can be * several at once, e.g. a pilot that is also operations. @@ -141,7 +136,6 @@ public function __construct() parent::__construct(); $this->organizationalAnchoring = new ArrayCollection(); $this->types = new ArrayCollection(); - $this->strategies = new ArrayCollection(); $this->contacts = new ArrayCollection(); $this->partners = new ArrayCollection(); $this->tags = new ArrayCollection(); @@ -207,39 +201,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; - } - /** @return Collection */ public function getTypes(): Collection { 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 813e714..b03a4a9 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('types', EntityType::class, [ 'label' => 'project.types', 'class' => ProjectTypeEntity::class, diff --git a/src/Repository/ProjectRepository.php b/src/Repository/ProjectRepository.php index 9afe010..90cab89 100644 --- a/src/Repository/ProjectRepository.php +++ b/src/Repository/ProjectRepository.php @@ -49,7 +49,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, area and type are related entities searched by @@ -147,7 +146,7 @@ public function findForExport(ProjectFilter $filter): array return []; } - foreach (['types', 'organizationalAnchoring', 'strategies', 'tags', 'contacts', 'partners'] as $association) { + foreach (['types', '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 db2001a..7f12aa6 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 59da553..451497a 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 bb11385..a7c92f9 100644 --- a/tests/Unit/Entity/ProjectTest.php +++ b/tests/Unit/Entity/ProjectTest.php @@ -29,7 +29,6 @@ public function testDefaults(): void self::assertSame([], $project->getLinks()); self::assertCount(0, $project->getOrganizationalAnchoring()); self::assertCount(0, $project->getTypes()); - self::assertCount(0, $project->getStrategies()); self::assertCount(0, $project->getTags()); self::assertCount(0, $project->getContacts()); self::assertCount(0, $project->getPartners()); @@ -177,24 +176,6 @@ public function testTypeCollection(): void self::assertCount(0, $project->getTypes()); } - 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 68b8362..7615bba 100644 --- a/translations/messages.da.yaml +++ b/translations/messages.da.yaml @@ -172,10 +172,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 types: Type types_help: Fx projekt eller drift. status: Status @@ -420,4 +419,3 @@ enum: external_partner: Ekstern partner vocabulary: tag: Tag - strategy: Strategi diff --git a/translations/messages.en.yaml b/translations/messages.en.yaml index 42a153f..ca5a7cf 100644 --- a/translations/messages.en.yaml +++ b/translations/messages.en.yaml @@ -172,10 +172,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 types: Type types_help: E.g. project or operation. status: Status @@ -420,4 +419,3 @@ enum: external_partner: External partner vocabulary: tag: Tag - strategy: Strategy