From e3230860d56a71301761eb7cdf2b2fad0fb10c8b Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Wed, 6 May 2026 11:01:00 +0200 Subject: [PATCH 01/30] Initial; based off service catalogue work --- ...override.node.community_resource.title.yml | 17 + ...isplay.node.community_resource.default.yml | 127 ++++++ ...isplay.node.community_resource.default.yml | 79 ++++ ...display.node.community_resource.teaser.yml | 78 ++++ ...eld.field.node.community_resource.body.yml | 23 ++ ...mmunity_resource.field_cpcommhub_image.yml | 37 ++ ...ommunity_resource.field_cpcommhub_link.yml | 22 ++ ...ity_resource.field_cpcommhub_link_text.yml | 19 + ...mmunity_resource.field_cpcommhub_scope.yml | 20 + ...y_resource.field_cpcommhub_user_groups.yml | 31 ++ ...munity_resource.field_cpcommhub_weight.yml | 23 ++ ...eld.storage.node.field_cpcommhub_image.yml | 29 ++ ...ield.storage.node.field_cpcommhub_link.yml | 18 + ...storage.node.field_cpcommhub_link_text.yml | 20 + ...eld.storage.node.field_cpcommhub_scope.yml | 38 ++ ...orage.node.field_cpcommhub_user_groups.yml | 19 + ...ld.storage.node.field_cpcommhub_weight.yml | 19 + .../install/node.type.community_resource.yml | 17 + .../pathauto.pattern.cp_community_hub.yml | 22 ++ ...onomy.vocabulary.community_user_groups.yml | 9 + .../views.view.cpcommhub_resources.yml | 373 ++++++++++++++++++ .../config/schema/cp_community_hub.schema.yml | 2 + .../cp_community_hub.info.yml | 15 + .../cp_community_hub.libraries.yml | 6 + .../cp_community_hub/cp_community_hub.module | 36 ++ .../cp_community_hub.routing.yml | 0 .../cp_community_hub/css/cp-community-hub.css | 86 ++++ .../js/cp-community-hub-view.js | 40 ++ ...-node--field-cpcommhub-link-text.html.twig | 14 + ...field--node--field-cpcommhub-tag.html.twig | 15 + .../node--community-resource--full.html.twig | 37 ++ ...node--community-resource--teaser.html.twig | 31 ++ 32 files changed, 1322 insertions(+) create mode 100644 modules/custom/cp_community_hub/config/install/core.base_field_override.node.community_resource.title.yml create mode 100644 modules/custom/cp_community_hub/config/install/core.entity_form_display.node.community_resource.default.yml create mode 100644 modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.default.yml create mode 100644 modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.teaser.yml create mode 100644 modules/custom/cp_community_hub/config/install/field.field.node.community_resource.body.yml create mode 100644 modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_image.yml create mode 100644 modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_link.yml create mode 100644 modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_link_text.yml create mode 100644 modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_scope.yml create mode 100644 modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_user_groups.yml create mode 100644 modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_weight.yml create mode 100644 modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_image.yml create mode 100644 modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_link.yml create mode 100644 modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_link_text.yml create mode 100644 modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_scope.yml create mode 100644 modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_user_groups.yml create mode 100644 modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_weight.yml create mode 100644 modules/custom/cp_community_hub/config/install/node.type.community_resource.yml create mode 100644 modules/custom/cp_community_hub/config/install/pathauto.pattern.cp_community_hub.yml create mode 100644 modules/custom/cp_community_hub/config/install/taxonomy.vocabulary.community_user_groups.yml create mode 100644 modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml create mode 100644 modules/custom/cp_community_hub/config/schema/cp_community_hub.schema.yml create mode 100644 modules/custom/cp_community_hub/cp_community_hub.info.yml create mode 100644 modules/custom/cp_community_hub/cp_community_hub.libraries.yml create mode 100644 modules/custom/cp_community_hub/cp_community_hub.module create mode 100644 modules/custom/cp_community_hub/cp_community_hub.routing.yml create mode 100644 modules/custom/cp_community_hub/css/cp-community-hub.css create mode 100644 modules/custom/cp_community_hub/js/cp-community-hub-view.js create mode 100644 modules/custom/cp_community_hub/templates/field--node--field-cpcommhub-link-text.html.twig create mode 100644 modules/custom/cp_community_hub/templates/field--node--field-cpcommhub-tag.html.twig create mode 100644 modules/custom/cp_community_hub/templates/node--community-resource--full.html.twig create mode 100644 modules/custom/cp_community_hub/templates/node--community-resource--teaser.html.twig diff --git a/modules/custom/cp_community_hub/config/install/core.base_field_override.node.community_resource.title.yml b/modules/custom/cp_community_hub/config/install/core.base_field_override.node.community_resource.title.yml new file mode 100644 index 00000000..f6bb57e8 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/core.base_field_override.node.community_resource.title.yml @@ -0,0 +1,17 @@ +langcode: en +status: true +dependencies: + config: + - node.type.community_resource +id: node.community_resource.title +field_name: title +entity_type: node +bundle: community_resource +label: 'Resource title' +description: '' +required: true +translatable: true +default_value: { } +default_value_callback: '' +settings: { } +field_type: string diff --git a/modules/custom/cp_community_hub/config/install/core.entity_form_display.node.community_resource.default.yml b/modules/custom/cp_community_hub/config/install/core.entity_form_display.node.community_resource.default.yml new file mode 100644 index 00000000..80f2ac76 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/core.entity_form_display.node.community_resource.default.yml @@ -0,0 +1,127 @@ +langcode: en +status: true +dependencies: + config: + - field.field.node.community_resource.body + - field.field.node.community_resource.field_cpcommhub_image + - field.field.node.community_resource.field_cpcommhub_link + - field.field.node.community_resource.field_cpcommhub_link_text + - field.field.node.community_resource.field_cpcommhub_scope + - field.field.node.community_resource.field_cpcommhub_user_groups + - field.field.node.community_resource.field_cpcommhub_weight + - node.type.community_resource + module: + - image + - link + - options + - path + - text +id: node.community_resource.default +targetEntityType: node +bundle: community_resource +mode: default +content: + title: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + field_cpcommhub_user_groups: + type: options_buttons + weight: 1 + region: content + settings: { } + third_party_settings: { } + field_cpcommhub_scope: + type: options_select + weight: 2 + region: content + settings: { } + third_party_settings: { } + field_cpcommhub_image: + type: image_image + weight: 3 + region: content + settings: + progress_indicator: throbber + preview_image_style: thumbnail + third_party_settings: { } + body: + type: text_textarea_with_summary + weight: 4 + region: content + settings: + rows: 9 + summary_rows: 3 + placeholder: '' + show_summary: false + third_party_settings: { } + field_cpcommhub_link: + type: link_default + weight: 5 + region: content + settings: + placeholder_url: '' + placeholder_title: '' + third_party_settings: { } + field_cpcommhub_link_text: + type: string_textfield + weight: 6 + region: content + settings: + size: 40 + placeholder: 'Go to resource' + third_party_settings: { } + field_cpcommhub_weight: + type: number + weight: 7 + region: content + settings: { } + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 8 + region: content + settings: + match_operator: CONTAINS + match_limit: 10 + size: 60 + placeholder: '' + third_party_settings: { } + created: + type: datetime_timestamp + weight: 9 + region: content + settings: { } + third_party_settings: { } + status: + type: boolean_checkbox + weight: 10 + region: content + settings: + display_label: true + third_party_settings: { } + path: + type: path + weight: 11 + region: content + settings: { } + third_party_settings: { } + promote: + type: boolean_checkbox + weight: 12 + region: content + settings: + display_label: true + third_party_settings: { } + sticky: + type: boolean_checkbox + weight: 13 + region: content + settings: + display_label: true + third_party_settings: { } +hidden: { } diff --git a/modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.default.yml b/modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.default.yml new file mode 100644 index 00000000..aba15d9d --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.default.yml @@ -0,0 +1,79 @@ +langcode: en +status: true +dependencies: + config: + - field.field.node.community_resource.body + - field.field.node.community_resource.field_cpcommhub_image + - field.field.node.community_resource.field_cpcommhub_link + - field.field.node.community_resource.field_cpcommhub_link_text + - field.field.node.community_resource.field_cpcommhub_scope + - field.field.node.community_resource.field_cpcommhub_user_groups + - field.field.node.community_resource.field_cpcommhub_weight + - node.type.community_resource + module: + - image + - link + - text + - user +id: node.community_resource.default +targetEntityType: node +bundle: community_resource +mode: default +content: + field_cpcommhub_image: + type: image + label: hidden + settings: + image_link: '' + image_style: '' + image_loading: + attribute: lazy + third_party_settings: { } + weight: 0 + region: content + body: + type: text_default + label: hidden + settings: { } + third_party_settings: { } + weight: 1 + region: content + field_cpcommhub_link: + type: link + label: hidden + settings: + trim_length: 80 + url_only: true + url_plain: true + rel: '0' + target: '0' + third_party_settings: { } + weight: 2 + region: content + field_cpcommhub_link_text: + type: string + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + weight: 3 + region: content + field_cpcommhub_user_groups: + type: entity_reference_label + label: above + settings: + link: false + third_party_settings: { } + weight: 4 + region: content + field_cpcommhub_scope: + type: list_default + label: above + settings: { } + third_party_settings: { } + weight: 5 + region: content +hidden: + field_cpcommhub_weight: true + links: true + search_api_excerpt: true diff --git a/modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.teaser.yml b/modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.teaser.yml new file mode 100644 index 00000000..7c4bb53b --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.teaser.yml @@ -0,0 +1,78 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - field.field.node.community_resource.body + - field.field.node.community_resource.field_cpcommhub_image + - field.field.node.community_resource.field_cpcommhub_link + - field.field.node.community_resource.field_cpcommhub_link_text + - field.field.node.community_resource.field_cpcommhub_scope + - field.field.node.community_resource.field_cpcommhub_user_groups + - field.field.node.community_resource.field_cpcommhub_weight + - node.type.community_resource + module: + - image + - link + - text + - user +id: node.community_resource.teaser +targetEntityType: node +bundle: community_resource +mode: teaser +content: + field_cpcommhub_image: + type: image + label: hidden + settings: + image_link: '' + image_style: '' + image_loading: + attribute: lazy + third_party_settings: { } + weight: 0 + region: content + field_cpcommhub_user_groups: + type: entity_reference_label + label: hidden + settings: + link: false + third_party_settings: { } + weight: 1 + region: content + field_cpcommhub_scope: + type: list_default + label: hidden + settings: { } + third_party_settings: { } + weight: 2 + region: content + field_cpcommhub_link: + type: link + label: hidden + settings: + trim_length: 80 + url_only: true + url_plain: true + rel: '0' + target: '0' + third_party_settings: { } + weight: 3 + region: content + field_cpcommhub_link_text: + type: string + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + weight: 4 + region: content + links: + settings: { } + third_party_settings: { } + weight: 5 + region: content +hidden: + body: true + field_cpcommhub_weight: true + search_api_excerpt: true diff --git a/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.body.yml b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.body.yml new file mode 100644 index 00000000..00746913 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.body.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.body + - node.type.community_resource + module: + - text +id: node.community_resource.body +field_name: body +entity_type: node +bundle: community_resource +label: Description +description: 'A brief description of this resource and what it provides to the community.' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: + display_summary: false + required_summary: false + allowed_formats: { } +field_type: text_with_summary diff --git a/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_image.yml b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_image.yml new file mode 100644 index 00000000..96b2bd2a --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_image.yml @@ -0,0 +1,37 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_cpcommhub_image + - node.type.community_resource + module: + - image +id: node.community_resource.field_cpcommhub_image +field_name: field_cpcommhub_image +entity_type: node +bundle: community_resource +label: Image +description: 'Thumbnail image for this resource card. Minimum 512x288 pixels (16:9 aspect ratio).' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + handler: 'default:file' + handler_settings: { } + file_directory: '[date:custom:Y]-[date:custom:m]' + file_extensions: 'png gif jpg jpeg webp' + max_filesize: '' + max_resolution: '' + min_resolution: 512x288 + alt_field: true + alt_field_required: false + title_field: false + title_field_required: false + default_image: + uuid: '' + alt: '' + title: '' + width: null + height: null +field_type: image diff --git a/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_link.yml b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_link.yml new file mode 100644 index 00000000..34f87ed8 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_link.yml @@ -0,0 +1,22 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_cpcommhub_link + - node.type.community_resource + module: + - link +id: node.community_resource.field_cpcommhub_link +field_name: field_cpcommhub_link +entity_type: node +bundle: community_resource +label: 'Resource URL' +description: 'The URL of the resource.' +required: true +translatable: false +default_value: { } +default_value_callback: '' +settings: + title: 0 + link_type: 17 +field_type: link diff --git a/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_link_text.yml b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_link_text.yml new file mode 100644 index 00000000..c4891014 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_link_text.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_cpcommhub_link_text + - node.type.community_resource +id: node.community_resource.field_cpcommhub_link_text +field_name: field_cpcommhub_link_text +entity_type: node +bundle: community_resource +label: 'Link button text' +description: 'Text for the call-to-action button. Defaults to "Go to resource" if left blank.' +required: false +translatable: false +default_value: + - value: 'Go to resource' +default_value_callback: '' +settings: { } +field_type: string diff --git a/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_scope.yml b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_scope.yml new file mode 100644 index 00000000..1663982e --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_scope.yml @@ -0,0 +1,20 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_cpcommhub_scope + - node.type.community_resource + module: + - options +id: node.community_resource.field_cpcommhub_scope +field_name: field_cpcommhub_scope +entity_type: node +bundle: community_resource +label: Scope +description: 'The operational scope or category of this resource.' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: list_string diff --git a/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_user_groups.yml b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_user_groups.yml new file mode 100644 index 00000000..529ffe58 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_user_groups.yml @@ -0,0 +1,31 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_cpcommhub_user_groups + - node.type.community_resource + - taxonomy.vocabulary.community_user_groups + module: + - options + - taxonomy +id: node.community_resource.field_cpcommhub_user_groups +field_name: field_cpcommhub_user_groups +entity_type: node +bundle: community_resource +label: 'User Groups' +description: 'The user groups / personas this resource is intended for.' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + handler: 'default:taxonomy_term' + handler_settings: + target_bundles: + community_user_groups: community_user_groups + sort: + field: name + direction: asc + auto_create: false + auto_create_bundle: '' +field_type: entity_reference diff --git a/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_weight.yml b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_weight.yml new file mode 100644 index 00000000..85df30ca --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_weight.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_cpcommhub_weight + - node.type.community_resource +id: node.community_resource.field_cpcommhub_weight +field_name: field_cpcommhub_weight +entity_type: node +bundle: community_resource +label: 'Display weight' +description: 'Lower numbers appear first. Use 0 for default ordering, negative numbers to promote above others.' +required: false +translatable: false +default_value: + - value: 0 +default_value_callback: '' +settings: + min: '' + max: '' + prefix: '' + suffix: '' +field_type: integer diff --git a/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_image.yml b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_image.yml new file mode 100644 index 00000000..1546288b --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_image.yml @@ -0,0 +1,29 @@ +langcode: en +status: true +dependencies: + module: + - file + - image + - node +id: node.field_cpcommhub_image +field_name: field_cpcommhub_image +entity_type: node +type: image +settings: + target_type: file + display_field: false + display_default: true + uri_scheme: public + default_image: + uuid: '' + alt: '' + title: '' + width: null + height: null +module: image +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_link.yml b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_link.yml new file mode 100644 index 00000000..844288d2 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_link.yml @@ -0,0 +1,18 @@ +langcode: en +status: true +dependencies: + module: + - link + - node +id: node.field_cpcommhub_link +field_name: field_cpcommhub_link +entity_type: node +type: link +settings: { } +module: link +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_link_text.yml b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_link_text.yml new file mode 100644 index 00000000..e8ae96b8 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_link_text.yml @@ -0,0 +1,20 @@ +langcode: en +status: true +dependencies: + module: + - node +id: node.field_cpcommhub_link_text +field_name: field_cpcommhub_link_text +entity_type: node +type: string +settings: + max_length: 40 + case_sensitive: false + is_ascii: false +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_scope.yml b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_scope.yml new file mode 100644 index 00000000..c8b8fe0d --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_scope.yml @@ -0,0 +1,38 @@ +langcode: en +status: true +dependencies: + module: + - node + - options +id: node.field_cpcommhub_scope +field_name: field_cpcommhub_scope +entity_type: node +type: list_string +settings: + allowed_values: + - + value: governance_management + label: 'Governance & Management' + - + value: strategy_policies_guidance + label: 'Strategy, Policies & Guidance' + - + value: operations_practical + label: 'Operations & Practical Instructions' + - + value: scientific_technical + label: 'Scientific & Technical Infrastructure' + - + value: communication_onboarding + label: 'Communication & Onboarding' + - + value: meetings_collaboration + label: 'Meetings & Internal Collaboration' + allowed_values_function: '' +module: options +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_user_groups.yml b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_user_groups.yml new file mode 100644 index 00000000..4c95dc43 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_user_groups.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + module: + - node + - taxonomy +id: node.field_cpcommhub_user_groups +field_name: field_cpcommhub_user_groups +entity_type: node +type: entity_reference +settings: + target_type: taxonomy_term +module: core +locked: false +cardinality: -1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_weight.yml b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_weight.yml new file mode 100644 index 00000000..27a86c7e --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_weight.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + module: + - node +id: node.field_cpcommhub_weight +field_name: field_cpcommhub_weight +entity_type: node +type: integer +settings: + unsigned: false + size: normal +module: core +locked: false +cardinality: 1 +translatable: false +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/custom/cp_community_hub/config/install/node.type.community_resource.yml b/modules/custom/cp_community_hub/config/install/node.type.community_resource.yml new file mode 100644 index 00000000..dc07c5d2 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/node.type.community_resource.yml @@ -0,0 +1,17 @@ +langcode: en +status: true +dependencies: + module: + - menu_ui +third_party_settings: + menu_ui: + available_menus: + - main + parent: 'main:' +name: 'Community Resource' +type: community_resource +description: 'A resource entry in the Community Hub catalogue' +help: null +new_revision: true +preview_mode: 1 +display_submitted: false diff --git a/modules/custom/cp_community_hub/config/install/pathauto.pattern.cp_community_hub.yml b/modules/custom/cp_community_hub/config/install/pathauto.pattern.cp_community_hub.yml new file mode 100644 index 00000000..7b92c0c3 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/pathauto.pattern.cp_community_hub.yml @@ -0,0 +1,22 @@ +uuid: e241d093-790e-44f9-8c71-f178425a958f +langcode: en +status: true +dependencies: + module: + - node +id: cp_community_hub +label: 'Community Hub Resources' +type: 'canonical_entities:node' +pattern: '/community-hub/[node:title]' +selection_criteria: + 1a483b67-0d3d-4c0b-9b70-dde7786861ff: + id: 'entity_bundle:node' + negate: false + uuid: 1a483b67-0d3d-4c0b-9b70-dde7786861ff + context_mapping: + node: node + bundles: + community_resource: community_resource +selection_logic: and +weight: -5 +relationships: { } diff --git a/modules/custom/cp_community_hub/config/install/taxonomy.vocabulary.community_user_groups.yml b/modules/custom/cp_community_hub/config/install/taxonomy.vocabulary.community_user_groups.yml new file mode 100644 index 00000000..4719ca44 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/taxonomy.vocabulary.community_user_groups.yml @@ -0,0 +1,9 @@ +langcode: en +status: true +dependencies: { } +third_party_settings: { } +name: 'Community User Groups' +vid: community_user_groups +description: 'User groups / personas for Community Hub resources' +weight: 0 +new_revision: false diff --git a/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml b/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml new file mode 100644 index 00000000..dcd3c4e3 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml @@ -0,0 +1,373 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - node.type.community_resource + module: + - better_exposed_filters + - node + - taxonomy + - user +id: cpcommhub_resources +label: 'Community Hub Resources' +module: views +description: 'Catalogue of Community Hub resources' +tag: '' +base_table: node_field_data +base_field: nid +display: + default: + id: default + display_title: Default + display_plugin: default + position: 0 + display_options: + title: 'Community Hub' + fields: + rendered_entity: + id: rendered_entity + table: node + field: rendered_entity + relationship: none + group_type: group + admin_label: '' + entity_type: node + plugin_id: rendered_entity + label: '' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + view_mode: teaser + pager: + type: mini + options: + offset: 0 + pagination_heading_level: h4 + items_per_page: 24 + total_pages: null + id: 0 + tags: + next: ›› + previous: ‹‹ + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + exposed_form: + type: bef + options: + submit_button: Apply + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: true + sort_asc_label: Asc + sort_desc_label: Desc + text_input_required: 'Select any filter and click on Apply to see results' + text_input_required_format: basic_html + bef: + general: + autosubmit: true + autosubmit_exclude_textfield: false + autosubmit_textfield_delay: 500 + autosubmit_textfield_minimum_length: 3 + autosubmit_hide: true + input_required: false + allow_secondary: false + secondary_label: 'Advanced options' + secondary_open: false + reset_button_always_show: false + filter: + field_cpcommhub_user_groups_target_id: + plugin_id: bef + advanced: + sort_options: false + rewrite: + filter_rewrite_values: '' + filter_rewrite_values_key: false + collapsible: false + collapsible_disable_automatic_open: false + is_secondary: false + hide_label: false + select_all_none: false + select_all_none_nested: false + display_inline: true + field_cpcommhub_scope_value: + plugin_id: bef + advanced: + sort_options: false + rewrite: + filter_rewrite_values: '' + filter_rewrite_values_key: false + collapsible: false + collapsible_disable_automatic_open: false + is_secondary: false + hide_label: false + select_all_none: false + select_all_none_nested: false + display_inline: false + access: + type: perm + options: + perm: 'access content' + cache: + type: tag + options: { } + empty: + area: + id: area + table: views + field: area + relationship: none + group_type: group + admin_label: '' + plugin_id: text + empty: true + content: + value: 'No resources found.' + format: basic_html + tokenize: false + sorts: + field_cpcommhub_weight_value: + id: field_cpcommhub_weight_value + table: node__field_cpcommhub_weight + field: field_cpcommhub_weight_value + relationship: none + group_type: group + admin_label: '' + plugin_id: standard + order: ASC + expose: + label: '' + field_identifier: '' + exposed: false + title: + id: title + table: node_field_data + field: title + relationship: none + group_type: group + admin_label: '' + entity_type: node + entity_field: title + plugin_id: standard + order: ASC + expose: + label: '' + field_identifier: '' + exposed: false + arguments: { } + filters: + status: + id: status + table: node_field_data + field: status + entity_type: node + entity_field: status + plugin_id: boolean + value: '1' + group: 1 + expose: + operator: '' + type: + id: type + table: node_field_data + field: type + entity_type: node + entity_field: type + plugin_id: bundle + value: + community_resource: community_resource + group: 1 + field_cpcommhub_user_groups_target_id: + id: field_cpcommhub_user_groups_target_id + table: node__field_cpcommhub_user_groups + field: field_cpcommhub_user_groups_target_id + relationship: none + group_type: group + admin_label: '' + plugin_id: taxonomy_index_tid + operator: or + value: { } + group: 1 + exposed: true + expose: + operator_id: field_cpcommhub_user_groups_target_id_op + label: 'User Group' + description: '' + use_operator: false + operator: field_cpcommhub_user_groups_target_id_op + operator_limit_selection: false + operator_list: { } + identifier: user_groups_target_id + required: false + remember: false + multiple: true + remember_roles: + authenticated: authenticated + anonymous: '0' + administrator: '0' + editor: '0' + reduce: false + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + reduce_duplicates: false + type: checkboxes + limit: true + vid: community_user_groups + hierarchy: 0 + error_message: true + field_cpcommhub_scope_value: + id: field_cpcommhub_scope_value + table: node__field_cpcommhub_scope + field: field_cpcommhub_scope_value + relationship: none + group_type: group + admin_label: '' + plugin_id: list_field + operator: or + value: { } + group: 1 + exposed: true + expose: + operator_id: field_cpcommhub_scope_value_op + label: Scope + description: '' + use_operator: false + operator: field_cpcommhub_scope_value_op + operator_limit_selection: false + operator_list: { } + identifier: scope_value + required: false + remember: false + multiple: true + remember_roles: + authenticated: authenticated + anonymous: '0' + administrator: '0' + editor: '0' + reduce: false + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + reduce_duplicates: false + filter_groups: + operator: AND + groups: + 1: AND + style: + type: default + options: + row_class: '' + default_row_class: true + uses_fields: false + row: + type: fields + options: + default_field_elements: true + inline: { } + separator: '' + hide_empty: false + query: + type: views_query + options: + query_comment: '' + disable_sql_rewrite: false + distinct: false + replica: false + query_tags: { } + relationships: { } + css_class: cpcommhub-resources + use_ajax: true + header: { } + footer: { } + display_extenders: { } + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - 'user.node_grants:view' + - user.permissions + tags: { } + page_1: + id: page_1 + display_title: Page + display_plugin: page + position: 1 + display_options: + display_extenders: { } + path: community-hub + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - 'user.node_grants:view' + - user.permissions + tags: { } diff --git a/modules/custom/cp_community_hub/config/schema/cp_community_hub.schema.yml b/modules/custom/cp_community_hub/config/schema/cp_community_hub.schema.yml new file mode 100644 index 00000000..9f9cc028 --- /dev/null +++ b/modules/custom/cp_community_hub/config/schema/cp_community_hub.schema.yml @@ -0,0 +1,2 @@ +# Schema for cp_community_hub module configuration. +# No custom field types in this module; all fields use core schemas. diff --git a/modules/custom/cp_community_hub/cp_community_hub.info.yml b/modules/custom/cp_community_hub/cp_community_hub.info.yml new file mode 100644 index 00000000..82977ebb --- /dev/null +++ b/modules/custom/cp_community_hub/cp_community_hub.info.yml @@ -0,0 +1,15 @@ +name: CP Community Hub +description: Community Hub resource catalogue for internal ICOS community resources +package: CP +type: module +core_version_requirement: ^10 +dependencies: + - drupal:views + - drupal:taxonomy + - drupal:link + - drupal:image + - drupal:options + - better_exposed_filters:better_exposed_filters + - pathauto:pathauto +libraries: + - cp_community_hub/style diff --git a/modules/custom/cp_community_hub/cp_community_hub.libraries.yml b/modules/custom/cp_community_hub/cp_community_hub.libraries.yml new file mode 100644 index 00000000..23b9ad1b --- /dev/null +++ b/modules/custom/cp_community_hub/cp_community_hub.libraries.yml @@ -0,0 +1,6 @@ +style: + css: + theme: + css/cp-community-hub.css: {} + js: + js/cp-community-hub-view.js: {} diff --git a/modules/custom/cp_community_hub/cp_community_hub.module b/modules/custom/cp_community_hub/cp_community_hub.module new file mode 100644 index 00000000..0741b9dd --- /dev/null +++ b/modules/custom/cp_community_hub/cp_community_hub.module @@ -0,0 +1,36 @@ + [ + 'template' => 'field--node--field-cpcommhub-tag', + 'base hook' => 'field', + ], + 'field__node__field_cpcommhub_scope' => [ + 'template' => 'field--node--field-cpcommhub-tag', + 'base hook' => 'field', + ], + 'field__node__field_cpcommhub_link_text' => [ + 'template' => 'field--node--field-cpcommhub-link-text', + 'base hook' => 'field', + ], + 'node__community_resource__full' => [ + 'template' => 'node--community-resource--full', + 'base hook' => 'node', + ], + 'node__community_resource__teaser' => [ + 'template' => 'node--community-resource--teaser', + 'base hook' => 'node', + ], + ]; +} diff --git a/modules/custom/cp_community_hub/cp_community_hub.routing.yml b/modules/custom/cp_community_hub/cp_community_hub.routing.yml new file mode 100644 index 00000000..e69de29b diff --git a/modules/custom/cp_community_hub/css/cp-community-hub.css b/modules/custom/cp_community_hub/css/cp-community-hub.css new file mode 100644 index 00000000..d3e9e607 --- /dev/null +++ b/modules/custom/cp_community_hub/css/cp-community-hub.css @@ -0,0 +1,86 @@ +/* Utility class for hiding external link icon */ + +.no-external::after { + content: "" !important; + margin: 0 !important; +} + +/* Full/Teaser view field styles */ + +.field--name-field-cpcommhub-image { + overflow: hidden; + display: flex; + margin-bottom: 1em; + aspect-ratio: 16 / 9; + img { + width: 100%; + height: 100%; + object-fit: cover; + object-position: center; + } +} + +/* Community Hub view grid styles */ + +.cpcommhub-resources { + container: community-hub / inline-size; + + .view-content { + display: grid; + gap: 1rem; + align-items: stretch; + margin-top: 0.5rem; + } + + .view-filters { + .views-exposed-form.bef-exposed-form { + .form--inline { + .form-item-user-groups-target-id { + min-width: 100%; + margin-bottom: 1rem; + } + .form-item-scope-value { + min-width: 200px; + width: 23%; + } + } + + legend, .form-item label { + font-size: 1em; + margin-bottom: 0.5rem; + } + + .form-item { + margin-right: 1rem; + } + } + } +} + +@container community-hub (min-width: calc(900px + 2rem)) { + .view-content { + grid-template-columns: repeat(3, minmax(300px, 1fr)); + } +} + +@container community-hub (max-width: calc(899px + 2rem)) { + .view-content { + grid-template-columns: repeat(2, minmax(300px, 1fr)); + } +} + +@container community-hub (max-width: calc(599px + 1rem)) { + .view-content { + grid-template-columns: 1fr; + } +} + +body.path-community-hub .ajax-progress { + display: none; +} + +/* Scope filter hidden until a user group is selected */ + +.cpcommhub-scope-hidden { + display: none; +} diff --git a/modules/custom/cp_community_hub/js/cp-community-hub-view.js b/modules/custom/cp_community_hub/js/cp-community-hub-view.js new file mode 100644 index 00000000..1d625779 --- /dev/null +++ b/modules/custom/cp_community_hub/js/cp-community-hub-view.js @@ -0,0 +1,40 @@ +(function (Drupal, drupalSettings) { + + function getScopeWrapper(context) { + return context.querySelector('[data-drupal-selector="edit-scope-value"]') + ?.closest('.form-item, .js-form-item, fieldset, details'); + } + + function hasGroupSelected(context) { + return context.querySelectorAll( + '[data-drupal-selector="edit-user-groups-target-id"] input[type="checkbox"]:checked' + ).length > 0; + } + + function updateScopeVisibility(context) { + const wrapper = getScopeWrapper(context); + if (!wrapper) { + return; + } + if (hasGroupSelected(context)) { + wrapper.classList.remove('cpcommhub-scope-hidden'); + } else { + wrapper.classList.add('cpcommhub-scope-hidden'); + } + } + + Drupal.behaviors.communityHubViewRefresh = { + attach: function (context, settings) { + updateScopeVisibility(context); + + context.querySelectorAll( + '[data-drupal-selector="edit-user-groups-target-id"] input[type="checkbox"]' + ).forEach(function (checkbox) { + checkbox.addEventListener('change', function () { + updateScopeVisibility(context); + }); + }); + } + }; + +})(Drupal, drupalSettings); diff --git a/modules/custom/cp_community_hub/templates/field--node--field-cpcommhub-link-text.html.twig b/modules/custom/cp_community_hub/templates/field--node--field-cpcommhub-link-text.html.twig new file mode 100644 index 00000000..f1e7219d --- /dev/null +++ b/modules/custom/cp_community_hub/templates/field--node--field-cpcommhub-link-text.html.twig @@ -0,0 +1,14 @@ +{# +/** + * @file + * Renders the link button text, falling back to "Go to resource" if empty. + * + * Available variables: see field.html.twig + */ +#} + +{% if items[0].content %} + {{ items[0].content }} +{% else %} + Go to resource +{% endif %} diff --git a/modules/custom/cp_community_hub/templates/field--node--field-cpcommhub-tag.html.twig b/modules/custom/cp_community_hub/templates/field--node--field-cpcommhub-tag.html.twig new file mode 100644 index 00000000..e1b7caab --- /dev/null +++ b/modules/custom/cp_community_hub/templates/field--node--field-cpcommhub-tag.html.twig @@ -0,0 +1,15 @@ +{# +/** + * @file + * Shared template for tag-style fields: field_cpcommhub_user_groups and + * field_cpcommhub_scope. Renders values as Bootstrap badge pills. + * + * Available variables: see field.html.twig + */ +#} + +{% if items[0].content %} + {% for item in items %} + {{ item.content }} + {% endfor %} +{% endif %} diff --git a/modules/custom/cp_community_hub/templates/node--community-resource--full.html.twig b/modules/custom/cp_community_hub/templates/node--community-resource--full.html.twig new file mode 100644 index 00000000..1cdf40bb --- /dev/null +++ b/modules/custom/cp_community_hub/templates/node--community-resource--full.html.twig @@ -0,0 +1,37 @@ +{# +/** + * @file + * Theme implementation for a community_resource node in full/default view mode. + * + * This page is used for admin and editing purposes. Catalogue visitors are + * directed straight to the external resource URL from the teaser card. + * + * Available variables: see node.html.twig + */ +#} + + + +
+
+ {{ content.field_cpcommhub_image }} + {{ content.body }} +
+
+ + {{ content.field_cpcommhub_link_text }} + + +
+
    + {{ content.field_cpcommhub_user_groups }} + {{ content.field_cpcommhub_scope }} +
