From 7604a1eedebaa47ee70b14df74eae466792ee28b Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 6 Dec 2016 02:44:42 -0700 Subject: [PATCH 1/6] =?UTF-8?q?chore:=20move=20table=20section=20of=20inde?= =?UTF-8?q?x=20into=20it=E2=80=99s=20own=20element?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will allow us to swap out the table for other display types --- src/Template/Element/index/table.ctp | 48 +++++++++++++++++++++++ src/Template/Scaffold/index.ctp | 57 +++++----------------------- 2 files changed, 57 insertions(+), 48 deletions(-) create mode 100644 src/Template/Element/index/table.ctp diff --git a/src/Template/Element/index/table.ctp b/src/Template/Element/index/table.ctp new file mode 100644 index 00000000..4044bee0 --- /dev/null +++ b/src/Template/Element/index/table.ctp @@ -0,0 +1,48 @@ +
+ + + + element('index/bulk_actions/table', compact('bulkActions', 'primaryKey', 'singularVar')); ?> + + $options) : + ?> + + + + + + + + + + + + element('index/bulk_actions/record', compact('bulkActions', 'primaryKey', 'singularVar')); ?> + element('index/table_columns', compact('singularVar')); ?> + + + + + + + +
+ Paginator->sort($field, isset($options['title']) ? $options['title'] : null, $options); + } + ?> +
element('actions', [ + 'singularVar' => $singularVar, + 'actions' => $actions['entity'] + ]); ?>
+
diff --git a/src/Template/Scaffold/index.ctp b/src/Template/Scaffold/index.ctp index 4b040cd4..82a0b6fc 100644 --- a/src/Template/Scaffold/index.ctp +++ b/src/Template/Scaffold/index.ctp @@ -17,54 +17,15 @@ element('index/bulk_actions/form_start', compact('bulkActions')); ?> -
- - - - element('index/bulk_actions/table', compact('bulkActions', 'primaryKey', 'singularVar')); ?> - - $options) : - ?> - - - - - - - - - - - - element('index/bulk_actions/record', compact('bulkActions', 'primaryKey', 'singularVar')); ?> - element('index/table_columns', compact('singularVar')); ?> - - - - - - - -
- Paginator->sort($field, isset($options['title']) ? $options['title'] : null, $options); - } - ?> -
element('actions', [ - 'singularVar' => $singularVar, - 'actions' => $actions['entity'] - ]); ?>
-
+ element('index/table', [ + 'fields' => $fields, + 'actions' => $actions, + 'bulkActions' => $bulkActions, + 'primaryKey' => $primaryKey, + 'singularVar' => $singularVar, + 'viewVar' => $viewVar, + $viewVar => ${$viewVar}, + ])?> element('index/bulk_actions/form_end', compact('bulkActions')); ?> element('index/pagination'); ?> From c5d7c3893eb71208bff3ef6709e288da011e093c Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 6 Dec 2016 03:43:56 -0700 Subject: [PATCH 2/6] feat: implement customizing the index section of the index view Also update index documentation --- docs/_themes/cakephp/static/css/app.css | 11 +- docs/contents.rst | 8 +- docs/customizing-templates.rst | 32 ----- docs/index-pages/components/custom.rst | 22 +++ docs/index-pages/components/table.rst | 76 ++++++++++ .../customizing-the-index-page.rst | 132 ++++++++++++++++++ src/Listener/Traits/IndexTypeTrait.php | 36 +++++ src/Listener/ViewListener.php | 3 + src/Template/Scaffold/index.ctp | 28 ++-- 9 files changed, 302 insertions(+), 46 deletions(-) create mode 100644 docs/index-pages/components/custom.rst create mode 100644 docs/index-pages/components/table.rst create mode 100644 docs/index-pages/customizing-the-index-page.rst create mode 100644 src/Listener/Traits/IndexTypeTrait.php diff --git a/docs/_themes/cakephp/static/css/app.css b/docs/_themes/cakephp/static/css/app.css index 906bf713..1c903e97 100644 --- a/docs/_themes/cakephp/static/css/app.css +++ b/docs/_themes/cakephp/static/css/app.css @@ -21,7 +21,8 @@ div.related { #sidebar-navigation > ul > li:nth-of-type(2):last-child:after, #sidebar-navigation > ul > li:nth-of-type(4):last-child:after, -#sidebar-navigation > ul > li:nth-of-type(7):last-child:after { +#sidebar-navigation > ul > li:nth-of-type(6):last-child:after, +#sidebar-navigation > ul > li:nth-of-type(9):last-child:after { content: " "; display: block; margin-bottom: 1em; @@ -31,10 +32,14 @@ div.related { padding-top: 0; } #sidebar-navigation > ul > li:nth-of-type(3):before { + content: "Usage"; +} +#sidebar-navigation > ul > li:nth-of-type(5):before { content: "General Configuration"; } -#sidebar-navigation > ul > li:nth-of-type(6):before { - content: "Usage"; + +#sidebar-navigation > ul > li:nth-of-type(8):before { + content: "Index Pages"; } /* Left for CSS overrides we need to make in the future */ diff --git a/docs/contents.rst b/docs/contents.rst index f0090015..772c9795 100644 --- a/docs/contents.rst +++ b/docs/contents.rst @@ -12,9 +12,13 @@ Contents Installation Quick Start + Basic Usage + Customizing Templates + Site Title Options Sidebar Navigation Utility Navigation - Basic Usage - Customizing Templates + Customizing the Index Page + Custom Index + Index as a Table diff --git a/docs/customizing-templates.rst b/docs/customizing-templates.rst index 21b7db5b..7682c3ba 100644 --- a/docs/customizing-templates.rst +++ b/docs/customizing-templates.rst @@ -250,35 +250,3 @@ type of action. In general, if you want to override a template, it is a good idea to copy the original implementation from ``vendor/friendsofcake/crud-view/src/Template/Element`` - -Index Action Elements -~~~~~~~~~~~~~~~~~~~~~ - -search - Create ``src/Template/Element/search.ctp`` for having full control over how - the search filters are displayed in your pagination table. You can expect the - ``$searchInputs`` and ``$searchOptions`` variables to be available - -index/pagination - Create ``src/Template/Element/index/pagination.ctp`` To implement your own - pagination links and counter. - -index/bulk_actions/table - Create ``src/Template/Element/index/bulk_actions/table.ctp`` for changing how - the bulk action inputs for the whole table. You can expect the - ``$bulkActions``, ``$primaryKey`` and ``$singularVar`` variables to be - available. - -index/bulk_actions/record - Create ``src/Template/Element/index/bulk_actions/record.ctp`` for changing how - the bulk action inputs for each row are displayed. You can expect the - ``$bulkActions``, ``$primaryKey`` and ``$singularVar`` variables to be - available. - -index/bulk_actions/form_start - Create ``src/Template/Element/index/bulk_actions/form_start.ctp`` To customize - the Form create call for bulk actions - -index/bulk_actions/form_end - Create ``src/Template/Element/index/bulk_actions/form_end.ctp`` To customize - the Form end call for bulk actions diff --git a/docs/index-pages/components/custom.rst b/docs/index-pages/components/custom.rst new file mode 100644 index 00000000..03531bf3 --- /dev/null +++ b/docs/index-pages/components/custom.rst @@ -0,0 +1,22 @@ +Custom Index +============ + +To use a custom index element, you can set the ``scaffold.index_type`` config option. + +.. code-block:: php + + $action = $this->Crud->action(); + $action->config('scaffold.index_type', 'an_element'); + +Available Variables +------------------- + +The following variables are available for use within the element: + +- `fields`: List of fields to show and their options +- `actions`: A list of actions that can be displayed for the index page. +- `bulkActions`: A list of bulk actions associated with this resource +- `primaryKey`: The name of the record's primary key field. +- `singularVar`: The singular version of the resource name. +- `viewVar`: Reference to the name of the variable holding all records. +- plural of `viewVar`: The set of records. diff --git a/docs/index-pages/components/table.rst b/docs/index-pages/components/table.rst new file mode 100644 index 00000000..930944b1 --- /dev/null +++ b/docs/index-pages/components/table.rst @@ -0,0 +1,76 @@ +Index as a Table +================ + +By default, the index page is a table with each of the models content columns +and links to show, edit and delete the object. There are many ways to +customize what gets displayed. + +Defining Columns +---------------- + +By default, all fields are displayed on the ``index`` page. To display an +attribute or a method on a record, you can use the ``scaffold.fields`` +config option. + +.. code-block:: php + + $action = $this->Crud->action(); + $action->config('scaffold.fields', ['id', 'title']); + +To specify the title used in the pagination header, you need to set +``scaffold.fields`` to an associative array and use the ``title`` parameter: + +.. code-block:: php + + $action = $this->Crud->action(); + $action->config('scaffold.fields', [ + 'id', + 'title' => [ + 'title' => __('Blog Post') + ] + ]); + +Index Action Elements +--------------------- + +All the ``CrudView`` templates are built from several elements that can be +overridden by creating them in your own ``src/Template/Element`` folder. The +following sections will list all the elements that can be overridden for each +type of action. + +In general, if you want to override a template, it is a good idea to copy the +original implementation from +``vendor/friendsofcake/crud-view/src/Template/Element`` + +search + Create ``src/Template/Element/search.ctp`` for having full control over how + the search filters are displayed in your pagination table. You can expect the + ``$searchInputs`` and ``$searchOptions`` variables to be available + +index/table + Create ``src/Template/Element/index/table.ctp`` To implement your own + table. + +index/pagination + Create ``src/Template/Element/index/pagination.ctp`` To implement your own + pagination links and counter. + +index/bulk_actions/table + Create ``src/Template/Element/index/bulk_actions/table.ctp`` for changing how + the bulk action inputs for the whole table. You can expect the + ``$bulkActions``, ``$primaryKey`` and ``$singularVar`` variables to be + available. + +index/bulk_actions/record + Create ``src/Template/Element/index/bulk_actions/record.ctp`` for changing how + the bulk action inputs for each row are displayed. You can expect the + ``$bulkActions``, ``$primaryKey`` and ``$singularVar`` variables to be + available. + +index/bulk_actions/form_start + Create ``src/Template/Element/index/bulk_actions/form_start.ctp`` To customize + the Form create call for bulk actions + +index/bulk_actions/form_end + Create ``src/Template/Element/index/bulk_actions/form_end.ctp`` To customize + the Form end call for bulk actions diff --git a/docs/index-pages/customizing-the-index-page.rst b/docs/index-pages/customizing-the-index-page.rst new file mode 100644 index 00000000..b49765da --- /dev/null +++ b/docs/index-pages/customizing-the-index-page.rst @@ -0,0 +1,132 @@ +Customizing the Index Page +========================== + +Multiple Index Pages +-------------------- + +Sometime you may want more than one index page for a resource to represent different views to the user. If multiple index pages exist, CrudView will automatically build links at the top of the `index` page. Including multiple views is simple and requires setting the `index` view in your action. + +.. code-block:: php + + $action = $this->Crud->action(); + $action->view('index'); + +Formatting fields +----------------- + +The most immediate changes you can do in the way data is displayed is by +applying formatters to any of your fields. Whenever you use the +``scaffold.fields`` configuration key, you can specify a ``formatter`` to be used. + +.. code-block:: php + + $action = $this->Crud->action(); + $action->config('scaffold.fields', [ + 'title', + 'published_time' => [ + 'formatter' => function ($name, Time $value) { + return $value->nice(); + } + ], + ]); + +You may also specify formatters using the ``scaffold.field_settings`` +configuration key. This is useful if you want to display all fields but wish +to only configure the settings for one or two. + +.. code-block:: php + + $action = $this->Crud->action(); + $action->config('scaffold.field_settings', [ + 'published_time' => [ + 'formatter' => function ($name, Time $value) { + return $value->nice(); + } + ], + ]); + +Formatting with a Callable +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The most immediate way of formatting a field is by passing a callable function +or object. Callable functions or objects will receive 3 arguments: + +* ``$name`` The name of the field to be displayed +* ``$value`` The value of the field that should be outputted +* ``$entity`` The entity object from which the field was extracted + +For example, imagine that when displaying the ``published_time`` property, we +wanted to also display who approved the article: + +.. code-block:: php + + $action = $this->Crud->action(); + $action->config('scaffold.fields', [ + 'published_time' => [ + 'formatter' => function ($name, $value, $entity) { + return $value->nice() . sprintf(' (Approved by %s)', $entity->approver->name); + } + ] + ]); + +Formatting with an Element +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sometimes you want to execute more complex formatting logic, that may involve +the use of view helpers or outputting HTML. Since building HTML outside of the +view layer is not ideal, you can use the ``element`` formatter for any of your +fields. + +For example, consider this example where we want to link the ``published_time`` +to the same index action by passing some search arguments: + +.. code-block:: php + + $action = $this->Crud->action(); + $action->config('scaffold.fields', [ + 'published_time' => [ + 'formatter' => 'element', + 'element' => 'search/published_time', + 'action' => 'index' + ] + ]); + +We have instructed the formatter to use ``search/published_time`` element. Then, +it is just a matter of creating the element file with the right content: + +.. code-block:: php + + // src/Template/Element/search/published_time.ctp + + echo $this->Html->link($value->timeAgoInWords(), [ + 'action' => $options['action'], + 'published_time' => $value->format('Y-m-d') + ]); + +After this, when displaying the ``published_time`` field, there will the will be +a link similar to this one:: + + 4 days ago + +Element files will have available at least the following variables: + +* ``$value``: The value of the field +* ``$field``: The name of the field it is intended to be rendered +* ``$context``: The entity from which the value came from +* ``$options``: The array of options associated to the field as passed in ``scaffold.fields`` + + +Index Buttons +------------- + +Index Filters +------------- + +Index Pagination +---------------- + +Custom Download Links +--------------------- + +Custom Blocks +------------- diff --git a/src/Listener/Traits/IndexTypeTrait.php b/src/Listener/Traits/IndexTypeTrait.php new file mode 100644 index 00000000..6fd72256 --- /dev/null +++ b/src/Listener/Traits/IndexTypeTrait.php @@ -0,0 +1,36 @@ +_controller(); + $controller->set('indexType', $this->_getIndexType()); + } + + /** + * Returns the index type to show on scaffolded view + * + * @return string + */ + protected function _getIndexType() + { + $action = $this->_action(); + + $indexType = $action->config('scaffold.index_type'); + if (empty($indexType)) { + $indexType = 'table'; + } + + return $indexType; + } +} diff --git a/src/Listener/ViewListener.php b/src/Listener/ViewListener.php index 7568395b..11553f82 100644 --- a/src/Listener/ViewListener.php +++ b/src/Listener/ViewListener.php @@ -6,6 +6,7 @@ use Cake\Event\Event; use Cake\Utility\Hash; use Cake\Utility\Inflector; +use CrudView\Listener\Traits\IndexTypeTrait; use CrudView\Listener\Traits\SidebarNavigationTrait; use CrudView\Listener\Traits\SiteTitleTrait; use CrudView\Listener\Traits\UtilityNavigationTrait; @@ -15,6 +16,7 @@ class ViewListener extends BaseListener { use CrudViewConfigTrait; + use IndexTypeTrait; use SidebarNavigationTrait; use SiteTitleTrait; use UtilityNavigationTrait; @@ -76,6 +78,7 @@ public function beforeRender(Event $event) $this->ensureConfig(); + $this->beforeRenderIndexType($event); $this->beforeRenderSiteTitle($event); $this->beforeRenderUtilityNavigation($event); $this->beforeRenderSidebarNavigation($event); diff --git a/src/Template/Scaffold/index.ctp b/src/Template/Scaffold/index.ctp index 82a0b6fc..f1557ed9 100644 --- a/src/Template/Scaffold/index.ctp +++ b/src/Template/Scaffold/index.ctp @@ -17,15 +17,25 @@ element('index/bulk_actions/form_start', compact('bulkActions')); ?> - element('index/table', [ - 'fields' => $fields, - 'actions' => $actions, - 'bulkActions' => $bulkActions, - 'primaryKey' => $primaryKey, - 'singularVar' => $singularVar, - 'viewVar' => $viewVar, - $viewVar => ${$viewVar}, - ])?> + $fields, + 'actions' => $actions, + 'bulkActions' => $bulkActions, + 'primaryKey' => $primaryKey, + 'singularVar' => $singularVar, + 'viewVar' => $viewVar, + $viewVar => ${$viewVar}, + ]; + switch ($indexType) { + case 'table': + echo $this->element('index/table', $_data); + break; + default: + echo $this->element($indexType, $_data); + break; + } + ?> element('index/bulk_actions/form_end', compact('bulkActions')); ?> element('index/pagination'); ?> From 5605d284b4d4057805cdf12a7a24e337782cc074 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 6 Dec 2016 03:56:15 -0700 Subject: [PATCH 3/6] feat: add a blog component for the index view --- docs/contents.rst | 1 + docs/index-pages/components/blog.rst | 23 ++++++++++++++++ src/Listener/Traits/IndexTypeTrait.php | 36 ++++++++++++++++++++++++++ src/Template/Element/index/blog.ctp | 18 +++++++++++++ src/Template/Scaffold/index.ctp | 3 +++ 5 files changed, 81 insertions(+) create mode 100644 docs/index-pages/components/blog.rst create mode 100644 src/Template/Element/index/blog.ctp diff --git a/docs/contents.rst b/docs/contents.rst index 772c9795..5af6bb59 100644 --- a/docs/contents.rst +++ b/docs/contents.rst @@ -21,4 +21,5 @@ Contents Customizing the Index Page Custom Index + Index as a Blog Index as a Table diff --git a/docs/index-pages/components/blog.rst b/docs/index-pages/components/blog.rst new file mode 100644 index 00000000..c071986c --- /dev/null +++ b/docs/index-pages/components/blog.rst @@ -0,0 +1,23 @@ +Index as a Blog +=============== + +Render your index page as a set of posts. + +.. code-block:: php + + $action = $this->Crud->action(); + $action->config('scaffold.index_type', 'blog'); + +Customizing the Blog fields +--------------------------- + +The post has two main options: + +- ``index_blog_title_field``: (default: ``title``) Controls the field used for the blog title. +- ``index_blog_body_field``: (default: ``body``) Controls the field used for the blog body. + +.. code-block:: php + + $action = $this->Crud->action(); + $action->config('scaffold.index_blog_title_field', 'name'); + $action->config('scaffold.index_blog_body_field', 'content'); diff --git a/src/Listener/Traits/IndexTypeTrait.php b/src/Listener/Traits/IndexTypeTrait.php index 6fd72256..cf80951b 100644 --- a/src/Listener/Traits/IndexTypeTrait.php +++ b/src/Listener/Traits/IndexTypeTrait.php @@ -15,6 +15,8 @@ public function beforeRenderIndexType(Event $event) { $controller = $this->_controller(); $controller->set('indexType', $this->_getIndexType()); + $controller->set('indexBlogTitleField', $this->_getIndexBlogTitleField()); + $controller->set('indexBlogBodyField', $this->_getIndexBlogBodyField()); } /** @@ -33,4 +35,38 @@ protected function _getIndexType() return $indexType; } + + /** + * Returns the blog title field to show on scaffolded view + * + * @return string + */ + protected function _getIndexBlogTitleField() + { + $action = $this->_action(); + + $field = $action->config('scaffold.index_blog_title_field'); + if (empty($field)) { + $field = 'title'; + } + + return $field; + } + + /** + * Returns the blog body field to show on scaffolded view + * + * @return string + */ + protected function _getIndexBlogBodyField() + { + $action = $this->_action(); + + $field = $action->config('scaffold.index_blog_body_field'); + if (empty($field)) { + $field = 'body'; + } + + return $field; + } } diff --git a/src/Template/Element/index/blog.ctp b/src/Template/Element/index/blog.ctp new file mode 100644 index 00000000..f4862898 --- /dev/null +++ b/src/Template/Element/index/blog.ctp @@ -0,0 +1,18 @@ + $options) { + unset($options['td']); + if ($field === $indexBlogTitleField) { + $titleOptions = $options; + } elseif ($field === $indexBlogBodyField) { + $bodyOptions = $options; + } +} +?> + +

CrudView->process($indexBlogTitleField, $singularVar, $titleOptions) ?>

+
+ CrudView->process($indexBlogBodyField, $singularVar, $bodyOptions) ?> +
+ diff --git a/src/Template/Scaffold/index.ctp b/src/Template/Scaffold/index.ctp index f1557ed9..3c67d6b4 100644 --- a/src/Template/Scaffold/index.ctp +++ b/src/Template/Scaffold/index.ctp @@ -31,6 +31,9 @@ case 'table': echo $this->element('index/table', $_data); break; + case 'blog': + echo $this->element('index/blog', $_data); + break; default: echo $this->element($indexType, $_data); break; From 1c5e8cb82ede3e977191f86a21a6caeb2571a50c Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 6 Dec 2016 03:56:44 -0700 Subject: [PATCH 4/6] docs: use `add` as example instead of `index` for forms --- docs/customizing-templates.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/customizing-templates.rst b/docs/customizing-templates.rst index 7682c3ba..e3be4826 100644 --- a/docs/customizing-templates.rst +++ b/docs/customizing-templates.rst @@ -21,7 +21,7 @@ pass any properties that ``FormHelper::inputs()`` supports. class ArticlesController extends AppController { - public function index() + public function add() { $action = $this->Crud->action(); $action->config('scaffold.fields', [ From 97fef27cd23bc6072105a1cb17d215b3332ded52 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 6 Dec 2016 03:56:51 -0700 Subject: [PATCH 5/6] docs: fix spelling issue --- docs/customizing-templates.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/customizing-templates.rst b/docs/customizing-templates.rst index e3be4826..64de5b95 100644 --- a/docs/customizing-templates.rst +++ b/docs/customizing-templates.rst @@ -37,7 +37,7 @@ pass any properties that ``FormHelper::inputs()`` supports. } } -Formating using a Formatter +Formatting using a Formatter ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The most immediate changes you can do in the way data is displayed is by From 7ff8960dfd8f0c1b16466dccfa021121001dff11 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 6 Dec 2016 03:57:03 -0700 Subject: [PATCH 6/6] chore: reference correct navigation section --- src/Listener/Traits/SidebarNavigationTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Listener/Traits/SidebarNavigationTrait.php b/src/Listener/Traits/SidebarNavigationTrait.php index 033545ab..31c7116e 100644 --- a/src/Listener/Traits/SidebarNavigationTrait.php +++ b/src/Listener/Traits/SidebarNavigationTrait.php @@ -18,7 +18,7 @@ public function beforeRenderSidebarNavigation(Event $event) } /** - * Returns the utility navigation to show on scaffolded view + * Returns the sidebar navigation to show on scaffolded view * * @return string */