Skip to content

View template and improve other templates #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions config/form-templates.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
return [
'button' => '<button class="bg-red-800 p-2 text-white rounded-sm"{{attrs}}>{{text}}</button>',
'checkbox' => '<input class="mr-2" type="checkbox" name="{{name}}" value="{{value}}"{{attrs}}>',
'input' => '<input class="border border-slate-500 rounded-sm max-w-md min-w-4" type="{{type}}" name="{{name}}"{{attrs}}>',
'error' => '<div class="text-red-700" id="{{id}}">{{content}}</div>',
'input' => '<input class="border border-slate-500 rounded-sm max-w-md min-w-4 p-1" type="{{type}}" name="{{name}}"{{attrs}}>',
'inputContainer' => '<div class="py-3 flex gap-2 justify-between">{{content}}</div>',
'inputContainerError' => '<div class="py-3 flex gap-2 justify-between text-red-700">{{content}}</div>{{error}}',
'label' => '<label class="mr-2" {{attrs}}>{{text}}</label>',
'textarea' => '<textarea class="border border-slate-500 rounded-sm max-w-md min-w-4" name="{{name}}"{{attrs}}>{{value}}</textarea>',
'select' => '<select class="border border-slate-500 rounded-sm max-w-md min-w-4" name="{{name}}"{{attrs}}>{{content}}</select>',
'selectMultiple' => '<select class="border border-slate-500 rounded-sm max-w-md min-w-50" name="{{name}}[]" multiple="multiple"{{attrs}}>{{content}}</select>',
'textarea' => '<textarea class="border border-slate-500 rounded-sm max-w-md min-w-4 p-1" name="{{name}}"{{attrs}}>{{value}}</textarea>',
'select' => '<select class="border border-slate-500 rounded-sm max-w-md min-w-4 p-1" name="{{name}}"{{attrs}}>{{content}}</select>',
'selectMultiple' => '<select class="border border-slate-500 rounded-sm max-w-md min-w-50 p-1" name="{{name}}[]" multiple="multiple"{{attrs}}>{{content}}</select>',
];
6 changes: 6 additions & 0 deletions config/html-templates.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php
declare(strict_types=1);

