diff --git a/modules/localgov_workflows_notifications/config/optional/views.view.localgov_content_by_owner.yml b/modules/localgov_workflows_notifications/config/optional/views.view.localgov_content_by_owner.yml new file mode 100644 index 0000000..0f1e3a8 --- /dev/null +++ b/modules/localgov_workflows_notifications/config/optional/views.view.localgov_content_by_owner.yml @@ -0,0 +1,623 @@ +langcode: en +status: true +dependencies: + module: + - localgov_workflows_notifications + - node + - user +id: localgov_content_by_owner +label: 'Content by owner' +module: views +description: '' +tag: '' +base_table: node_field_data +base_field: nid +display: + default: + id: default + display_title: Default + display_plugin: default + position: 0 + display_options: + title: 'Content by owner' + 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: false + alter: + alter_text: false + make_link: false + absolute: false + word_boundary: false + ellipsis: false + strip_tags: false + trim: false + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + 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: true + 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 + user: + id: user + table: localgov_service_contact + field: user + relationship: localgov_service_contacts_target_id + group_type: group + admin_label: '' + entity_type: localgov_service_contact + entity_field: user + plugin_id: field + label: 'Service contact' + 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: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: target_id + type: entity_reference_label + settings: + link: true + group_column: target_id + 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 + type: + id: type + table: node_field_data + field: type + relationship: none + group_type: group + admin_label: '' + entity_type: node + entity_field: type + plugin_id: field + label: 'Content type' + 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: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: target_id + type: entity_reference_label + settings: + link: false + group_column: target_id + 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 + name: + id: name + table: users_field_data + field: name + relationship: uid + group_type: group + admin_label: '' + entity_type: user + entity_field: name + plugin_id: field + label: Author + 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: true + 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: user_name + settings: + link_to_entity: true + 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 + status: + id: status + table: node_field_data + field: status + relationship: none + group_type: group + admin_label: '' + entity_type: node + entity_field: status + plugin_id: field + label: Status + 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: true + 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: boolean + settings: + format: custom + format_custom_false: Unpublished + format_custom_true: Published + 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 + changed: + id: changed + table: node_field_data + field: changed + relationship: none + group_type: group + admin_label: '' + entity_type: node + entity_field: changed + plugin_id: field + label: Updated + 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: true + 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: timestamp + settings: + date_format: short + custom_date_format: '' + timezone: '' + tooltip: + date_format: long + custom_date_format: '' + time_diff: + enabled: false + future_format: '@interval hence' + past_format: '@interval ago' + granularity: 2 + refresh: 60 + 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 + pager: + type: mini + options: + offset: 0 + pagination_heading_level: h4 + items_per_page: 50 + 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: basic + 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 + access: + type: perm + options: + perm: 'access content' + cache: + type: tag + options: { } + empty: { } + sorts: { } + arguments: + id: + id: id + table: localgov_service_contact + field: id + relationship: localgov_service_contacts_target_id + group_type: group + admin_label: '' + entity_type: localgov_service_contact + entity_field: id + plugin_id: numeric + default_action: default + exception: + value: all + title_enable: false + title: All + title_enable: false + title: '' + default_argument_type: query_parameter + default_argument_options: + query_param: service-contact-id + fallback: all + multiple: or + summary_options: + base_path: '' + count: true + override: false + items_per_page: 25 + summary: + sort_order: asc + number_of_records: 0 + format: default_summary + specify_validation: true + validate: + type: none + fail: empty + validate_options: { } + break_phrase: false + not: false + filters: { } + filter_groups: + operator: AND + groups: { } + style: + type: table + options: + grouping: { } + row_class: '' + default_row_class: true + columns: + user: user + title: title + type: type + name: name + status: status + changed: changed + operations: operations + default: changed + info: + user: + sortable: true + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + title: + sortable: true + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + type: + sortable: true + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + name: + sortable: false + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + status: + sortable: true + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + changed: + sortable: true + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: priority-low + operations: + align: '' + separator: '' + empty_column: false + responsive: '' + override: true + sticky: true + summary: '' + empty_table: true + caption: '' + description: '' + row: + type: fields + query: + type: views_query + options: + query_comment: '' + disable_sql_rewrite: false + distinct: false + replica: false + query_tags: { } + relationships: + uid: + id: uid + table: node_field_data + field: uid + relationship: none + group_type: group + admin_label: author + entity_type: node + entity_field: uid + plugin_id: standard + required: true + localgov_service_contacts_target_id: + id: localgov_service_contacts_target_id + table: node__localgov_service_contacts + field: localgov_service_contacts_target_id + relationship: none + group_type: group + admin_label: 'Service contact' + entity_type: node + entity_field: localgov_service_contacts + plugin_id: standard + required: 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: 'Content by owner View' + display_plugin: page + position: 1 + display_options: + display_description: 'Displays a list of content by service contact' + display_extenders: { } + path: admin/content/localgov-service-contact/content-by-owner + 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/localgov_workflows_notifications/localgov_workflows_notifications.install b/modules/localgov_workflows_notifications/localgov_workflows_notifications.install index 8921a8d..acbb12d 100644 --- a/modules/localgov_workflows_notifications/localgov_workflows_notifications.install +++ b/modules/localgov_workflows_notifications/localgov_workflows_notifications.install @@ -5,6 +5,9 @@ * Install functions for the LocalGov Review Notifications module. */ +use Drupal\Core\Config\FileStorage; +use Drupal\Core\Config\StorageInterface; + /** * Implements hook_install(). */ @@ -40,3 +43,20 @@ function localgov_workflows_notifications_update_10001(&$sandbox) { $timer->update(); } } + +/** + * Enable Content By Owner View. + */ +function localgov_workflows_notifications_update_10002(&$sandbox) { + /** @var \Drupal\Core\Config\ConfigInstallerInterface $config_installer */ + $config_installer = \Drupal::service('config.installer'); + $config_installer->installDefaultConfig('module', 'localgov_workflows_notifications'); + $optional_install_path = \Drupal::moduleHandler() + ->getModule('localgov_workflows_notifications') + ->getPath() . '/config/optional'; + if (is_dir($optional_install_path)) { + // Install the module's optional configuration that's not installed yet. + $storage = new FileStorage($optional_install_path, StorageInterface::DEFAULT_COLLECTION); + $config_installer->installOptionalConfig($storage); + } +} diff --git a/modules/localgov_workflows_notifications/localgov_workflows_notifications.links.menu.yml b/modules/localgov_workflows_notifications/localgov_workflows_notifications.links.menu.yml index abe311b..0f3211b 100644 --- a/modules/localgov_workflows_notifications/localgov_workflows_notifications.links.menu.yml +++ b/modules/localgov_workflows_notifications/localgov_workflows_notifications.links.menu.yml @@ -10,3 +10,7 @@ localgov_workflows_notifications.settings: parent: system.admin_config_workflow route_name: localgov_workflows_notifications.settings weight: 10 + +localgov_workflows_notifications.content_by_owner: + deriver: 'Drupal\localgov_workflows_notifications\Plugin\Derivative\LocalgovWorkflowsNotificationsContentByOwner' + weight: 11 diff --git a/modules/localgov_workflows_notifications/localgov_workflows_notifications.links.task.yml b/modules/localgov_workflows_notifications/localgov_workflows_notifications.links.task.yml index 2fdbbf5..43aa38e 100644 --- a/modules/localgov_workflows_notifications/localgov_workflows_notifications.links.task.yml +++ b/modules/localgov_workflows_notifications/localgov_workflows_notifications.links.task.yml @@ -15,4 +15,7 @@ entity.localgov_service_contact.collection: title: 'Service contacts' route_name: entity.localgov_service_contact.collection base_route: system.admin_content - weight: 80 + weight: 10 +localgov_workflows_notifications.local_tasks: + deriver: 'Drupal\localgov_workflows_notifications\Plugin\Derivative\LocalgovWorkflowsNotificationsLocalTasks' + weight: 11 diff --git a/modules/localgov_workflows_notifications/localgov_workflows_notifications.module b/modules/localgov_workflows_notifications/localgov_workflows_notifications.module index 3468bb2..65e93ee 100644 --- a/modules/localgov_workflows_notifications/localgov_workflows_notifications.module +++ b/modules/localgov_workflows_notifications/localgov_workflows_notifications.module @@ -5,11 +5,15 @@ * Primary module hooks for LocalGov Review Notifications module. */ +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Url; use Drupal\localgov_roles\RolesHelper; +use Drupal\views\ViewExecutable; +use Drupal\views\Views; /** * Implements hook_entity_base_field_info(). @@ -182,3 +186,26 @@ function localgov_workflows_notifications_localgov_roles_default(): array { ], ]; } + +/** + * Implements hook_entity_operation_alter(). + */ +function localgov_workflows_notifications_entity_operation_alter(array &$operations, EntityInterface $entity) { + // Add "View content" operation link for every service contact listed. + // First make sure that the "Content by owner" View is enabled. + $view = Views::getView('localgov_content_by_owner'); + if ($view instanceof ViewExecutable) { + // Only add the operation link to the Service contact entity collection. + if ($entity->bundle() === 'localgov_service_contact') { + $operations['service_contact_view_content'] = [ + 'title' => t('View content'), + // Point to a filtered version of the "Content by owner" View, + // using the View's contextual filter. + 'url' => Url::fromRoute('view.localgov_content_by_owner.page_1', [ + ['service-contact-id' => $entity->id()], + ]), + 'weight' => 150, + ]; + } + } +} diff --git a/modules/localgov_workflows_notifications/src/Plugin/Derivative/LocalgovWorkflowsNotificationsContentByOwner.php b/modules/localgov_workflows_notifications/src/Plugin/Derivative/LocalgovWorkflowsNotificationsContentByOwner.php new file mode 100644 index 0000000..c5b5a95 --- /dev/null +++ b/modules/localgov_workflows_notifications/src/Plugin/Derivative/LocalgovWorkflowsNotificationsContentByOwner.php @@ -0,0 +1,72 @@ +basePluginId = $base_plugin_id; + $this->entityTypeManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, $base_plugin_id) { + return new static( + $base_plugin_id, + $container->get('entity_type.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function getDerivativeDefinitions($base_plugin_definition) { + $links = []; + + // Only create the menu link if the corresponding View is present. + $view = Views::getView('localgov_content_by_owner'); + if ($view instanceof ViewExecutable) { + $links['localgov_workflows_notifications_content_by_owner'] = [ + 'title' => $this->t('Content by owner'), + 'description' => $this->t('Table of contents, by owner.'), + 'route_name' => 'view.localgov_content_by_owner.page_1', + 'parent' => 'entity.localgov_service_contact.collection', + ] + $base_plugin_definition; + } + + return $links; + } + +} diff --git a/modules/localgov_workflows_notifications/src/Plugin/Derivative/LocalgovWorkflowsNotificationsLocalTasks.php b/modules/localgov_workflows_notifications/src/Plugin/Derivative/LocalgovWorkflowsNotificationsLocalTasks.php new file mode 100644 index 0000000..2d1200e --- /dev/null +++ b/modules/localgov_workflows_notifications/src/Plugin/Derivative/LocalgovWorkflowsNotificationsLocalTasks.php @@ -0,0 +1,49 @@ +derivatives = []; + // Only create the local task if the corresponding View is present. + $view = Views::getView('localgov_content_by_owner'); + if ($view instanceof ViewExecutable) { + $this->derivatives['localgov_workflows_notifications.contacts'] = $base_plugin_definition; + $this->derivatives['localgov_workflows_notifications.contacts']['route_name'] = 'entity.localgov_service_contact.collection'; + $this->derivatives['localgov_workflows_notifications.contacts']['base_route'] = 'entity.localgov_service_contact.collection'; + $this->derivatives['localgov_workflows_notifications.contacts']['parent_id'] = 'entity.localgov_service_contact.collection'; + $this->derivatives['localgov_workflows_notifications.contacts']['title'] = $this->t('Contacts'); + + $this->derivatives['localgov_workflows_notifications.content'] = $base_plugin_definition; + $this->derivatives['localgov_workflows_notifications.content']['route_name'] = 'view.localgov_content_by_owner.page_1'; + $this->derivatives['localgov_workflows_notifications.content']['parent_id'] = 'entity.localgov_service_contact.collection'; + $this->derivatives['localgov_workflows_notifications.content']['base_route'] = 'entity.localgov_service_contact.collection'; + $this->derivatives['localgov_workflows_notifications.content']['title'] = $this->t('Content'); + } + return parent::getDerivativeDefinitions($base_plugin_definition); + } + +}