+
+
+
+ + diff --git a/modules/custom/cp_community_hub/templates/node--community-resource--teaser.html.twig b/modules/custom/cp_community_hub/templates/node--community-resource--teaser.html.twig new file mode 100644 index 00000000..03d63053 --- /dev/null +++ b/modules/custom/cp_community_hub/templates/node--community-resource--teaser.html.twig @@ -0,0 +1,31 @@ +{# +/** + * @file + * Theme implementation for a community_resource node in teaser view mode. + * + * Cards link only to the external resource URL — the Drupal detail page is not + * surfaced to catalogue visitors. + * + * Available variables: see node.html.twig + */ +#} + + + {{ content.field_cpcommhub_image }} +
+

{{ label }}

+
+ {{ content.field_cpcommhub_user_groups }} + {{ content.field_cpcommhub_scope }} +
+ +
+ From 69d582c1e27927ac50bdfdd1155958fd90198932 Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Thu, 7 May 2026 14:51:40 +0200 Subject: [PATCH 02/30] Basic setup refined, JS added for custom view visibility --- ...isplay.node.community_resource.default.yml | 21 +- ...isplay.node.community_resource.default.yml | 9 - ...display.node.community_resource.teaser.yml | 29 +-- ...ommunity_resource.field_cpcommhub_link.yml | 6 +- ...ity_resource.field_cpcommhub_link_text.yml | 19 -- ...storage.node.field_cpcommhub_link_text.yml | 20 -- ...eld.storage.node.field_cpcommhub_scope.yml | 2 +- .../views.view.cpcommhub_resources.yml | 185 ++++++++++++++++-- .../cp_community_hub/cp_community_hub.module | 16 -- .../cp_community_hub/css/cp-community-hub.css | 85 +------- .../js/cp-community-hub-view.js | 77 ++++++-- ...-node--field-cpcommhub-link-text.html.twig | 14 -- ...field--node--field-cpcommhub-tag.html.twig | 15 -- .../node--community-resource--full.html.twig | 37 ---- ...node--community-resource--teaser.html.twig | 54 +++-- 15 files changed, 280 insertions(+), 309 deletions(-) delete mode 100644 modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_link_text.yml delete mode 100644 modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_link_text.yml delete mode 100644 modules/custom/cp_community_hub/templates/field--node--field-cpcommhub-link-text.html.twig delete mode 100644 modules/custom/cp_community_hub/templates/field--node--field-cpcommhub-tag.html.twig delete mode 100644 modules/custom/cp_community_hub/templates/node--community-resource--full.html.twig diff --git a/modules/custom/cp_community_hub/config/install/core.entity_form_display.node.community_resource.default.yml b/modules/custom/cp_community_hub/config/install/core.entity_form_display.node.community_resource.default.yml index 80f2ac76..b0a570e1 100644 --- a/modules/custom/cp_community_hub/config/install/core.entity_form_display.node.community_resource.default.yml +++ b/modules/custom/cp_community_hub/config/install/core.entity_form_display.node.community_resource.default.yml @@ -5,7 +5,6 @@ dependencies: - field.field.node.community_resource.body - field.field.node.community_resource.field_cpcommhub_image - field.field.node.community_resource.field_cpcommhub_link - - field.field.node.community_resource.field_cpcommhub_link_text - field.field.node.community_resource.field_cpcommhub_scope - field.field.node.community_resource.field_cpcommhub_user_groups - field.field.node.community_resource.field_cpcommhub_weight @@ -31,19 +30,19 @@ content: third_party_settings: { } field_cpcommhub_user_groups: type: options_buttons - weight: 1 + weight: 3 region: content settings: { } third_party_settings: { } field_cpcommhub_scope: - type: options_select - weight: 2 + type: options_buttons + weight: 4 region: content settings: { } third_party_settings: { } field_cpcommhub_image: type: image_image - weight: 3 + weight: 2 region: content settings: progress_indicator: throbber @@ -51,7 +50,7 @@ content: third_party_settings: { } body: type: text_textarea_with_summary - weight: 4 + weight: 1 region: content settings: rows: 9 @@ -65,15 +64,7 @@ content: region: content settings: placeholder_url: '' - placeholder_title: '' - third_party_settings: { } - field_cpcommhub_link_text: - type: string_textfield - weight: 6 - region: content - settings: - size: 40 - placeholder: 'Go to resource' + placeholder_title: 'Go to resource' third_party_settings: { } field_cpcommhub_weight: type: number diff --git a/modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.default.yml b/modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.default.yml index aba15d9d..f7d8fb24 100644 --- a/modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.default.yml +++ b/modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.default.yml @@ -5,7 +5,6 @@ dependencies: - field.field.node.community_resource.body - field.field.node.community_resource.field_cpcommhub_image - field.field.node.community_resource.field_cpcommhub_link - - field.field.node.community_resource.field_cpcommhub_link_text - field.field.node.community_resource.field_cpcommhub_scope - field.field.node.community_resource.field_cpcommhub_user_groups - field.field.node.community_resource.field_cpcommhub_weight @@ -50,14 +49,6 @@ content: third_party_settings: { } weight: 2 region: content - field_cpcommhub_link_text: - type: string - label: hidden - settings: - link_to_entity: false - third_party_settings: { } - weight: 3 - region: content field_cpcommhub_user_groups: type: entity_reference_label label: above diff --git a/modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.teaser.yml b/modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.teaser.yml index 7c4bb53b..694215e4 100644 --- a/modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.teaser.yml +++ b/modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.teaser.yml @@ -6,7 +6,6 @@ dependencies: - field.field.node.community_resource.body - field.field.node.community_resource.field_cpcommhub_image - field.field.node.community_resource.field_cpcommhub_link - - field.field.node.community_resource.field_cpcommhub_link_text - field.field.node.community_resource.field_cpcommhub_scope - field.field.node.community_resource.field_cpcommhub_user_groups - field.field.node.community_resource.field_cpcommhub_weight @@ -32,21 +31,14 @@ content: third_party_settings: { } weight: 0 region: content - field_cpcommhub_user_groups: - type: entity_reference_label + body: + type: text_summary_or_trimmed label: hidden settings: - link: false + trim_length: 200 third_party_settings: { } weight: 1 region: content - field_cpcommhub_scope: - type: list_default - label: hidden - settings: { } - third_party_settings: { } - weight: 2 - region: content field_cpcommhub_link: type: link label: hidden @@ -57,22 +49,15 @@ content: rel: '0' target: '0' third_party_settings: { } - weight: 3 - region: content - field_cpcommhub_link_text: - type: string - label: hidden - settings: - link_to_entity: false - third_party_settings: { } - weight: 4 + weight: 2 region: content links: settings: { } third_party_settings: { } - weight: 5 + weight: 4 region: content hidden: - body: true + field_cpcommhub_scope: true + field_cpcommhub_user_groups: true field_cpcommhub_weight: true search_api_excerpt: true diff --git a/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_link.yml b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_link.yml index 34f87ed8..b5f8d56a 100644 --- a/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_link.yml +++ b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_link.yml @@ -10,13 +10,13 @@ id: node.community_resource.field_cpcommhub_link field_name: field_cpcommhub_link entity_type: node bundle: community_resource -label: 'Resource URL' -description: 'The URL of the resource.' +label: 'Resource link' +description: 'The URL and button text for the resource. Button text defaults to "Go to resource" if left blank.' required: true translatable: false default_value: { } default_value_callback: '' settings: - title: 0 + title: 1 link_type: 17 field_type: link diff --git a/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_link_text.yml b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_link_text.yml deleted file mode 100644 index c4891014..00000000 --- a/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_link_text.yml +++ /dev/null @@ -1,19 +0,0 @@ -langcode: en -status: true -dependencies: - config: - - field.storage.node.field_cpcommhub_link_text - - node.type.community_resource -id: node.community_resource.field_cpcommhub_link_text -field_name: field_cpcommhub_link_text -entity_type: node -bundle: community_resource -label: 'Link button text' -description: 'Text for the call-to-action button. Defaults to "Go to resource" if left blank.' -required: false -translatable: false -default_value: - - value: 'Go to resource' -default_value_callback: '' -settings: { } -field_type: string diff --git a/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_link_text.yml b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_link_text.yml deleted file mode 100644 index e8ae96b8..00000000 --- a/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_link_text.yml +++ /dev/null @@ -1,20 +0,0 @@ -langcode: en -status: true -dependencies: - module: - - node -id: node.field_cpcommhub_link_text -field_name: field_cpcommhub_link_text -entity_type: node -type: string -settings: - max_length: 40 - case_sensitive: false - is_ascii: false -module: core -locked: false -cardinality: 1 -translatable: true -indexes: { } -persist_with_no_fields: false -custom_storage: false diff --git a/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_scope.yml b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_scope.yml index c8b8fe0d..37cfe478 100644 --- a/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_scope.yml +++ b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_scope.yml @@ -31,7 +31,7 @@ settings: allowed_values_function: '' module: options locked: false -cardinality: 1 +cardinality: -1 translatable: true indexes: { } persist_with_no_fields: false diff --git a/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml b/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml index dcd3c4e3..063192b8 100644 --- a/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml +++ b/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml @@ -25,6 +25,133 @@ display: display_options: title: 'Community Hub' fields: + title: + id: title + table: node_field_data + field: title + relationship: none + group_type: group + admin_label: '' + entity_type: node + entity_field: title + plugin_id: field + label: Title + exclude: true + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: string + settings: + link_to_entity: false + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + body_value: + id: body_value + table: node__body + field: body_value + relationship: none + group_type: group + admin_label: '' + plugin_id: field + label: Body + exclude: true + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: text_default + settings: { } + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false rendered_entity: id: rendered_entity table: node @@ -135,7 +262,7 @@ display: select_all_none_nested: false display_inline: true field_cpcommhub_scope_value: - plugin_id: bef + plugin_id: default advanced: sort_options: false rewrite: @@ -145,9 +272,6 @@ display: collapsible_disable_automatic_open: false is_secondary: false hide_label: false - select_all_none: false - select_all_none_nested: false - display_inline: false access: type: perm options: @@ -221,6 +345,38 @@ display: value: community_resource: community_resource group: 1 + combine: + id: combine + table: views + field: combine + relationship: none + group_type: group + admin_label: '' + plugin_id: combine + operator: contains + value: '' + group: 1 + exposed: true + expose: + operator_id: '' + label: Search + description: '' + use_operator: false + operator: combine_op + operator_limit_selection: false + operator_list: { } + identifier: search + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + anonymous: '0' + administrator: '0' + editor: '0' + fields: + - title + - body_value field_cpcommhub_user_groups_target_id: id: field_cpcommhub_user_groups_target_id table: node__field_cpcommhub_user_groups @@ -292,7 +448,7 @@ display: identifier: scope_value required: false remember: false - multiple: true + multiple: false remember_roles: authenticated: authenticated anonymous: '0' @@ -317,11 +473,13 @@ display: groups: 1: AND style: - type: default + type: grid_responsive options: - row_class: '' - default_row_class: true - uses_fields: false + grouping: { } + columns: 3 + cell_min_width: 300 + grid_gutter: 16 + alignment: horizontal row: type: fields options: @@ -353,14 +511,13 @@ display: - 'user.node_grants:view' - user.permissions tags: { } - page_1: - id: page_1 - display_title: Page - display_plugin: page + block_1: + id: block_1 + display_title: Block + display_plugin: block position: 1 display_options: display_extenders: { } - path: community-hub cache_metadata: max-age: -1 contexts: diff --git a/modules/custom/cp_community_hub/cp_community_hub.module b/modules/custom/cp_community_hub/cp_community_hub.module index 0741b9dd..c9c7e0fe 100644 --- a/modules/custom/cp_community_hub/cp_community_hub.module +++ b/modules/custom/cp_community_hub/cp_community_hub.module @@ -12,22 +12,6 @@ function cp_community_hub_preprocess_node__community_resource(&$variables) { */ function cp_community_hub_theme() { return [ - 'field__node__field_cpcommhub_user_groups' => [ - 'template' => 'field--node--field-cpcommhub-tag', - 'base hook' => 'field', - ], - 'field__node__field_cpcommhub_scope' => [ - 'template' => 'field--node--field-cpcommhub-tag', - 'base hook' => 'field', - ], - 'field__node__field_cpcommhub_link_text' => [ - 'template' => 'field--node--field-cpcommhub-link-text', - 'base hook' => 'field', - ], - 'node__community_resource__full' => [ - 'template' => 'node--community-resource--full', - 'base hook' => 'node', - ], 'node__community_resource__teaser' => [ 'template' => 'node--community-resource--teaser', 'base hook' => 'node', diff --git a/modules/custom/cp_community_hub/css/cp-community-hub.css b/modules/custom/cp_community_hub/css/cp-community-hub.css index d3e9e607..d50a091b 100644 --- a/modules/custom/cp_community_hub/css/cp-community-hub.css +++ b/modules/custom/cp_community_hub/css/cp-community-hub.css @@ -1,86 +1,3 @@ -/* Utility class for hiding external link icon */ - -.no-external::after { - content: "" !important; - margin: 0 !important; -} - -/* Full/Teaser view field styles */ - -.field--name-field-cpcommhub-image { - overflow: hidden; - display: flex; - margin-bottom: 1em; - aspect-ratio: 16 / 9; - img { - width: 100%; - height: 100%; - object-fit: cover; - object-position: center; - } -} - -/* Community Hub view grid styles */ - -.cpcommhub-resources { - container: community-hub / inline-size; - - .view-content { - display: grid; - gap: 1rem; - align-items: stretch; - margin-top: 0.5rem; - } - - .view-filters { - .views-exposed-form.bef-exposed-form { - .form--inline { - .form-item-user-groups-target-id { - min-width: 100%; - margin-bottom: 1rem; - } - .form-item-scope-value { - min-width: 200px; - width: 23%; - } - } - - legend, .form-item label { - font-size: 1em; - margin-bottom: 0.5rem; - } - - .form-item { - margin-right: 1rem; - } - } - } -} - -@container community-hub (min-width: calc(900px + 2rem)) { - .view-content { - grid-template-columns: repeat(3, minmax(300px, 1fr)); - } -} - -@container community-hub (max-width: calc(899px + 2rem)) { - .view-content { - grid-template-columns: repeat(2, minmax(300px, 1fr)); - } -} - -@container community-hub (max-width: calc(599px + 1rem)) { - .view-content { - grid-template-columns: 1fr; - } -} - -body.path-community-hub .ajax-progress { - display: none; -} - -/* Scope filter hidden until a user group is selected */ - -.cpcommhub-scope-hidden { +#page-wrapper:not(.layout-builder-overrides-node-view) .block-views-blockcpcommhub-resources-block-1 { display: none; } diff --git a/modules/custom/cp_community_hub/js/cp-community-hub-view.js b/modules/custom/cp_community_hub/js/cp-community-hub-view.js index 1d625779..08ba1aea 100644 --- a/modules/custom/cp_community_hub/js/cp-community-hub-view.js +++ b/modules/custom/cp_community_hub/js/cp-community-hub-view.js @@ -1,40 +1,75 @@ -(function (Drupal, drupalSettings) { +(function (Drupal, once) { - function getScopeWrapper(context) { - return context.querySelector('[data-drupal-selector="edit-scope-value"]') + var VIEW_BLOCK = '.block-views-blockcpcommhub-resources-block-1'; + var INTRO_BLOCK = '.block-inline-blockbasic'; + var GROUP_CONTAINER = '#user-groups-container'; + var GROUP_SELECTOR = '[data-drupal-selector="edit-user-groups-target-id"]'; + var FORM_ID = 'views-exposed-form-cpcommhub-resources-block-1'; + + function moveUserGroupsFilter() { + var groupContainer = document.querySelector(GROUP_CONTAINER); + if (!groupContainer) { + return; + } + var filterWrapper = document.querySelector(GROUP_SELECTOR) ?.closest('.form-item, .js-form-item, fieldset, details'); + if (!filterWrapper) { + return; + } + filterWrapper.querySelectorAll('input[type="checkbox"]').forEach(function (checkbox) { + checkbox.setAttribute('form', FORM_ID); + }); + groupContainer.appendChild(filterWrapper); } - function hasGroupSelected(context) { - return context.querySelectorAll( - '[data-drupal-selector="edit-user-groups-target-id"] input[type="checkbox"]:checked' + function hideInViewGroupsFilter(context) { + var wrapper = context.querySelector(GROUP_SELECTOR) + ?.closest('.form-item, .js-form-item, fieldset, details'); + if (wrapper && !wrapper.closest(GROUP_CONTAINER)) { + wrapper.classList.add('d-none'); + } + } + + function hasGroupSelected() { + return document.querySelectorAll( + GROUP_CONTAINER + ' input[type="checkbox"]:checked' ).length > 0; } - function updateScopeVisibility(context) { - const wrapper = getScopeWrapper(context); - if (!wrapper) { + function updateBlockVisibility() { + var viewBlock = document.querySelector(VIEW_BLOCK); + var introBlock = document.querySelector(INTRO_BLOCK); + if (!viewBlock || !introBlock) { return; } - if (hasGroupSelected(context)) { - wrapper.classList.remove('cpcommhub-scope-hidden'); + if (hasGroupSelected()) { + viewBlock.classList.add('d-block'); + introBlock.classList.add('d-none'); } else { - wrapper.classList.add('cpcommhub-scope-hidden'); + viewBlock.classList.remove('d-block'); + introBlock.classList.remove('d-none'); } } - Drupal.behaviors.communityHubViewRefresh = { + Drupal.behaviors.communityHubView = { attach: function (context, settings) { - updateScopeVisibility(context); + once('commhub-move-groups', 'body', document).forEach(function () { + moveUserGroupsFilter(); + }); - context.querySelectorAll( - '[data-drupal-selector="edit-user-groups-target-id"] input[type="checkbox"]' - ).forEach(function (checkbox) { - checkbox.addEventListener('change', function () { - updateScopeVisibility(context); + hideInViewGroupsFilter(context); + + updateBlockVisibility(); + + once('commhub-group-listeners', GROUP_CONTAINER, document) + .forEach(function (container) { + container.addEventListener('change', function (e) { + if (e.target.matches('input[type="checkbox"]')) { + updateBlockVisibility(); + } + }); }); - }); } }; -})(Drupal, drupalSettings); +})(Drupal, once); diff --git a/modules/custom/cp_community_hub/templates/field--node--field-cpcommhub-link-text.html.twig b/modules/custom/cp_community_hub/templates/field--node--field-cpcommhub-link-text.html.twig deleted file mode 100644 index f1e7219d..00000000 --- a/modules/custom/cp_community_hub/templates/field--node--field-cpcommhub-link-text.html.twig +++ /dev/null @@ -1,14 +0,0 @@ -{# -/** - * @file - * Renders the link button text, falling back to "Go to resource" if empty. - * - * Available variables: see field.html.twig - */ -#} - -{% if items[0].content %} - {{ items[0].content }} -{% else %} - Go to resource -{% endif %} diff --git a/modules/custom/cp_community_hub/templates/field--node--field-cpcommhub-tag.html.twig b/modules/custom/cp_community_hub/templates/field--node--field-cpcommhub-tag.html.twig deleted file mode 100644 index e1b7caab..00000000 --- a/modules/custom/cp_community_hub/templates/field--node--field-cpcommhub-tag.html.twig +++ /dev/null @@ -1,15 +0,0 @@ -{# -/** - * @file - * Shared template for tag-style fields: field_cpcommhub_user_groups and - * field_cpcommhub_scope. Renders values as Bootstrap badge pills. - * - * Available variables: see field.html.twig - */ -#} - -{% if items[0].content %} - {% for item in items %} - {{ item.content }} - {% endfor %} -{% endif %} diff --git a/modules/custom/cp_community_hub/templates/node--community-resource--full.html.twig b/modules/custom/cp_community_hub/templates/node--community-resource--full.html.twig deleted file mode 100644 index 1cdf40bb..00000000 --- a/modules/custom/cp_community_hub/templates/node--community-resource--full.html.twig +++ /dev/null @@ -1,37 +0,0 @@ -{# -/** - * @file - * Theme implementation for a community_resource node in full/default view mode. - * - * This page is used for admin and editing purposes. Catalogue visitors are - * directed straight to the external resource URL from the teaser card. - * - * Available variables: see node.html.twig - */ -#} - - - -
-
- {{ content.field_cpcommhub_image }} - {{ content.body }} -
-
- - {{ content.field_cpcommhub_link_text }} - - -
-
    - {{ content.field_cpcommhub_user_groups }} - {{ content.field_cpcommhub_scope }} -
-
-
-
- - diff --git a/modules/custom/cp_community_hub/templates/node--community-resource--teaser.html.twig b/modules/custom/cp_community_hub/templates/node--community-resource--teaser.html.twig index 03d63053..d2f2a14e 100644 --- a/modules/custom/cp_community_hub/templates/node--community-resource--teaser.html.twig +++ b/modules/custom/cp_community_hub/templates/node--community-resource--teaser.html.twig @@ -3,29 +3,45 @@ * @file * Theme implementation for a community_resource node in teaser view mode. * - * Cards link only to the external resource URL — the Drupal detail page is not - * surfaced to catalogue visitors. + * Modeled on the news article teaser, but with body text included and all + * links pointing directly to the external resource URL (the Drupal detail + * page is not surfaced to catalogue visitors). * * Available variables: see node.html.twig */ #} +{% + set classes = [ + 'node', + 'node--type-' ~ node.bundle|clean_class, + view_mode ? 'node--view-mode-' ~ view_mode|clean_class, + 'col', + ] +%} +{% set resource_url = content.field_cpcommhub_link[0] %} - - {{ content.field_cpcommhub_image }} -
-

{{ label }}

-
- {{ content.field_cpcommhub_user_groups }} - {{ content.field_cpcommhub_scope }} + + + +
+ {{ content.field_cpcommhub_image }}
-
- - {{ content.field_cpcommhub_link_text }} - + + + {{ title_prefix }} + {% if label %} + + + {{ label }} -
-
-
+ + {% endif %} + {{ title_suffix }} + + {{ content.body }} + + + {{ node.field_cpcommhub_link.0.title ?: 'Go to resource' }} + + + From 19fdef4e38a83f6c96b2ef2acbf0b47d9cee5df6 Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Fri, 8 May 2026 10:36:42 +0200 Subject: [PATCH 03/30] Improve JS code, hide user group legend --- .../cp_community_hub/css/cp-community-hub.css | 4 ++ .../js/cp-community-hub-view.js | 70 ++++++++++--------- 2 files changed, 40 insertions(+), 34 deletions(-) diff --git a/modules/custom/cp_community_hub/css/cp-community-hub.css b/modules/custom/cp_community_hub/css/cp-community-hub.css index d50a091b..7cde4e7a 100644 --- a/modules/custom/cp_community_hub/css/cp-community-hub.css +++ b/modules/custom/cp_community_hub/css/cp-community-hub.css @@ -1,3 +1,7 @@ #page-wrapper:not(.layout-builder-overrides-node-view) .block-views-blockcpcommhub-resources-block-1 { display: none; } + +#edit-user-groups-target-id--wrapper legend { + display: none; +} diff --git a/modules/custom/cp_community_hub/js/cp-community-hub-view.js b/modules/custom/cp_community_hub/js/cp-community-hub-view.js index 08ba1aea..28d4ecb0 100644 --- a/modules/custom/cp_community_hub/js/cp-community-hub-view.js +++ b/modules/custom/cp_community_hub/js/cp-community-hub-view.js @@ -1,47 +1,52 @@ (function (Drupal, once) { - var VIEW_BLOCK = '.block-views-blockcpcommhub-resources-block-1'; - var INTRO_BLOCK = '.block-inline-blockbasic'; - var GROUP_CONTAINER = '#user-groups-container'; - var GROUP_SELECTOR = '[data-drupal-selector="edit-user-groups-target-id"]'; - var FORM_ID = 'views-exposed-form-cpcommhub-resources-block-1'; + const viewBlockSelector = '.block-views-blockcpcommhub-resources-block-1'; + const introBlockSelector = '.block-inline-blockbasic'; + const groupContainerSelector = '#user-groups-container'; + const filterGroupsSelector = '[data-drupal-selector="edit-user-groups-target-id"]'; + const viewsFormId = 'views-exposed-form-cpcommhub-resources-block-1'; function moveUserGroupsFilter() { - var groupContainer = document.querySelector(GROUP_CONTAINER); - if (!groupContainer) { + const groupContainer = document.querySelector(groupContainerSelector); + const filterWrapper = document.querySelector(filterGroupsSelector)?.closest('.form-item, .js-form-item, fieldset, details'); + + if (!groupContainer || !filterWrapper) { return; } - var filterWrapper = document.querySelector(GROUP_SELECTOR) - ?.closest('.form-item, .js-form-item, fieldset, details'); - if (!filterWrapper) { - return; + + for (let checkbox of filterWrapper.querySelectorAll('input[type="checkbox"]')) { + checkbox.setAttribute('form', viewsFormId); + checkbox.classList.add('btn-check'); + checkbox.setAttribute('autocomplete', 'off'); + checkbox.closest('.form-check')?.classList.add('d-inline'); + const label = filterWrapper.querySelector('label[for="' + checkbox.id + '"]'); + if (label) { + label.classList.add('btn', 'btn-outline-primary'); + } } - filterWrapper.querySelectorAll('input[type="checkbox"]').forEach(function (checkbox) { - checkbox.setAttribute('form', FORM_ID); - }); + groupContainer.appendChild(filterWrapper); } - function hideInViewGroupsFilter(context) { - var wrapper = context.querySelector(GROUP_SELECTOR) - ?.closest('.form-item, .js-form-item, fieldset, details'); - if (wrapper && !wrapper.closest(GROUP_CONTAINER)) { + function hideGroupsFilterInView(context) { + const wrapper = context.querySelector(filterGroupsSelector)?.closest('.form-item, .js-form-item, fieldset, details'); + if (wrapper && !wrapper.closest(groupContainerSelector)) { wrapper.classList.add('d-none'); } } function hasGroupSelected() { - return document.querySelectorAll( - GROUP_CONTAINER + ' input[type="checkbox"]:checked' - ).length > 0; + return document.querySelectorAll(groupContainerSelector + ' input[type="checkbox"]:checked').length > 0; } function updateBlockVisibility() { - var viewBlock = document.querySelector(VIEW_BLOCK); - var introBlock = document.querySelector(INTRO_BLOCK); + const viewBlock = document.querySelector(viewBlockSelector); + const introBlock = document.querySelector(introBlockSelector); + if (!viewBlock || !introBlock) { return; } + if (hasGroupSelected()) { viewBlock.classList.add('d-block'); introBlock.classList.add('d-none'); @@ -53,22 +58,19 @@ Drupal.behaviors.communityHubView = { attach: function (context, settings) { - once('commhub-move-groups', 'body', document).forEach(function () { - moveUserGroupsFilter(); - }); + once('commhub-move-groups', 'body', document).forEach(() => moveUserGroupsFilter()); - hideInViewGroupsFilter(context); + hideGroupsFilterInView(context); updateBlockVisibility(); - once('commhub-group-listeners', GROUP_CONTAINER, document) - .forEach(function (container) { - container.addEventListener('change', function (e) { - if (e.target.matches('input[type="checkbox"]')) { - updateBlockVisibility(); - } - }); + once('commhub-group-listeners', groupContainerSelector, document).forEach((container) => { + container.addEventListener('change', (e) => { + if (e.target.matches('input[type="checkbox"]')) { + updateBlockVisibility(); + } }); + }); } }; From bbc32235946d1807bc324446ab95a4d29cb73432 Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Mon, 11 May 2026 16:28:47 +0200 Subject: [PATCH 04/30] WIP CSS and module changes --- .../install/views.view.cpcommhub_resources.yml | 2 +- .../cp_community_hub/cp_community_hub.module | 14 ++++++++++++++ .../cp_community_hub/css/cp-community-hub.css | 7 +++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml b/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml index 063192b8..a42bfb7e 100644 --- a/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml +++ b/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml @@ -492,7 +492,7 @@ display: options: query_comment: '' disable_sql_rewrite: false - distinct: false + distinct: true replica: false query_tags: { } relationships: { } diff --git a/modules/custom/cp_community_hub/cp_community_hub.module b/modules/custom/cp_community_hub/cp_community_hub.module index c9c7e0fe..91d28c12 100644 --- a/modules/custom/cp_community_hub/cp_community_hub.module +++ b/modules/custom/cp_community_hub/cp_community_hub.module @@ -1,5 +1,7 @@ id() === 'cpcommhub_resources') { + $view->element['#attached']['library'][] = 'cp_community_hub/style'; + } +} + /** * Implements hook_theme(). */ diff --git a/modules/custom/cp_community_hub/css/cp-community-hub.css b/modules/custom/cp_community_hub/css/cp-community-hub.css index 7cde4e7a..1701a13e 100644 --- a/modules/custom/cp_community_hub/css/cp-community-hub.css +++ b/modules/custom/cp_community_hub/css/cp-community-hub.css @@ -5,3 +5,10 @@ #edit-user-groups-target-id--wrapper legend { display: none; } + +#edit-user-groups-target-id--wrapper .form-checkboxes.bef-checkboxes { + display: flex; + flex-wrap: wrap; + justify-content: center; + margin-top: 1rem; +} From bd6026e9dfe7e2a0e39538aa92141439bd3da9dc Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Mon, 11 May 2026 17:05:15 +0200 Subject: [PATCH 05/30] WIP Working sync between filters and buttons --- .../cp_community_hub/css/cp-community-hub.css | 4 ++++ .../js/cp-community-hub-view.js | 24 +++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/modules/custom/cp_community_hub/css/cp-community-hub.css b/modules/custom/cp_community_hub/css/cp-community-hub.css index 1701a13e..ef0c97e7 100644 --- a/modules/custom/cp_community_hub/css/cp-community-hub.css +++ b/modules/custom/cp_community_hub/css/cp-community-hub.css @@ -12,3 +12,7 @@ justify-content: center; margin-top: 1rem; } + +.ajax-progress { + display: none; +} diff --git a/modules/custom/cp_community_hub/js/cp-community-hub-view.js b/modules/custom/cp_community_hub/js/cp-community-hub-view.js index 28d4ecb0..2c7b8cb6 100644 --- a/modules/custom/cp_community_hub/js/cp-community-hub-view.js +++ b/modules/custom/cp_community_hub/js/cp-community-hub-view.js @@ -6,26 +6,28 @@ const filterGroupsSelector = '[data-drupal-selector="edit-user-groups-target-id"]'; const viewsFormId = 'views-exposed-form-cpcommhub-resources-block-1'; - function moveUserGroupsFilter() { + function cloneUserGroupsFilter() { const groupContainer = document.querySelector(groupContainerSelector); - const filterWrapper = document.querySelector(filterGroupsSelector)?.closest('.form-item, .js-form-item, fieldset, details'); + const filterEl = document.querySelector(filterGroupsSelector); + const filterWrapper = filterEl?.closest('.form-item, .js-form-item, fieldset, details'); if (!groupContainer || !filterWrapper) { return; } - for (let checkbox of filterWrapper.querySelectorAll('input[type="checkbox"]')) { + const clone = filterWrapper.cloneNode(true); + for (let checkbox of clone.querySelectorAll('input[type="checkbox"]')) { checkbox.setAttribute('form', viewsFormId); checkbox.classList.add('btn-check'); checkbox.setAttribute('autocomplete', 'off'); - checkbox.closest('.form-check')?.classList.add('d-inline'); - const label = filterWrapper.querySelector('label[for="' + checkbox.id + '"]'); + const label = clone.querySelector('label[for="' + checkbox.id + '"]'); if (label) { label.classList.add('btn', 'btn-outline-primary'); } } - groupContainer.appendChild(filterWrapper); + groupContainer.appendChild(clone); + filterWrapper.classList.add('d-none'); } function hideGroupsFilterInView(context) { @@ -58,7 +60,7 @@ Drupal.behaviors.communityHubView = { attach: function (context, settings) { - once('commhub-move-groups', 'body', document).forEach(() => moveUserGroupsFilter()); + once('commhub-clone-groups', 'body', document).forEach(() => cloneUserGroupsFilter()); hideGroupsFilterInView(context); @@ -68,6 +70,14 @@ container.addEventListener('change', (e) => { if (e.target.matches('input[type="checkbox"]')) { updateBlockVisibility(); + const form = document.getElementById(viewsFormId); + const internalCb = form + ? Array.from(form.querySelectorAll('input[type="checkbox"]')).find(cb => cb.name === e.target.name) + : null; + if (internalCb) { + internalCb.checked = e.target.checked; + internalCb.dispatchEvent(new Event('change', { bubbles: true })); + } } }); }); From 9016324ac0469551a0eece5d82a773ae59f12d53 Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Mon, 11 May 2026 17:15:17 +0200 Subject: [PATCH 06/30] Ensure content is not visible until loaded --- .../custom/cp_community_hub/js/cp-community-hub-view.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/custom/cp_community_hub/js/cp-community-hub-view.js b/modules/custom/cp_community_hub/js/cp-community-hub-view.js index 2c7b8cb6..b592cd1e 100644 --- a/modules/custom/cp_community_hub/js/cp-community-hub-view.js +++ b/modules/custom/cp_community_hub/js/cp-community-hub-view.js @@ -65,17 +65,25 @@ hideGroupsFilterInView(context); updateBlockVisibility(); + document.querySelector(viewBlockSelector + ' .view-content')?.classList.remove('invisible'); once('commhub-group-listeners', groupContainerSelector, document).forEach((container) => { container.addEventListener('change', (e) => { if (e.target.matches('input[type="checkbox"]')) { + const viewBlock = document.querySelector(viewBlockSelector); + const wasHidden = viewBlock && !viewBlock.classList.contains('d-block'); + updateBlockVisibility(); + const form = document.getElementById(viewsFormId); const internalCb = form ? Array.from(form.querySelectorAll('input[type="checkbox"]')).find(cb => cb.name === e.target.name) : null; if (internalCb) { internalCb.checked = e.target.checked; + if (wasHidden) { + document.querySelector(viewBlockSelector + ' .view-content')?.classList.add('invisible'); + } internalCb.dispatchEvent(new Event('change', { bubbles: true })); } } From f6ef5713d58aeda768f00074a7ee9edfbb9fa889 Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Tue, 12 May 2026 10:15:56 +0200 Subject: [PATCH 07/30] Refine configuration and styling --- .../views.view.cpcommhub_resources.yml | 78 +++++++++---------- .../cp_community_hub/css/cp-community-hub.css | 4 + 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml b/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml index a42bfb7e..5c2e548b 100644 --- a/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml +++ b/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml @@ -90,15 +90,15 @@ display: multi_type: separator separator: ', ' field_api_classes: false - body_value: - id: body_value + body: + id: body table: node__body - field: body_value + field: body relationship: none group_type: group admin_label: '' plugin_id: field - label: Body + label: '' exclude: true alter: alter_text: false @@ -225,7 +225,7 @@ display: exposed_form: type: bef options: - submit_button: Apply + submit_button: Search reset_button: false reset_button_label: Reset exposed_sorts_label: 'Sort by' @@ -240,7 +240,7 @@ display: autosubmit_exclude_textfield: false autosubmit_textfield_delay: 500 autosubmit_textfield_minimum_length: 3 - autosubmit_hide: true + autosubmit_hide: false input_required: false allow_secondary: false secondary_label: 'Advanced options' @@ -258,7 +258,7 @@ display: collapsible_disable_automatic_open: false is_secondary: false hide_label: false - select_all_none: false + select_all_none: true select_all_none_nested: false display_inline: true field_cpcommhub_scope_value: @@ -345,38 +345,6 @@ display: value: community_resource: community_resource group: 1 - combine: - id: combine - table: views - field: combine - relationship: none - group_type: group - admin_label: '' - plugin_id: combine - operator: contains - value: '' - group: 1 - exposed: true - expose: - operator_id: '' - label: Search - description: '' - use_operator: false - operator: combine_op - operator_limit_selection: false - operator_list: { } - identifier: search - required: false - remember: false - multiple: false - remember_roles: - authenticated: authenticated - anonymous: '0' - administrator: '0' - editor: '0' - fields: - - title - - body_value field_cpcommhub_user_groups_target_id: id: field_cpcommhub_user_groups_target_id table: node__field_cpcommhub_user_groups @@ -468,6 +436,38 @@ display: default_group_multiple: { } group_items: { } reduce_duplicates: false + combine: + id: combine + table: views + field: combine + relationship: none + group_type: group + admin_label: '' + plugin_id: combine + operator: contains + value: '' + group: 1 + exposed: true + expose: + operator_id: '' + label: Search + description: '' + use_operator: false + operator: combine_op + operator_limit_selection: false + operator_list: { } + identifier: search + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + anonymous: '0' + administrator: '0' + editor: '0' + fields: + - title + - body_value filter_groups: operator: AND groups: diff --git a/modules/custom/cp_community_hub/css/cp-community-hub.css b/modules/custom/cp_community_hub/css/cp-community-hub.css index ef0c97e7..5bdcc752 100644 --- a/modules/custom/cp_community_hub/css/cp-community-hub.css +++ b/modules/custom/cp_community_hub/css/cp-community-hub.css @@ -13,6 +13,10 @@ margin-top: 1rem; } +.form-item-scope-value { + margin-right: 1rem; +} + .ajax-progress { display: none; } From 3701fb5bf8f90f31c7d2999a5ea193bb5140a4de Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Tue, 12 May 2026 10:52:23 +0200 Subject: [PATCH 08/30] Properly implement select all button --- .../views.view.cpcommhub_resources.yml | 2 +- .../js/cp-community-hub-view.js | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml b/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml index 5c2e548b..b396a8cc 100644 --- a/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml +++ b/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml @@ -258,7 +258,7 @@ display: collapsible_disable_automatic_open: false is_secondary: false hide_label: false - select_all_none: true + select_all_none: false select_all_none_nested: false display_inline: true field_cpcommhub_scope_value: diff --git a/modules/custom/cp_community_hub/js/cp-community-hub-view.js b/modules/custom/cp_community_hub/js/cp-community-hub-view.js index b592cd1e..78436a89 100644 --- a/modules/custom/cp_community_hub/js/cp-community-hub-view.js +++ b/modules/custom/cp_community_hub/js/cp-community-hub-view.js @@ -26,6 +26,46 @@ } } + const selectAllBtn = document.createElement('button'); + selectAllBtn.type = 'button'; + selectAllBtn.classList.add('btn', 'btn-outline-secondary', 'mb-3', 'ms-4'); + selectAllBtn.textContent = 'Select all'; + clone.querySelector(".form-checkboxes").appendChild(selectAllBtn); + + selectAllBtn.addEventListener('click', () => { + const checkboxes = Array.from(document.querySelectorAll(groupContainerSelector + ' input[type="checkbox"]')); + const allChecked = checkboxes.every(cb => cb.checked); + const newState = !allChecked; + + const viewBlock = document.querySelector(viewBlockSelector); + const wasHidden = viewBlock && !viewBlock.classList.contains('d-block'); + + for (const cb of checkboxes) { + cb.checked = newState; + } + + updateBlockVisibility(); + + const form = document.getElementById(viewsFormId); + let lastInternalCb = null; + for (const cb of checkboxes) { + const internalCb = form + ? Array.from(form.querySelectorAll('input[type="checkbox"]')).find(icb => icb.name === cb.name) + : null; + if (internalCb) { + internalCb.checked = newState; + lastInternalCb = internalCb; + } + } + + if (lastInternalCb) { + if (wasHidden && newState) { + document.querySelector(viewBlockSelector + ' .view-content')?.classList.add('invisible'); + } + lastInternalCb.dispatchEvent(new Event('change', { bubbles: true })); + } + }); + groupContainer.appendChild(clone); filterWrapper.classList.add('d-none'); } From 1aa56f05381d873e7df30719d6ca1f996c3b8d90 Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Tue, 12 May 2026 11:15:39 +0200 Subject: [PATCH 09/30] Refactor slightly, fix view error --- .../views.view.cpcommhub_resources.yml | 4 +- .../js/cp-community-hub-view.js | 66 +++++++++---------- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml b/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml index b396a8cc..581a8812 100644 --- a/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml +++ b/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml @@ -35,7 +35,7 @@ display: entity_type: node entity_field: title plugin_id: field - label: Title + label: '' exclude: true alter: alter_text: false @@ -467,7 +467,7 @@ display: editor: '0' fields: - title - - body_value + - body filter_groups: operator: AND groups: diff --git a/modules/custom/cp_community_hub/js/cp-community-hub-view.js b/modules/custom/cp_community_hub/js/cp-community-hub-view.js index 78436a89..abfb0977 100644 --- a/modules/custom/cp_community_hub/js/cp-community-hub-view.js +++ b/modules/custom/cp_community_hub/js/cp-community-hub-view.js @@ -6,6 +6,34 @@ const filterGroupsSelector = '[data-drupal-selector="edit-user-groups-target-id"]'; const viewsFormId = 'views-exposed-form-cpcommhub-resources-block-1'; + function isViewBlockHidden() { + const viewBlock = document.querySelector(viewBlockSelector); + return viewBlock ? !viewBlock.classList.contains('d-block') : false; + } + + // Mirrors all cloned checkbox states into the hidden Views form, then fires a + // single change event on the last matched checkbox to trigger Views AJAX. + function syncInternalCheckboxes(wasHidden) { + const form = document.getElementById(viewsFormId); + if (!form) { + return; + } + const clonedCheckboxes = Array.from(document.querySelectorAll(groupContainerSelector + ' input[type="checkbox"]')); + const formCheckboxes = Array.from(form.querySelectorAll('input[type="checkbox"]')); + let lastInternalCb; + for (let cb of clonedCheckboxes) { + const internalCb = formCheckboxes.find(icb => icb.name === cb.name); + if (internalCb) { + internalCb.checked = cb.checked; + lastInternalCb = internalCb; + } + } + if (wasHidden) { + document.querySelector(viewBlockSelector + ' .view-content')?.classList.add('invisible'); + } + lastInternalCb.dispatchEvent(new Event('change', { bubbles: true })); + } + function cloneUserGroupsFilter() { const groupContainer = document.querySelector(groupContainerSelector); const filterEl = document.querySelector(filterGroupsSelector); @@ -36,9 +64,7 @@ const checkboxes = Array.from(document.querySelectorAll(groupContainerSelector + ' input[type="checkbox"]')); const allChecked = checkboxes.every(cb => cb.checked); const newState = !allChecked; - - const viewBlock = document.querySelector(viewBlockSelector); - const wasHidden = viewBlock && !viewBlock.classList.contains('d-block'); + const wasHidden = isViewBlockHidden(); for (const cb of checkboxes) { cb.checked = newState; @@ -46,24 +72,7 @@ updateBlockVisibility(); - const form = document.getElementById(viewsFormId); - let lastInternalCb = null; - for (const cb of checkboxes) { - const internalCb = form - ? Array.from(form.querySelectorAll('input[type="checkbox"]')).find(icb => icb.name === cb.name) - : null; - if (internalCb) { - internalCb.checked = newState; - lastInternalCb = internalCb; - } - } - - if (lastInternalCb) { - if (wasHidden && newState) { - document.querySelector(viewBlockSelector + ' .view-content')?.classList.add('invisible'); - } - lastInternalCb.dispatchEvent(new Event('change', { bubbles: true })); - } + syncInternalCheckboxes(wasHidden); }); groupContainer.appendChild(clone); @@ -110,22 +119,11 @@ once('commhub-group-listeners', groupContainerSelector, document).forEach((container) => { container.addEventListener('change', (e) => { if (e.target.matches('input[type="checkbox"]')) { - const viewBlock = document.querySelector(viewBlockSelector); - const wasHidden = viewBlock && !viewBlock.classList.contains('d-block'); + const wasHidden = isViewBlockHidden(); updateBlockVisibility(); - const form = document.getElementById(viewsFormId); - const internalCb = form - ? Array.from(form.querySelectorAll('input[type="checkbox"]')).find(cb => cb.name === e.target.name) - : null; - if (internalCb) { - internalCb.checked = e.target.checked; - if (wasHidden) { - document.querySelector(viewBlockSelector + ' .view-content')?.classList.add('invisible'); - } - internalCb.dispatchEvent(new Event('change', { bubbles: true })); - } + syncInternalCheckboxes(wasHidden); } }); }); From f8d1fa75f0193ec0669f6fdeb3af7e63ab00076c Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Tue, 12 May 2026 12:17:30 +0200 Subject: [PATCH 10/30] Suppress top scrolling behavior when filters change --- modules/custom/cp_community_hub/js/cp-community-hub-view.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/custom/cp_community_hub/js/cp-community-hub-view.js b/modules/custom/cp_community_hub/js/cp-community-hub-view.js index abfb0977..b7c01164 100644 --- a/modules/custom/cp_community_hub/js/cp-community-hub-view.js +++ b/modules/custom/cp_community_hub/js/cp-community-hub-view.js @@ -109,6 +109,10 @@ Drupal.behaviors.communityHubView = { attach: function (context, settings) { + once('commhub-disable-views-scroll', 'html', document).forEach(() => { + Drupal.AjaxCommands.prototype.scrollTop = function () {}; + }); + once('commhub-clone-groups', 'body', document).forEach(() => cloneUserGroupsFilter()); hideGroupsFilterInView(context); From d1de58f6f544e67902ea64234ce27a3adae05ebd Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Tue, 12 May 2026 12:26:52 +0200 Subject: [PATCH 11/30] Ensure options deselected when page reloaded --- modules/custom/cp_community_hub/cp_community_hub.module | 9 +++++++++ .../custom/cp_community_hub/js/cp-community-hub-view.js | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/modules/custom/cp_community_hub/cp_community_hub.module b/modules/custom/cp_community_hub/cp_community_hub.module index 91d28c12..eac8fd1c 100644 --- a/modules/custom/cp_community_hub/cp_community_hub.module +++ b/modules/custom/cp_community_hub/cp_community_hub.module @@ -21,6 +21,15 @@ function cp_community_hub_views_pre_render(ViewExecutable $view) { } } +/** + * Implements hook_form_views_exposed_form_alter(). + */ +function cp_community_hub_form_views_exposed_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { + if (isset($form['#id']) && $form['#id'] === 'views-exposed-form-cpcommhub-resources-block-1') { + $form['#attributes']['autocomplete'] = 'off'; + } +} + /** * Implements hook_theme(). */ diff --git a/modules/custom/cp_community_hub/js/cp-community-hub-view.js b/modules/custom/cp_community_hub/js/cp-community-hub-view.js index b7c01164..bf1c6afa 100644 --- a/modules/custom/cp_community_hub/js/cp-community-hub-view.js +++ b/modules/custom/cp_community_hub/js/cp-community-hub-view.js @@ -43,6 +43,10 @@ return; } + for (const cb of filterWrapper.querySelectorAll('input[type="checkbox"]')) { + cb.checked = false; + } + const clone = filterWrapper.cloneNode(true); for (let checkbox of clone.querySelectorAll('input[type="checkbox"]')) { checkbox.setAttribute('form', viewsFormId); From dbe44a212e84441e9fb648bef86f634467d6b125 Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Tue, 12 May 2026 12:40:10 +0200 Subject: [PATCH 12/30] Rename view --- ....cpcommhub_resources.yml => views.view.cp_community_hub.yml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename modules/custom/cp_community_hub/config/install/{views.view.cpcommhub_resources.yml => views.view.cp_community_hub.yml} (99%) diff --git a/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml b/modules/custom/cp_community_hub/config/install/views.view.cp_community_hub.yml similarity index 99% rename from modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml rename to modules/custom/cp_community_hub/config/install/views.view.cp_community_hub.yml index 581a8812..1c298243 100644 --- a/modules/custom/cp_community_hub/config/install/views.view.cpcommhub_resources.yml +++ b/modules/custom/cp_community_hub/config/install/views.view.cp_community_hub.yml @@ -9,7 +9,7 @@ dependencies: - node - taxonomy - user -id: cpcommhub_resources +id: cp_community_hub label: 'Community Hub Resources' module: views description: 'Catalogue of Community Hub resources' From 6eaeb34d7b83a1e7ed63ab54c7fb91b3e21c5647 Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Tue, 12 May 2026 14:00:18 +0200 Subject: [PATCH 13/30] Adjust spacing of search button --- modules/custom/cp_community_hub/css/cp-community-hub.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/custom/cp_community_hub/css/cp-community-hub.css b/modules/custom/cp_community_hub/css/cp-community-hub.css index 5bdcc752..1175b547 100644 --- a/modules/custom/cp_community_hub/css/cp-community-hub.css +++ b/modules/custom/cp_community_hub/css/cp-community-hub.css @@ -13,7 +13,7 @@ margin-top: 1rem; } -.form-item-scope-value { +.form-item-scope-value, .form-item-search-value { margin-right: 1rem; } From ab70b8d8515b9f36dae982d2e705c207596f6bd2 Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Tue, 12 May 2026 14:02:07 +0200 Subject: [PATCH 14/30] Fix errors associated with earlier renaming --- modules/custom/cp_community_hub/cp_community_hub.module | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/custom/cp_community_hub/cp_community_hub.module b/modules/custom/cp_community_hub/cp_community_hub.module index eac8fd1c..4b5b6634 100644 --- a/modules/custom/cp_community_hub/cp_community_hub.module +++ b/modules/custom/cp_community_hub/cp_community_hub.module @@ -16,7 +16,7 @@ function cp_community_hub_preprocess_node__community_resource(&$variables) { * so hook_preprocess_node never fires, leaving the page JS missing). */ function cp_community_hub_views_pre_render(ViewExecutable $view) { - if ($view->id() === 'cpcommhub_resources') { + if ($view->id() === 'cp_community_hub') { $view->element['#attached']['library'][] = 'cp_community_hub/style'; } } @@ -25,7 +25,7 @@ function cp_community_hub_views_pre_render(ViewExecutable $view) { * Implements hook_form_views_exposed_form_alter(). */ function cp_community_hub_form_views_exposed_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { - if (isset($form['#id']) && $form['#id'] === 'views-exposed-form-cpcommhub-resources-block-1') { + if (isset($form['#id']) && $form['#id'] === 'views-exposed-form-cp-community-hub-block-1') { $form['#attributes']['autocomplete'] = 'off'; } } From 41934c55b9dff01f0102dca2dfd80025746b45d2 Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Tue, 12 May 2026 14:48:44 +0200 Subject: [PATCH 15/30] Further rename clean-up --- modules/custom/cp_community_hub/css/cp-community-hub.css | 2 +- modules/custom/cp_community_hub/js/cp-community-hub-view.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/custom/cp_community_hub/css/cp-community-hub.css b/modules/custom/cp_community_hub/css/cp-community-hub.css index 1175b547..811a8647 100644 --- a/modules/custom/cp_community_hub/css/cp-community-hub.css +++ b/modules/custom/cp_community_hub/css/cp-community-hub.css @@ -1,4 +1,4 @@ -#page-wrapper:not(.layout-builder-overrides-node-view) .block-views-blockcpcommhub-resources-block-1 { +#page-wrapper:not(.layout-builder-overrides-node-view) .block-views-blockcp-community-hub-block-1 { display: none; } diff --git a/modules/custom/cp_community_hub/js/cp-community-hub-view.js b/modules/custom/cp_community_hub/js/cp-community-hub-view.js index bf1c6afa..82d6dd7e 100644 --- a/modules/custom/cp_community_hub/js/cp-community-hub-view.js +++ b/modules/custom/cp_community_hub/js/cp-community-hub-view.js @@ -1,10 +1,10 @@ (function (Drupal, once) { - const viewBlockSelector = '.block-views-blockcpcommhub-resources-block-1'; + const viewBlockSelector = '.block-views-blockcp-community-hub-block-1'; const introBlockSelector = '.block-inline-blockbasic'; const groupContainerSelector = '#user-groups-container'; const filterGroupsSelector = '[data-drupal-selector="edit-user-groups-target-id"]'; - const viewsFormId = 'views-exposed-form-cpcommhub-resources-block-1'; + const viewsFormId = 'views-exposed-form-cp-community-hub-block-1'; function isViewBlockHidden() { const viewBlock = document.querySelector(viewBlockSelector); From 291411e64870c346058b350a016abed43361b0b5 Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Tue, 12 May 2026 14:54:42 +0200 Subject: [PATCH 16/30] Update CSS --- modules/custom/cp_community_hub/css/cp-community-hub.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/custom/cp_community_hub/css/cp-community-hub.css b/modules/custom/cp_community_hub/css/cp-community-hub.css index 811a8647..fa96fd11 100644 --- a/modules/custom/cp_community_hub/css/cp-community-hub.css +++ b/modules/custom/cp_community_hub/css/cp-community-hub.css @@ -13,7 +13,7 @@ margin-top: 1rem; } -.form-item-scope-value, .form-item-search-value { +.form-item-scope-value, .form-type-textfield { margin-right: 1rem; } From 9cffe19b98c3e1363c1ae6896891913d9ba78844 Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Tue, 12 May 2026 14:57:58 +0200 Subject: [PATCH 17/30] Require image --- ...ield.field.node.community_resource.field_cpcommhub_image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_image.yml b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_image.yml index 96b2bd2a..65959cf5 100644 --- a/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_image.yml +++ b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_image.yml @@ -12,7 +12,7 @@ entity_type: node bundle: community_resource label: Image description: 'Thumbnail image for this resource card. Minimum 512x288 pixels (16:9 aspect ratio).' -required: false +required: true translatable: false default_value: { } default_value_callback: '' From 8c7e1b07d1932f1b4ec675f0c6851108288724df Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Tue, 12 May 2026 15:24:43 +0200 Subject: [PATCH 18/30] Ensure newly added resources look OK on stand-alone view --- modules/custom/cp_community_hub/cp_community_hub.module | 4 ++++ modules/custom/cp_community_hub/css/cp-community-hub.css | 7 +++++++ themes/cp_theme_d10/css/page.css | 3 ++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/modules/custom/cp_community_hub/cp_community_hub.module b/modules/custom/cp_community_hub/cp_community_hub.module index 4b5b6634..34a7d2ea 100644 --- a/modules/custom/cp_community_hub/cp_community_hub.module +++ b/modules/custom/cp_community_hub/cp_community_hub.module @@ -39,5 +39,9 @@ function cp_community_hub_theme() { 'template' => 'node--community-resource--teaser', 'base hook' => 'node', ], + 'node__community_resource__full' => [ + 'template' => 'node--community-resource--teaser', + 'base hook' => 'node', + ], ]; } diff --git a/modules/custom/cp_community_hub/css/cp-community-hub.css b/modules/custom/cp_community_hub/css/cp-community-hub.css index fa96fd11..4b0fae53 100644 --- a/modules/custom/cp_community_hub/css/cp-community-hub.css +++ b/modules/custom/cp_community_hub/css/cp-community-hub.css @@ -20,3 +20,10 @@ .ajax-progress { display: none; } + +.community_resource #page .page-content { + margin-bottom: 2rem; + .node--type-community-resource, .teaser-news-image { + max-width: 441px; + } +} diff --git a/themes/cp_theme_d10/css/page.css b/themes/cp_theme_d10/css/page.css index d8fe0b83..b3556182 100644 --- a/themes/cp_theme_d10/css/page.css +++ b/themes/cp_theme_d10/css/page.css @@ -390,7 +390,8 @@ iframe { .cp_event #page .page-content, .system-404 .page-content, .system-403 .page-content, -.cp-search-search-results-page #page .page-content { +.cp-search-search-results-page #page .page-content, +.community_resource #page .page-content { max-width: 70.5rem; margin-left: auto; margin-right: auto; From 8a852b14ebc85742176b8c68212e63e5cf7a2e6b Mon Sep 17 00:00:00 2001 From: Andrew Debevec Date: Wed, 13 May 2026 16:36:13 +0200 Subject: [PATCH 19/30] Make menu tighter to accommodate new link and prevent wrapping --- themes/cp_theme_d10/templates/navigation/menu--main.html.twig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/themes/cp_theme_d10/templates/navigation/menu--main.html.twig b/themes/cp_theme_d10/templates/navigation/menu--main.html.twig index 548b37b5..ead4ae4d 100644 --- a/themes/cp_theme_d10/templates/navigation/menu--main.html.twig +++ b/themes/cp_theme_d10/templates/navigation/menu--main.html.twig @@ -54,7 +54,7 @@ {% if items %} {% if menu_level == 0 %}
- + {% elseif menu_level == 1 %}