From be224b814dade1ed836d63b75447a9c6e9ed067e Mon Sep 17 00:00:00 2001 From: Benn Oshrin Date: Wed, 13 Oct 2021 18:43:59 -0400 Subject: [PATCH] Initial pagination commit and other miscellanea --- app/resources/locales/en_US/default.po | 42 ++++++- app/src/Controller/ApiUsersController.php | 6 + app/src/Controller/CosController.php | 6 + app/src/Controller/CousController.php | 6 + app/src/Controller/StandardController.php | 31 +++-- app/src/Lib/Traits/QueryModificationTrait.php | 100 +++++++++++++++++ app/templates/ApiUsers/columns.inc | 6 +- app/templates/Standard/add-edit-view.php | 7 ++ app/templates/Standard/index.php | 21 +++- app/templates/element/pagination.php | 106 ++++++++++++++++++ 10 files changed, 313 insertions(+), 18 deletions(-) create mode 100644 app/templates/element/pagination.php diff --git a/app/resources/locales/en_US/default.po b/app/resources/locales/en_US/default.po index 4aedbdc17..c6a235dc2 100644 --- a/app/resources/locales/en_US/default.po +++ b/app/resources/locales/en_US/default.po @@ -250,6 +250,12 @@ msgstr "{0} not found" msgid "registry.er.notprov" msgstr "{0} not provided" +msgid "registry.er.pagenum.exceeded" +msgstr "Page number may not be larger than {0}" + +msgid "registry.er.pagenum.nan" +msgstr "Page number must be an integer" + msgid "registry.er.perm" msgstr "Permission Denied" @@ -347,16 +353,19 @@ msgstr "API Users created in the COmanage CO are given full privileges to all Re msgid "registry.in.api.key" msgstr "This newly generated API Key cannot be recovered. If it is lost a new key must be generated." -### Menu Messages -msgid "registry.me.co.switch" -msgstr "Switch Collaboration" - -msgid "registry.me.co.co_people" -msgstr "CO People" +msgid "registry.in.pagination.format" +msgstr "Page {{page}} of {{pages}}, Viewing {{start}}-{{end}} of {{count}}" +### Menu Messages msgid "registry.me.co.configuration" msgstr "Configuration" +msgid "registry.me.co.people" +msgstr "People" + +msgid "registry.me.co.switch" +msgstr "Switch Collaboration" + ### Operations (Commands) msgid "registry.op.add.a" msgstr "Add New {0}" @@ -385,12 +394,33 @@ msgstr "Edit" msgid "registry.op.edit.a" msgstr "Edit {0}" +msgid "registry.op.first" +msgstr "First" + +msgid "registry.op.go" +msgstr "Go" + +msgid "registry.op.last" +msgstr "Last" + msgid "registry.op.login" msgstr "Login" msgid "registry.op.logout" msgstr "Logout" +msgid "registry.op.next" +msgstr "Next" + +msgid "registry.op.page.display" +msgstr "Display" + +msgid "registry.op.page.goto" +msgstr "Go To Page" + +msgid "registry.op.previous" +msgstr "Previous" + msgid "registry.op.save" msgstr "Save" diff --git a/app/src/Controller/ApiUsersController.php b/app/src/Controller/ApiUsersController.php index fd5eb2a3c..96d0b5a1f 100644 --- a/app/src/Controller/ApiUsersController.php +++ b/app/src/Controller/ApiUsersController.php @@ -45,6 +45,12 @@ class ApiUsersController extends StandardController { ] ]; + public $pagination = [ + 'order' => [ + 'ApiUsers.username' => 'asc' + ] + ]; + /** * Generate a new API Key. * diff --git a/app/src/Controller/CosController.php b/app/src/Controller/CosController.php index 01b5a450f..f6ee02231 100644 --- a/app/src/Controller/CosController.php +++ b/app/src/Controller/CosController.php @@ -54,6 +54,12 @@ class CosController extends StandardController { ] ]; + public $pagination = [ + 'order' => [ + 'Cos.name' => 'asc' + ] + ]; + /* * XXX implement, also REST API * diff --git a/app/src/Controller/CousController.php b/app/src/Controller/CousController.php index df3251485..c90fdeba7 100644 --- a/app/src/Controller/CousController.php +++ b/app/src/Controller/CousController.php @@ -48,6 +48,12 @@ class CousController extends StandardController { ] ]; + public $pagination = [ + 'order' => [ + 'Cous.name' => 'asc' + ] + ]; + /** * Callback run prior to the request render. * diff --git a/app/src/Controller/StandardController.php b/app/src/Controller/StandardController.php index 5be3fa589..16af3c53e 100644 --- a/app/src/Controller/StandardController.php +++ b/app/src/Controller/StandardController.php @@ -33,6 +33,9 @@ use \Cake\Http\Exception\BadRequestException; class StandardController extends AppController { + // Pagination defaults should be set in each controller + public $pagination = []; + /** * Handle an add action for a Standard object. * @@ -298,11 +301,10 @@ public function edit($id) { // query modifications via traits $query = $table->findById($id); - // AssociationTrait -/* - if(method_exists($table, "getEditContains")) { - $query = $query->contain($table->getEditContains()); - }*/ + // QueryModificationTrait + if(method_exists($this->$modelsName, "getEditContains")) { + $query = $query->contain($this->$modelsName->getEditContains()); + } try { // Pull the current record @@ -478,7 +480,10 @@ public function index() { $query->contain($table->getIndexContains()); } - $resultSet = $this->Paginator->paginate($query); + // The Cake documents describe $this->paginate (which worked in Cake 2), + // but it doesn't seem to work in Cake 4. So we just use $this->pagination + // ourselves here. + $resultSet = $this->Paginator->paginate($query, $this->pagination); $this->set($tableName, $resultSet); $this->set('vv_permission_set', $this->RegistryAuth->calculatePermissionsForResultSet($resultSet)); @@ -517,7 +522,12 @@ protected function populateAutoViewVars(object $obj=null) { break; // "auxiliary" and "select" do basically the same thing, but the former // returns the full object and the latter just returns a hash suitable - // for a select + // for a select. "type" is a shorthand for "select" for type_id. + case 'type': + // Inject configuration + $avv['model'] = 'Types'; + // We assume the model using type_id has a primary link of co_id + $avv['find'] = 'filterPrimaryLink'; case 'auxiliary': // XXX add list as in match? case 'select': @@ -553,7 +563,7 @@ protected function populateAutoViewVars(object $obj=null) { // to PrimaryLinkTrait and call it there? if($v) { - $query = $query->find($avv['find'], [$linkFilter => $v]); + $query = $query->where([$linkFilter => $v]); } } } else { @@ -562,6 +572,11 @@ protected function populateAutoViewVars(object $obj=null) { } } + if(!empty($avv['where'])) { + // Filter on the specified clause (of the form [column=>value]) + $query = $query->where($avv['where']); + } + $this->set($vvar, $query->toArray()); break; default: diff --git a/app/src/Lib/Traits/QueryModificationTrait.php b/app/src/Lib/Traits/QueryModificationTrait.php index c188302d6..4f74664a8 100644 --- a/app/src/Lib/Traits/QueryModificationTrait.php +++ b/app/src/Lib/Traits/QueryModificationTrait.php @@ -30,9 +30,43 @@ namespace App\Lib\Traits; trait QueryModificationTrait { + // Array of associated models to copy during a duplicate + private $duplicateContains = false; + + // Array of associated models to pull during an edit + private $editContains = false; + // Containable models for index actions private $indexContains = null; + // Array of associated models to save during a patch + private $patchAssociated = []; + + // Array of associated models to pull during a view + private $viewContains = false; + + /** + * Obtain the set of associated models to copy during a duplicate. + * + * @since COmanage Registry v5.0.0 + * @return array Array of associated models + */ + + public function getDuplicateContains() { + return $this->duplicateContains; + } + + /** + * Obtain the set of associated models to pull during an edit. + * + * @since COmanage Registry v5.0.0 + * @return array Array of associated models + */ + + public function getEditContains() { + return $this->editContains; + } + /** * Containable models for index actions. * @@ -44,6 +78,50 @@ public function getIndexContains() { return $this->indexContains; } + /** + * Obtain the set of associated models to save during a patch. + * + * @since COmanage Registry v5.0.0 + * @return array Array of associated models + */ + + public function getPatchAssociated() { + return $this->patchAssociated; + } + + /** + * Obtain the set of associated models to pull during a view. + * + * @since COmanage Registry v5.0.0 + * @return array Array of associated models + */ + + public function getViewContains() { + return $this->viewContains; + } + + /** + * Set the associated models to copy during a duplicate. + * + * @since COmanage Registry v5.0.0 + * @param array $c Array of associated models + */ + + public function setDuplicateContains(array $c) { + $this->duplicateContains = $c; + } + + /** + * Set the associated models to pull during an edit. + * + * @since COmanage Registry v5.0.0 + * @param array $c Array of associated models + */ + + public function setEditContains(array $c) { + $this->editContains = $c; + } + /** * Set containable models for index actions. * @@ -54,4 +132,26 @@ public function getIndexContains() { public function setIndexContains(array $contains) { $this->indexContains = $contains; } + + /** + * Set the associated models to save during a patch. + * + * @since COmanage Registry v5.0.0 + * @param array $a Array of associated models + */ + + public function setPatchAssociated(array $a) { + $this->patchAssociated = $a; + } + + /** + * Set the associated models to pull during a view. + * + * @since COmanage Registry v5.0.0 + * @param array $c Array of associated models + */ + + public function setViewContains(array $c) { + $this->viewContains = $c; + } } diff --git a/app/templates/ApiUsers/columns.inc b/app/templates/ApiUsers/columns.inc index 23e7b1667..29d9aef96 100644 --- a/app/templates/ApiUsers/columns.inc +++ b/app/templates/ApiUsers/columns.inc @@ -34,11 +34,13 @@ if($vv_cur_co->id == 1) { $indexColumns = [ 'username' => [ - 'type' => 'link' + 'type' => 'link', + 'sortable' => true ], 'status' => [ 'type' => 'enum', - 'class' => 'SuspendableStatusEnum' + 'class' => 'SuspendableStatusEnum', + 'sortable' => true ], 'api_key' => [ 'type' => 'boolean', diff --git a/app/templates/Standard/add-edit-view.php b/app/templates/Standard/add-edit-view.php index a261fbf29..d39b1940a 100644 --- a/app/templates/Standard/add-edit-view.php +++ b/app/templates/Standard/add-edit-view.php @@ -101,6 +101,13 @@ include(ROOT . DS . "templates" . DS . $modelsName . DS . $fieldsFile); +if(!empty($hidden)) { + // Inject any hidden variables set by the include file + foreach($hidden as $attr => $v) { + print $this->Form->hidden($attr, ['value' => $v]); + } +} + if($vv_action == 'add' || $vv_action == 'edit') { // We don't want/need to output these for view actions diff --git a/app/templates/Standard/index.php b/app/templates/Standard/index.php index e2bebfcc0..19d195713 100644 --- a/app/templates/Standard/index.php +++ b/app/templates/Standard/index.php @@ -119,7 +119,21 @@ function _column_key($modelsName, $c, $tz=null) { $cfg): ?> - + @@ -268,4 +282,7 @@ function _column_key($modelsName, $c, $tz=null) {
+ Paginator->sort($cfg['sortable'], $label); + } else { + print $this->Paginator->sort($col, $label); + } + } else { + print $label; + } + ?> +
- \ No newline at end of file + + +element("pagination"); \ No newline at end of file diff --git a/app/templates/element/pagination.php b/app/templates/element/pagination.php new file mode 100644 index 000000000..965bb8bf7 --- /dev/null +++ b/app/templates/element/pagination.php @@ -0,0 +1,106 @@ +Paginator->hasPage(2)) { + $paginationClass = "with-pagination-elements"; + } +?> + \ No newline at end of file