diff --git a/app/resources/locales/en_US/menu.po b/app/resources/locales/en_US/menu.po index 60bdcfedc..72149952c 100644 --- a/app/resources/locales/en_US/menu.po +++ b/app/resources/locales/en_US/menu.po @@ -27,6 +27,9 @@ msgid "artifacts" msgstr "Available {0} Artifacts" +msgid "available.filters" +msgstr "Available Filters" + msgid "co.artifacts" msgstr "Artifacts" @@ -201,6 +204,9 @@ msgstr "User Menu" msgid "menu.toggle" msgstr "Toggle menu collapse button" +msgid "options" +msgstr "Options" + msgid "registries" msgstr "Available {0} Registries" diff --git a/app/src/Lib/Traits/SearchFilterTrait.php b/app/src/Lib/Traits/SearchFilterTrait.php index 00d52957c..2dff433ce 100644 --- a/app/src/Lib/Traits/SearchFilterTrait.php +++ b/app/src/Lib/Traits/SearchFilterTrait.php @@ -35,6 +35,19 @@ trait SearchFilterTrait { // Array (and configuration) of permitted search filters private $searchFilters = array(); + // Optional filter configuration that dictates display state and allows for related models + private $filterConfig = array(); + + /** + * Get explicilty defined filter configuration defined in the table class. + * + * @since COmanage Registry v5.0.0 + */ + + public function getFilterConfig(): array { + return $this->filterConfig; + } + /** * Obtain the set of permitted search attributes. * @@ -44,14 +57,42 @@ trait SearchFilterTrait { public function getSearchableAttributes(string $controller, string $vv_tz=null): array { $modelname = Inflector::classify(Inflector::underscore($controller)); + $filterConfig = $this->getFilterConfig(); + + // Gather up related models defined in the $filterConfig + // XXX For now, we'll list these first - but we should probably provide a better way to order these. + foreach ($filterConfig as $field => $f) { + if($f['type'] == 'relatedModel') { + $fieldName = Inflector::classify(Inflector::underscore($field)); + $this->searchFilters[$field] = [ + 'type' => 'string', // XXX for now - this needs to be looked up. + 'label' => \App\Lib\Util\StringUtilities::columnKey($fieldName, $field, $vv_tz, true), + 'active' => isset($f['active']) ? $f['active'] : true + ]; + } + } + foreach ($this->filterMetadataFields() as $column => $type) { // If the column is an array then we are accessing the Metadata fields. Skip if(is_array($type)) { continue; } + + // Set defaults + $fieldIsActive = true; + + // Gather filter configurations, if any, for local table fields. + // An active field is visible in the filter form. An inactive field is not but can be enabled. + if(!empty($filterConfig[$column])) { + if(isset($filterConfig[$column]['active'])) { + $fieldIsActive = $filterConfig[$column]['active']; + } + } + $this->searchFilters[$column] = [ 'type' => $type, - 'label' => \App\Lib\Util\StringUtilities::columnKey($modelname, $column, $vv_tz, true) + 'label' => \App\Lib\Util\StringUtilities::columnKey($modelname, $column, $vv_tz, true), + 'active' => $fieldIsActive ]; // For the date fields we search ranges @@ -63,6 +104,16 @@ public function getSearchableAttributes(string $controller, string $vv_tz=null): return $this->searchFilters ?? []; } + + /** + * Set explicilty defined filter configuration defined in the table class. + * + * @since COmanage Registry v5.0.0 + */ + + public function setFilterConfig(array $filterConfig): void { + $this->filterConfig = $filterConfig; + } /** * Build a query where() clause for the configured attribute. diff --git a/app/src/Model/Table/PeopleTable.php b/app/src/Model/Table/PeopleTable.php index 066393201..7347a53b8 100644 --- a/app/src/Model/Table/PeopleTable.php +++ b/app/src/Model/Table/PeopleTable.php @@ -154,6 +154,34 @@ public function initialize(array $config): void { ] ]); + // XXX expand/revise this as needed to work best with looking up the related models + $this->setFilterConfig([ + 'family' => [ + 'type' => 'relatedModel', + 'model' => 'names', + 'active' => true + ], + 'given' => [ + 'type' => 'relatedModel', + 'model' => 'names', + 'active' => true + ], + 'mail' => [ + 'type' => 'relatedModel', + 'model' => 'email_addresses', + 'active' => true + ], + 'identifier' => [ + 'type' => 'relatedModel', + 'model' => 'identifiers', + 'active' => true + ], + 'timezone' => [ + 'type' => 'field', + 'active' => false + ] + ]); + $this->setPermissions([ // Actions that operate over an entity (ie: require an $id) // See also CFM-126 diff --git a/app/templates/element/filter.php b/app/templates/element/filter.php index c316e9e0f..a748cc452 100644 --- a/app/templates/element/filter.php +++ b/app/templates/element/filter.php @@ -145,12 +145,17 @@ $field_booleans_columns = []; $field_datetime_columns = []; + $inactiveFiltersCount = 0; // for re-balancing the columns and submit buttons + if(!empty($columns)) { // To make our filters consistently ordered with the index columns, sort the $vv_searchable_attributes // by the keys of columns.inc $indexColumns (passed in to this View element as $indexColumns and referenced // as "$columns"). The fields found in $columns will be placed first in the resulting array. // The result should only include fields that exist in the original $vv_searchable_attributes array. - $vv_searchable_attributes = array_intersect_key(array_replace(array_flip(array_keys($columns)), $vv_searchable_attributes), $vv_searchable_attributes); + + // XXX Turn this off. We should have more arbitrary control over the order of the filters, and for the moment + // it is better (at least for now) to let the explicitly defined filters come first. + // $vv_searchable_attributes = array_intersect_key(array_replace(array_flip(array_keys($columns)), $vv_searchable_attributes), $vv_searchable_attributes); } foreach($vv_searchable_attributes as $key => $options) { @@ -188,8 +193,15 @@ 'pickerType' => \App\Lib\Enum\DateTypeEnum::DateOnly, 'pickerFloor' => $pickerFloor ]; + + $wrapperCssClass = 'filter-active'; + if(empty($options['active'])) { + $wrapperCssClass = 'filter-inactive'; + $inactiveFiltersCount++; + } + // Create a text field to hold our date value. - print '