diff --git a/modules/custom/cp_community_hub/README.md b/modules/custom/cp_community_hub/README.md new file mode 100644 index 0000000..d2b0ebb --- /dev/null +++ b/modules/custom/cp_community_hub/README.md @@ -0,0 +1,47 @@ +# Community Hub + +## Setup instructions + +Once installed/enabled, requires a specific page setup to render properly. + +1) Create a new basic page. Set the desired URL alias and disable the TOC. +2) Body should have several elements, including a replacement `h1`, introductory text that is always displayed, and a `div` with the id `user-groups-container`. Ensure "Full HTML" is selected. Example content: + +```html +
+ (placeholder for introductory text TBD) +
++ Here are some resources curated for you! +
+``` + +4) Upload a header image for the page. +5) Save page. +6) In the layout manager: + 1) Add a new section at the bottom (e.g., "Light Blue Full Width (one column)") + 2) Add block to bottom section -- select the "Community Hub Resources" view block. + 3) Move the Introduction block from the top section to the bottom section, above the view block. + 4) Add block to bottom section -- create content block, add text that should appear when no user group is selected, e.g. `Tell us what your role is, and we’ll show you what you need...` + 5) Save layout. + +## Create taxonomy terms for "User groups" + +Go to `/admin/structure/taxonomy/manage/community_user_groups/overview` and add user groups. Reorder as desired. + +## Add content + +Add new content, select "Community resource". 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 0000000..f6bb57e --- /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 0000000..5778de6 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/core.entity_form_display.node.community_resource.default.yml @@ -0,0 +1,126 @@ +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_restricted + - 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: 3 + region: content + settings: { } + third_party_settings: { } + field_cpcommhub_scope: + type: options_buttons + weight: 4 + region: content + settings: { } + third_party_settings: { } + field_cpcommhub_image: + type: image_image + weight: 2 + region: content + settings: + progress_indicator: throbber + preview_image_style: thumbnail + third_party_settings: { } + body: + type: text_textarea_with_summary + weight: 1 + region: content + settings: + rows: 9 + summary_rows: 3 + placeholder: '' + show_summary: false + third_party_settings: { } + field_cpcommhub_link: + type: link_default + weight: 6 + region: content + settings: + placeholder_url: '' + placeholder_title: 'Go to resource' + third_party_settings: { } + field_cpcommhub_restricted: + type: boolean_checkbox + weight: 5 + region: content + settings: + display_label: true + 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 0000000..f7d8fb2 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.default.yml @@ -0,0 +1,70 @@ +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_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_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 0000000..5a18359 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/core.entity_view_display.node.community_resource.teaser.yml @@ -0,0 +1,65 @@ +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_restricted + - 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 + body: + type: text_summary_or_trimmed + label: hidden + settings: + trim_length: 200 + 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 + links: + settings: { } + third_party_settings: { } + weight: 4 + region: content +hidden: + field_cpcommhub_restricted: 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.body.yml b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.body.yml new file mode 100644 index 0000000..0074691 --- /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 0000000..65959cf --- /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: true +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 0000000..b5f8d56 --- /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 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: 1 + link_type: 17 +field_type: link diff --git a/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_restricted.yml b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_restricted.yml new file mode 100644 index 0000000..5431d16 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/field.field.node.community_resource.field_cpcommhub_restricted.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_cpcommhub_restricted + - node.type.community_resource +id: node.community_resource.field_cpcommhub_restricted +field_name: field_cpcommhub_restricted +entity_type: node +bundle: community_resource +label: 'Restricted access' +description: '' +required: false +translatable: false +default_value: + - value: 0 +default_value_callback: '' +settings: { } +field_type: boolean 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 0000000..1663982 --- /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 0000000..529ffe5 --- /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 0000000..85df30c --- /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 0000000..1546288 --- /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 0000000..844288d --- /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_restricted.yml b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_restricted.yml new file mode 100644 index 0000000..2d427d5 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/field.storage.node.field_cpcommhub_restricted.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + module: + - node +id: node.field_cpcommhub_restricted +field_name: field_cpcommhub_restricted +entity_type: node +type: boolean +settings: + on_label: 'On' + off_label: 'Off' +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 0000000..37cfe47 --- /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 0000000..4c95dc4 --- /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 0000000..27a86c7 --- /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 0000000..dc07c5d --- /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 0000000..7b92c0c --- /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 0000000..4719ca4 --- /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.cp_community_hub.yml b/modules/custom/cp_community_hub/config/install/views.view.cp_community_hub.yml new file mode 100644 index 0000000..1c29824 --- /dev/null +++ b/modules/custom/cp_community_hub/config/install/views.view.cp_community_hub.yml @@ -0,0 +1,530 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - node.type.community_resource + module: + - better_exposed_filters + - node + - taxonomy + - user +id: cp_community_hub +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: + 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: '' + 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: + id: body + table: node__body + field: body + relationship: none + group_type: group + admin_label: '' + plugin_id: field + label: '' + 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 + 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: Search + 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: false + 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: default + 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 + 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: false + 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 + 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 + filter_groups: + operator: AND + groups: + 1: AND + style: + type: grid_responsive + options: + grouping: { } + columns: 3 + cell_min_width: 300 + grid_gutter: 16 + alignment: horizontal + 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: true + 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: { } + block_1: + id: block_1 + display_title: Block + display_plugin: block + position: 1 + display_options: + 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: { } 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 0000000..9f9cc02 --- /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 0000000..82977eb --- /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 0000000..23b9ad1 --- /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 0000000..34a7d2e --- /dev/null +++ b/modules/custom/cp_community_hub/cp_community_hub.module @@ -0,0 +1,47 @@ +id() === 'cp_community_hub') { + $view->element['#attached']['library'][] = 'cp_community_hub/style'; + } +} + +/** + * 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-cp-community-hub-block-1') { + $form['#attributes']['autocomplete'] = 'off'; + } +} + +/** + * Implements hook_theme(). + */ +function cp_community_hub_theme() { + return [ + 'node__community_resource__teaser' => [ + '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/cp_community_hub.routing.yml b/modules/custom/cp_community_hub/cp_community_hub.routing.yml new file mode 100644 index 0000000..e69de29 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 0000000..fd33a87 --- /dev/null +++ b/modules/custom/cp_community_hub/css/cp-community-hub.css @@ -0,0 +1,67 @@ +#page-wrapper:not(.layout-builder-overrides-node-view) { + .block-views-blockcp-community-hub-block-1 { + display: none; + } + + .block-field-blocknodepagefield-introduction { + display: none; + } +} + +h1.title, .ajax-progress { + display: none; +} + +ol.breadcrumb { + visibility: hidden; +} + +.view-filters fieldset[data-drupal-selector="edit-user-groups-target-id"] { + display: none; +} + +.block-views-blockcp-community-hub-block-1 { + .form-item-scope-value, .form-type-textfield { + margin-right: 1rem; + } + + .community_resource #page .page-content { + margin-bottom: 2rem; + .node--type-community-resource, .teaser-news-image { + max-width: 441px; + } + } + + .form-submit:disabled { + color: var(--bs-btn-color); + background-color: var(--bs-btn-bg); + border-color: var(--bs-btn-border-color); + opacity: var(--bs-btn-opacity); + box-shadow: var(--bs-btn-box-shadow); + } +} + +#user-groups-container { + margin-top: 2rem; + + #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; + } + + .btn-check:not(:checked) + .btn-outline-primary:hover { + color: var(--bs-primary); + background-color: rgba(var(--bs-primary-rgb), 0.1); + } + + .btn-check:checked + .btn-outline-primary:hover { + color: var(--bs-body-bg); + background-color: rgba(var(--bs-primary-rgb), 0.8); + } +} 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 0000000..24c5e91 --- /dev/null +++ b/modules/custom/cp_community_hub/js/cp-community-hub-view.js @@ -0,0 +1,147 @@ +(function (Drupal, once) { + + const viewBlockSelector = '.block-views-blockcp-community-hub-block-1'; + const introBlockSelector = '.block-field-blocknodepagefield-introduction'; + const inlineBlockSelector = '.block-inline-blockbasic'; + const groupContainerSelector = '#user-groups-container'; + const filterGroupsSelector = '[data-drupal-selector="edit-user-groups-target-id"]'; + const viewsFormId = 'views-exposed-form-cp-community-hub-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 })); + + const selectAllBtn = document.getElementById('selectAllBtn'); + if (selectAllBtn && clonedCheckboxes.every(cb => cb.checked)) { + selectAllBtn.innerText = 'Select none'; + } else { + selectAllBtn.innerText = 'Select all'; + } + } + + function cloneUserGroupsFilter() { + const groupContainer = document.querySelector(groupContainerSelector); + const filterEl = document.querySelector(filterGroupsSelector); + const filterWrapper = filterEl?.closest('.form-item, .js-form-item, fieldset, details'); + + if (!groupContainer || !filterWrapper) { + 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); + checkbox.classList.add('btn-check'); + checkbox.setAttribute('autocomplete', 'off'); + const label = clone.querySelector('label[for="' + checkbox.id + '"]'); + if (label) { + label.classList.add('btn', 'btn-outline-primary'); + } + } + + const selectAllBtn = document.createElement('button'); + selectAllBtn.id = 'selectAllBtn'; + 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 newState = !(checkboxes.every(cb => cb.checked)); + const wasHidden = isViewBlockHidden(); + + for (const cb of checkboxes) { + cb.checked = newState; + } + + updateBlockVisibility(); + + syncInternalCheckboxes(wasHidden); + }); + + groupContainer.appendChild(clone); + filterWrapper.classList.add('d-none'); + } + + function hasGroupSelected() { + return document.querySelectorAll(groupContainerSelector + ' input[type="checkbox"]:checked').length > 0; + } + + function updateBlockVisibility() { + const viewBlock = document.querySelector(viewBlockSelector); + const introBlock = document.querySelector(introBlockSelector); + const inlineBlock = document.querySelector(inlineBlockSelector); + + if (!viewBlock || !introBlock || !inlineBlock) { + console.error("Unable to find all blocks for updating visibility") + return; + } + + if (hasGroupSelected()) { + viewBlock.classList.add('d-block'); + introBlock.classList.add('d-block'); + inlineBlock.classList.add('d-none'); + } else { + viewBlock.classList.remove('d-block'); + introBlock.classList.remove('d-block'); + inlineBlock.classList.remove('d-none'); + } + } + + 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()); + + 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 wasHidden = isViewBlockHidden(); + + updateBlockVisibility(); + + syncInternalCheckboxes(wasHidden); + } + }); + }); + } + }; + +})(Drupal, once); 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 0000000..6449957 --- /dev/null +++ b/modules/custom/cp_community_hub/templates/node--community-resource--teaser.html.twig @@ -0,0 +1,50 @@ +{# +/** + * @file + * Theme implementation for a community_resource node in teaser view mode. + * + * 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] %} + +