3
0
Fork 0
mirror of https://github.com/farmOS/farmOS.git synced 2024-02-23 11:37:38 +01:00

Add owner field to assets #537

This commit is contained in:
Michael Stenta 2022-09-27 14:23:08 -04:00
commit d52eb621e2
19 changed files with 487 additions and 107 deletions

View file

@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [Issue #3306344: Allow views exposed filters to be collapsed](https://www.drupal.org/project/farm/issues/3306344)
- [Issue #3309234: Add PHPStan to test and delivery workflow](https://www.drupal.org/project/farm/issues/3309234)
- [Issue #3309198: Allow users to override Gin theme settings](https://www.drupal.org/project/farm/issues/3309198)
- [Add owner field to assets #537](https://github.com/farmOS/farmOS/pull/537)
### Changed

View file

@ -23,6 +23,10 @@ Assets can also be cloned by selecting one or more in a list and clicking the
"Clone asset" button that appears at the bottom. This will clone the Asset
record(s), but will not clone the Logs that are associated with them.
Assets can be assigned to one or more person(s) in farmOS using the Asset's
*Owner* field. Users can view a list of all Assets assigned to them by
navigating to their profile and then clicking the "Assets" tab.
For more information on Asset records, refer the [Assets](/model/type/asset)
section of the [farmOS data model](/model) docs.

View file

@ -170,6 +170,7 @@ Relationships that are common to all Asset types include:
- Location
- Parents
- Owners
- Images
- Files
@ -195,6 +196,10 @@ two Land Assets related through the Parents field).
Multiple parents are allowed, but circular relationships are not.
#### Owners
Assets can be assigned to one or more Users in farmOS.
#### Images
Images can be attached to Assets. This provides a place to store photos of the

View file

@ -150,7 +150,7 @@ Relationships that are common to all Log types include:
- Assets
- Locations
- Quantities
- Owners (whom the Log is assigned to)
- Owners
- Categories
- Images
- Files

View file

@ -0,0 +1,11 @@
langcode: en
status: true
dependencies:
module:
- farm_owner
- asset
id: asset_assign_action
label: 'Assign owners'
type: asset
plugin: 'asset_assign_action'
configuration: { }

View file

@ -5,7 +5,7 @@ dependencies:
- farm_owner
- log
id: log_assign_action
label: 'Assign log'
label: 'Assign owners'
type: log
plugin: 'log_assign_action'
configuration: { }

View file

@ -1,4 +1,7 @@
# Schema for actions.
action.configuration.asset_assign_action:
type: action_configuration_default
label: 'Configuration for the asset assign action'
action.configuration.log_assign_action:
type: action_configuration_default
label: 'Configuration for the log assign action'

View file

@ -7,3 +7,4 @@ dependencies:
- drupal:user
- farm:farm_field
- log:log
- asset:asset

View file

@ -13,12 +13,12 @@ use Drupal\Core\Entity\EntityTypeInterface;
function farm_owner_entity_base_field_info(EntityTypeInterface $entity_type) {
$fields = [];
// Add owner field to logs.
if ($entity_type->id() == 'log') {
// Add owner field to logs and assets.
if (in_array($entity_type->id(), ['asset', 'log'])) {
$field_info = [
'type' => 'entity_reference',
'label' => t('Assigned to'),
'description' => t('Optionally assign this task to one or more people.'),
'label' => t('Owner'),
'description' => t('Optionally specify who is in charge of this record.'),
'target_type' => 'user',
'multiple' => TRUE,
'weight' => [
@ -26,6 +26,7 @@ function farm_owner_entity_base_field_info(EntityTypeInterface $entity_type) {
'view' => -70,
],
];
$fields['owner'] = \Drupal::service('farm_field.factory')->baseFieldDefinition($field_info);
}

View file

@ -0,0 +1,47 @@
<?php
/**
* @file
* Updates farm_owner module.
*/
use Drupal\system\Entity\Action;
/**
* Add 'owner' field to assets.
*/
function farm_owner_post_update_add_asset_owner(&$sandbox = NULL) {
$entity_type = 'asset';
$module_name = 'farm_owner';
$field_name = 'owner';
$field_info = [
'type' => 'entity_reference',
'label' => t('Owner'),
'description' => t('Optionally specify an owner for this asset.'),
'target_type' => 'user',
'multiple' => TRUE,
'weight' => [
'form' => -70,
'view' => -70,
],
];
$field_definition = \Drupal::service('farm_field.factory')->baseFieldDefinition($field_info);
\Drupal::entityDefinitionUpdateManager()
->installFieldStorageDefinition($field_name, $entity_type, $module_name, $field_definition);
// Update the label of the log_assign_action config.
$action = Action::load('log_assign_action');
$action->set('label', t('Assign owners'));
$action->save();
// Create action for assigning assets to users.
$action = Action::create([
'id' => 'asset_assign_action',
'label' => t('Assign owners'),
'type' => 'asset',
'plugin' => 'asset_assign_action',
'configuration' => [],
]);
$action->save();
}

View file

@ -1,6 +1,14 @@
farm_owner.log_assign_action_form:
path: '/log/assign'
defaults:
_form: 'Drupal\farm_owner\Form\LogAssignActionForm'
_form: 'Drupal\farm_owner\Form\AssignActionForm'
entity_type: 'log'
requirements:
_user_is_logged_in: 'TRUE'
farm_owner.asset_assign_action_form:
path: '/asset/assign'
defaults:
_form: 'Drupal\farm_owner\Form\AssignActionForm'
entity_type: 'asset'
requirements:
_user_is_logged_in: 'TRUE'

View file

@ -8,14 +8,15 @@ use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\Core\Url;
use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\farm_role\ManagedRolePermissionsManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Provides a log assign confirmation form.
* Provides an assign confirmation form.
*/
class LogAssignActionForm extends ConfirmFormBase {
class AssignActionForm extends ConfirmFormBase {
/**
* The tempstore factory.
@ -53,14 +54,14 @@ class LogAssignActionForm extends ConfirmFormBase {
protected $entityType;
/**
* The logs to assign.
* The entities to assign.
*
* @var \Drupal\Core\Entity\EntityInterface[]
*/
protected $entities;
/**
* Constructs a LogAssignActionForm form object.
* Constructs an AssignActionForm form object.
*
* @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
* The tempstore factory.
@ -72,7 +73,7 @@ class LogAssignActionForm extends ConfirmFormBase {
* The current user.
*/
public function __construct(PrivateTempStoreFactory $temp_store_factory, EntityTypeManagerInterface $entity_type_manager, ManagedRolePermissionsManagerInterface $managed_role_permissions_manager, AccountInterface $user) {
$this->tempStore = $temp_store_factory->get('log_assign_confirm');
$this->tempStore = $temp_store_factory->get('entity_assign_confirm');
$this->entityTypeManager = $entity_type_manager;
$this->managedRolePermissionsManager = $managed_role_permissions_manager;
$this->user = $user;
@ -94,7 +95,7 @@ class LogAssignActionForm extends ConfirmFormBase {
* {@inheritdoc}
*/
public function getFormId() {
return 'log_assign_action_confirm_form';
return 'assign_action_confirm_form';
}
/**
@ -136,9 +137,21 @@ class LogAssignActionForm extends ConfirmFormBase {
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$this->entityType = $this->entityTypeManager->getDefinition('log');
public function buildForm(array $form, FormStateInterface $form_state, string $entity_type = NULL) {
// Only allow asset and log entities.
if (!in_array($entity_type, ['asset', 'log'])) {
throw new PluginException('Unsupported entity type given when building form to assign entity');
}
// Load the entity type definition.
$this->entityType = $this->entityTypeManager->getDefinition($entity_type);
// Load saved entities.
$this->entities = $this->tempStore->get($this->user->id());
// If there are no entities, or if the entity type definition didn't load,
// redirect the user to the cancel URL.
if (empty($this->entityType) || empty($this->entities)) {
return new RedirectResponse($this->getCancelUrl()
->setAbsolute()
@ -157,8 +170,8 @@ class LogAssignActionForm extends ConfirmFormBase {
$form['users'] = [
'#type' => 'select',
'#title' => $this->t('Assign log(s) to'),
'#description' => $this->t('Select people to assign these logs to.'),
'#title' => $this->t('Assign owners'),
'#description' => $this->t('Select people to assign ownership of the record(s).'),
'#options' => $user_options,
'#multiple' => TRUE,
];
@ -166,7 +179,7 @@ class LogAssignActionForm extends ConfirmFormBase {
$form['operation'] = [
'#type' => 'radios',
'#title' => $this->t('Append or replace'),
'#description' => $this->t('Select "Append" if you want to add users to the logs, but keep the existing assignments. Select "Replace" if you want to replace existing assignments with the ones specified above.'),
'#description' => $this->t('Select "Append" if you want to add owners, but keep the existing assignments. Select "Replace" if you want to replace existing assignments with the people specified above.'),
'#options' => [
'append' => $this->t('Append'),
'replace' => $this->t('Replace'),
@ -215,11 +228,11 @@ class LogAssignActionForm extends ConfirmFormBase {
$owner_field->appendItem($owner);
}
// Validate the log before saving.
// Validate the entity before saving.
$violations = $entity->validate();
if ($violations->count() > 0) {
$this->messenger()->addWarning(
$this->t('Could not assign log <a href=":entity_link">%entity_label</a>: validation failed.',
$this->t('Could not assign <a href=":entity_link">%entity_label</a>: validation failed.',
[
':entity_link' => $entity->toUrl()->setAbsolute()->toString(),
'%entity_label' => $entity->label(),

View file

@ -0,0 +1,17 @@
<?php
namespace Drupal\farm_owner\Plugin\Action;
/**
* Action that assigns users to assets.
*
* @Action(
* id = "asset_assign_action",
* label = @Translation("Assign assets to users."),
* type = "asset",
* confirm_form_route_name = "farm_owner.asset_assign_action_form"
* )
*/
class AssetAssign extends AssignBase {
}

View file

@ -0,0 +1,89 @@
<?php
namespace Drupal\farm_owner\Plugin\Action;
use Drupal\Core\Action\Plugin\Action\EntityActionBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Action that assigns users to entities.
*/
abstract class AssignBase extends EntityActionBase {
/**
* The tempstore object.
*
* @var \Drupal\Core\TempStore\SharedTempStore
*/
protected $tempStore;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* Constructs a new AssignBase object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin ID for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
* The tempstore factory.
* @param \Drupal\Core\Session\AccountInterface $current_user
* Current user.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, PrivateTempStoreFactory $temp_store_factory, AccountInterface $current_user) {
$this->currentUser = $current_user;
$this->tempStore = $temp_store_factory->get('entity_assign_confirm');
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity_type.manager'),
$container->get('tempstore.private'),
$container->get('current_user')
);
}
/**
* {@inheritdoc}
*/
public function executeMultiple(array $entities) {
/** @var \Drupal\Core\Entity\EntityInterface[] $entities */
$this->tempStore->set($this->currentUser->id(), $entities);
}
/**
* {@inheritdoc}
*/
public function execute($object = NULL) {
$this->executeMultiple([$object]);
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
return $object->access('update', $account, $return_as_object);
}
}

View file

@ -2,95 +2,16 @@
namespace Drupal\farm_owner\Plugin\Action;
use Drupal\Core\Action\Plugin\Action\EntityActionBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Action that assigns users to logs.
*
* @Action(
* id = "log_assign_action",
* label = @Translation("Assign users to logs."),
* label = @Translation("Assign logs to users."),
* type = "log",
* confirm_form_route_name = "farm_owner.log_assign_action_form"
* )
*/
class LogAssign extends EntityActionBase {
/**
* The tempstore object.
*
* @var \Drupal\Core\TempStore\SharedTempStore
*/
protected $tempStore;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* Constructs a new LogAssign object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin ID for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory
* The tempstore factory.
* @param \Drupal\Core\Session\AccountInterface $current_user
* Current user.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, PrivateTempStoreFactory $temp_store_factory, AccountInterface $current_user) {
$this->currentUser = $current_user;
$this->tempStore = $temp_store_factory->get('log_assign_confirm');
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity_type.manager'),
$container->get('tempstore.private'),
$container->get('current_user')
);
}
/**
* {@inheritdoc}
*/
public function executeMultiple(array $entities) {
/** @var \Drupal\Core\Entity\EntityInterface[] $entities */
$this->tempStore->set($this->currentUser->id(), $entities);
}
/**
* {@inheritdoc}
*/
public function execute($object = NULL) {
$this->executeMultiple([$object]);
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
return $object->access('update', $account, $return_as_object);
}
class LogAssign extends AssignBase {
}

View file

@ -137,6 +137,7 @@ function farm_ui_theme_farm_ui_theme_region_items(string $entity_type) {
'is_location',
'is_fixed',
'location',
'owner',
'status',
'type',
],
@ -154,6 +155,7 @@ function farm_ui_theme_farm_ui_theme_region_items(string $entity_type) {
'first' => [],
'second' => [
'image',
'owner',
'status',
'type',
],

View file

@ -481,6 +481,71 @@ display:
multi_type: separator
separator: ', '
field_api_classes: false
owner_target_id:
id: owner_target_id
table: asset__owner
field: owner_target_id
relationship: none
group_type: group
admin_label: ''
entity_type: asset
entity_field: owner
plugin_id: field
label: Owner
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
location:
id: location
table: asset
@ -908,6 +973,63 @@ display:
default_group: All
default_group_multiple: { }
group_items: { }
owner_target_id:
id: owner_target_id
table: asset__owner
field: owner_target_id
relationship: none
group_type: group
admin_label: ''
entity_type: asset
entity_field: owner
plugin_id: entity_reference
operator: or
value: { }
group: 1
exposed: true
expose:
operator_id: owner_target_id_op
label: Owner
description: ''
use_operator: false
operator: owner_target_id_op
operator_limit_selection: false
operator_list: { }
identifier: owner_target_id
required: false
remember: false
multiple: true
remember_roles:
authenticated: authenticated
anonymous: '0'
farm_manager: '0'
farm_viewer: '0'
farm_worker: '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
handler: 'default:user'
widget: select
handler_settings:
target_bundles: null
sort:
field: _none
direction: ASC
auto_create: false
filter:
type: _none
include_anonymous: false
filter_groups:
operator: AND
groups:
@ -926,6 +1048,7 @@ display:
type: type
flag_value: flag_value
parent_target_id: parent_target_id
owner_target_id: owner_target_id
location: location
status: status
default: name
@ -971,6 +1094,11 @@ display:
separator: ''
empty_column: false
responsive: ''
owner_target_id:
align: ''
separator: ''
empty_column: false
responsive: ''
location:
align: ''
separator: ''
@ -1031,7 +1159,7 @@ display:
id: csv
display_title: 'CSV export (rest)'
display_plugin: rest_export
position: 5
position: 7
display_options:
pager:
type: none
@ -1086,7 +1214,7 @@ display:
id: entity_browser
display_title: 'Entity browser'
display_plugin: entity_browser
position: 6
position: 8
display_options:
fields:
entity_browser_select:
@ -1598,11 +1726,85 @@ display:
- url.query_args
- user.permissions
tags: { }
page_assigned_to:
id: page_assigned_to
display_title: 'Assigned (page)'
display_plugin: page
position: 4
display_options:
title: 'Assigned assets'
arguments:
owner_target_id:
id: owner_target_id
table: asset__owner
field: owner_target_id
relationship: none
group_type: group
admin_label: ''
entity_type: asset
entity_field: owner
plugin_id: numeric
default_action: 'not found'
exception:
value: all
title_enable: false
title: All
title_enable: false
title: ''
default_argument_type: fixed
default_argument_options:
argument: ''
default_argument_skip_url: false
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: 'entity:user'
fail: 'not found'
validate_options:
access: false
operation: view
multiple: 0
restrict_roles: false
roles: { }
break_phrase: false
not: false
defaults:
title: false
arguments: false
display_description: ''
display_extenders: { }
path: user/%user/assets
menu:
type: tab
title: Assets
description: ''
weight: 0
expanded: false
menu_name: account
parent: ''
context: '0'
cache_metadata:
max-age: 0
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url
- url.query_args
- user.permissions
tags: { }
page_children:
id: page_children
display_title: 'Children (page)'
display_plugin: page
position: 4
position: 5
display_options:
title: 'Asset children'
arguments:
@ -1746,7 +1948,7 @@ display:
id: page_term
display_title: 'By term (page)'
display_plugin: page
position: 4
position: 6
display_options:
arguments:
asset_taxonomy_term_reference:

View file

@ -689,7 +689,7 @@ display:
entity_type: log
entity_field: owner
plugin_id: field
label: 'Assigned to'
label: Owner
exclude: false
alter:
alter_text: false
@ -1159,7 +1159,7 @@ display:
exposed: true
expose:
operator_id: owner_target_id_op
label: 'Assigned to'
label: Owner
description: ''
use_operator: false
operator: owner_target_id_op

View file

@ -437,6 +437,55 @@ display:
hide_empty: false
empty_zero: false
hide_alter_empty: false
nothing_1:
id: nothing_1
table: views
field: nothing
relationship: none
group_type: group
admin_label: ''
plugin_id: custom
label: 'Assigned assets'
exclude: false
alter:
alter_text: true
text: 'Assigned assets'
make_link: true
path: 'user/{{ uid }}/assets'
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: false
pager:
type: full
options:
@ -634,6 +683,7 @@ display:
access: access
status: status
nothing: nothing
nothing_1: nothing_1
default: name
info:
uid:
@ -683,6 +733,11 @@ display:
separator: ''
empty_column: false
responsive: ''
nothing_1:
align: ''
separator: ''
empty_column: false
responsive: ''
override: true
sticky: false
summary: ''