From a898734e742acbcefa8fb789066ae8efbcb25e08 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Thu, 12 Sep 2024 09:29:11 +0200 Subject: [PATCH 01/26] Added more test setup stuff --- CHANGELOG.md | 3 +++ web/modules/custom/hoeringsportal_deskpro/README.md | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2620a825..5b1fa03a 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +* [PR-417](https://github.com/itk-dev/hoeringsportal/pull/417) + Added more test setup stuff + ## [4.5.1] - 2024-09-06 * [PR-416](https://github.com/itk-dev/hoeringsportal/pull/416) diff --git a/web/modules/custom/hoeringsportal_deskpro/README.md b/web/modules/custom/hoeringsportal_deskpro/README.md index e8130002..031bc0bc 100644 --- a/web/modules/custom/hoeringsportal_deskpro/README.md +++ b/web/modules/custom/hoeringsportal_deskpro/README.md @@ -18,6 +18,19 @@ not call an actual Deskpro API. Enable test mode in `settings.local.php`: $settings['hoeringsportal_deskpro']['test_mode'] = TRUE; ``` +and inject a little Deskpro configuration (cf. `/admin/site-setup/deskpro`): + +``` shell name=deskpro-test-setup +docker compose exec phpfpm vendor/bin/drush sql:query "INSERT INTO key_value(collection, name, value) VALUES ('hoeringsportal_deskpro.config', 'deskpro_available_department_ids', '[1]') ON DUPLICATE KEY UPDATE value = '[1]'\G" +# Check that setting is as expected. +docker compose exec phpfpm vendor/bin/drush sql:query "SELECT * FROM key_value WHERE collection = 'hoeringsportal_deskpro.config' AND name = 'deskpro_available_department_ids'\G" +``` + +When in test mode, the Deskpro service will return data defined in [YAML +files](https://en.wikipedia.org/wiki/YAML) in the +[`src/Service/mock`](src/Service/mock) folder. (The `1` in the SQL incantations +above match `id: 1` in `src/Service/mock/ticket_departments.yaml`). + ## Drush commands ```sh From 8a4027a5a83442fc5fcbb41594fbfeba6c933a2d Mon Sep 17 00:00:00 2001 From: Jesper Pedersen Date: Thu, 12 Sep 2024 10:43:57 +0200 Subject: [PATCH 02/26] 2288: Show deleted tickets message after delete_date has passed --- .../block/hoeringsportal-hearing-tickets.html.twig | 14 ++++++++++++++ .../custom/hoeringsportal/assets/js/icons.js | 6 ++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig b/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig index 1ad2b5ea..3c64880a 100644 --- a/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig +++ b/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig @@ -59,6 +59,20 @@ {% endif %} + + {# Deleted tickets information #} + {% if node.field_delete_date.value < "now"|date('Y-m-d') %} +
+ +

{{ 'You can read more about why and how we delete old tickets'|trans }}

+
+ {% endif %} {% if not has_external_hearing_tickets and tickets %} diff --git a/web/themes/custom/hoeringsportal/assets/js/icons.js b/web/themes/custom/hoeringsportal/assets/js/icons.js index 9708d1d9..c964a92b 100644 --- a/web/themes/custom/hoeringsportal/assets/js/icons.js +++ b/web/themes/custom/hoeringsportal/assets/js/icons.js @@ -24,7 +24,8 @@ import { faFileAlt, faFileImage, faFileExcel, - faTicketAlt + faTicketAlt, + faTriangleExclamation, } from '@fortawesome/free-solid-svg-icons' // Import icons from the free brands package @@ -70,6 +71,7 @@ library.add( faReddit, faTumblr, faWhatsapp, - faXTwitter + faXTwitter, + faTriangleExclamation, ) dom.i2svg() From 36d4188e1ff5e331fb1e4866f41416d12096dfda Mon Sep 17 00:00:00 2001 From: Jesper Pedersen Date: Thu, 12 Sep 2024 10:54:40 +0200 Subject: [PATCH 03/26] 2288: Move block outside ticket checks --- .../hoeringsportal-hearing-tickets.html.twig | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig b/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig index 3c64880a..c596eac3 100644 --- a/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig +++ b/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig @@ -59,20 +59,6 @@ {% endif %} - - {# Deleted tickets information #} - {% if node.field_delete_date.value < "now"|date('Y-m-d') %} -
- -

{{ 'You can read more about why and how we delete old tickets'|trans }}

-
- {% endif %} {% if not has_external_hearing_tickets and tickets %} @@ -95,4 +81,19 @@ {% endif %} {% endif %} + + {# Deleted tickets information #} + {% if node.field_delete_date.value > "now"|date('Y-m-d') %} +
+ +

{{ 'You can read more about why and how we delete old tickets'|trans }}

+
+ {% endif %} + From bf2990abb11be3e6e1537880f3c4fb69dbac3173 Mon Sep 17 00:00:00 2001 From: Jesper Pedersen Date: Thu, 12 Sep 2024 10:55:34 +0200 Subject: [PATCH 04/26] 2288: Revert > to < after taking screenshot for PR --- .../templates/block/hoeringsportal-hearing-tickets.html.twig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig b/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig index c596eac3..9ba31c31 100644 --- a/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig +++ b/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig @@ -83,7 +83,7 @@ {% endif %} {# Deleted tickets information #} - {% if node.field_delete_date.value > "now"|date('Y-m-d') %} + {% if node.field_delete_date.value < "now"|date('Y-m-d') %}
{% endif %} - +
From f5269fe6cba368e034318467e86a3ac8b93d0ce7 Mon Sep 17 00:00:00 2001 From: Jesper Pedersen Date: Thu, 12 Sep 2024 10:58:15 +0200 Subject: [PATCH 05/26] 2288: Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b1fa03a..5de9a1fd 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +* [PR-418](https://github.com/itk-dev/hoeringsportal/pull/418) + Add message when hearing tickets is deleted. * [PR-417](https://github.com/itk-dev/hoeringsportal/pull/417) Added more test setup stuff From df3965f2ff378cc360ee17b89110128aca945a89 Mon Sep 17 00:00:00 2001 From: Jesper Pedersen Date: Thu, 12 Sep 2024 10:59:41 +0200 Subject: [PATCH 06/26] 2288: Config export --- ...tity_form_display.node.hearing.default.yml | 25 ++++++---- ...tity_view_display.node.hearing.default.yml | 48 +++++++++---------- ...isplay.node.hearing.hearing_ticket_add.yml | 2 + ...splay.node.hearing.hearing_ticket_view.yml | 31 ++++++++---- ...view_display.node.hearing.list_display.yml | 2 + ...ntity_view_display.node.hearing.teaser.yml | 2 + ...d.field.node.hearing.field_delete_date.yml | 21 ++++++++ .../field.storage.node.field_delete_date.yml | 20 ++++++++ 8 files changed, 109 insertions(+), 42 deletions(-) create mode 100644 config/sync/field.field.node.hearing.field_delete_date.yml create mode 100644 config/sync/field.storage.node.field_delete_date.yml diff --git a/config/sync/core.entity_form_display.node.hearing.default.yml b/config/sync/core.entity_form_display.node.hearing.default.yml index b389484e..fda62429 100644 --- a/config/sync/core.entity_form_display.node.hearing.default.yml +++ b/config/sync/core.entity_form_display.node.hearing.default.yml @@ -7,6 +7,7 @@ dependencies: - field.field.node.hearing.field_area - field.field.node.hearing.field_contact - field.field.node.hearing.field_content_state + - field.field.node.hearing.field_delete_date - field.field.node.hearing.field_description - field.field.node.hearing.field_deskpro_agent_email - field.field.node.hearing.field_deskpro_department_id @@ -34,6 +35,7 @@ dependencies: - field_group - hoeringsportal_data - link + - publication_date - text third_party_settings: field_group: @@ -41,6 +43,7 @@ third_party_settings: children: - field_start_date - field_reply_deadline + - field_delete_date - field_type - field_lokalplaner - field_project_reference @@ -88,7 +91,7 @@ third_party_settings: label: eDoc region: content parent_name: '' - weight: 10 + weight: 12 format_type: details format_settings: classes: '' @@ -101,7 +104,7 @@ third_party_settings: label: Kontakt region: content parent_name: '' - weight: 11 + weight: 13 format_type: details format_settings: classes: '' @@ -115,7 +118,7 @@ third_party_settings: label: 'Vil du vide mere?' region: content parent_name: '' - weight: 13 + weight: 15 format_type: details format_settings: classes: '' @@ -129,7 +132,7 @@ third_party_settings: label: GetOrganized region: content parent_name: '' - weight: 12 + weight: 14 format_type: details format_settings: classes: '' @@ -145,7 +148,7 @@ third_party_settings: label: Høringssvarsystem region: content parent_name: '' - weight: 16 + weight: 17 format_type: details format_settings: classes: '' @@ -173,6 +176,12 @@ content: rows: 5 placeholder: '' third_party_settings: { } + field_delete_date: + type: datetime_default + weight: 28 + region: content + settings: { } + third_party_settings: { } field_description: type: text_textarea weight: 2 @@ -231,7 +240,7 @@ content: third_party_settings: { } field_lokalplaner: type: hoeringsportal_data_localplan_default - weight: 29 + weight: 30 region: content settings: { } third_party_settings: { } @@ -311,7 +320,7 @@ content: third_party_settings: { } field_type: type: options_buttons - weight: 28 + weight: 29 region: content settings: { } third_party_settings: { } @@ -345,7 +354,7 @@ content: placeholder: '' third_party_settings: { } url_redirects: - weight: 14 + weight: 16 region: content settings: { } third_party_settings: { } diff --git a/config/sync/core.entity_view_display.node.hearing.default.yml b/config/sync/core.entity_view_display.node.hearing.default.yml index 59a596e3..b0db3d46 100644 --- a/config/sync/core.entity_view_display.node.hearing.default.yml +++ b/config/sync/core.entity_view_display.node.hearing.default.yml @@ -6,6 +6,7 @@ dependencies: - field.field.node.hearing.field_area - field.field.node.hearing.field_contact - field.field.node.hearing.field_content_state + - field.field.node.hearing.field_delete_date - field.field.node.hearing.field_description - field.field.node.hearing.field_deskpro_agent_email - field.field.node.hearing.field_deskpro_department_id @@ -80,16 +81,6 @@ third_party_settings: - field_map - 'dynamic_block_field:node-nearest_hearings' fields: - 'dynamic_token_field:node-header_information': - plugin_id: 'dynamic_token_field:node-header_information' - weight: 10 - label: hidden - formatter: default - 'dynamic_token_field:node-node_id_hearing': - plugin_id: 'dynamic_token_field:node-node_id_hearing' - weight: 17 - label: above - formatter: default 'dynamic_block_field:node-hearing_tickets': plugin_id: 'dynamic_block_field:node-hearing_tickets' weight: 7 @@ -102,17 +93,27 @@ third_party_settings: formatter: default 'dynamic_block_field:node-nearest_hearings': plugin_id: 'dynamic_block_field:node-nearest_hearings' - weight: 22 + weight: 20 label: above formatter: default 'dynamic_block_field:node-project_timeline': plugin_id: 'dynamic_block_field:node-project_timeline' - weight: 20 + weight: 18 label: hidden formatter: default 'dynamic_block_field:node-quicklinks': plugin_id: 'dynamic_block_field:node-quicklinks' + weight: 8 + label: above + formatter: default + 'dynamic_token_field:node-header_information': + plugin_id: 'dynamic_token_field:node-header_information' weight: 9 + label: hidden + formatter: default + 'dynamic_token_field:node-node_id_hearing': + plugin_id: 'dynamic_token_field:node-node_id_hearing' + weight: 15 label: above formatter: default node_title: @@ -135,14 +136,14 @@ content: settings: link: false third_party_settings: { } - weight: 16 + weight: 14 region: right field_contact: type: text_default label: above settings: { } third_party_settings: { } - weight: 18 + weight: 16 region: right field_description: type: text_default @@ -156,14 +157,14 @@ content: label: above settings: { } third_party_settings: { } - weight: 14 + weight: 13 region: right field_map: type: hoeringsportal_data_map_default label: hidden settings: { } third_party_settings: { } - weight: 21 + weight: 19 region: footer field_media_document: type: entity_reference_entity_view @@ -192,7 +193,7 @@ content: label: above settings: { } third_party_settings: { } - weight: 19 + weight: 17 region: right field_reply_deadline: type: datetime_default @@ -201,7 +202,7 @@ content: timezone_override: '' format_type: hoeringsportal_datetime third_party_settings: { } - weight: 12 + weight: 11 region: right field_start_date: type: datetime_default @@ -210,7 +211,7 @@ content: timezone_override: '' format_type: hoeringsportal_date third_party_settings: { } - weight: 11 + weight: 10 region: right field_teaser: type: basic_string @@ -225,7 +226,7 @@ content: settings: link: false third_party_settings: { } - weight: 13 + weight: 12 region: right field_video_embed: type: basic_string @@ -234,13 +235,9 @@ content: third_party_settings: { } weight: 5 region: left - sharing_buttons: - settings: { } - third_party_settings: { } - weight: 100 - region: content hidden: field_content_state: true + field_delete_date: true field_deskpro_agent_email: true field_deskpro_department_id: true field_edoc_casefile_id: true @@ -253,3 +250,4 @@ hidden: langcode: true links: true published_at: true + sharing_buttons: true diff --git a/config/sync/core.entity_view_display.node.hearing.hearing_ticket_add.yml b/config/sync/core.entity_view_display.node.hearing.hearing_ticket_add.yml index 96a98b1b..8579f5ac 100644 --- a/config/sync/core.entity_view_display.node.hearing.hearing_ticket_add.yml +++ b/config/sync/core.entity_view_display.node.hearing.hearing_ticket_add.yml @@ -7,6 +7,7 @@ dependencies: - field.field.node.hearing.field_area - field.field.node.hearing.field_contact - field.field.node.hearing.field_content_state + - field.field.node.hearing.field_delete_date - field.field.node.hearing.field_description - field.field.node.hearing.field_deskpro_agent_email - field.field.node.hearing.field_deskpro_department_id @@ -167,6 +168,7 @@ content: region: content hidden: field_content_state: true + field_delete_date: true field_description: true field_deskpro_agent_email: true field_deskpro_department_id: true diff --git a/config/sync/core.entity_view_display.node.hearing.hearing_ticket_view.yml b/config/sync/core.entity_view_display.node.hearing.hearing_ticket_view.yml index 1c84a874..a59ca78c 100644 --- a/config/sync/core.entity_view_display.node.hearing.hearing_ticket_view.yml +++ b/config/sync/core.entity_view_display.node.hearing.hearing_ticket_view.yml @@ -7,6 +7,7 @@ dependencies: - field.field.node.hearing.field_area - field.field.node.hearing.field_contact - field.field.node.hearing.field_content_state + - field.field.node.hearing.field_delete_date - field.field.node.hearing.field_description - field.field.node.hearing.field_deskpro_agent_email - field.field.node.hearing.field_deskpro_department_id @@ -52,9 +53,11 @@ third_party_settings: attributes: '' link_attribute: '' link_custom: '' + label: '' regions: header: - 'dynamic_block_field:node-hearing_ticket_title' + - sharing_buttons left: - node_title - 'dynamic_block_field:node-hearing_ticket' @@ -63,22 +66,23 @@ third_party_settings: - 'dynamic_token_field:node-header_information' - field_start_date - field_reply_deadline - - field_hearing_type - field_type - field_tags - field_area - 'dynamic_token_field:node-node_id_hearing' - field_contact - field_more_info + footer: + - field_delete_date fields: 'dynamic_block_field:node-hearing_ticket': plugin_id: 'dynamic_block_field:node-hearing_ticket' - weight: 2 + weight: 3 label: hidden formatter: default 'dynamic_block_field:node-hearing_ticket_author': plugin_id: 'dynamic_block_field:node-hearing_ticket_author' - weight: 3 + weight: 4 label: above formatter: default 'dynamic_block_field:node-hearing_ticket_title': @@ -88,7 +92,7 @@ third_party_settings: formatter: default 'dynamic_token_field:node-header_information': plugin_id: 'dynamic_token_field:node-header_information' - weight: 4 + weight: 5 label: hidden formatter: default 'dynamic_token_field:node-node_id_hearing': @@ -98,7 +102,7 @@ third_party_settings: formatter: default node_title: plugin_id: node_title - weight: 1 + weight: 2 label: hidden formatter: default settings: @@ -125,6 +129,15 @@ content: third_party_settings: { } weight: 12 region: right + field_delete_date: + type: datetime_default + label: above + settings: + timezone_override: '' + format_type: medium + third_party_settings: { } + weight: 14 + region: footer field_more_info: type: text_default label: above @@ -139,7 +152,7 @@ content: timezone_override: '' format_type: hoeringsportal_datetime third_party_settings: { } - weight: 6 + weight: 7 region: right field_start_date: type: datetime_default @@ -148,7 +161,7 @@ content: timezone_override: '' format_type: hoeringsportal_date third_party_settings: { } - weight: 5 + weight: 6 region: right field_tags: type: entity_reference_label @@ -169,8 +182,8 @@ content: sharing_buttons: settings: { } third_party_settings: { } - weight: 100 - region: content + weight: 1 + region: header hidden: field_content_state: true field_description: true diff --git a/config/sync/core.entity_view_display.node.hearing.list_display.yml b/config/sync/core.entity_view_display.node.hearing.list_display.yml index 81384532..ca8c39ee 100644 --- a/config/sync/core.entity_view_display.node.hearing.list_display.yml +++ b/config/sync/core.entity_view_display.node.hearing.list_display.yml @@ -7,6 +7,7 @@ dependencies: - field.field.node.hearing.field_area - field.field.node.hearing.field_contact - field.field.node.hearing.field_content_state + - field.field.node.hearing.field_delete_date - field.field.node.hearing.field_description - field.field.node.hearing.field_deskpro_agent_email - field.field.node.hearing.field_deskpro_department_id @@ -78,6 +79,7 @@ content: hidden: field_contact: true field_content_state: true + field_delete_date: true field_description: true field_deskpro_agent_email: true field_deskpro_department_id: true diff --git a/config/sync/core.entity_view_display.node.hearing.teaser.yml b/config/sync/core.entity_view_display.node.hearing.teaser.yml index 92d98ba9..741a80cf 100644 --- a/config/sync/core.entity_view_display.node.hearing.teaser.yml +++ b/config/sync/core.entity_view_display.node.hearing.teaser.yml @@ -7,6 +7,7 @@ dependencies: - field.field.node.hearing.field_area - field.field.node.hearing.field_contact - field.field.node.hearing.field_content_state + - field.field.node.hearing.field_delete_date - field.field.node.hearing.field_description - field.field.node.hearing.field_deskpro_agent_email - field.field.node.hearing.field_deskpro_department_id @@ -99,6 +100,7 @@ content: region: content hidden: field_contact: true + field_delete_date: true field_description: true field_deskpro_agent_email: true field_deskpro_department_id: true diff --git a/config/sync/field.field.node.hearing.field_delete_date.yml b/config/sync/field.field.node.hearing.field_delete_date.yml new file mode 100644 index 00000000..7aa5e825 --- /dev/null +++ b/config/sync/field.field.node.hearing.field_delete_date.yml @@ -0,0 +1,21 @@ +uuid: 1368ee79-00fb-48fd-b130-562dc0528233 +langcode: da +status: true +dependencies: + config: + - field.storage.node.field_delete_date + - node.type.hearing + module: + - datetime +id: node.hearing.field_delete_date +field_name: field_delete_date +entity_type: node +bundle: hearing +label: 'Slette dato' +description: 'Bruges til at sætte dato for sletning af høringssvar.' +required: true +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: datetime diff --git a/config/sync/field.storage.node.field_delete_date.yml b/config/sync/field.storage.node.field_delete_date.yml new file mode 100644 index 00000000..d6470d20 --- /dev/null +++ b/config/sync/field.storage.node.field_delete_date.yml @@ -0,0 +1,20 @@ +uuid: 55199c67-4189-4b36-957f-49ba0d8d0d39 +langcode: da +status: true +dependencies: + module: + - datetime + - node +id: node.field_delete_date +field_name: field_delete_date +entity_type: node +type: datetime +settings: + datetime_type: date +module: datetime +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false From 6ac636adc8a739cac3e65ecfd43191083cc66448 Mon Sep 17 00:00:00 2001 From: Jesper Pedersen Date: Thu, 12 Sep 2024 11:04:48 +0200 Subject: [PATCH 07/26] 2288: Apply coding standards --- web/themes/custom/hoeringsportal/assets/js/icons.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/themes/custom/hoeringsportal/assets/js/icons.js b/web/themes/custom/hoeringsportal/assets/js/icons.js index c964a92b..3347e364 100644 --- a/web/themes/custom/hoeringsportal/assets/js/icons.js +++ b/web/themes/custom/hoeringsportal/assets/js/icons.js @@ -25,7 +25,7 @@ import { faFileImage, faFileExcel, faTicketAlt, - faTriangleExclamation, + faTriangleExclamation } from '@fortawesome/free-solid-svg-icons' // Import icons from the free brands package @@ -72,6 +72,6 @@ library.add( faTumblr, faWhatsapp, faXTwitter, - faTriangleExclamation, + faTriangleExclamation ) dom.i2svg() From c67652a21941dff65017b4ac93f335afa9cb821d Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Thu, 3 Oct 2024 15:40:37 +0200 Subject: [PATCH 08/26] 2456: Updated field label and description --- config/sync/field.field.node.hearing.field_delete_date.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/sync/field.field.node.hearing.field_delete_date.yml b/config/sync/field.field.node.hearing.field_delete_date.yml index 7aa5e825..76d97345 100644 --- a/config/sync/field.field.node.hearing.field_delete_date.yml +++ b/config/sync/field.field.node.hearing.field_delete_date.yml @@ -11,8 +11,8 @@ id: node.hearing.field_delete_date field_name: field_delete_date entity_type: node bundle: hearing -label: 'Slette dato' -description: 'Bruges til at sætte dato for sletning af høringssvar.' +label: 'Dato for sletning af høringssvar' +description: 'Vælg hvornår høringssvar skal slettes fra høringen.' required: true translatable: false default_value: { } From 65fe6e05bcb3dcbb738dae749e955a2ac432b3b7 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Thu, 3 Oct 2024 17:06:31 +0200 Subject: [PATCH 09/26] 2456: Added stuff for deleting hearing replies --- CHANGELOG.md | 4 +- .../hoeringsportal_data.services.yml | 6 +- .../src/Drush/Commands/DrushCommands.php | 71 +++++++++++++++++++ .../src/Helper/HearingHelper.php | 69 +++++++++++++++--- .../hoeringsportal_deskpro.module | 1 + .../src/Plugin/Block/HearingTicketsBlock.php | 1 + .../src/Service/HearingHelper.php | 36 ++++++++++ .../hoeringsportal-hearing-tickets.html.twig | 29 ++++---- 8 files changed, 190 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5de9a1fd..83cb7766 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,10 @@ Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +* [PR-419](https://github.com/itk-dev/hoeringsportal/pull/419) + Added Drush command to delete hearing replies * [PR-418](https://github.com/itk-dev/hoeringsportal/pull/418) - Add message when hearing tickets is deleted. + Add message when hearing replies are deleted * [PR-417](https://github.com/itk-dev/hoeringsportal/pull/417) Added more test setup stuff diff --git a/web/modules/custom/hoeringsportal_data/hoeringsportal_data.services.yml b/web/modules/custom/hoeringsportal_data/hoeringsportal_data.services.yml index c745ec57..97f611f1 100644 --- a/web/modules/custom/hoeringsportal_data/hoeringsportal_data.services.yml +++ b/web/modules/custom/hoeringsportal_data/hoeringsportal_data.services.yml @@ -1,4 +1,8 @@ services: + logger.channel.hoeringsportal_data: + parent: logger.channel_base + arguments: [ 'hoeringsportal_data' ] + hoeringsportal_data.plandata: class: Drupal\hoeringsportal_data\Service\Plandata arguments: ['@settings'] @@ -8,7 +12,7 @@ services: hoeringsportal_data.hearing_helper: class: Drupal\hoeringsportal_data\Helper\HearingHelper - arguments: ['@entity_type.manager'] + arguments: ['@entity_type.manager', '@logger.channel.hoeringsportal_data'] hoeringsportal_data.map_item_helper: class: Drupal\hoeringsportal_data\Helper\MapItemHelper diff --git a/web/modules/custom/hoeringsportal_data/src/Drush/Commands/DrushCommands.php b/web/modules/custom/hoeringsportal_data/src/Drush/Commands/DrushCommands.php index a9fbf190..018cd829 100644 --- a/web/modules/custom/hoeringsportal_data/src/Drush/Commands/DrushCommands.php +++ b/web/modules/custom/hoeringsportal_data/src/Drush/Commands/DrushCommands.php @@ -2,7 +2,11 @@ namespace Drupal\hoeringsportal_data\Drush\Commands; +use Drupal\Component\Datetime\TimeInterface; +use Drupal\Core\Datetime\DrupalDateTime; +use Drupal\Core\State\StateInterface; use Drupal\hoeringsportal_data\Helper\HearingHelper; +use Drupal\hoeringsportal_deskpro\Service\HearingHelper as DeskproHearingHelper; use Drush\Attributes as CLI; use Drush\Commands\DrushCommands as BaseDrushCommands; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -17,6 +21,9 @@ final class DrushCommands extends BaseDrushCommands { */ public function __construct( private readonly HearingHelper $helper, + private readonly DeskproHearingHelper $deskproHelper, + private readonly TimeInterface $time, + private readonly StateInterface $state, ) { parent::__construct(); } @@ -27,6 +34,9 @@ public function __construct( public static function create(ContainerInterface $container) { return new static( $container->get('hoeringsportal_data.hearing_helper'), + $container->get('hoeringsportal_deskpro.helper'), + $container->get('datetime.time'), + $container->get('state') ); } @@ -66,4 +76,65 @@ public function showHearingState() { } } + /** + * A drush command for deleting replies from hearings. + */ + #[CLI\Command(name: 'hoeringsportal:data:delete-replies')] + public function processDeleteHearingReplies( + array $options = [ + 'last-run-at' => NULL, + ], + ): void { + $lastRunAt = $options['last-run-at'] ? new DrupalDateTime($options['last-run-at']) : $this->getLastRunAt(__METHOD__); + $requestTime = $this->getRequestTime(); + + $hearingIds = $this->helper->findHearingWhoseRepliesMustBeDeleted($lastRunAt, + $requestTime); + + if ($this->io()->isVerbose()) { + $this->io()->info(sprintf('Deleting hearing replies between %s and %s: %s', $lastRunAt->format('Y-m-d'), $requestTime->format('Y-m-d'), implode(', ', $hearingIds))); + } + + if ($options['yes'] || $this->confirm(sprintf('Delete replies on hearings %s', implode(', ', $hearingIds)))) { + $result = $this->deskproHelper->deleteHearingReplies($hearingIds); + + $this->io()->success(1 === $result + ? sprintf('Replies deleted from 1 hearing: %s', implode(', ', $hearingIds)) + : sprintf('Replies deleted from %d hearings: %s', $result, implode(', ', $hearingIds)) + ); + + $this->setLastRunAt(__METHOD__); + } + } + + /** + * Get request time. + */ + private function getRequestTime(): DrupalDateTime { + return DrupalDateTime::createFromTimestamp($this->time->getRequestTime()); + } + + /** + * Get time of last run. + */ + private function getLastRunAt(string $method): DrupalDateTime { + $time = $this->state->get($this->getLastRunKey($method)); + + return DrupalDateTime::createFromTimestamp($time ?? 0); + } + + /** + * Set time of last run. + */ + private function setLastRunAt(string $method) { + $this->state->set($this->getLastRunKey($method), $this->time->getRequestTime()); + } + + /** + * Get last run key. + */ + private function getLastRunKey(string $method): string { + return $method . '_last_run_at'; + } + } diff --git a/web/modules/custom/hoeringsportal_data/src/Helper/HearingHelper.php b/web/modules/custom/hoeringsportal_data/src/Helper/HearingHelper.php index f57db833..bc590ea6 100644 --- a/web/modules/custom/hoeringsportal_data/src/Helper/HearingHelper.php +++ b/web/modules/custom/hoeringsportal_data/src/Helper/HearingHelper.php @@ -4,30 +4,32 @@ use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Logger\LoggerChannelInterface; +use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface; use Drupal\node\Entity\Node; use Drupal\node\NodeInterface; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; /** * Hearing helper. */ -class HearingHelper { +class HearingHelper implements LoggerAwareInterface { + use LoggerAwareTrait; + const NODE_TYPE_HEARING = 'hearing'; const STATE_UPCOMING = 'upcoming'; const STATE_ACTIVE = 'active'; const STATE_FINISHED = 'finished'; - /** - * The entity type manager. - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - private $entityTypeManager; - /** * Constructor. */ - public function __construct(EntityTypeManagerInterface $entityTypeManager) { - $this->entityTypeManager = $entityTypeManager; + public function __construct( + private readonly EntityTypeManagerInterface $entityTypeManager, + LoggerChannelInterface $logger, + ) { + $this->setLogger($logger); } /** @@ -90,6 +92,51 @@ public function isDeadlinePassed(NodeInterface $node) { return $this->getDateTime() > new DrupalDateTime($deadline); } + /** + * Check if hearing's delete replies date is passed. + */ + public function isDeleteRepliesDatePassed(NodeInterface $node) { + if (!$this->isHearing($node)) { + return FALSE; + } + + $deadline = $node->field_delete_date->date; + + if (empty($deadline)) { + return FALSE; + } + + return $this->getDateTime() > new DrupalDateTime($deadline); + } + + /** + * Find hearings whose replies must be deleted. + * + * @return array + * A list of hearing ids. + */ + public function findHearingWhoseRepliesMustBeDeleted(DrupalDateTime $from, DrupalDateTime $to): array { + try { + return $this->entityTypeManager + ->getStorage('node') + ->getQuery() + ->condition('type', 'hearing') + ->condition('field_delete_date', [ + $from->format(DateTimeItemInterface::DATE_STORAGE_FORMAT), + $to->format(DateTimeItemInterface::DATE_STORAGE_FORMAT), + ], 'BETWEEN') + ->accessCheck(FALSE) + ->execute(); + } + catch (\Exception $exception) { + $this->logger->error('Error finding hearing whose replies must be deleted: @message', [ + '@message' => $exception->getMessage(), + ]); + + return []; + } + } + /** * A list of conditions. * @@ -125,7 +172,7 @@ public function isHearing($node) { /** * Get a date time object. */ - private function getDateTime($time = 'now', $timezone = 'UTC') { + private function getDateTime($time = 'now', $timezone = 'UTC'): DrupalDateTime { return new DrupalDateTime($time, $timezone); } diff --git a/web/modules/custom/hoeringsportal_deskpro/hoeringsportal_deskpro.module b/web/modules/custom/hoeringsportal_deskpro/hoeringsportal_deskpro.module index d5026c34..cafea7c2 100644 --- a/web/modules/custom/hoeringsportal_deskpro/hoeringsportal_deskpro.module +++ b/web/modules/custom/hoeringsportal_deskpro/hoeringsportal_deskpro.module @@ -37,6 +37,7 @@ function hoeringsportal_deskpro_theme() { 'is_deadline_passed' => NULL, 'tickets' => NULL, 'is_hearing_started' => NULL, + 'is_delete_replies_date_passed' => NULL, ], ], 'hoeringsportal_hearing_ticket' => [ diff --git a/web/modules/custom/hoeringsportal_deskpro/src/Plugin/Block/HearingTicketsBlock.php b/web/modules/custom/hoeringsportal_deskpro/src/Plugin/Block/HearingTicketsBlock.php index 92ff684b..a562ef6f 100644 --- a/web/modules/custom/hoeringsportal_deskpro/src/Plugin/Block/HearingTicketsBlock.php +++ b/web/modules/custom/hoeringsportal_deskpro/src/Plugin/Block/HearingTicketsBlock.php @@ -35,6 +35,7 @@ public function build() { '#is_deadline_passed' => $this->helper->isDeadlinePassed($node), '#tickets' => $this->helper->getHearingTickets($node), '#is_hearing_started' => $is_hearing_started, + '#is_delete_replies_date_passed' => $this->helper->isDeleteRepliesDatePassed($node), ]; } diff --git a/web/modules/custom/hoeringsportal_deskpro/src/Service/HearingHelper.php b/web/modules/custom/hoeringsportal_deskpro/src/Service/HearingHelper.php index 70561593..883178ba 100644 --- a/web/modules/custom/hoeringsportal_deskpro/src/Service/HearingHelper.php +++ b/web/modules/custom/hoeringsportal_deskpro/src/Service/HearingHelper.php @@ -81,6 +81,10 @@ public function __construct(DeskproService $deskpro, EntityTypeManagerInterface * Check if hearing deadline is passed. */ public function isDeadlinePassed(NodeInterface $node) { + if ($this->isDeleteRepliesDatePassed($node)) { + return TRUE; + } + if (!$this->isHearing($node)) { return FALSE; } @@ -99,6 +103,23 @@ public function isDeadlinePassed(NodeInterface $node) { return new DrupalDateTime() > new DrupalDateTime($deadline); } + /** + * Check if hearing's delete replies date is passed. + */ + public function isDeleteRepliesDatePassed(NodeInterface $node): bool { + if (!$this->isHearing($node)) { + return FALSE; + } + + $deadline = $node->field_delete_date->date; + + if (empty($deadline)) { + return FALSE; + } + + return new DrupalDateTime() > new DrupalDateTime($deadline); + } + /** * Check if node is a hearing. */ @@ -627,6 +648,21 @@ public function getDeskproTicket(NodeInterface $node, int $ticketId, bool $reset return $info[$bundle][$entity_id][$ticketId] ?? NULL; } + /** + * Delete hearing replies. + */ + public function deleteHearingReplies(array $nodeIds): int { + if (empty($nodeIds)) { + return 0; + } + + return $this->database->delete('hoeringsportal_deskpro_deskpro_tickets') + ->condition('entity_type', 'node', '=') + ->condition('bundle', 'hearing') + ->condition('entity_id', $nodeIds, 'IN') + ->execute(); + } + /** * Set Deskpro data for a node. * diff --git a/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig b/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig index 9ba31c31..999a3975 100644 --- a/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig +++ b/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig @@ -40,6 +40,20 @@ {% else %} + {% if is_delete_replies_date_passed %} + {# Deleted tickets information #} +
+ +

{{ 'You can read more about why and how we delete old tickets'|trans }}

+
+ + {% else %}
{% if hearing_ticket_list_url %} @@ -80,20 +94,7 @@ {% endfor %} {% endif %} - {% endif %} - - {# Deleted tickets information #} - {% if node.field_delete_date.value < "now"|date('Y-m-d') %} -
- -

{{ 'You can read more about why and how we delete old tickets'|trans }}

-
+ {% endif %} {% endif %}
From 47bae008c566df731aca41fb9e57fadd796a0e06 Mon Sep 17 00:00:00 2001 From: Mikkel Ricky Date: Fri, 4 Oct 2024 09:55:25 +0200 Subject: [PATCH 10/26] 2456: Improved stuff --- .../custom/hoeringsportal_data/README.md | 13 ++++++ .../src/Drush/Commands/DrushCommands.php | 44 ++++++++++++++----- .../hoeringsportal_deskpro.module | 2 +- .../src/Plugin/Block/HearingTicketsBlock.php | 2 +- .../src/Service/HearingHelper.php | 27 ++++++------ .../hoeringsportal-hearing-tickets.html.twig | 20 ++++----- 6 files changed, 71 insertions(+), 37 deletions(-) diff --git a/web/modules/custom/hoeringsportal_data/README.md b/web/modules/custom/hoeringsportal_data/README.md index 659ae791..89c15094 100644 --- a/web/modules/custom/hoeringsportal_data/README.md +++ b/web/modules/custom/hoeringsportal_data/README.md @@ -36,6 +36,19 @@ e.g. every minute */5 * * * * drush hoeringsportal:data:hearing-state-update ``` +Delete replies on hearings by running + +```sh +drush hoeringsportal:data:delete-replies +``` + +This should be done regularly by `cron` or other similar means, +e.g. daily at 03:00 + +```sh +0 3 * * * drush hoeringsportal:data:delete-replies +``` + ## Building assets First, install tools and requirements: diff --git a/web/modules/custom/hoeringsportal_data/src/Drush/Commands/DrushCommands.php b/web/modules/custom/hoeringsportal_data/src/Drush/Commands/DrushCommands.php index 018cd829..20dbd832 100644 --- a/web/modules/custom/hoeringsportal_data/src/Drush/Commands/DrushCommands.php +++ b/web/modules/custom/hoeringsportal_data/src/Drush/Commands/DrushCommands.php @@ -3,6 +3,7 @@ namespace Drupal\hoeringsportal_data\Drush\Commands; use Drupal\Component\Datetime\TimeInterface; +use Drupal\Core\Cache\Cache; use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\State\StateInterface; use Drupal\hoeringsportal_data\Helper\HearingHelper; @@ -80,28 +81,47 @@ public function showHearingState() { * A drush command for deleting replies from hearings. */ #[CLI\Command(name: 'hoeringsportal:data:delete-replies')] + #[CLI\Option(name: 'ids', description: 'Comma separated list of ids')] public function processDeleteHearingReplies( array $options = [ + 'ids' => NULL, 'last-run-at' => NULL, ], ): void { - $lastRunAt = $options['last-run-at'] ? new DrupalDateTime($options['last-run-at']) : $this->getLastRunAt(__METHOD__); - $requestTime = $this->getRequestTime(); + if (!empty($options['ids'])) { + $hearingIds = preg_split('/\s*,\s*/', $options['ids'] ?? '', PREG_SPLIT_NO_EMPTY); + } + else { + $lastRunAt = $options['last-run-at'] ? new DrupalDateTime($options['last-run-at']) : $this->getLastRunAt(__METHOD__); + $requestTime = $this->getRequestTime(); - $hearingIds = $this->helper->findHearingWhoseRepliesMustBeDeleted($lastRunAt, - $requestTime); + if ($this->io()->isVerbose()) { + $this->io()->info(sprintf('Finding hearings with delete replies date between %s and %s', $lastRunAt->format('Y-m-d'), $requestTime->format('Y-m-d'))); + } - if ($this->io()->isVerbose()) { - $this->io()->info(sprintf('Deleting hearing replies between %s and %s: %s', $lastRunAt->format('Y-m-d'), $requestTime->format('Y-m-d'), implode(', ', $hearingIds))); + $hearingIds = $options['ids'] ?? $this->helper->findHearingWhoseRepliesMustBeDeleted($lastRunAt, $requestTime); } - if ($options['yes'] || $this->confirm(sprintf('Delete replies on hearings %s', implode(', ', $hearingIds)))) { - $result = $this->deskproHelper->deleteHearingReplies($hearingIds); + if (empty($hearingIds)) { + $this->io()->info('No hearings found'); + return; + } - $this->io()->success(1 === $result - ? sprintf('Replies deleted from 1 hearing: %s', implode(', ', $hearingIds)) - : sprintf('Replies deleted from %d hearings: %s', $result, implode(', ', $hearingIds)) - ); + if ($options['yes'] || $this->confirm(sprintf('Delete replies on hearings %s', implode(', ', $hearingIds)))) { + $hearings = $this->helper->loadHearings([['nid', $hearingIds, 'IN']]); + foreach ($hearings as $hearing) { + $hearingRepliesDeletedOn = $this->deskproHelper->getHearingRepliesDeletedOn($hearing); + if (NULL !== $hearingRepliesDeletedOn) { + $this->deskproHelper->deleteHearingReplies([$hearing->id()]); + Cache::invalidateTags($hearing->getCacheTags()); + + $this->io()->success(sprintf('Replies deleted from hearing %s', + $hearing->id())); + } + else { + $this->io()->warning(sprintf('Replies on hearing %s must not yet be deleted', $hearing->id())); + } + } $this->setLastRunAt(__METHOD__); } diff --git a/web/modules/custom/hoeringsportal_deskpro/hoeringsportal_deskpro.module b/web/modules/custom/hoeringsportal_deskpro/hoeringsportal_deskpro.module index cafea7c2..0fb6d0e1 100644 --- a/web/modules/custom/hoeringsportal_deskpro/hoeringsportal_deskpro.module +++ b/web/modules/custom/hoeringsportal_deskpro/hoeringsportal_deskpro.module @@ -37,7 +37,7 @@ function hoeringsportal_deskpro_theme() { 'is_deadline_passed' => NULL, 'tickets' => NULL, 'is_hearing_started' => NULL, - 'is_delete_replies_date_passed' => NULL, + 'hearing_replies_deleted_on' => NULL, ], ], 'hoeringsportal_hearing_ticket' => [ diff --git a/web/modules/custom/hoeringsportal_deskpro/src/Plugin/Block/HearingTicketsBlock.php b/web/modules/custom/hoeringsportal_deskpro/src/Plugin/Block/HearingTicketsBlock.php index a562ef6f..5f14af24 100644 --- a/web/modules/custom/hoeringsportal_deskpro/src/Plugin/Block/HearingTicketsBlock.php +++ b/web/modules/custom/hoeringsportal_deskpro/src/Plugin/Block/HearingTicketsBlock.php @@ -35,7 +35,7 @@ public function build() { '#is_deadline_passed' => $this->helper->isDeadlinePassed($node), '#tickets' => $this->helper->getHearingTickets($node), '#is_hearing_started' => $is_hearing_started, - '#is_delete_replies_date_passed' => $this->helper->isDeleteRepliesDatePassed($node), + '#hearing_replies_deleted_on' => $this->helper->getHearingRepliesDeletedOn($node), ]; } diff --git a/web/modules/custom/hoeringsportal_deskpro/src/Service/HearingHelper.php b/web/modules/custom/hoeringsportal_deskpro/src/Service/HearingHelper.php index 883178ba..551360b3 100644 --- a/web/modules/custom/hoeringsportal_deskpro/src/Service/HearingHelper.php +++ b/web/modules/custom/hoeringsportal_deskpro/src/Service/HearingHelper.php @@ -81,7 +81,7 @@ public function __construct(DeskproService $deskpro, EntityTypeManagerInterface * Check if hearing deadline is passed. */ public function isDeadlinePassed(NodeInterface $node) { - if ($this->isDeleteRepliesDatePassed($node)) { + if (NULL !== $this->getHearingRepliesDeletedOn($node)) { return TRUE; } @@ -104,20 +104,23 @@ public function isDeadlinePassed(NodeInterface $node) { } /** - * Check if hearing's delete replies date is passed. + * Get the date when a hearing's replies should be deleted. + * + * @return \Drupal\Core\Datetime\DrupalDateTime|null + * The delete date if it's set and not in the future. */ - public function isDeleteRepliesDatePassed(NodeInterface $node): bool { + public function getHearingRepliesDeletedOn(NodeInterface $node): ?DrupalDateTime { if (!$this->isHearing($node)) { - return FALSE; + return NULL; } - $deadline = $node->field_delete_date->date; + $date = $node->field_delete_date->date; - if (empty($deadline)) { - return FALSE; + if (empty($date)) { + return NULL; } - return new DrupalDateTime() > new DrupalDateTime($deadline); + return new DrupalDateTime() > $date ? $date : NULL; } /** @@ -651,15 +654,13 @@ public function getDeskproTicket(NodeInterface $node, int $ticketId, bool $reset /** * Delete hearing replies. */ - public function deleteHearingReplies(array $nodeIds): int { - if (empty($nodeIds)) { - return 0; - } + public function deleteHearingReplies(int|array $nodeIds): int { + $nodeId = (array) $nodeIds; return $this->database->delete('hoeringsportal_deskpro_deskpro_tickets') ->condition('entity_type', 'node', '=') ->condition('bundle', 'hearing') - ->condition('entity_id', $nodeIds, 'IN') + ->condition('entity_id', $nodeIds ?: [0], 'IN') ->execute(); } diff --git a/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig b/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig index 999a3975..3b1029b8 100644 --- a/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig +++ b/web/modules/custom/hoeringsportal_deskpro/templates/block/hoeringsportal-hearing-tickets.html.twig @@ -40,18 +40,18 @@ {% else %} - {% if is_delete_replies_date_passed %} - {# Deleted tickets information #} -
-