https://github.com/zofe/rapyd-admin
So Rapyd, as far as possible, will still be brought forward.
deprecated rewritten in rapyd-livewire
License: MIT License
https://github.com/zofe/rapyd-admin
So Rapyd, as far as possible, will still be brought forward.
As most of grids now a days are using ajax class to render grid, it would be nice if this library can also support ajax calls.
If i want to use belongsTo relations within DataEdit
f.i.:
$edit = DataEdit::source(new Article);
..
$edit->add('author.firstname','Author', 'text');
...
it just shows the id. (using your DemoController)
hasOne works fine. Shouldn't work belongsTo as well?
I want to implement a field to manage a belongsTo relation on the same model.
I mean the classic "Category" table with parent_id relation on same table (no nested set, keep it simple).
class Category extends Eloquent
{
...
public function parent()
{
return $this->belongsTo('Category', 'parent_id');
}
public function childrens()
{
return $this->hasMany('Category', 'parent_id');
}
}
This can be already managed (with a select or an autocomplete) but a better field should display the current "tree" :
- maincat
L___subcat1
L___subcat2
........L subcat 2.1
Someone know how-to do this with a select or some jquery plugin ?
After saving a data-edit, the user lands on the view mode of the data-edit itself. It'd be nice to be able to have him land straight back to the datagrid or any other URL of choice.
"joseph-lenton/php-error": "dev-master",
"filp/whoops": "1.*",
"zeuxisoo/slim-whoops": "dev-master",
thanks
Looks great, any laravel 4.1 support and please tag releases.
On public function anyEdit(), this: $grid->add('{{ Strings::truncate(wordwrap($description), 20, "...") }}', 'redactor')->rule('required'), only returns null, why?
Gruesome.
When displaying a DataGrid, there are conflicts among fields name between the main and related objects.
This is my controller:
class ArticlesController extends BaseController
{
public function getIndex()
{
$grid = DataGrid::source(Article::with('author')); //same source types of DataSet
$grid->add('id', 'id', true); //field name, label, sortable
$grid->add('title', 'Title', true); //field name, label, sortable
$grid->add('{{ substr($body,0,20) }}...', 'Body'); //blade syntax with main field
$grid->add('{{ $author->fullname }}', 'Author'); //blade syntax with related field
$grid->edit('/admin/articles/edit', 'Edit', 'modify|delete'); //shortcut to link DataEdit actions
$grid->orderBy('id', 'desc'); //default orderby
$grid->paginate(10); //pagination
$title = 'dsds';
return View::make('admin/article/index', compact('title', 'grid'));
}
public function anyEdit()
{
$edit = DataEdit::source(new Article);
$edit->add('title', 'Title', 'text')->rule('required|min:5');
$edit->add('body', 'Body', 'textarea');
$edit->add('author_id', 'User', 'select')->options(User::lists("fullname",
"id"));
$edit->add('publication_date', 'Date', 'date')->format('d/m/Y', 'it');
$edit->add('photo', 'Photo', 'image')->move('uploads/demo/')->fit(240,
160)->preview(120,
80);
$edit->add('public', 'Public', 'checkbox');
$title = 'dsds';
return $edit->view('admin/article/edit', compact('title', 'edit'));
}
}
As you see, I use id
as the incremental for both the Article and Author models.
The result is this:
After a while, I've been able to trace down the issue: my users table has just two users, so all the articles with id > 2 trigger the bug.
Help?
Example:
$edit->linkAction('ArticlesController@getIndex');
Rapyd should not delete a record when called with this URL:
http://localhost/admin/articles/edit?do_delete=4
This is actually dangerous in case the DataEdit gets used on the frontend or any preloading method is used on the backend (InstantClick or similar stuff).
A POST request should be used, or even better a DELETE request.
Sample code to create a delete button in Laravel:
{{ Form::open(array('url' => "http://localhost/admin/articles/edit?do_delete=4", 'method' => 'delete')) }}
<button type="submit" class="btn btn-danger">Delete</button>
{{ Form::close() }}
Laravel will create a form that actually fakes a delete request (as DELETE is not supported by the browsers yet). You will be then able to know it is a delete request with this code:
$method = Request::method();
if (Request::isMethod('delete'))
{
//
}
did make my own class:
add('hexcolor','Color','\Serviceteam\Field\Colorpicker'); but get: Class '\Zofe\Rapyd\DataForm\Field\Serviceteam\Field\Colorpicker' not foundmissed stuffs for dataedit on deletion:
Is it possible to order by a related field? for example:
$grid = DataGrid::source(Article::with('author'));
$grid->add('author.firstname', 'Author', 'author.firstname');
The problem is that if you load a model using eager loading then you can't sort by a related field using the notation author.firstname
.
The solution is to load the related model using a join, but in this case I have problems of ambiguity (because both models have the fields 'id', 'created_at', etc.).
Usually in a Rapyd CRUD we search a record on DataFilter & DataGrid then we switch to a DataEdit. But when the update is done we need to come back to DataFilter & DataGrid page.
We lose filters, pagination and sort
The idea to keep persistence is:
I think this do the trick
I would like to separate the load of Rapyd stylesheets and javascripts in order to delay the loading of the javascripts to the end of the load. For example:
<html>
<head>
...
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
{{ Rapyd::stylesheets() }}
</head>
<body>
...
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
{{ Rapyd::javascripts() }}
</body>
</html>
rules on redactor (on a related hasOne field) always fails.
i extened actions.blade.php:
@if (in_array("modal", $actions))
@endif
and DataGrid.php (i need second link with insteda of )
public function modal($uri, $label='Edit', $actions='modal', $key = '')
{
return $this->add('mena2', $label)->actions($uri, explode('|', $actions))->key($key);
}
using it in the controller:
$grid->modal( '../file/show', '','modal');
would it fit into your widget?
I've some problem with a filter and an autocomplete field.
basically the field is related with an hasOne with the main entity (like author in the sample: http://www.rapyd.com/rapyd-demo/filter)
my autocomplete works properly.. but the filter query is wrong
$filter->add('type.name','Type','autocomplete');
the datafilter execute this query
Select * from `articles` where (
select count(*)
from `types`
where `types`.`id` = `articles`.`type_id`
and `name` = 'xx'
) >= 1
the expected query was
Select * from `articles` where (
select count(*)
from `types`
where `types`.`id` = `articles`.`type_id`
and `type_id` = 'xx'
) >= 1
*xx is the autocomplete choosen value, numeric, correct, it's the "id" of related type
When you modify the content of a column, such as:
$grid = DataGrid::source( $admins );
$grid->add( 'Dr. {{$row->name}}', 'Name', true);
...
You get an error because the system tries to sort by ?ord=Dr. {{$row->name}}
.
One possible solution is to change the constructor of the class "Column.php" as below:
public function __construct($name, $label = null, $orderby = false)
{
$this->name = $name;
$this->label($label);
if( $orderby === true )
$this->orderby( $name );
else
$this->orderby( $orderby ); // Now you can use a string to indicate the order
}
And to modify the view used to parse the "DataGrid" by changing the call to "onOrderby" and to "orderbyLink" as shown below:
@if ($dg->onOrderby($column->orderby, 'asc'))
<span class="glyphicon glyphicon-arrow-up"></span>
@else
<a href="{{ $dg->orderbyLink($column->orderby,'asc') }}">
<span class="glyphicon glyphicon-arrow-up"></span>
</a>
@endif
@if ($dg->onOrderby($column->orderby, 'desc'))
<span class="glyphicon glyphicon-arrow-down"></span>
@else
<a href="{{ $dg->orderbyLink($column->orderby,'desc') }}">
<span class="glyphicon glyphicon-arrow-down"></span>
</a>
@endif
So now you can do things like:
$grid = DataGrid::source( $admins );
$grid->add( 'Dr. {{$row->name}}', 'Name', 'name');
$grid->add( '<i>{{$row->address}}</i>', 'Address', false);
$grid->add( 'email', 'e-Mail', true);
...
Reproduce by submitting the form at http://www.rapyd.com/rapyd-demo/edit?insert=1 filling in only the title field.
The actual error is:
Call to a member function getTimestamp() on a non-object on /var/www/g2.loc/vendor/zofe/rapyd/src/Zofe/Rapyd/DataForm/Field/Date.php at line 50
protected function humanDateToIso($humandate)
{
$datetime = \DateTime::createFromFormat( $this->format, $humandate);
---> $timestamp = $datetime->getTimestamp(); <---
$humandate = date('Y-m-d', $timestamp);
return $humandate;
It seems, there is a function to specify a certain filename for images/files.
within file.php:
...
$filename = ($this->filename!='') ? $this->filename : $this->file->getClientOriginalName();
...
how to use this in dataform/dataedit?
test support for 4.2 and split versioning:
tag 1.1.* for 4.1
tag 1.2.* for 4.2
then plan to switch dev-master to 4.2
When you submit a DataEdit without changing a field, the record is not saved.
While this may seem correct at first there are some issues:
Sample setup to reproduce (without relations to save, but you still see the redirect doesn't work if you try to update an existing model without changing anything)
Model:
<?php
/**
* Industry
*
*/
class Industry extends \Eloquent {
protected $fillable = [];
}
Migration:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateIndustriesTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up() {
Schema::create('industries', function(Blueprint $table) {
$table->increments('id');
$table->string('name', 255);
$table->timestamps();
});
Schema::create("article_industry", function (Blueprint $table) {
$table->integer('article_id')->unsigned();
$table->foreign('article_id')
->references('id')
->on('articles')
->onDelete('CASCADE')
->onUpdate('CASCADE');
$table->integer('industry_id')->unsigned();
$table->foreign('industry_id')
->references('id')
->on('industries')
->onDelete('CASCADE')
->onUpdate('CASCADE');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down() {
Schema::drop('article_industry');
Schema::drop('industries');
}
}
Controller:
<?php
class IndustriesController extends AdminController
{
public function getIndex()
{
$grid = DataGrid::source(Industry::query());
$grid->add('id', 'Id', true);
$grid->add('name', 'Name', true);
$grid->edit('/admin/industries/edit', 'Edit', 'modify|delete');
$grid->orderBy('name', 'asc');
$grid->paginate(100);
$title = 'Industries';
return View::make('admin/base/index', compact('title', 'grid'));
}
public function anyEdit()
{
$edit = DataEdit::source(new Industry);
$edit->add('name', 'Name', 'text')->rule('required|min:5');
$edit->link("/admin/industries","", "hide")->back();
$title = 'Edit industry';
return $edit->view('admin/base/edit', compact('title', 'edit'));
}
}
I didn't have yet the time to try to reproduce it on the rapyd demo, still on my setup this code will insert 2 records in the magazine table rather than one.
Update seems to work fine.
$edit = DataEdit::source(new Article);
$edit->add('magazine.title', 'Magazine title', 'text');
$edit->add('magazine.number', 'Magazine number', 'text');
Please, could you add support for blade syntax when it starts with @
? I have been trying this and the only modification needed is to change line 71 on the DataGrid.php
model with the following code:
if (strpos($column->name, '{{') !== false || strpos($column->name, '@') !== false)
This way you can do something like this:
$grid->add( '@if($status)
On
@else
Off
@endif', 'Status', 'status');
Or more advanced things:
$grid->add( '@if( count( $users ) == 0 )
<span class="text-muted">Sin usuarios asignados</span>
@else
@foreach( $users as $ind => $user )
@if( $ind > 0 ) <br/> @endif
<i class="fa fa-user" style="color:gray"></i>
<a href="{{ URL::route(\'users.show\', $user->id) }}">
{{ $user->first_name }}
</a>
@endforeach
@endif', 'Usuarios', false);
Using DataSet in the following form results in errors if you use sorting as well:
$query = "select a,b,c from x";
$dataset = DataSet::source( DB::select($query, array()) )->paginate(10)->getSet();
Solution (or hack) can be achieved bij the following modification in zofe\rapyd\src\Zofe\Rapyd\DataSet.php on line 141:
$column[$key] = (is_object($row) ? $row->{$field} : $row[$field] );
was:
$column[$key] = $row[$field];
we should explain i18n and how to contribute with language file
we should link i18n for validation
is there any way to add styles or attributes to a column or a row?
DF should be customizable via section-override, to make possible a complete different layout.
I.E. : field by field output (for grouping, aligning etc..), or just adding/removing html portions
Is there a way to implement filtering by related fields?
like: $filter->add('contact.lastname', 'name', 'text');
thxs.
I used DataEdit to upload files.
But how do I delete those files? I'm just able to delete the database entry. (f.e. filename)
is there a way to use 'checkboxgroup' within DtaFilter?
I must drop support for redactor.js as wysiwyg.
We use the old v7.6.1 of 2012, it "was" mit licensed (so open source) as you can see here:
https://github.com/zofe/rapyd-laravel/blob/master/public/assets/redactor/redactor.js
But now It's ONLY commercial, to prevent legal problems I decided to remove all js/css and "redactor" field type for DataForm.
$form->add('body','Body', 'redactor'); //from
$form->add('body','Body', 'textarea')->attr('class','redactor'); //to
Please write here to suggest an open source alternative to replace redactor.
It must be small (few files), recent, and with a good community, free for commercial use
on: http://www.rapyd.com/rapyd-demo/customfilter sarching "jhon doe" doesen't match results, so it's better to rearrange the query using a whereRaw and a concat on both fields?
DataFilter is good enough as is, but in some cases a closure on fields or main class can help to build better/complex filters.
Another idea is to bind datafilter with eloquent query-scopes.
Some Ideas:
$filter->add('search','Find Something', 'text')->scope(function ($query, $value) {
return $query->whereRaw("MATCH(`title`, `descr`, `tags`) AGAINST (?)", array($value));
});
Or eloquent query scope binding:
$filter = DataFilter::source(new Article);
$filter->add('search','Find Something', 'text')->scope("search");
..
class Article extends Eloquent
{
...
public function scopeSearch($query, $value)
{
return $query->whereRaw("MATCH(`title`, `descr`, `tags`) AGAINST (?)", array($value));
}
..
Note that $value, it's not just Input::get('search'); It is $filter->field('search')->getValue();
So for complex or multiple fields (like autocomplete, date, tags..) it's a pre-processed value.
For example for a Date field that use a custom format $value is instead a iso datestamp Y-m-d, so ready to be used in queries.
purposal: currently autocomplete need that you declare the "other key" as second parameter of remote()
$form->add('author.fullname','Author','autocomplete')->remote(array("firstname", "lastname"), "user_id");
$form->add('categories.name','Categories','tags')->remote("name", "category_id");
in this case "user_id", and "category_id", but basically the outerKey can be deducted (if you use relation name).
Then, "remote" it's not so intuitive so we can change also the method name:
$form->add('author.fullname','Author','autocomplete')->search(array("firstname", "lastname"));
$form->add('categories.name','Categories','tags')->search("name");
i think that "search" is more expressive that "remote" because the only needed param is the field (or the fields) to search into.
someone approve this or can suggest different name/approach?
I have this field:
$edit->add('photo','Photo', 'image')->move('uploads/demo/')->fit(240, 160)->preview(120,80);
If I don't add any file, the form submission takes me back to the form (url: http://xxx.loc/admin/articles/edit?update=11
), but no validation error shows up.
Either validation messages are not displayed or there's something broken.
validation errors should use field-labels instead of field-names.
Not sure why, but my blade syntax isn't being parsed :s
Controller:
$grid = \DataGrid::source(\Post::select('*')); //same source types of DataSet
$grid->add('title', 'Title', true); //field name, label, sortable
$grid->add('{{ $post->created_at }}', 'Posted'); //blade syntax with main field
$grid->edit('/admin/blog/edit/', 'Edit', 'modify|delete'); //shortcut to link DataEdit actions
$grid->orderBy('created_at', 'desc'); //default orderby
$grid->paginate(10); //pagination
return \View::make('admin::blog.index', compact('grid'));
View:
@section('content')
<div class="col-md-12">
<div class="box box-primary">
<div class="box-header">
<h3 class="box-title">Edit Blog</h3>
</div><!-- /.box-header -->
<!-- form start -->
{{ $form }}
</div>
</div>
@endsection
I've encountered a problem: when a default order is set ($grid->orderBy('label');), the arrow of the corresponding column in the view is not marked as active.
To fix this I need to access the "$orderby" property.
Is it possible to modify the contents of the "edit" column to add or remove buttons depending on a value in the row? For example something like this:
$grid = DataGrid::source( $users );
$grid->add( 'name', 'Name', true);
$grid->edit('users', '<i class="fa fa-cog"></i>', 'show|modify|delete');
$grid->orderBy('name', 'asc');
$grid->paginate( 20 );
$grid->row(function ($row) {
if ($row->cells[0]->value == 'admin') {
$row->cells[0]->style('font-weight:bold');
$row->cells[1]->actions('show');
}
});
is there a function to show photos in a grid?
I don't know what i am doing wrong, but i forked your project, and now i can't seem to put edit colum on table rows (on datagrid) .
The error is always this: Undefined property: stdClass::$_edit Line 185
The code to build the table (in my UserController) is the following:
public function getIndex(){
$grid = DataGrid::source(DB::table('users'));
$grid->add('first_name','First Name');
$grid->add('last_name','Last Name');
$grid->edit('/admin/user/edit/1', 'Edit', 'modify');
return \View::make('admin.pages.userView', compact('grid'));
}
The routes is the following:
Route::group(array('prefix' => 'admin', 'before' => 'auth.admin'), function(){
Route::any('/', 'App\Controllers\Admin\PagesController@index');
Route::resource('pages', 'App\Controllers\Admin\PagesController');
Route::controller('user', 'App\Controllers\Admin\UserController');
});
Most of time DataForm contains only few fields, so a bootstrap form-horizontal is too tall.
So we should be able to choose a form-inline: one row form, using html5 placeholders instead labels.
This will be perfect to build small DataFilters and to leave more space to DataGrid.
how to implement some colorpicker?
f.i. jQuery MiniColors 2.1
some stuff like this must be implemented:
$grid->add('body|strip_tags', 'Body');
$grid->add('body|strip_tags|substr[0,100]', 'Body');
//or with a different syntax :
$grid->add('body', 'Body')->filter('strip_tags|substr[0,20]');
//or even a closure on cell:
$grid->add('body', 'Body')->cell( function ($cell) {
return substr($cell, 0, 20);
});
supporting native php functions and if possible also Facades.
This way we can limit some horrible blade/php syntax inline like this:
$grid->add('ucfirst(substr( {{ $body }}, 0,100))', 'Body');
Another way (currently available) is to play more with accessors, to define field formatting on models side, but in some situation does wasting more time
...
$grid->add('shortbody', 'Body');
...
class Article extends Eloquent
{
protected $appends = array('shortbody');
...
public function getShortbodyAttribute($value)
{
return ucfirst( substr(strip_tags($this->body), 0,100) );
}
...
The most common filter for a grid is a "date-range", so we should implement it.
There is already a "date" field, at this moment we can use it to filter <= or >=, but a range is not trivial because works on same field so it need field aliases (or custom query scope)
Now, we used a datepicker that support ranges, however it need different html and probably a "range" make sense only in datafilters.. so this is why I think that another field is a good option.
Works fine except in the show view, where it trigger the following error:
Undefined property: Zofe\Rapyd\DataForm\Field\Tags::$description
File: /var/www/g2.loc/vendor/zofe/rapyd/src/Zofe/Rapyd/DataForm/Field/Tags.php
Line: 164
If I define a protected $description = '';
inside the class declaration it doesn't error anymore, but still displays empty.
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.