return [
'link' => '<a href="{{url}}" class="hover:text-red-800" {{attrs}}>{{content}}</a>',
];
10 changes: 5 additions & 5 deletions config/paginator-templates.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
* Custom templates for pagination elements.
*/
return [
'nextActive' => '<li class="next"><a rel="next" href="{{url}}">{{text}}</a></li>',
'nextActive' => '<li class=""><a rel="next" href="{{url}}">{{text}}</a></li>',
'nextDisabled' => '<li class="next text-gray-400"><a>{{text}}</a></li>',
'prevActive' => '<li class="prev"><a rel="prev" href="{{url}}">{{text}}</a></li>',
'prevActive' => '<li class="text-red-700"><a rel="prev" href="{{url}}">{{text}}</a></li>',
'prevDisabled' => '<li class="prev text-gray-400"><a>{{text}}</a></li>',
'counterRange' => '{{start}} - {{end}} of {{count}}',
'counterPages' => '{{page}} of {{pages}}',
Expand All @@ -16,9 +16,9 @@
'number' => '<li><a href="{{url}}">{{text}}</a></li>',
'current' => '<li class="active"><a href="">{{text}}</a></li>',
'ellipsis' => '<li class="ellipsis">&hellip;</li>',
'sort' => '<a href="{{url}}">{{text}}</a>',
'sortAsc' => '<a class="asc" href="{{url}}">{{text}}</a>',
'sortDesc' => '<a class="desc" href="{{url}}">{{text}}</a>',
'sort' => '<a class="hover:text-red-800" href="{{url}}">{{text}}</a>',
'sortAsc' => "<a class=\"whitespace-nowrap text-red-700 after:text-red-700 after:content-['_↓']\" href=\"{{url}}\">{{text}}</a>",
'sortDesc' => "<a class=\"whitespace-nowrap text-red-700 after:text-red-700 after:content-['_↑']\" href=\"{{url}}\">{{text}}</a>",
'sortAscLocked' => '<a class="asc locked" href="{{url}}">{{text}}</a>',
'sortDescLocked' => '<a class="desc locked" href="{{url}}">{{text}}</a>',
];
1 change: 1 addition & 0 deletions src/View/AppView.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,6 @@ public function initialize(): void
{
$this->loadHelper('Paginator', ['templates' => 'paginator-templates']);
$this->loadHelper('Form', ['templates' => 'form-templates']);
$this->loadHelper('Html', ['templates' => 'html-templates']);
}
}
2 changes: 1 addition & 1 deletion templates/element/flash/error.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
$message = h($message);
}
?>
<div class="message error" onclick="this.classList.add('hidden');"><?= $message ?></div>
<div class="bg-red-200 mb-3 p-3 rounded-sm" onclick="this.classList.add('hidden');"><?= $message ?></div>
2 changes: 1 addition & 1 deletion templates/element/flash/info.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
$message = h($message);
}
?>
<div class="message" onclick="this.classList.add('hidden');"><?= $message ?></div>
<div class="bg-blue-200 mb-3 p-3 rounded-sm" onclick="this.classList.add('hidden');"><?= $message ?></div>
2 changes: 1 addition & 1 deletion templates/element/flash/success.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
$message = h($message);
}
?>
<div class="message success" onclick="this.classList.add('hidden')"><?= $message ?></div>
<div class="bg-green-200 mb-3 p-3 rounded-sm" onclick="this.classList.add('hidden')"><?= $message ?></div>
2 changes: 1 addition & 1 deletion templates/element/flash/warning.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
$message = h($message);
}
?>
<div class="message warning" onclick="this.classList.add('hidden');"><?= $message ?></div>
<div class="bg-orange-200 mb-3 p-3 rounded-sm" onclick="this.classList.add('hidden');"><?= $message ?></div>
6 changes: 3 additions & 3 deletions templates/layout/default.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@
</a>
</div>
<div class="flex gap-2">
<a target="_blank" rel="noopener" href="https://book.cakephp.org/5/">Documentation</a>
<a target="_blank" rel="noopener" href="https://api.cakephp.org/">API</a>
<?= $this->Html->link('Documentation', 'https://book.cakephp.org/5/', ['target' => '_blank', 'rel' => 'noopener']) ?>
<?= $this->Html->link('Documentation', 'https://api.cakephp.org/', ['target' => '_blank', 'rel' => 'noopener']) ?>
</div>
</nav>
<main class="main max-w-3xl mx-auto">
<main class="main max-w-4xl mx-auto">
<div class="container">
<?= $this->Flash->render() ?>
<?= $this->fetch('content') ?>
Expand Down
35 changes: 35 additions & 0 deletions templates/plugin/Bake/Template/edit.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{#
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 2.0.0
* @license https://www.opensource.org/licenses/mit-license.php MIT License
*/
#}
<?php
/**
* @var \{{ namespace }}\View\AppView $this
* @var \{{ entityClass }} ${{ singularVar }}
{{- "\n" }}
{%- if associations.BelongsTo is defined %}
{%- for assocName, assocData in associations.BelongsTo %}
* @var string[]|\Cake\Collection\CollectionInterface ${{ assocData.variable }}
{{- "\n" }}
{%- endfor %}
{% endif %}
{%- if associations.BelongsToMany is defined %}
{%- for assocName, assocData in associations.BelongsToMany %}
* @var string[]|\Cake\Collection\CollectionInterface ${{ assocData.variable }}
{{- "\n" }}
{%- endfor %}
{% endif %}
*/
?>
{{ element('Bake.form') }}
8 changes: 2 additions & 6 deletions templates/plugin/Bake/Template/index.twig
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,7 @@
{% set fields = Bake.filterFields(fields, schema, modelObject, indexColumns, ['binary', 'text']) %}
<div class="pb-3 flex justify-between items-center">
<h3 class="text-lg"><?= __('{{ pluralHumanName }}') ?></h3>
<?= $this->Html->link(
__('New {{ singularHumanName }}'),
['action' => 'add'],
['class' => 'bg-red-700 hover:bg-red-900 text-white font-bold py-2 px-4 rounded']
) ?>
<?= $this->Html->link( __('New {{ singularHumanName }}'), ['action' => 'add']) ?>
</div>
{% set done = [] %}
<div>
Expand All @@ -42,7 +38,7 @@
</thead>
<tbody>
<?php foreach (${{ pluralVar }} as ${{ singularVar }}): ?>
<tr>
<tr class="odd:bg-white even:bg-gray-50 *:py-2 *:px-1">
{% for field in fields %}
{% set isKey = false %}
{% if associations.BelongsTo is defined %}
Expand Down
158 changes: 158 additions & 0 deletions templates/plugin/Bake/Template/view.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
{#
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 2.0.0
* @license https://www.opensource.org/licenses/mit-license.php MIT License
*/
#}
<?php
/**
* @var \{{ namespace }}\View\AppView $this
* @var \{{ entityClass }} ${{ singularVar }}
*/
?>
{% set associations = {'BelongsTo': [], 'HasOne': [], 'HasMany': [], 'BelongsToMany': []}|merge(associations) %}
{% set fieldsData = Bake.getViewFieldsData(fields, schema, associations) %}
{% set associationFields = fieldsData.associationFields %}
{% set groupedFields = fieldsData.groupedFields %}
{% set pK = '$' ~ singularVar ~ '->' ~ primaryKey[0] %}
<div class="grid grid-cols-3 gap-2">
<aside class="col-span-1 flex flex-col gap-2">
<h4 class="text-lg"><?= __('Actions') ?></h4>
<?= $this->Html->link(__('Edit {{ singularHumanName }}'), ['action' => 'edit', {{ pK|raw }}]) ?>
<?= $this->Form->postLink(__('Delete {{ singularHumanName }}'), ['action' => 'delete', {{ pK|raw }}], ['confirm' => __('Are you sure you want to delete # {0}?', {{ pK|raw }})]) ?>
<?= $this->Html->link(__('List {{ pluralHumanName }}'), ['action' => 'index']) ?>
<?= $this->Html->link(__('New {{ singularHumanName }}'), ['action' => 'add'], ['class' => 'bg-red-50']) ?>
{% set done = [] %}
</aside>
<div class="col-span-2">
<div class="w-full">
<h3 class="text-xl"><?= h(${{ singularVar }}->{{ displayField }}) ?></h3>
<table class="w-full">
{% if groupedFields['string'] %}
{% for field in groupedFields['string'] %}
{% if associationFields[field] is defined %}
{% set details = associationFields[field] %}
<tr>
<th class="text-left pb-2"><?= __('{{ details.property|humanize }}') ?></th>
<td><?= ${{ singularVar }}->hasValue('{{ details.property }}') ? $this->Html->link(${{ singularVar }}->{{ details.property }}->{{ details.displayField }}, ['controller' => '{{ details.controller }}', 'action' => 'view', ${{ singularVar }}->{{ details.property }}->{{ details.primaryKey[0] }}]) : '' ?></td>
</tr>
{% else %}
<tr>
<th class="text-left pb-2"><?= __('{{ field|humanize }}') ?></th>
<td><?= h(${{ singularVar }}->{{ field }}) ?></td>
</tr>
{% endif %}
{% endfor %}
{% endif %}
{% if associations.HasOne %}
{% for alias, details in associations.HasOne %}
<tr>
<th class="text-left pb-2"><?= __('{{ alias|underscore|singularize|humanize }}') ?></th>
<td><?= ${{ singularVar }}->hasValue('{{ details.property }}') ? $this->Html->link(${{ singularVar }}->{{ details.property }}->{{ details.displayField }}, ['controller' => '{{ details.controller }}', 'action' => 'view', ${{ singularVar }}->{{ details.property }}->{{ details.primaryKey[0] }}]) : '' ?></td>
</tr>
{% endfor %}
{% endif %}
{% if groupedFields.number %}
{% for field in groupedFields.number %}
<tr>
<th class="text-left pb-2"><?= __('{{ field|humanize }}') ?></th>
{% set columnData = Bake.columnData(field, schema) %}
{% if columnData.null %}
<td><?= ${{ singularVar }}->{{ field }} === null ? '' : $this->Number->format(${{ singularVar }}->{{ field }}) ?></td>
{% else %}
<td><?= $this->Number->format(${{ singularVar }}->{{ field }}) ?></td>
{% endif %}
</tr>
{% endfor %}
{% endif %}
{% if groupedFields.enum %}
{% for field in groupedFields.enum %}
<tr>
<th class="text-left pb-2"><?= __('{{ field|humanize }}') ?></th>
{% set columnData = Bake.columnData(field, schema) %}
{% set supportsLabel = Bake.enumSupportsLabel(field, schema) %}
{% if columnData.null %}
<td><?= ${{ singularVar }}->{{ field }} === null ? '' : h(${{ singularVar }}->{{ field }}->{% if supportsLabel %}label(){% else %}value{% endif %}) ?></td>
{% else %}
<td><?= h(${{ singularVar }}->{{ field }}->{% if supportsLabel %}label(){% else %}value{% endif %}) ?></td>
{% endif %}
</tr>
{% endfor %}
{% endif %}
{% if groupedFields.date %}
{% for field in groupedFields.date %}
<tr>
<th class="text-left pb-2"><?= __('{{ field|humanize }}') ?></th>
<td><?= h(${{ singularVar }}->{{ field }}) ?></td>
</tr>
{% endfor %}
{% endif %}
{% if groupedFields.boolean %}
{% for field in groupedFields.boolean %}
<tr>
<th class="text-left pb-2"><?= __('{{ field|humanize }}') ?></th>
<td><?= ${{ singularVar }}->{{ field }} ? __('Yes') : __('No'); ?></td>
</tr>
{% endfor %}
{% endif %}
</table>
{% if groupedFields.text %}
{% for field in groupedFields.text %}
<div class="text">
<strong><?= __('{{ field|humanize }}') ?></strong>
<blockquote>
<?= $this->Text->autoParagraph(h(${{ singularVar }}->{{ field }})); ?>
</blockquote>
</div>
{% endfor %}
{% endif %}
{% set relations = associations.BelongsToMany|merge(associations.HasMany) %}
{% for alias, details in relations %}
{% set otherSingularVar = alias|singularize|variable %}
{% set otherPluralHumanName = details.controller|underscore|humanize %}
<div class="mt-4">
<h4 class="text-lg"><?= __('Related {{ otherPluralHumanName }}') ?></h4>
<?php if (!empty(${{ singularVar }}->{{ details.property }})) : ?>
<table class="w-full">
<tr>
{% for field in details.fields %}
<th class="text-left pb-2"><?= __('{{ field|humanize }}') ?></th>
{% endfor %}
<th class="actions"><?= __('Actions') ?></th>
</tr>
<?php foreach (${{ singularVar }}->{{ details.property }} as ${{ otherSingularVar }}) : ?>
<tr>
{% for field in details.fields %}
<td><?= h(${{ otherSingularVar }}->{{ field }}) ?></td>
{% endfor %}
{% set otherPk = '$' ~ otherSingularVar ~ '->' ~ details.primaryKey[0] %}
<td class="actions">
<?= $this->Html->link(__('View'), ['controller' => '{{ details.controller }}', 'action' => 'view', {{ otherPk|raw }}]) ?>
<?= $this->Html->link(__('Edit'), ['controller' => '{{ details.controller }}', 'action' => 'edit', {{ otherPk|raw }}]) ?>
<?= $this->Form->postLink(
__('Delete'),
['controller' => '{{ details.controller }}', 'action' => 'delete', {{ otherPk|raw }}],
[
'method' => 'delete',
'confirm' => __('Are you sure you want to delete # {0}?', {{ otherPk|raw }}),
]
) ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<?php endif; ?>
</div>
{% endfor %}
</div>
</div>
</div>
20 changes: 9 additions & 11 deletions templates/plugin/Bake/element/form.twig
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,18 @@
#}
{% set fields = Bake.filterFields(fields, schema, modelObject) %}
<div class="grid grid-cols-3 gap-2">
<aside class="col-span-1">
<div class="side-nav">
<h4 class="text-lg"><?= __('Actions') ?></h4>
<aside class="col-span-1 flex flex-col gap-2">
<h4 class="text-lg"><?= __('Actions') ?></h4>
{% if 'add' not in action %}
<?= $this->Form->postLink(
__('Delete'),
['action' => 'delete', ${{ singularVar }}->{{ primaryKey[0] }}],
['confirm' => __('Are you sure you want to delete # {0}?', ${{ singularVar }}->{{ primaryKey[0] }}), 'class' => 'side-nav-item']
) ?>
<?= $this->Form->postLink(
__('Delete'),
['action' => 'delete', ${{ singularVar }}->{{ primaryKey[0] }}],
['confirm' => __('Are you sure you want to delete # {0}?', ${{ singularVar }}->{{ primaryKey[0] }})]
) ?>
{% endif %}
<?= $this->Html->link(__('List {{ pluralHumanName }}'), ['action' => 'index'], ['class' => 'side-nav-item']) ?>
{{- "\n" }}
<?= $this->Html->link(__('List {{ pluralHumanName }}'), ['action' => 'index']) ?>
{{- "\n" }}
{%- set done = [] %}
</div>
</aside>
<div class="col-span-2">
<div class="w-full">
Expand Down