friendsofcake / crud-view Goto Github PK
View Code? Open in Web Editor NEWCakePHP: Automated admin backend based on your CRUD configuration
Home Page: https://crud-view.readthedocs.io/en/latest/
License: MIT License
CakePHP: Automated admin backend based on your CRUD configuration
Home Page: https://crud-view.readthedocs.io/en/latest/
License: MIT License
To display input fields for datetime
properties CrudView use the DateTimeWidget
. This widget uses a date picker which detects the clients time zone. This causes an unexpected behavior when the clients time zone doesn't match the one configured in the app config.
For my app I use UTC, but my computer is at UTC+2.
For example, this are the the values I'm seeing at the moment:
value
:
2015-09-30 16:53:41
data-timestamp
:
1443632021
This is the timestamp for value
on UTC.
Displayed value after loading date picker:
30/09/2015 18:53
This is my current time on UTC+2.
Now when I post it gets interesting. Since it's posting the current time in UTC+2, it goes wrong:
value
:
2015-09-30 18:53:00
This was the time in UTC+2, but the app now assumes it's UTC.
data-timestamp
:
1443639180
This is the timestamp for value
on UTC.
Displayed value after loading date picker:
30/09/2015 20:53
Now the time is 2 hours later than I selected.
I don't think the date picker should look at the clients time zone by default, or if it does it should send it along so it can be saved correctly. Been looking into the configuration options of https://github.com/Eonasdan/bootstrap-datetimepicker/, but with the used version there doesn't seem to be a way to get it right.
My current admin panel is under Controller/Admin and Template/Admin. I have duplicated controllers and views. Crud-view works well, but under the Admin namespace it is acting strage: css classes is missing and altering the configs in actions won't react.
This is my Admin/AppController:
namespace App\Controller\Admin;
use Cake\Controller\Controller;
class AppController extends Controller
{
use \Crud\Controller\ControllerTrait;
public function initialize()
{
parent::initialize();
$this->loadComponent('Flash');
$this->viewClass = "CrudView\View\CrudView";
$this->loadComponent('Crud.Crud', [
'actions' => [
'Crud.Index',
'Crud.Add',
'Crud.Edit',
'Crud.View',
'Crud.Delete',
],
'listeners' => [
'CrudView.View',
'Crud.RelatedModels',
'Crud.Redirect',
],
]);
}
}
Since CrudView does not extend AppView loading custom helpers or passing custom options in AppView::initialize() does not work.
Hi,
I faced the need to improve the index action result due customers requirements, and would be amazing if some of them came with the core:
An example : (http://admin.motum.com.br/screen.png)
Let me know if I can help in any way!
Hi folks. I wrote up the following code:
https://gist.github.com/bdodds/148dcd7eef6c724627f4d0596f09d004
and if I go to /clientpocs/add the select dropdown for client_id is populated with sequential integers starting at 0, rather than the uuids that are in the 'id' column of the client table. I created these databases through a migrate, and if I go to /clientpocs/edit and look at the variables, I see a clientpoc->client->id variable with the right information, in fact you can see I had to pull clientpoc->client->name out to display in the list. Hopefully I'm doing something wrong, but @hmic intimated this may be a bug. So, thanks, and let me know what other information you might need.
CrudView.php is used to render the views, and it's loading BootstrapUI.Flash
with default settings.
My app has a custom render element for Flash messages, but it's not being used because of the defaults.
I also noticed BootstrapUI.Flash is loaded twice by the view.
protected function _setupHelpers()
{
$this->loadHelper('Html', ['className' => 'BootstrapUI.Html']);
$this->loadHelper('Form', [
'className' => 'BootstrapUI.Form',
'widgets' => [
'datetime' => ['CrudView\View\Widget\DateTimeWidget', 'select']
]
]);
$this->loadHelper('Flash', ['className' => 'BootstrapUI.Flash']);
$this->loadHelper('Paginator', ['className' => 'BootstrapUI.Paginator']);
$this->loadHelper('CrudView.CrudView');
$this->loadHelper('BootstrapUI.Flash');
if (Configure::read('CrudView.useAssetCompress')) {
$this->loadHelper('AssetCompress.AssetCompress');
}
}
Any ideas how I can make CrudView use my Template\Element\Flash
elements?
If you set a filed in scaffold.fields as
'onefield' => ['type'=>'select']
'otherfield' => ['type'=>'select','multiple'=>'multiple']
The resulting html will be
So the visible input select is presented OUTSIDE the div container as it should.
$action = $this->Crud->action();
$action->config('scaffold.index_type', 'gallery');
// any of these can also be set to false
$action->config('scaffold.index_title_field', 'name'); // defaults to title
$action->config('scaffold.index_image_field', 'avatar_url'); // defaults to image
$action->config('scaffold.index_body_field', 'content'); // defaults to body
Would use the "custom content" functionality from bootstrap thumbnails
#i want to use my material-design css but crud-view overwrite css
and how to customize crud-view
give file name where i can change
how to modify bootstrap's css and any additional bootstrap theme css ?
Delete action is using GET, instead of POST.
Refs #165
Hello,
yesterday I started using CRUDView. I followed the tutorial/docs of CRUDView. After checkout (master and dev-master lateron) and setting up the AppController I browsed to a Controller (e.g. UsersController). Each controller now throws an Exception "Unkown Method "searchManager"".
And yes, all the Plugins (CRUD, CRUDView, BootstrapUI and Search) are loaded. I also tried Search master and dev-master lateron.
I think, this is a bug because I didn't do anything what's not in the docs.
But since CRUDView is new to me, I don't want to dig in the code and hack into it.
So could you please check and/or give me a response, what's wrong here?
Thanks in advance.
This IF is unnecessary and can be removed
crud-view/src/Template/Element/actions.ctp
Lines 85 to 92 in 2a59b15
Its already handled here
crud-view/src/Template/Element/action-button.ctp
Lines 7 to 10 in 2a59b15
I can remove all deprecated crud-view configuration/variables at the same time as well.
We should also update all docs to not use deprecated examples
I just updated crud-view hoping to fix some other issues and found that I can no longer save new models. I have a test application setup just pulling the latest version of cake3 and crud-view. When trying to add a new entry to my "blog_entries" table it never saves. Instead it just redirects me back to the add page with the query string filled with the data I had in it.
To replicate update crud-view. Try to add a new model.
I've been trying to use the DateTimeWidget
in my app, which uses the en_GB
locale. Because of the line below, only "en" gets passed to the date picker which causes the problem (defaults to US, I guess).
https://github.com/FriendsOfCake/crud-view/blob/master/src/View/Widget/DateTimeWidget.php#L29
When I post the current time - "09/30/2015 7:07 PM" - it's parsed to "06/09/2017 9:07 AM" because of the wrong locale.
I tried removing the locale_get_primary_language()
which seems to fix it. Does anyone know why it's been used and if it has to stay here?
Happy to PR if needed, but thought I'd ask you guys before.
When I do fresh installation of crud plugin, there is "Lookup" button
But when I try to use it I am getting missing template error
imo there should be either Scaffold/lookup.ctp file or the button should not appear.
Just starting with CrudView, Crud and Search plugins so I might misunderstood.
Thanks
Just installed this plugin and got this message
Could not find listener class: CrudView.Redirect
Crud\Error\Exception\MissingListenerException
How can I fix it ?
snippet from CrudView.php:87:
$this->loadHelper('Form', [
'className' => 'BootstrapUI.Form',
'widgets' => [
'datetime' => ['CrudView\View\Widget\DateTimeWidget', 'select']
]
]);
This code causes SecurityComponent to throw following errors when trying to submit any form with date field because date is posted as a localized string
Unexpected field 'expires' in POST data, Missing field 'expires.year, expires.month, expires.day, expires.hour, expires.minute' in POST data
Cake\Controller\Exception\AuthSecurityException
I'm attempting to implement CrudView within an admin
prefix; however, this results with the view link generated for index pages incorrectly pointing as the view
action within admin
. Should the createViewLink
method in the CrudViewHelper
maybe set the prefix
to false by default like this:-
public function createViewLink($title, $options = [])
{
return $this->Html->link(
$title,
['action' => 'view', $this->getContext()->get($this->getViewVar('primaryKey')), 'prefix' => false],
$options
);
}
Is there a simple way with the current setup of the plugin to override this for all view links as I do not want any view links remaining within my admin
prefix?
I don't (and neither does @ADmad) think it makes sense to show the phinxlog
table used by Phinx - but I'm unsure how we should implement this properly.
It could be implemented as https://gist.github.com/anonymous/c6ac8712102bef1b205f22871cd1cb08, but that's not very customisable - so what do you think should be appropriate?
https://gist.github.com/anonymous/e090ec5cf5192e08ea7ca3b7cab46359 could easily be done for the default settings, but touching the crud action from within the ViewHelper (
crud-view/src/Listener/ViewListener.php
Line 74 in 6e7f359
Should it be done in
? That also feels a bit weird to me.Why does crud-view have
"phpunit/phpunit": "3.7.33"
as dependency?
It should either use 4.0 or none as it doesnt have any tests yet :)
DateTimeWidget.php itself is not "replaceable". If you create another one in the app directory it is not readed.
Regardless, the line 49 is
$val = $val->format($type === 'date' ? 'Y-m-d' : 'Y-m-d H:i:s');
meaning it is ignoring locale configurations (other dates formats)...
These would be documented under the Customizing Download Links section of the docs.
Should be something like:
$this->Crud->action()->config('scaffold.index_formats', [
'CSV' => Router::url(['_ext' => 'csv'])
]);
The above would simply add the .csv
extension to the current page. It would be up to the user to define what renders for such a link.
The link should render in a new window/tab/whatever.
Refs #165
In bootstrap.php:
Type::build('datetime')
->useImmutable();
Now all datetime fields (created/modified) get displayed as N/A.
got this when trying to install
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Can only install one of: friendsofcake/bootstrap-ui[0.4.x-dev, dev-master].
- Can only install one of: friendsofcake/bootstrap-ui[dev-master, 0.4.x-dev].
- Can only install one of: friendsofcake/bootstrap-ui[0.4.x-dev, dev-master].
- friendsofcake/crud-view dev-master requires friendsofcake/bootstrap-ui ~0.3 -> satisfiable by friendsofcake/bootstrap-ui[0.4.x-dev].
- Installation request for friendsofcake/crud-view dev-master -> satisfiable by friendsofcake/crud-view[dev-master].
- Installation request for friendsofcake/bootstrap-ui dev-master -> satisfiable by friendsofcake/bootstrap-ui[dev-master].
When action's messages are sets in configuration, there is a problem with actions links.
$this->loadComponent('Crud.Crud', [
'actions' => [
'add' => [
'className' => 'Crud.Add',
'link_title' => 'Ajouter',
'messages' => [
'success' => ['text'=>'{name} correctement ajouté !'],
'error' => ['text' => "Erreur lors de l'ajout de {name}."]
]
]
]
]);
messages
option is added to $this->Form->link()
third parameter to allow for customization and this cause an error when parsed. messages
option must be removed before being passed to FormHelper.
The following resolves this issue :
// CrudView\Listener\ViewListener.php::__getControllerActions()
// ...
${$scope}[$actionName] = [
'title' => $title,
'url' => [
'action' => $actionName
],
'method' => $method,
'options' => array_diff_key(
$config,
array_flip(['method', 'scope', 'className', 'link_title', 'messages']) // Line updated
)
];
// ...
Maybe this problem occurs with others options. I did not notice it for the moment...
I can make a PR if needed.
When I attempt to composer require friendsofcake/crud-view
, I receive the following error:
Problem 1
- Installation request for friendsofcake/crud-view ^0.4.3 -> satisfiable by friendsofcake/crud-view[0.4.3].
- friendsofcake/crud-view 0.4.3 requires friendsofcake/bootstrap-ui ~0.3 -> satisfiable by friendsofcake/bootstrap-ui[v0.3.0, v0.3.1, v0.3.2, v0.3.3, v0.3.4, v0.3.5, v0.4.0, v0.4.1, v0.5.0, v0.5.1, v0.5.2, v0.6.0, v0.6.1, v0.6.2] but these conflict with your requirements or minimum-stability.
I tried to update bootstrap-ui
but there are no new updates coming through:
mobility:socialplexus trowland$ composer update friendsofcake/bootstrap-ui
You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Generating autoload files
> Cake\Composer\Installer\PluginInstaller::postAutoloadDump
mobility:socialplexus trowland$
in a view, after an editAction the variable "$associations" is filled.
But if in a view, after an AddAction the variable "$associations" is empty.
I can't find anything on how to use action_groups in the index field.
I think it's support to render action buttons as a drop-down button, but when I do the following it just gives me an error.
public function index()
{
$action = $this->Crud->action();
$action->config('scaffold', [
'action_groups'=>[
'index','edit','delete'
]
]);
return $this->Crud->execute();
}
Anyone know how this feature is suppose to work?
This would work in conjunction with custom logic in the mapped Crud IndexAction. You could specify finder scopes to display for the user:
// where the key is the finder scope and the value is the title
$indexFinderScopes = [
__('All') => 'all',
__('In Progress') => 'inProgress',
__('Complete') => 'completed',
]
$this->Crud->action()->config('scaffold.index_finder_scopes', $indexFinderScopes);
This would then generate a url with the appropriate ?finder=FINDER
querystring argument. The all
finder would remove the finder
querystring argument (as there isn't anything special about this in CakePHP).
We would also document the - very simple - code to change the findMethod to the appropriate thing:
if (in_array($this->request->query('finder'), array_values($indexFinderScopes))) {
$this->Crud->action()->config('findMethod', $this->request->query('finder'));
}
The text currently reads
"composer require friendsofcake/crud-vew:dev-master"
and should be
"composer require friendsofcake/crud-view:dev-master"
Obviously I am a rookie and that is why I stumbled on it.
Not sure how we can write tests for this. We can do one of two things (or both)
We should probably aim for about 80-90% coverage regardless. All functionality should be tested.
Also a good opportunity for removing as much logic as possible from the templates and moving them either into listeners/traits or helpers.
Thoughts?
scaffold.index_allow_field_changing
Refs #165
This is semi-related to having sections via "legends". Not sure the legends stuff works, but being able to have multiple tabs for a single form would be quite useful for certain classes of applications.
Recently had a requirement to display a shorter name for a related field in the index table (from the default name
field to one called short_name
).
This is the most elegant solution I could come up with:
public function index()
{
$action = $this->Crud->action();
$action->config([
'scaffold.fields' => [
'facility_id' => [
'formatter' => function ($name, $value, $entity) {
return $this->getView()->Html->link(
$entity->facility->short_name,
['controller' => 'Facilities', 'action' => 'view', $entity->facility->id]
);
}
],
Other things I tried included:
beforePaginate
and back again in relatedModel
, which wasn't ideal either.)Is this a common enough use case where it should be configurable like like title
and label
?
public function index()
{
$action = $this->Crud->action();
$action->config([
'scaffold.fields' => [
'facility_id' => ['displayField' => 'short_name'],
I had an issue where the search fields were the same name as columns in associated tables. So MySQL would throw an ambiguous column reference error when performing searches.
I had to make a change to Crud (see my PR here for that FriendsOfCake/crud#427)
That fixes the search query, but than the search form was broken.
To fix that I modified the search form listener and updated _deriveFields()
/**
* [_deriveFields description]
*
* @return array
*/
protected function _deriveFields()
{
/**
* @var SearchBehavior|Table $table
*/
$table = $this->_table();
$request = $this->_request();
$filters = null;
if (method_exists($table, 'searchConfiguration')) {
$filters = $table->searchConfiguration();
} else {
$filters = $table->searchManager();
}
$fields = [];
$schema = $table->schema();
$config = $this->_config;
foreach ($filters->all() as $filter) {
if ($filter->config('form') === false) {
continue;
}
$name = $filter->name();
list($table, $field) = GemsPlugins::split_plugin($name);
$input = [];
$filterFormConfig = $filter->config();
if (!empty($filterFormConfig['form'])) {
$input = $filterFormConfig['form'];
}
$input += [
'label' => Inflector::humanize(preg_replace('/_id$/', '', $field)),
'required' => false,
'type' => 'text'
];
$input['value'] = $request->query($name);
if (empty($input['options']) && $schema->columnType($field) === 'boolean') {
$input['options'] = ['No', 'Yes'];
$input['type'] = 'select';
}
if (!empty($input['options'])) {
$input['empty'] = true;
if (empty($input['class']) && !$config['selectize']) {
$input['class'] = 'no-selectize';
}
$fields[$name] = $input;
continue;
}
if (empty($input['class']) && $config['autocomplete']) {
$input['class'] = 'autocomplete';
}
$urlArgs = [];
$fieldKeys = isset($input['fields']) ? $input['fields'] : ['id' => $field, 'value' => $field];
foreach ($fieldKeys as $key => $val) {
$urlArgs[$key] = $val;
}
unset($input['fields']);
$url = array_merge(['action' => 'lookup', '_ext' => 'json'], $urlArgs);
$input['data-url'] = Router::url($url);
$fields[$name] = $input;
}
return $fields;
}
The important part is
$name = $filter->name();
list($table, $field) = GemsPlugins::split_plugin($name);
The split_plugin
is my own function. Does anyone know of a Cake built-in function that will split a "Table.Field" string into it's two parts? There must be something already.
First and foremost, thank you all very much for this amazing plugin! 👍
The issue I'm facing:
When setting (in my controller action)
$this->Crud->action()->config('scaffold.relations', false);
I still end up getting all fields for the relations in that view.
The same issue also occurs if the scaffold.relations_blacklist
configuration happens to include all associations currently defined for the table.
Upon some investigating:
ViewListener::_getRelatedModels()
returns an empty array in both aforementioned cases which is passed to ViewListener::_associations()
as $whitelist
parameter which ultimately returns all associations assuming all associations are whitelisted.
Am I missing something of how this is supposed to work? or is it a hidden feature 😉?
Tried to find it in documentation and in code, but can't see how the bulk actions should work out? Also not sure if it is related to crud-view or crud.
When I use following config, the bulk actions select appears
public function index()
{
$action = $this->Crud->action();
$action->config('scaffold.bulk_actions', [
'delete' => 'Delete records'
]);
return $this->Crud->execute();
}
But when I submit, it tries to use non-existing controller. How do I need to config scaffold.bulk_actions? And do I need to handle delete it self in bulk action?
Any hint would be useful.
Thanks
I originally opened this item in the crud repository but have tracked it down to crud-view. The edit method always results in "Invalid CSRF token" when editing a record.
I did a fresh install of cake 3, added crud, crud-view, bootstrap-ui, and search. Added only the required config.
Schema (I've redacted some schema here to make testing easier):
CREATE TABLE `blog_entries` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`featured` tinyint(1) NOT NULL,
`title` varchar(255) NOT NULL,
`content` text NOT NULL,
`created` datetime NOT NULL,
`updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
AppController
<?php
namespace App\Controller;
use Cake\Controller\Controller;
class AppController extends Controller
{
use \Crud\Controller\ControllerTrait;
public $viewClass = 'CrudView\View\CrudView';
public $components = [
'Csrf',
'Search.Prg',
'Crud.Crud' => [
'actions' => [
'Crud.Index',
'Crud.Add',
'Crud.Edit',
'Crud.View',
'Crud.Delete'
],
'listeners' => [
'Crud.RelatedModels',
'Crud.Redirect',
'CrudView.View',
'CrudView.Search',
]
]
];
public function initialize()
{
parent::initialize();
$this->loadComponent('Flash');
}
}
BlogEntriesController
<?php
namespace App\Controller;
use App\Model\Entity\Users;
use Cake\Event\Event;
class BlogEntriesController extends AppController {
public $paginate = ['limit' => 20];
public function beforeFilter(Event $event) {
return parent::beforeFilter($event);
}
public function index() {
return $this->Crud->execute();
}
public function add() {
return $this->Crud->execute();
}
public function edit($id) {
return $this->Crud->execute();
}
}
And finally BlogEntriesTable
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\Validation\Validator;
use App\Model\Table\Entity;
class BlogEntriesTable extends Table
{
public function initialize(array $config)
{
$this->addBehavior('Search.Search');
$this->addBehavior('Timestamp', [
'events' => [
'Model.beforeSave' => [
'created' => 'new',
]
]
]);
parent::initialize($config);
}
public function validationDefault(Validator $validator)
{
$validator->provider('validation', 'Cake\Validation\Validation');
return $validator
->add('title', [
'minLength' => [
'rule' => ['minLength', 10],
'last' => true,
'message' => '10 character minimum'
],
'maxLength' => [
'rule' => ['maxLength', 255],
'message' => 'Title is too long, 255 character max'
]
])
->add('content', [
'minLength' => [
'rule' => ['minLength', 10],
'last' => true,
'message' => '10 character minimum'
],
'maxLength' => [
'rule' => ['maxLength', 5000],
'message' => 'Content is too long, 5000 character max'
]
])
->add('user_id', 'naturalNumber', [
'rule' => 'naturalNumber',
'provider' => 'validation'
])
->add('blog_category_id', 'naturalNumber', [
'rule' => 'naturalNumber',
'provider' => 'validation'
]);
}
}
Bootstrap:
Plugin::load('Search');
Plugin::load('Crud');
Plugin::load('CrudView');
Plugin::load('BootstrapUI');
I can browse to /blog_entries and add a record, no problem. Now edit the record and you'll see "Invalid CSRF token". I've also noticed that the generated token in the form is identical on every request. If anyone sees anything obviously wrong with what I've done above I'd appreciate the help. I'll try and continue to debug this in the meantime.
Thanks!
We can do this at the same time as requiring CakePHP 3.4.
Two issues with tables with irregular plural names (like salesman -> salesmen).
Fixes:
$associationConfiguration[$type][$assocKey]['controller'] = $assocKey;
This is a pretty useful feature but has zaro docs.
I have a belongsTo association for a table that is optional. It can contain a null value or the ID of the association.
When I go to the add or edit view this field contains a dropdown from the association, but there is no way to select "none" for the null value.
I'm not sure how to fix this. Is this possible, and if so how?
I thinking maybe I can use the RelatedModel action events some how.
echo $this->Form->control('text_test',['type'=>'text','data-custom'=>'xyz']);
echo $this->Form->control('datetime_test',['type'=>'datetime','data-custom'=>'xyz']);
...
<input name="text_test" class="form-control" data-custom="xyz" id="text-test" type="text">
...
<input class="form-control" name="datetime_test" value="2017-09-27 03:04:21" id="datetime-test" role="datetime-picker" data-locale="pl_PL" data-format="" type="text">
...
...
<input name="text_test" class="form-control" data-custom="xyz" id="text-test" type="text">
...
<input data-custom="xyz" class="form-control" name="datetime_test" value="2017-09-27 03:04:21" id="datetime-test" role="datetime-picker" data-locale="pl_PL" data-format="" type="text">
...
scaffold.index_pagination_limit_options
Example:
Refs #165
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.