diff --git a/.github/workflows/add-to-project.yml b/.github/workflows/add-to-project.yml
new file mode 100644
index 00000000..09987553
--- /dev/null
+++ b/.github/workflows/add-to-project.yml
@@ -0,0 +1,20 @@
+name: Add new bugs & PRs to This Week project
+
+on:
+ issues:
+ types:
+ - opened
+ - transferred
+ pull_request:
+ types:
+ - opened
+
+jobs:
+ add-to-project:
+ name: Add new bugs and PRs to This Week project
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/add-to-project@main
+ with:
+ project-url: https://github.com/orgs/Laravel-Backpack/projects/13
+ github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
diff --git a/3.3/introduction.md b/3.3/introduction.md
index 5dd9f6a6..203a2293 100644
--- a/3.3/introduction.md
+++ b/3.3/introduction.md
@@ -1,3 +1,5 @@
-### Moved
+### Unavailable online
-For Backpack v3.3 documentation, please head over to [our old readme.io documentation](https://laravel-backpack.readme.io/v3.3/docs).
\ No newline at end of file
+For Backpack v3.3 documentation, please [download our old documentation](https://drive.google.com/open?id=1f55_5DEHnyGpiRBbCSZzvMTG-X1AG9EV).
+
+This is a full archive of our old documentation, hosted on readme.io. We're no longer using Readme.io for our documentation, but [our own github repo](https://github.com/laravel-backpack/docs). We've had to deleted our Readme.io account, and remove the results from Google search, because people got to the old docs (which were inaccurate and incomplete) instead of our current docs.
diff --git a/3.4/add-ons-community.md b/3.4/add-ons-community.md
index 6178e504..6a4c9b22 100644
--- a/3.4/add-ons-community.md
+++ b/3.4/add-ons-community.md
@@ -14,4 +14,5 @@ We've been blessed with a wonderful, supportive community, where developers help
| [novius/laravel-backpack-translation-manager](https://github.com/novius/laravel-backpack-translation-manager) | manage translations stored in the database | - |
| [updivision/estarter-ecommerce-for-laravel](https://github.com/updivision/estarter-ecommerce-for-laravel) | complete e-commerce back-end (products, categories, clients, orders) | [YUMMY](https://github.com/updivision/estarter-ecommerce-for-laravel/blob/master/LICENSE.md) |
| [webfactor/laravel-generators](https://github.com/webfactor/laravel-generators) | CLI to generate migrations, factories, seeders, CRUDs, lang files, route files | [MIT](https://github.com/webfactor/laravel-generators/blob/master/LICENSE.md) |
-| [seandowney/laravel-backpack-gallery-crud](https://github.com/seandowney/laravel-backpack-gallery-crud) | manage photo galleries | [MIT](https://github.com/seandowney/laravel-backpack-gallery-crud/blob/master/LICENSE.md) |
+| [seandowney/laravel-backpack-gallery-crud](https://gitlab.com/seandowney/laravel-backpack-gallery-crud) | Manage photo galleries | [MIT](https://github.com/seandowney/laravel-backpack-gallery-crud/blob/master/LICENSE.md) |
+| [seandowney/laravel-backpack-store-crud](https://gitlab.com/seandowney/laravel-backpack-store-crud) | Manage a shop with the beginnings of a Frontend - Categories, Products, Price Options and Groups, Delivery Options and Groups and Orders. Not tested above Crud 3.4 | [MIT](https://gitlab.com/seandowney/laravel-backpack-store-crud/blob/master/LICENSE.md) |
diff --git a/3.4/base-how-to.md b/3.4/base-how-to.md
index 11e9efa4..d0dae179 100644
--- a/3.4/base-how-to.md
+++ b/3.4/base-how-to.md
@@ -5,7 +5,7 @@
## Customize the menu or sidebar
-During installation, Backpack publishes a few files in you ```resources/views/vendor/backpack/base``` folder. In there, you'll also find ```inc/sidebar_content.php``` and ```inc/menu.php```. Change those files as you please.
+During installation, Backpack publishes a few files in your ```resources/views/vendor/backpack/base``` folder. In there, you'll also find ```inc/sidebar_content.php``` and ```inc/menu.php```. Change those files as you please.
## Customize the dashboard
@@ -78,7 +78,7 @@ In ```config/backpack/base.php``` you'll find these configuration options:
In order to completely customize the auth routes, you can change both ```setup_auth_routes``` and ```setup_dashboard_routes``` to ```false```. This means Backpack\Base won't register any routes any more, so you'll have to manually register them in your route file. Here's what you can use to get started:
```php
-Route::group(['middleware' => 'web', 'prefix' => config('backpack.base.route_prefix', 'namespace' => 'Backpack\Base\app\Http\Controllers')], function () {
+Route::group(['middleware' => 'web', 'prefix' => config('backpack.base.route_prefix'), 'namespace' => 'Backpack\Base\app\Http\Controllers'], function () {
Route::auth();
Route::get('logout', 'Auth\LoginController@logout');
Route::get('dashboard', 'AdminController@dashboard');
diff --git a/3.4/crud-basics.md b/3.4/crud-basics.md
index ab869a44..a629169e 100644
--- a/3.4/crud-basics.md
+++ b/3.4/crud-basics.md
@@ -2,7 +2,7 @@
---
-Backpack\CRUD provides a fast way to build admininistration panels - places where your administrators can Create, Read, Update, Delete entries for a specific Eloquent model. **One CRUD Panel provides functionality for one Eloquent Model.**
+Backpack\CRUD provides a fast way to build administration panels - places where your administrators can Create, Read, Update, Delete entries for a specific Eloquent model. **One CRUD Panel provides functionality for one Eloquent Model.**
## Requirements
@@ -43,4 +43,4 @@ For a ```Tag``` entity, your CRUD Panel would consist of:
- a route inside ```routes/backpack/custom.php```;
- your existing model (```app/Models/Tag.php```);
-To further your understading of how a CRUD Panel works, [read more about this example in the tutorial](/docs/{{version}}/crud-tutorial).
+To further your understanding of how a CRUD Panel works, [read more about this example in the tutorial](/docs/{{version}}/crud-tutorial).
diff --git a/3.4/crud-buttons.md b/3.4/crud-buttons.md
index e7a48e61..273d6e08 100644
--- a/3.4/crud-buttons.md
+++ b/3.4/crud-buttons.md
@@ -89,7 +89,7 @@ Let's say we want to create a simple ```moderate.blade.php``` button. This butto
Route::get('user/{id}/moderate', 'UserCrudController@ban');
```
-- We can now create add a ```moderate()``` method to our ```UserCrudController```, which would moderate the user, and redirect back.
+- We can now add a ```moderate()``` method to our ```UserCrudController```, which would moderate the user, and redirect back.
```php
public function moderate()
{
diff --git a/3.4/crud-cheat-sheet.md b/3.4/crud-cheat-sheet.md
index 3a2c9acb..f9121c59 100644
--- a/3.4/crud-cheat-sheet.md
+++ b/3.4/crud-cheat-sheet.md
@@ -63,7 +63,7 @@ $this->crud->filters(); // gets all the filters
#### Details Row
```php
-// Shows a + sign next to each table row, so that the user can expand that row and reveal details. You are responsible for creting the view with those details.
+// Shows a + sign next to each table row, so that the user can expand that row and reveal details. You are responsible for creating the view with those details.
$this->crud->enableDetailsRow();
// NOTE: you also need to do allow access to the right users: $this->crud->allowAccess('details_row');
// NOTE: you also need to do overwrite the showDetailsRow($id) method in your EntityCrudController to show whatever you'd like in the details row OR overwrite the views/backpack/crud/details_row.blade.php
@@ -107,7 +107,7 @@ $this->crud->setActionsColumnPriority(10000);
#### Custom / Advanced Queries
```php
-// Change what entries are show in the table view.
+// Change what entries are shown in the table view.
// This changes all queries on the table view,
// as opposed to filters, who only change it when that filter is applied.
$this->crud->addClause('active'); // apply local scope
diff --git a/3.4/crud-columns.md b/3.4/crud-columns.md
index 9a58a23c..1171aba8 100644
--- a/3.4/crud-columns.md
+++ b/3.4/crud-columns.md
@@ -174,7 +174,9 @@ Show custom HTML based on a closure you specify in your EntityCrudController. Pl
### date
-The date column will show a localized date in the default date format (as specified in the ```config/backpack/base.php``` file), whether the attribute is casted as date in the model or not:
+The date column will show a localized date in the default date format (as specified in the ```config/backpack/base.php``` file), whether the attribute is casted as date in the model or not.
+
+Note that the ```format``` attribute uses ISO date formatting parameters and not PHP ```date()``` formatters. See for more information.
```php
[
@@ -189,7 +191,10 @@ The date column will show a localized date in the default date format (as specif
### datetime
-The date column will show a localized datetime in the default datetime format (as specified in the ```config/backpack/base.php``` file), whether the attribute is casted as datetime in the model or not:
+The date column will show a localized datetime in the default datetime format (as specified in the ```config/backpack/base.php``` file), whether the attribute is casted as datetime in the model or not.
+
+Note that the ```format``` attribute uses ISO date formatting parameters and not PHP ```date()``` formatters. See for more information.
+
```php
[
@@ -236,11 +241,11 @@ The model_function column will output a function on your main model. Its definit
For this example, if your model would feature this method, it would return the link to that entity:
```php
public function getSlugWithLink() {
- return ''.$this->slug.'';
- }
+ return ''.$this->slug.'';
+}
```
-**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent that JS and CSS from reaching your DB in the first place.
+**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent JS and CSS from reaching your DB in the first place.
### model_function_attribute
@@ -258,7 +263,7 @@ If the function you're trying to use returns an object, not a string, you can us
],
```
-**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent that JS and CSS from reaching your DB in the first place.
+**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent JS and CSS from reaching your DB in the first place.
### multidimensional_array
@@ -349,7 +354,7 @@ The text column will just output the text value of a db column (or model attribu
],
```
-**Advanced use case:** The ```text``` column type can also show the attribute of a 1-1 relationship. If you have a relationship (like ```parent()```) set up in your Model, you can use relationship and attibute in the ```name```, using dot notation:
+**Advanced use case:** The ```text``` column type can also show the attribute of a 1-1 relationship. If you have a relationship (like ```parent()```) set up in your Model, you can use relationship and attribute in the ```name```, using dot notation:
```php
[
'name' => 'parent.title',
@@ -375,7 +380,7 @@ The select column will output its connected entity. Its name and definition is t
],
```
-**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent that JS and CSS from reaching your DB in the first place.
+**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent JS and CSS from reaching your DB in the first place.
### select_from_array
@@ -388,7 +393,7 @@ Show a particular text depending on the value of the attribute.
'name' => 'status',
'label' => "Status",
'type' => 'select_from_array',
- 'options' => [‘draft’ => ‘Draft (invisible)’, ‘published’ => ‘Published (visible)’],
+ 'options' => ['draft' => 'Draft (invisible)', 'published' => 'Published (visible)'],
],
```
@@ -409,7 +414,7 @@ The select_multiple column will output a comma separated list of its connected e
],
```
-**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent that JS and CSS from reaching your DB in the first place.
+**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent JS and CSS from reaching your DB in the first place.
### table
@@ -616,4 +621,4 @@ You can make the last column be less important (and hide) by giving it an unreas
$this->crud->setActionsColumnPriority(10000);
```
->Note that repsonsive tables adopt special behavior if the table is not able to show all columns. This includes displaying a vertical elipsis to the left of the row, and making the row clickable to reveal more detail. This behavior is automatic and is not manually controllable via a field property.
+>Note that responsive tables adopt special behavior if the table is not able to show all columns. This includes displaying a vertical ellipsis to the left of the row, and making the row clickable to reveal more detail. This behavior is automatic and is not manually controllable via a field property.
diff --git a/3.4/crud-fields.md b/3.4/crud-fields.md
index 50bdf78b..399972a5 100644
--- a/3.4/crud-fields.md
+++ b/3.4/crud-fields.md
@@ -7,7 +7,7 @@
Field types define how the admin can manipulate an entry's values. They're used by the Create and Update operations.
-Think of the field type as the type of input: ``````. But for most entities, you won't just need text inputs - you'll need datepickers, upload buttons, 1-n relationship, n-n relationships, textareas, etc.
+Think of the field type as the type of input: ``````. But for most entities, you won't just need text inputs - you'll need datepickers, upload buttons, 1-n relationship, n-n relationships, textareas, etc.
We have a lot of default field types, detailed below. If you don't find what you're looking for, you can [create a custom field type](/docs/{{version}}/crud-fields#creating-a-custom-field-type). Or if you just want to tweak a default field type a little bit, you can [overwrite default field types](/docs/{{version}}/crud-fields#overwriting-default-field-types).
@@ -96,7 +96,7 @@ $this->crud->addField($field_definition_array)->afterField('name');
#### Fake Fields (all stored as JSON in the database)
-In case you want to store insignificant information for an entry, that don't need a database column, you can add any number of Fake Fields, and all their information will be store inside one column in the db, as JSON. By default, an ```extras``` column is assumed on the database table, but you can change that.
+In case you want to store insignificant information for an entry that doesn't need a database column, you can add any number of Fake Fields, and all their information will be stored inside one column in the db, as JSON. By default, an ```extras``` column is assumed on the database table, but you can change that.
**Step 1.** Use the fake attribute on your field:
```php
@@ -104,7 +104,7 @@ In case you want to store insignificant information for an entry, that don't nee
'name' => 'name', // JSON variable name
'label' => "Tag Name", // human-readable label for the input
- 'fake' => true, // show the field, but don’t store it in the database column above
+ 'fake' => true, // show the field, but don't store it in the database column above
'store_in' => 'extras' // [optional] the database column name where you want the fake fields to ACTUALLY be stored as a JSON array
],
```
@@ -138,7 +138,7 @@ Example:
],
```
-In this example, these 3 fields will show up in the create & update forms, the CRUD will process as usual, but in the database these values won’t be stored in the ```meta_title```, ```meta_description``` and ```meta_keywords``` columns. They will be stored in the ```metas``` column as a JSON array:
+In this example, these 3 fields will show up in the create & update forms, the CRUD will process as usual, but in the database these values won't be stored in the ```meta_title```, ```meta_description``` and ```meta_keywords``` columns. They will be stored in the ```metas``` column as a JSON array:
```php
{"meta_title":"title","meta_description":"desc","meta_keywords":"keywords"}
@@ -220,7 +220,7 @@ Onclick preview:
### browse_multiple
-Open elFinder and select multiple file from there.
+Open elFinder and select multiple files from there.
```php
[ // Browse multiple
@@ -617,7 +617,7 @@ $this->crud->addField([ // image
'type' => 'image',
'upload' => true,
'crop' => true, // set to true to allow cropping, false to disable
- 'aspect_ratio' => 1, // ommit or set to 0 to allow any aspect ratio
+ 'aspect_ratio' => 1, // omit or set to 0 to allow any aspect ratio
// 'disk' => 's3_bucket', // in case you need to show images from a different disk
// 'prefix' => 'uploads/images/profile_pictures/' // in case your db value is only the file name (no path), you can use this to prepend your path to the image src (in HTML), before it's shown to the user;
]);
@@ -720,14 +720,14 @@ Input preview:
### page_or_link
-Select an existing page from PageManager or an internal or external link. It’s used in the MenuManager package, but can be used in any other model just as well. Its definition looks like this:
+Select an existing page from PageManager or an internal or external link. It's used in the MenuManager package, but can be used in any other model just as well. Its definition looks like this:
```php
[ // PageOrLink
'name' => 'type',
'label' => "Type",
'type' => 'page_or_link',
'page_model' => '\Backpack\PageManager\app\Models\Page'
-]
+],
```
Input preview:
@@ -765,7 +765,7 @@ Show radios according to an associative array you give the input and let the use
],
// optional
//'inline' => false, // show the radios all on the same line?
-]
+],
```
Input preview:
@@ -801,7 +801,7 @@ Your relationships should already be defined on your models.
'entity' => 'category', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
'model' => "App\Models\Tag" // foreign key model
-]
+],
```
Input preview:
@@ -822,7 +822,7 @@ Your relationships should already be defined on your models.
'entity' => 'category', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
'model' => "App\Models\Tag" // foreign key model
-]
+],
```
Input preview:
@@ -844,7 +844,7 @@ Your relationships should already be defined on your models.
'attribute' => 'name', // foreign key attribute that is shown to user
'model' => "App\Models\Tag", // foreign key model
'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
-]
+],
```
Input preview:
@@ -856,7 +856,7 @@ Input preview:
[Works just like the SELECT field, but prettier]
-Show a Select2 with the names of the connected entity and let the user select any number of them.
+Shows a Select2 with the names of the connected entity and let the user select any number of them.
Your relationships should already be defined on your models.
```php
@@ -869,7 +869,7 @@ Your relationships should already be defined on your models.
'model' => "App\Models\Tag", // foreign key model
'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
// 'select_all' => true, // show Select All and Clear buttons?
-]
+],
```
Input preview:
@@ -886,7 +886,7 @@ Display a select with the values you want:
'name' => 'template',
'label' => "Template",
'type' => 'select_from_array',
- 'options' => [‘one’ => ‘One’, ‘two’ => ‘Two’],
+ 'options' => ['one' => 'One', 'two' => 'Two'],
'allows_null' => false,
'default' => 'one',
// 'allows_multiple' => true, // OPTIONAL; needs you to cast this to array in your model;
@@ -907,7 +907,7 @@ Display a select2 with the values you want:
'name' => 'template',
'label' => "Template",
'type' => 'select2_from_array',
- 'options' => [‘one’ => ‘One’, ‘two’ => ‘Two’],
+ 'options' => ['one' => 'One', 'two' => 'Two'],
'allows_null' => false,
'default' => 'one',
// 'allows_multiple' => true, // OPTIONAL; needs you to cast this to array in your model;
@@ -1209,7 +1209,7 @@ Input preview:
'label' => 'Image',
'type' => 'upload',
'upload' => true,
- 'disk' => 'uploads' // if you store files in the /public folder, please ommit this; if you store them in /storage or S3, please specify it;
+ 'disk' => 'uploads' // if you store files in the /public folder, please omit this; if you store them in /storage or S3, please specify it;
],
```
@@ -1276,7 +1276,7 @@ Shows a multiple file input to the user and stores the values as a JSON array in
'label' => 'Photos',
'type' => 'upload_multiple',
'upload' => true,
- 'disk' => 'uploads' // if you store files in the /public folder, please ommit this; if you store them in /storage or S3, please specify it;
+ 'disk' => 'uploads' // if you store files in the /public folder, please omit this; if you store them in /storage or S3, please specify it;
],
```
@@ -1374,10 +1374,10 @@ An entry stored in the database will look like this:
```
$video = {
id: 234324,
- title: ‘my video title’,
- image: ‘https://provider.com/image.jpg',
- url: ‘http://provider.com/video',
- provider: ‘youtube’
+ title: 'my video title',
+ image: 'https://provider.com/image.jpg',
+ url: 'http://provider.com/video',
+ provider: 'youtube'
}
```
@@ -1430,11 +1430,11 @@ Show a wysiwyg (CKEditor) to the user.
## Overwriting Default Field Types
-The actual field types are stored in the Backpack/CRUD package in ```/resources/views/fields```. If you need to change an existing field, you don’t need to modify the package, you just need to add a blade file in your application in ```/resources/views/vendor/backpack/crud/fields```, with the same name. The package checks there first, and only if there's no file there, will it load it from the package.
+The actual field types are stored in the Backpack/CRUD package in ```/resources/views/fields```. If you need to change an existing field, you don't need to modify the package, you just need to add a blade file in your application in ```/resources/views/vendor/backpack/crud/fields```, with the same name. The package checks there first, and only if there's no file there, will it load it from the package.
To quickly publish a field blade file in your project, you can use ```php artisan backpack:crud:publish fields/field_name```. For example, to publish the number field type, you'd type ```php artisan backpack:crud:publish fields/number```
->Please keep in mind that if you're using _your_ file for a field type, you're not using the _package file_. So any updates we push to that file, you're not getting them. In most cases, it's recommended you crate a custom field type for your use case, instead of overwriting default field types.
+>Please keep in mind that if you're using _your_ file for a field type, you're not using the _package file_. So any updates we push to that file, you're not getting them. In most cases, it's recommended you create a custom field type for your use case, instead of overwriting default field types.
## Creating a Custom Field Type
@@ -1450,7 +1450,7 @@ Your field definition will be something like:
'label' => 'Home address',
'type' => 'address'
/// 'view_namespace' => 'yourpackage' // use a custom namespace of your package to load views within a custom view folder.
-]);
+],
```
And your blade file something like:
diff --git a/3.4/crud-filters.md b/3.4/crud-filters.md
index 1feb07b6..21bed0d1 100644
--- a/3.4/crud-filters.md
+++ b/3.4/crud-filters.md
@@ -55,7 +55,7 @@ function() { // if the filter is active (the GET parameter "draft" exits)
> - you can get the filter value by specifying a parameter to the function (ex: ```$value```);
> - you have access to other request variables using ```$this->crud->request```;
> - you also have read/write access to public properties using ```$this->crud```;
-> - when building complicated "OR" logic, make sure the first "where" in your closure is a "where" and only the subsequent are "orWhere"; Laravel 5.3+ no longer convers the first "orWhere" into a "where";
+> - when building complicated "OR" logic, make sure the first "where" in your closure is a "where" and only the subsequent are "orWhere"; Laravel 5.3+ no longer converts the first "orWhere" into a "where";
## Filter types
@@ -80,7 +80,7 @@ function() { // if the filter is active
### Text
-Shows a text input. Most useful for letting the user filter through information that not shown as a column in the CRUD table - otherwise they could just use the DataTables search field.
+Shows a text input. Most useful for letting the user filter through information that's not shown as a column in the CRUD table - otherwise they could just use the DataTables search field.

@@ -104,15 +104,15 @@ Show a datepicker. The user can select one day.

```php
- $this->crud->addFilter([ // date filter
- 'type' => 'date',
- 'name' => 'date',
- 'label'=> 'Date'
- ],
- false,
- function($value) { // if the filter is active, apply these constraints
- // $this->crud->addClause('where', 'date', $value);
- });
+$this->crud->addFilter([ // date filter
+ 'type' => 'date',
+ 'name' => 'date',
+ 'label'=> 'Date'
+],
+false,
+function($value) { // if the filter is active, apply these constraints
+ // $this->crud->addClause('where', 'date', $value);
+});
```
@@ -123,17 +123,17 @@ Show a daterange picker. The user can select a start date and an end date.

```php
- $this->crud->addFilter([ // daterange filter
- 'type' => 'date_range',
- 'name' => 'from_to',
- 'label'=> 'Date range'
- ],
- false,
- function($value) { // if the filter is active, apply these constraints
- // $dates = json_decode($value);
- // $this->crud->addClause('where', 'date', '>=', $dates->from);
- // $this->crud->addClause('where', 'date', '<=', $dates->to . ' 23:59:59');
- });
+$this->crud->addFilter([ // daterange filter
+ 'type' => 'date_range',
+ 'name' => 'from_to',
+ 'label'=> 'Date range'
+],
+false,
+function($value) { // if the filter is active, apply these constraints
+ // $dates = json_decode($value);
+ // $this->crud->addClause('where', 'date', '>=', $dates->from);
+ // $this->crud->addClause('where', 'date', '<=', $dates->to . ' 23:59:59');
+});
```
diff --git a/3.4/crud-how-to.md b/3.4/crud-how-to.md
index 84a642a4..c5290169 100644
--- a/3.4/crud-how-to.md
+++ b/3.4/crud-how-to.md
@@ -36,7 +36,7 @@ If you don't find one there, you can create one, and Backpack will pick it up in
Starting with Backpack\CRUD 3.2, you can use the ```with()``` method on ```CRUD::resource``` to better organize your routes. Something like this:
```php
-CRUD::resource(‘teams’, ‘Admin\TeamCrudController’)->with(function(){
+CRUD::resource('teams', 'Admin\TeamCrudController')->with(function(){
// add extra routes to this resource
Route::get('teams/ajax-name-options', 'Admin\TeamCrudController@nameOptions');
Route::get('teams/ajax-category-options', 'Admin\TeamCrudController@categoryOptions');
@@ -102,7 +102,7 @@ class CompanyUser extends User
If you try to add multiple columns with the same ```name```, by default Backpack will only show the last one. That's because ```name``` is also used as a key in the ```$column``` array. So when you ```addColumn()``` with the same name twice, it just overwrites the previous one.
-In order to insert two column with the same name, use the ```key``` attribute on the second column (or both columns). If this attribute is present for a column, Backpack will use ```key``` instead of ```name```. Example:
+In order to insert two columns with the same name, use the ```key``` attribute on the second column (or both columns). If this attribute is present for a column, Backpack will use ```key``` instead of ```name```. Example:
```diff
$this->crud->addColumn([
@@ -132,10 +132,10 @@ In order to insert two column with the same name, use the ```key``` attribute on
## Use the Media Library (File Manager)
-If you've chosen to install [elFinder](http://elfinder.org/) when installing Backpack, you already have a media manager. And it’s integrated into:
-- TinyMCE (as “tinymce” fieldtype)
-- CKEditor (as “ckeditor” fieldtype)
-- CRUD “browse” fieldtype
+If you've chosen to install [elFinder](http://elfinder.org/) when installing Backpack, you already have a media manager. And it's integrated into:
+- TinyMCE (as "tinymce" fieldtype)
+- CKEditor (as "ckeditor" fieldtype)
+- CRUD "browse" fieldtype
- standalone, at the *your-project/admin/elfinder* route;
For the integration, barryvdh's [laravel-elfinder](https://github.com/barryvdh/laravel-elfinder) package is used.
diff --git a/3.4/crud-operation-list-entries.md b/3.4/crud-operation-list-entries.md
index 1db7fa19..3e825e17 100644
--- a/3.4/crud-operation-list-entries.md
+++ b/3.4/crud-operation-list-entries.md
@@ -110,7 +110,7 @@ Exporting the DataTable to PDF, CSV, XLS is as easy as typing ```$this->crud->en
By default, all entries are shown in the ListEntries table, before filtering. If you want to restrict the entries to a subset, you can use the methods below in your EntityCrudController's ```setup()``` method:
```php
-// Change what entries are show in the table view.
+// Change what entries are shown in the table view.
// This changes all queries on the table view,
// as opposed to filters, who only change it when that filter is applied.
$this->crud->addClause('active'); // apply a local scope
@@ -130,7 +130,7 @@ $this->crud->orderBy();
#### Responsive Table
-If you CRUD table has more columns than can fit inside the viewport (on mobile / tablet or smaller desktop screens), unimportant columns will start hiding and an expansion icon (three dots) will appear to the left of each row. We call this behaviour "_responsive table_", and consider this to be the best UX. By behaviour we consider the 1st column the most important, than 2nd, than 3rd, etc; the "actions" column is considered as important as the 1st column. You can of course [change the importance of columns](/docs/{{version}}/crud-columns#define-which-columns-to-hide-in-responsive-table).
+If your CRUD table has more columns than can fit inside the viewport (on mobile / tablet or smaller desktop screens), unimportant columns will start hiding and an expansion icon (three dots) will appear to the left of each row. We call this behaviour "_responsive table_", and consider this to be the best UX. By behaviour we consider the 1st column the most important, then 2nd, then 3rd, etc; the "actions" column is considered as important as the 1st column. You can of course [change the importance of columns](/docs/{{version}}/crud-columns#define-which-columns-to-hide-in-responsive-table).
If you do not like this, you can **toggle off the responsive behaviour for all CRUD tables** by changing this config value in your ```config/backpack/crud.php``` to ```false```:
```php
diff --git a/3.4/crud-operation-revisions.md b/3.4/crud-operation-revisions.md
index 54ce292b..57dff75c 100644
--- a/3.4/crud-operation-revisions.md
+++ b/3.4/crud-operation-revisions.md
@@ -7,7 +7,7 @@
Revisions allows your admins to store, see and undo changes to entries on an Eloquent model.
-The operation provides you with a simple interface to work with [venturecraft/revisionable](https://github.com/VentureCraft/revisionable#implementation), which is a great pacakge that stores all changes in a separate table. It can work as an audit trail, a backup system and an accountability system for the admins.
+The operation provides you with a simple interface to work with [venturecraft/revisionable](https://github.com/VentureCraft/revisionable#implementation), which is a great package that stores all changes in a separate table. It can work as an audit trail, a backup system and an accountability system for the admins.
When enabled, ```Revisions``` will show another button in the table view, between _Edit_ and _Delete_. On click, that button opens another page which will allow an admin to see all changes and who made them:
diff --git a/3.4/crud-operation-update.md b/3.4/crud-operation-update.md
index b94127a1..ccd23a64 100644
--- a/3.4/crud-operation-update.md
+++ b/3.4/crud-operation-update.md
@@ -26,7 +26,7 @@ To use the Update operation, you must:
```php
// add a field only to the Update operation
$this->crud->addField($field_definition_array, 'update');
-// add a field to both the Update and Update operations
+// add a field to both the Create and Update operations
$this->crud->addField($field_definition_array);
```
@@ -75,7 +75,7 @@ public function update(UpdateRequest $request)
You can let your admins edit multi-lingual entries. Only translations stored the [spatie/laravel-translatable](https://github.com/spatie/laravel-translatable) way are supported right now, but more options will be coming soon.
In order to make one of your Models translatable, you need to:
-0. Be running MySQL 5.7+ (or a PosgreSQL with JSON column support);
+0. Be running MySQL 5.7+ (or a PostgreSQL with JSON column support);
1. [Install spatie/laravel-translatable](https://github.com/spatie/laravel-translatable#installation);
2. In your database, make all translatable columns either JSON or TEXT.
3. Use Backpack's ```HasTranslations``` trait on your model (instead of using spatie's ```HasTranslations```) and define what fields are translatable, inside the ```$translatable``` property. For example:
diff --git a/3.4/crud-operations.md b/3.4/crud-operations.md
index a4edc15d..27f37b2c 100644
--- a/3.4/crud-operations.md
+++ b/3.4/crud-operations.md
@@ -400,7 +400,7 @@ The button makes one call for all entries, and only triggers one notification. I
crud.checkedItems.forEach(function(item) {
var clone_route = "{{ url(http://github.com/$crud-%3Eroute) }}/"+item+"/clone";
- // submit an AJAX delete call
+ // submit an AJAX clone call
ajax_calls.push($.ajax({
url: clone_route,
type: 'POST',
@@ -433,4 +433,4 @@ The button makes one call for all entries, and only triggers one notification. I
}
@endpush
-```
\ No newline at end of file
+```
diff --git a/3.4/crud-tutorial.md b/3.4/crud-tutorial.md
index 2d97174b..c5394877 100644
--- a/3.4/crud-tutorial.md
+++ b/3.4/crud-tutorial.md
@@ -98,7 +98,7 @@ class Tag extends Model {
/*
|--------------------------------------------------------------------------
- | ACCESORS
+ | ACCESSORS
|--------------------------------------------------------------------------
*/
@@ -205,7 +205,7 @@ What we should notice inside this TagCrudController is that:
Let's move our attention to the ```setup()``` method, which is the gateway to configuring our CRUD Panel.
-As we can tell from the comments there, in most cases we _shouldn't_ use ```$this->crud->setFromDb()```, which automagically figures out which columns and fields to show. That's because for real models, in real projects, it would _never_ be able to 100% figure out which field types to use. Real projects are very custom - that's a fact. In real projects, models are complicated, use a bunch of fields types and you'll want to customize things. Instead of using ```setFromDb()``` then gradually changing what you don't like, **we heavily recommend you manually define all fields and columns you need**.
+As we can tell from the comments there, in most cases we _shouldn't_ use ```$this->crud->setFromDb()```, which automagically figures out which columns and fields to show. That's because for real models, in real projects, it would _never_ be able to 100% figure out which field types to use. Real projects are very custom - that's a fact. In real projects, models are complicated, use a bunch of field types and you'll want to customize things. Instead of using ```setFromDb()``` then gradually changing what you don't like, **we heavily recommend you manually define all fields and columns you need**.
Since our ```Tag``` model is so simple, we _can_ leave it like this - it will work perfectly, since we only need a ```text``` field and a ```text``` column. But let's not do that. Let's define our fields and columns manually, like big boys:
@@ -244,7 +244,7 @@ This will:
- add a simple ```text``` column for our ```name``` attribute to the ListEntries operation (the table view);
- add a simple ```text``` field for our ```name``` attribute to the Create and Update forms;
-It the exact same thing ```setFromDb()``` would have figured out, but done manually. This way, if we want to add [other columns](/docs/{{version}}/crud-columns)) or [other fields](/docs/{{version}}/crud-fields), we can easily do that. If we want to change the label of the ```name``` field from ```Name``` to ```Tag name```, we just make that small change. The benefits of _not_ using ```setFromDb()``` will be more obvious once you use Backpack on real models, we promise.
+It's the exact same thing ```setFromDb()``` would have figured out, but done manually. This way, if we want to add [other columns](/docs/{{version}}/crud-columns)) or [other fields](/docs/{{version}}/crud-fields), we can easily do that. If we want to change the label of the ```name``` field from ```Name``` to ```Tag name```, we just make that small change. The benefits of _not_ using ```setFromDb()``` will be more obvious once you use Backpack on real models, we promise.
Here, in the ```setup()``` method, is where you can also do a lot of other things, like enabling other operations, adding buttons, adding filters, customizing your query, etc. For a full list of the things you can do inside ```setup()``` check out our [cheat sheet](/docs/{{version}}/crud-cheat-sheet).
diff --git a/3.4/demo.md b/3.4/demo.md
index 8ad6e2aa..280ac8c3 100644
--- a/3.4/demo.md
+++ b/3.4/demo.md
@@ -2,7 +2,7 @@
---
-We've put toghether a working Laravel backend app, that you can install on your machine. This should make it easier for see how it looks and works. You can even change stuff in code, to see how easy it is to customize Backpack. In this [Demo repository](https://github.com/laravel-backpack/demo), we've:
+We've put together a working Laravel backend app, that you can install on your machine. This should make it easier for see how it looks and works. You can even change stuff in code, to see how easy it is to customize Backpack. In this [Demo repository](https://github.com/laravel-backpack/demo), we've:
- installed Laravel 5.6;
- installed Backpack\Base and Backpack\CRUD on top;
- created a few demo models (Monsters, Icons, Products) and admin panels for them, using dozens of field types, column types, filters, etc - to show off most of Backpack's default features;
@@ -47,7 +47,7 @@ Once everything's installed, and your database has been set up:
- By default, registration is open only in your local environment. Check out ```config/backpack/base.php``` to change this and other preferences.
- Check out the Monsters admin panel - it features over 40 field types.
- The magic of Backpack is not in its standard functionality, but in how easy it is to code your own, then customize every little bit of it. Our recommendation:
- - Go through the [CRUD Tutorial](/docs/{version}/crud-tutorial) to understand it;
+ - Go through the [CRUD Tutorial](/docs/{{version}}/crud-tutorial) to understand it;
- Create a new CRUD panel for an entity, using the faster procedure outlined at the end of that page; say... ```car```;
diff --git a/3.4/getting-started-advanced-features.md b/3.4/getting-started-advanced-features.md
index 5252217a..60148539 100644
--- a/3.4/getting-started-advanced-features.md
+++ b/3.4/getting-started-advanced-features.md
@@ -4,14 +4,14 @@
**Duration:** 5 min
-Here are some other cool things Backpack makes easy for you. We recommend going through them one by one, just browsing. You might not need the feature _right now_, but when _you do_, you’ll know how to find it.
+Here are some other cool things Backpack makes easy for you. We recommend going through them one by one, just browsing. You might not need the feature _right now_, but when _you do_, you'll know how to find it.
---
## Other Operations
- [Show](/docs/{{version}}/crud-operation-show) Operation - you can let your admins preview an entry
-- [Reorder](/docs/{{version}}/crud-operation-reorder) Operation - you can reorder and nesting entries (hierarcy tree)
+- [Reorder](/docs/{{version}}/crud-operation-reorder) Operation - you can reorder and nesting entries (hierarchy tree)
- [Revisions](/docs/{{version}}/crud-operation-revisions) Operation - you can keep a record of all modifications to an entry, and let your admin revert changes
---
@@ -27,7 +27,7 @@ Here are some other cool things Backpack makes easy for you. We recommend going
--
- **ListEntries**
- - you can add a “+” button next to each entry, to allow the admin to easily preview some quick information that was too big to fit inside a columns - we call it [details row](/docs/{{version}}/crud-operation-list-entries#details-row)
+ - you can add a "+" button next to each entry, to allow the admin to easily preview some quick information that was too big to fit inside a columns - we call it [details row](/docs/{{version}}/crud-operation-list-entries#details-row)
- export all visible items in the table by adding [export buttons](/docs/{{version}}/crud-operation-list-entries#export-buttons)
- [custom search logic](/docs/{{version}}/crud-columns#custom-search-logic) for the columns in the list view
@@ -36,4 +36,4 @@ Additionally, here are a few more ways you can customize your CRUDs:
- [Custom Views for each CRUD](/docs/{{version}}/crud-how-to#customize-views-for-each-crud-panel)
- [Custom CSS or JS](/docs/{{version}}/crud-how-to#customize-css-and-js-for-default-crud-operations) for each CRUD Operation
-**That’s it for today!** Told you we’re done with long lessons :-) Hopefully some of the above have peaked your interest and you’ve clicked to see what Backpack can do. In the [next lesson](/docs/{{version}}/getting-started-license-and-support) we’ll go through a few other Backpack packages, that cover some recurring use cases.
+**That's it for today!** Told you we're done with long lessons :-) Hopefully some of the above have peaked your interest and you've clicked to see what Backpack can do. In the [next lesson](/docs/{{version}}/getting-started-license-and-support) we'll go through a few other Backpack packages that cover some recurring use cases.
diff --git a/3.4/getting-started-basics.md b/3.4/getting-started-basics.md
index e2f00079..26de284a 100644
--- a/3.4/getting-started-basics.md
+++ b/3.4/getting-started-basics.md
@@ -4,14 +4,14 @@
**Duration:** 5 minutes
-> **Are you already comfortable with Laravel?** In order to understand this series and make use of Backpack, you’ll need to have a decent understanding of the Laravel framework. If you don’t, please go ahead and [watch this excellent intro series on Laracasts](https://laracasts.com/series/laravel-from-scratch-2017) and accomodate yourself with Laravel first.
+> **Are you already comfortable with Laravel?** In order to understand this series and make use of Backpack, you'll need to have a decent understanding of the Laravel framework. If you don't, please go ahead and [watch this excellent intro series on Laracasts](https://laracasts.com/series/laravel-from-scratch-2017) and accommodate yourself with Laravel first.
## What is Backpack?
A software that helps Laravel professionals build administration panels - secure areas where administrators login and create, read, update and delete application information. It is *not* a CMS, it is more a framework that lets you *build your own* CMS. You can install it in your existing project or in a totally new project.
-It’s designed to be flexible enough to allow you to **build admin panels for everything from simple presentation websites to CRMs, ERPs, eCommerce, eLearning, etc**. We can vouch for that, because we have built all that stuff using Backpack already.
+It's designed to be flexible enough to allow you to **build admin panels for everything from simple presentation websites to CRMs, ERPs, eCommerce, eLearning, etc**. We can vouch for that, because we have built all that stuff using Backpack already.
## How to use?
@@ -22,7 +22,7 @@ Backpack consists of two **core packages**:
A **CRUD** is what we call a section of your admin panel that lets the admin _Create, Read, Update or Delete_ entries of a certain entity (or Model). So you can have a CRUD for Products, a CRUD for Articles, a CRUD for Categories, or whatever else you might want to create, read, update or delete.
-For the purpose of this series, we’ll show examples on the Tag entry. This is what it could look like:
+For the purpose of this series, we'll show examples on the Tag entry. This is what it could look like:

@@ -32,15 +32,15 @@ For the purpose of this series, we’ll show examples on the Tag entry. This is
### Backpack\Base
-**Backpack/Base** is the package that **will handle the authentication** and provide you with minimal admin area functionality. **Your admin will be able to login and change his password or email.** And that’s pretty much it.
+**Backpack/Base** is the package that **will handle the authentication** and provide you with minimal admin area functionality. **Your admin will be able to login and change his password or email.** And that's pretty much it.
-Thanks to Base, after you [install Backpack](/docs/{{version}}/installation) (don't do it now), you’ll be able to log into your admin panel at ```http://yourapp/admin```. You can change the URL prefix from ```admin``` to something else in your ```config/backpack/base.php``` file, along with a bunch of other configuration options. [Click here](https://github.com/Laravel-Backpack/Base/blob/master/src/config/backpack/base.php) to browse the configuration file and see what it can do for you.
+Thanks to Base, after you [install Backpack](/docs/{{version}}/installation) (don't do it now), you'll be able to log into your admin panel at ```http://yourapp/admin```. You can change the URL prefix from ```admin``` to something else in your ```config/backpack/base.php``` file, along with a bunch of other configuration options. [Click here](https://github.com/Laravel-Backpack/Base/blob/master/src/config/backpack/base.php) to browse the configuration file and see what it can do for you.
Backpack\Base pulls in the free [AdminLTE](https://adminlte.io/themes/AdminLTE/index2.html) theme and enhances the design a little bit. So any front-end block that AdminLTE has, you'll also be able to use in your custom pages. It also includes a system for bubble notifications, which you can use across the admin panel. You can easily [trigger notification bubbles in PHP](/docs/{{version}}/base-about#triggering-notification-bubbles-in-php) or [trigger notification bubbles in JavaScript](/docs/{{version}}/base-about#triggering-notification-bubbles-in-javascript).
### Backpack\CRUD
-This is where it gets interesting. As soon as you [install Backpack](docs/3.4/installation) in your project, you can create **CRUDs** for your admins to easily manipulate DB information. Let’s browse through a simple example, of creating a CRUD administration panel for a Tag entity:
+This is where it gets interesting. As soon as you [install Backpack](docs/3.4/installation) in your project, you can create **CRUDs** for your admins to easily manipulate DB information. Let's browse through a simple example, of creating a CRUD administration panel for a Tag entity:
```zsh
# STEP 1. create migration
@@ -59,7 +59,7 @@ php artisan backpack:base:add-sidebar-content "
## Create & Update Operations
@@ -95,7 +95,7 @@ A typical *field definition array* will need at least three things:
- ```label``` - the human-readable label for the input (will be generated from ```name``` if not given);
-You can use [one of the 44+ field types we’ve provided](/docs/{{version}}/crud-fields#default-field-types), or easily [create a custom field type](/docs/{{version}}/crud-fields#creating-a-custom-field-type) if you have some super-specific need that we haven’t covered yet, or even [overwrite how a field type works](#overwriting-default-field-types). Take a few minutes and [browse the 44+ field types](/docs/{{version}}/crud-fields#default-field-types), to understand how the definition array differs from one to another and how many use cases you have already covered.
+You can use [one of the 44+ field types we've provided](/docs/{{version}}/crud-fields#default-field-types), or easily [create a custom field type](/docs/{{version}}/crud-fields#creating-a-custom-field-type) if you have some super-specific need that we haven't covered yet, or even [overwrite how a field type works](#overwriting-default-field-types). Take a few minutes and [browse the 44+ field types](/docs/{{version}}/crud-fields#default-field-types), to understand how the definition array differs from one to another and how many use cases you have already covered.
Let's take another example, slightly more complicated than the ```text``` fields we used above. Something you'll find encounter all the time is relationship fields. So let's say the ```Tag``` model has an **n-n relationship** with an Article model:
@@ -116,7 +116,7 @@ $this->crud->addField([
'entity' => 'articles', // the relationship name in your Model
'attribute' => 'title', // attribute on Article that is shown to admin
'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
-], ‘update’);
+], 'update');
```
**Notes:**
@@ -139,7 +139,7 @@ $this->crud->addField([
**Note: **Because the last parameter is missing, the field will be added to both Create and Update forms.
-> When generating a CrudController, you’ll be using the ```$this->crud->setFromDb();``` method by default, which tries to figure out what fields you might need in your create/update forms and in your list view, but - as you'd expect - only works for the simple field types. You can:
+> When generating a CrudController, you'll be using the ```$this->crud->setFromDb();``` method by default, which tries to figure out what fields you might need in your create/update forms and in your list view, but - as you'd expect - only works for the simple field types. You can:
>
> (1) choose to keep using ```setFromDb()``` and add/remove/change additional fields
>
@@ -184,7 +184,7 @@ ListEntries shows the admin a table with all entries. On the front-end, the info
### Columns
-Columns help you specify *which* attributes are shown in the table and *in which order*. **They’re defined in the ```setup()``` method, the same as fields, and their syntax is super-similar to fields too**:
+Columns help you specify *which* attributes are shown in the table and *in which order*. **They're defined in the ```setup()``` method, the same as fields, and their syntax is super-similar to fields too**:
```php
$this->crud->addColumn($column_definition_array); // add a single column, at the end of the table
@@ -241,4 +241,4 @@ $this->crud->removeButton($name);
$this->crud->removeButtonFromStack($name, $stack);
```
-**That’s it for today!** Thanks for sticking with us this long. This has been the most important and longest lesson. You can go ahead and [install Backpack](/docs/{{version}}/installation) now, as you’ve already gone through the most important features. Or [read the next lesson](/docs/{{version}}/getting-started-advanced-features), about advanced features.
\ No newline at end of file
+**That's it for today!** Thanks for sticking with us this long. This has been the most important and longest lesson. You can go ahead and [install Backpack](/docs/{{version}}/installation) now, as you've already gone through the most important features. Or [read the next lesson](/docs/{{version}}/getting-started-advanced-features), about advanced features.
\ No newline at end of file
diff --git a/3.4/getting-started-license-and-support.md b/3.4/getting-started-license-and-support.md
index 191c3714..f3887feb 100644
--- a/3.4/getting-started-license-and-support.md
+++ b/3.4/getting-started-license-and-support.md
@@ -16,7 +16,7 @@ Take a look at:
## License
-Backpack is **free for non-commercial use**, but needs a license code in order to prevent “_unlicensed use_” notification bubbles and interruption of service. You can get a license code for your project:
+Backpack is **free for non-commercial use**, but needs a license code in order to prevent "_unlicensed use_" notification bubbles and interruption of service. You can get a license code for your project:
- ```free```, if you're using it for non-commercial purposes;
- ```free```, if you've contributed to Backpack on Github;
- ```$49 EUR/project```, if you're making money using it for a project;
@@ -25,14 +25,14 @@ Backpack is **free for non-commercial use**, but needs a license code in order t
But **developers** or companies **who make money using it** - for themselves, their employers or their clients, **should [purchase a commercial license here](https://backpackforlaravel.com/pricing)**. We do give away free license codes for personal use, non-commercial purposes, non-profits or Backpack contributors, just [let us know](https://backpackforlaravel.com/contact), happy to help.
->**You don't need a license code on LOCALHOST.** If you’re just trying Backpack on your own machine, you don’t need a license code. You only need a license code when you take your application to production.
+>**You don't need a license code on LOCALHOST.** If you're just trying Backpack on your own machine, you don't need a license code. You only need a license code when you take your application to production.
## Support
-With thousands of developers using Backpack, a lot of them non-commercial, and such a small price, **we can’t offer official support for the packages**. We've been doing this since 2016, we actively maintain the packages, we try to squash any bugs ASAP and add new features all the time, but we unfortunately can't spend time on back-and-forth on implementation issues in your project. But. We do have good documentation and have been blessed with a **great community**, where people help each other out. If Backpack becomes your tool of preference, I highly recommend you join our gang. Help others get started, create cool stuff, or even influence the direction of Backpack:
+With thousands of developers using Backpack, a lot of them non-commercial, and such a small price, **we can't offer official support for the packages**. We've been doing this since 2016, we actively maintain the packages, we try to squash any bugs ASAP and add new features all the time, but we unfortunately can't spend time on back-and-forth on implementation issues in your project. But. We do have good documentation and have been blessed with a **great community**, where people help each other out. If Backpack becomes your tool of preference, I highly recommend you join our gang. Help others get started, create cool stuff, or even influence the direction of Backpack:
-- **[StackOverflow tag](https://stackoverflow.com/questions/tagged/backpack-for-laravel) for support requests** (If you need help creating something using Backpack, post your question on StackOverflow using the ```backpack-for-laravel``` tag. We've been blessed with a great community, that is happy to help. Who doesn't like getting StackOverflow points?)
+- **[StackOverflow tag](https://stackoverflow.com/questions/tagged/backpack-for-laravel) for support requests** (If you need help creating something using Backpack, post your question on StackOverflow using the ```backpack-for-laravel``` tag. We've been blessed with a great community that is happy to help. Who doesn't like getting StackOverflow points?)
- **[Gitter Chatroom](https://gitter.im/BackpackForLaravel/Lobby) for quick questions** (If you have an urgent matter that won't take much time to answer, use our 24/7 Gitter chatroom. Be considerate, everyone's probably working on their own project right now.)
- **[Github Issues](https://github.com/laravel-backpack/) for bugs** (Found a bug? Great! Please search for it on Github first - someone might have already found it. If not, open an issue, we're happy to learn about it and make Backpack better. )
diff --git a/3.4/install-optionals.md b/3.4/install-optionals.md
index 0dfa043c..7a99e6e3 100644
--- a/3.4/install-optionals.md
+++ b/3.4/install-optionals.md
@@ -4,7 +4,7 @@
Each Backpack package has its own installation instructions in its readme file. We duplicate them here for easy access.
-Everything else is optional. Your project might use them or it might not. Only do each following steps if you need the functionality that package provides.
+Everything else is optional. Your project might use them or it might not. Only do each of the following steps if you need the functionality that package provides.
## BackupManager
diff --git a/3.4/installation.md b/3.4/installation.md
index caf3247b..baa221c3 100644
--- a/3.4/installation.md
+++ b/3.4/installation.md
@@ -5,9 +5,9 @@
## Requirements
-If you can run Laravel 5.6, you can install Backpack. Backpack does _not_ have additional requirements. For the following process, we assume:
+If you can run Laravel 5.7, you can install Backpack. Backpack does _not_ have additional requirements. For the following process, we assume:
-- you have a working [installation of Laravel 5.6](https://laravel.com/docs/5.6#installing-laravel) (an existing project is fine, you don't need a *fresh* Laravel install);
+- you have a working [installation of Laravel 5.7](https://laravel.com/docs/5.7#installing-laravel) (an existing project is fine, you don't need a *fresh* Laravel install);
- you can run the ```composer``` command from any directory (you have composer registered as a global command); if you need to run ```php composer.phar``` or reference another directory, please remember to adapt the commands below to your configuration;
diff --git a/3.4/introduction.md b/3.4/introduction.md
index c2930933..61aa29b5 100644
--- a/3.4/introduction.md
+++ b/3.4/introduction.md
@@ -34,12 +34,12 @@ php artisan backpack:base:add-sidebar-content "
### Screenshots
-Take a look at [our homepage](http://www.backpackforlaravel.com/).
+Take a look at [our homepage](https://www.backpackforlaravel.com/).
### Demo
@@ -75,5 +75,5 @@ For more, please see:
We heavily recommend you spend a little time to understand Backpack, and only afterwards install and use it. Currently your options are:
- **[Text Tutorial](/docs/{{version}}/getting-started-basics)** - 23 minutes
-- **[Email Tutorial](http://backpackforlaravel.com/getting-started-emails)** - 1 email per day, for 5 days, 5 minutes each
+- **[Email Tutorial](https://backpackforlaravel.com/getting-started-emails)** - 1 email per day, for 5 days, 5 minutes each
- **Video Tutorial** - working on it
diff --git a/3.5/add-ons-how-to-create-a-backpack-addon.md b/3.5/add-ons-how-to-create-a-backpack-addon.md
index a7773621..9c8baa14 100644
--- a/3.5/add-ons-how-to-create-a-backpack-addon.md
+++ b/3.5/add-ons-how-to-create-a-backpack-addon.md
@@ -33,7 +33,7 @@ Requirements:
### Install Backpack Demo
-We're going to use [the Backpack demo project](https://github.com/laravel-backpack/demo) to generate create a new package. Follow the instructions in [the Installation chapter](https://github.com/laravel-backpack/demo#install).
+We're going to use [the Backpack demo project](https://github.com/laravel-backpack/demo) to create a new package. Follow the instructions in [the Installation chapter](https://github.com/laravel-backpack/demo#install).
Any Laravel & Backpack app would work. But since you're going to require packages that you only need during package development, and make various changes to app files, we recommended you _create_ the package using a Backpack demo. After the package is online (with zero functionality), you will _install_ it in a real application, and _modify_ it right there, in the ```vendor``` folder. You will then delete this Backpack demo project.
@@ -59,7 +59,7 @@ This will create a ```/packages/``` folder in your root directory, where your pa
Now let's customise it and add some boilerplate code, everything that most Laravel Packages will need. Replace everything you need in ```composer.json```, ```CHANGELOG.md```, ```CONTRIBUTING.md```, ```LICENSE.md```, ```README.md```. Make it yours.
-If you want to use Laravel package auto-discovery (and why wouldn't you), make sure to include the Laravel prviders section in your ```composer.json```'s ```extra``` section, like so:
+If you want to use Laravel package auto-discovery (and why wouldn't you), make sure to include the Laravel providers section in your ```composer.json```'s ```extra``` section, like so:
```
"extra": {
"branch-alias": {
@@ -164,13 +164,13 @@ Tags are the way you will version your package, so it's important you do it. Peo
## Step 3. Put it on Packagist
-On [Packagist.org](http://packagist.org), submit a new package. Enter you package's GitHub URL and click Check. If any errors occur, follow the onscreen instructions.
+On [Packagist.org](https://packagist.org), submit a new package. Enter your package's GitHub URL and click Check. If any errors occur, follow the onscreen instructions.
When you're done, you'll be taken to your packagist page, where you'll probably get a notice like this:
>This package is not auto-updated. Please set up the [GitHub Service Hook](https://packagist.org/profile/) for Packagist so that it gets updated whenever you push!
-Let's take care of that. Click that link, get your API token and go to your package's GitHub page, in ```Settings / Webhooks & Services / Add a new service```. Search for Packagist. Enter your username and the token and hit Submit. Your error in Packagist should dissapear in 5–10 minutes.
+Let's take care of that. Click that link, get your API token and go to your package's GitHub page, in ```Settings / Webhooks & Services / Add a new service```. Search for Packagist. Enter your username and the token and hit Submit. Your error in Packagist should disappear in 5–10 minutes.
Congrats! You now have a working package online. You can now require it with composer.
@@ -209,7 +209,7 @@ git push origin master --tags
You can now delete the Backpack project, and the database you've created for it (if any).
For extra reading credits, these are the resources we've used to create this guide:
-- http://laravel.com/docs/packages
+- https://laravel.com/docs/packages
- https://laracasts.com/discuss/channels/tips/developing-your-packages-in-laravel-5
- https://github.com/jaiwalker/setup-laravel5-package
- https://github.com/Jeroen-G/laravel-packager
diff --git a/3.5/crud-api.md b/3.5/crud-api.md
index 85240dad..1c22bb4a 100644
--- a/3.5/crud-api.md
+++ b/3.5/crud-api.md
@@ -66,7 +66,7 @@ $this->crud->addColumn()->beforeColumn('name');
$this->crud->addColumn()->afterColumn('name');
```
-- **Chained - makeFirstColumn()** - make this colum the first one in the list
+- **Chained - makeFirstColumn()** - make this column the first one in the list
```php
$this->crud->addColumn()->makeFirstColumn();
// Please note: you need to also specify priority 1 in your addColumn statement for details_row or responsive expand buttons to show
@@ -136,7 +136,7 @@ $this->crud->filters();
#### Details Row
-Shows a ```+``` (plus sign) next to each table row, so that the user can expand that row and reveal details. You are responsible for creting the view with those details.
+Shows a ```+``` (plus sign) next to each table row, so that the user can expand that row and reveal details. You are responsible for creating the view with those details.
- **enableDetailsRow()** - show the + sign in the table view
```php
diff --git a/3.5/crud-basics.md b/3.5/crud-basics.md
index ab869a44..a629169e 100644
--- a/3.5/crud-basics.md
+++ b/3.5/crud-basics.md
@@ -2,7 +2,7 @@
---
-Backpack\CRUD provides a fast way to build admininistration panels - places where your administrators can Create, Read, Update, Delete entries for a specific Eloquent model. **One CRUD Panel provides functionality for one Eloquent Model.**
+Backpack\CRUD provides a fast way to build administration panels - places where your administrators can Create, Read, Update, Delete entries for a specific Eloquent model. **One CRUD Panel provides functionality for one Eloquent Model.**
## Requirements
@@ -43,4 +43,4 @@ For a ```Tag``` entity, your CRUD Panel would consist of:
- a route inside ```routes/backpack/custom.php```;
- your existing model (```app/Models/Tag.php```);
-To further your understading of how a CRUD Panel works, [read more about this example in the tutorial](/docs/{{version}}/crud-tutorial).
+To further your understanding of how a CRUD Panel works, [read more about this example in the tutorial](/docs/{{version}}/crud-tutorial).
diff --git a/3.5/crud-buttons.md b/3.5/crud-buttons.md
index c151d5ca..49eab483 100644
--- a/3.5/crud-buttons.md
+++ b/3.5/crud-buttons.md
@@ -86,10 +86,10 @@ Let's say we want to create a simple ```moderate.blade.php``` button. This butto
```
- Add the new route, next to ```UserCrudController```'s route (most likely inside ```routes/backpack/custom.php```):
```php
-Route::get('user/{id}/moderate', 'UserCrudController@ban');
+Route::get('user/{id}/moderate', 'UserCrudController@moderate');
```
-- We can now create add a ```moderate()``` method to our ```UserCrudController```, which would moderate the user, and redirect back.
+- We can now add a ```moderate()``` method to our ```UserCrudController```, which would moderate the user, and redirect back.
```php
public function moderate()
{
diff --git a/3.5/crud-cheat-sheet.md b/3.5/crud-cheat-sheet.md
index bc9da204..79ef3c59 100644
--- a/3.5/crud-cheat-sheet.md
+++ b/3.5/crud-cheat-sheet.md
@@ -63,7 +63,7 @@ $this->crud->filters(); // gets all the filters
#### Details Row
```php
-// Shows a + sign next to each table row, so that the user can expand that row and reveal details. You are responsible for creting the view with those details.
+// Shows a + sign next to each table row, so that the user can expand that row and reveal details. You are responsible for creating the view with those details.
$this->crud->enableDetailsRow();
// NOTE: you also need to do allow access to the right users: $this->crud->allowAccess('details_row');
// NOTE: you also need to do overwrite the showDetailsRow($id) method in your EntityCrudController to show whatever you'd like in the details row OR overwrite the views/backpack/crud/details_row.blade.php
@@ -115,7 +115,7 @@ $this->crud->setActionsColumnPriority(10000);
#### Custom / Advanced Queries
```php
-// Change what entries are show in the table view.
+// Change what entries are shown in the table view.
// This changes all queries on the table view,
// as opposed to filters, who only change it when that filter is applied.
$this->crud->addClause('active'); // apply local scope
diff --git a/3.5/crud-columns.md b/3.5/crud-columns.md
index df6d924c..6b089e37 100644
--- a/3.5/crud-columns.md
+++ b/3.5/crud-columns.md
@@ -181,7 +181,9 @@ Show custom HTML based on a closure you specify in your EntityCrudController. Pl
### date
-The date column will show a localized date in the default date format (as specified in the ```config/backpack/base.php``` file), whether the attribute is casted as date in the model or not:
+The date column will show a localized date in the default date format (as specified in the ```config/backpack/base.php``` file), whether the attribute is casted as date in the model or not.
+
+Note that the ```format``` attribute uses ISO date formatting parameters and not PHP ```date()``` formatters. See for more information.
```php
[
@@ -196,7 +198,10 @@ The date column will show a localized date in the default date format (as specif
### datetime
-The date column will show a localized datetime in the default datetime format (as specified in the ```config/backpack/base.php``` file), whether the attribute is casted as datetime in the model or not:
+The date column will show a localized datetime in the default datetime format (as specified in the ```config/backpack/base.php``` file), whether the attribute is casted as datetime in the model or not.
+
+Note that the ```format``` attribute uses ISO date formatting parameters and not PHP ```date()``` formatters. See for more information.
+
```php
[
@@ -257,11 +262,11 @@ The model_function column will output a function on your main model. Its definit
For this example, if your model would feature this method, it would return the link to that entity:
```php
public function getSlugWithLink() {
- return ''.$this->slug.'';
- }
+ return ''.$this->slug.'';
+}
```
-**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent that JS and CSS from reaching your DB in the first place.
+**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent JS and CSS from reaching your DB in the first place.
### model_function_attribute
@@ -280,7 +285,7 @@ If the function you're trying to use returns an object, not a string, you can us
],
```
-**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent that JS and CSS from reaching your DB in the first place.
+**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent JS and CSS from reaching your DB in the first place.
### multidimensional_array
@@ -371,7 +376,7 @@ The text column will just output the text value of a db column (or model attribu
],
```
-**Advanced use case:** The ```text``` column type can also show the attribute of a 1-1 relationship. If you have a relationship (like ```parent()```) set up in your Model, you can use relationship and attibute in the ```name```, using dot notation:
+**Advanced use case:** The ```text``` column type can also show the attribute of a 1-1 relationship. If you have a relationship (like ```parent()```) set up in your Model, you can use relationship and attribute in the ```name```, using dot notation:
```php
[
'name' => 'parent.title',
@@ -406,7 +411,7 @@ Show a particular text depending on the value of the attribute.
'name' => 'status',
'label' => "Status",
'type' => 'select_from_array',
- 'options' => [‘draft’ => ‘Draft (invisible)’, ‘published’ => ‘Published (visible)’],
+ 'options' => ['draft' => 'Draft (invisible)', 'published' => 'Published (visible)'],
],
```
@@ -599,7 +604,7 @@ If you want a column to not be orderable at all, just pass ```'orderable' => fal
### Choose Where Columns are Visible
-Starting with Backpack\CRUD 3.5.0, you can choose to show/hide column in different contexts. You can pass ```true``` / ```false``` to the column attributes below, and Backpack will know to show the column or not, in different contexts:
+Starting with Backpack\CRUD 3.5.0, you can choose to show/hide columns in different contexts. You can pass ```true``` / ```false``` to the column attributes below, and Backpack will know to show the column or not, in different contexts:
```php
$this->crud->addColumn([
@@ -674,4 +679,4 @@ You can make the last column be less important (and hide) by giving it an unreas
$this->crud->setActionsColumnPriority(10000);
```
->Note that repsonsive tables adopt special behavior if the table is not able to show all columns. This includes displaying a vertical elipsis to the left of the row, and making the row clickable to reveal more detail. This behavior is automatic and is not manually controllable via a field property.
+>Note that responsive tables adopt special behavior if the table is not able to show all columns. This includes displaying a vertical ellipsis to the left of the row, and making the row clickable to reveal more detail. This behavior is automatic and is not manually controllable via a field property.
diff --git a/3.5/crud-fields.md b/3.5/crud-fields.md
index 3cd56d5a..187debc8 100644
--- a/3.5/crud-fields.md
+++ b/3.5/crud-fields.md
@@ -7,7 +7,7 @@
Field types define how the admin can manipulate an entry's values. They're used by the Create and Update operations.
-Think of the field type as the type of input: ``````. But for most entities, you won't just need text inputs - you'll need datepickers, upload buttons, 1-n relationship, n-n relationships, textareas, etc.
+Think of the field type as the type of input: ``````. But for most entities, you won't just need text inputs - you'll need datepickers, upload buttons, 1-n relationship, n-n relationships, textareas, etc.
We have a lot of default field types, detailed below. If you don't find what you're looking for, you can [create a custom field type](/docs/{{version}}/crud-fields#creating-a-custom-field-type). Or if you just want to tweak a default field type a little bit, you can [overwrite default field types](/docs/{{version}}/crud-fields#overwriting-default-field-types).
@@ -105,7 +105,7 @@ $this->crud->addField($field_definition_array)->afterField('name');
#### Fake Fields (all stored as JSON in the database)
-In case you want to store insignificant information for an entry, that don't need a database column, you can add any number of Fake Fields, and all their information will be store inside one column in the db, as JSON. By default, an ```extras``` column is assumed on the database table, but you can change that.
+In case you want to store insignificant information for an entry that doesn't need a database column, you can add any number of Fake Fields, and all their information will be stored inside one column in the db, as JSON. By default, an ```extras``` column is assumed on the database table, but you can change that.
**Step 1.** Use the fake attribute on your field:
```php
@@ -113,7 +113,7 @@ In case you want to store insignificant information for an entry, that don't nee
'name' => 'name', // JSON variable name
'label' => "Tag Name", // human-readable label for the input
- 'fake' => true, // show the field, but don’t store it in the database column above
+ 'fake' => true, // show the field, but don't store it in the database column above
'store_in' => 'extras' // [optional] the database column name where you want the fake fields to ACTUALLY be stored as a JSON array
],
```
@@ -147,7 +147,7 @@ Example:
],
```
-In this example, these 3 fields will show up in the create & update forms, the CRUD will process as usual, but in the database these values won’t be stored in the ```meta_title```, ```meta_description``` and ```meta_keywords``` columns. They will be stored in the ```metas``` column as a JSON array:
+In this example, these 3 fields will show up in the create & update forms, the CRUD will process as usual, but in the database these values won't be stored in the ```meta_title```, ```meta_description``` and ```meta_keywords``` columns. They will be stored in the ```metas``` column as a JSON array:
```php
{"meta_title":"title","meta_description":"desc","meta_keywords":"keywords"}
@@ -223,7 +223,7 @@ Using Google Places API is dependant on using an API Key. Please [get an API key
```php
'google_places' => [
- 'key' => ’the-key-you-got-from-google-places'
+ 'key' => 'the-key-you-got-from-google-places'
],
```
@@ -258,7 +258,7 @@ Onclick preview:
### browse_multiple
-Open elFinder and select multiple file from there.
+Open elFinder and select multiple files from there.
```php
[ // Browse multiple
@@ -471,7 +471,7 @@ Show a pretty [Bootstrap Datepicker](http://bootstrap-datepicker.readthedocs.io/
'label' => 'Date',
// optional:
'date_picker_options' => [
- 'todayBtn' => true,
+ 'todayBtn' => 'linked',
'format' => 'dd-mm-yyyy',
'language' => 'fr'
],
@@ -655,7 +655,7 @@ $this->crud->addField([ // image
'type' => 'image',
'upload' => true,
'crop' => true, // set to true to allow cropping, false to disable
- 'aspect_ratio' => 1, // ommit or set to 0 to allow any aspect ratio
+ 'aspect_ratio' => 1, // omit or set to 0 to allow any aspect ratio
// 'disk' => 's3_bucket', // in case you need to show images from a different disk
// 'prefix' => 'uploads/images/profile_pictures/' // in case your db value is only the file name (no path), you can use this to prepend your path to the image src (in HTML), before it's shown to the user;
]);
@@ -758,14 +758,14 @@ Input preview:
### page_or_link
-Select an existing page from PageManager or an internal or external link. It’s used in the MenuManager package, but can be used in any other model just as well. Its definition looks like this:
+Select an existing page from PageManager or an internal or external link. It's used in the MenuManager package, but can be used in any other model just as well. Its definition looks like this:
```php
[ // PageOrLink
'name' => 'type',
'label' => "Type",
'type' => 'page_or_link',
'page_model' => '\Backpack\PageManager\app\Models\Page'
-]
+],
```
Input preview:
@@ -803,7 +803,7 @@ Show radios according to an associative array you give the input and let the use
],
// optional
//'inline' => false, // show the radios all on the same line?
-]
+],
```
Input preview:
@@ -844,7 +844,7 @@ Your relationships should already be defined on your models as hasOne() or belon
'options' => (function ($query) {
return $query->orderBy('name', 'ASC')->where('depth', 1)->get();
}), // force the related options to be a custom query, instead of all(); you can use this to filter the results show in the select
-]
+],
```
Input preview:
@@ -893,7 +893,7 @@ Your relationships should already be defined on your models as hasOne() or belon
'options' => (function ($query) {
return $query->orderBy('name', 'ASC')->where('depth', 1)->get();
}), // force the related options to be a custom query, instead of all(); you can use this to filter the results show in the select
-]
+],
```
Input preview:
@@ -920,7 +920,7 @@ Your relationships should already be defined on your models as hasMany() or belo
'options' => (function ($query) {
return $query->orderBy('name', 'ASC')->where('depth', 1)->get();
}), // force the related options to be a custom query, instead of all(); you can use this to filter the results show in the select
-]
+],
```
Input preview:
@@ -934,7 +934,7 @@ Input preview:
[Works just like the SELECT field, but prettier]
-Show a Select2 with the names of the connected entity and let the user select any number of them.
+Shows a Select2 with the names of the connected entity and let the user select any number of them.
Your relationships should already be defined on your models as hasMany() or belongsToMany().
```php
@@ -952,7 +952,7 @@ Your relationships should already be defined on your models as hasMany() or belo
'options' => (function ($query) {
return $query->orderBy('name', 'ASC')->where('depth', 1)->get();
}), // force the related options to be a custom query, instead of all(); you can use this to filter the results show in the select
-]
+],
```
Input preview:
@@ -1008,7 +1008,7 @@ Input preview:
### select_and_order
-Display items on two columns and let the user drag&drop between them to choose which items are selected an which are not, and reorder the selected items with drag&drop.
+Display items on two columns and let the user drag&drop between them to choose which items are selected and which are not, and reorder the selected items with drag&drop.
Its definition is exactly as ```select_from_array```, but the value will be stored as JSON in the database: ```["3","5","7","6"]```, so it needs the attribute to be cast to array on the Model:
@@ -1040,7 +1040,7 @@ Also possible:
'label' => 'Featured',
'type' => 'select_and_order',
'options' => Product::get()->pluck('title','id')->toArray(),
-]
+],
```
Input preview:
@@ -1058,7 +1058,7 @@ Display a select with the values you want:
'name' => 'template',
'label' => "Template",
'type' => 'select_from_array',
- 'options' => [‘one’ => ‘One’, ‘two’ => ‘Two’],
+ 'options' => ['one' => 'One', 'two' => 'Two'],
'allows_null' => false,
'default' => 'one',
// 'allows_multiple' => true, // OPTIONAL; needs you to cast this to array in your model;
@@ -1079,7 +1079,7 @@ Display a select2 with the values you want:
'name' => 'template',
'label' => "Template",
'type' => 'select2_from_array',
- 'options' => [‘one’ => ‘One’, ‘two’ => ‘Two’],
+ 'options' => ['one' => 'One', 'two' => 'Two'],
'allows_null' => false,
'default' => 'one',
// 'allows_multiple' => true, // OPTIONAL; needs you to cast this to array in your model;
@@ -1107,8 +1107,8 @@ Display a select2 that takes its values from an AJAX call.
'data_source' => url("http://github.com/api/category"), // url to controller search function (with /{id} should return model)
'placeholder' => "Select a category", // placeholder for the select
'minimum_input_length' => 2, // minimum characters to type before querying results
- // 'dependencies' => [‘category’], // when a dependency changes, this select2 is reset to null
- // ‘method' => ‘GET’, // optional - HTTP method to use for the AJAX call (GET, POST)
+ // 'dependencies' => ['category'], // when a dependency changes, this select2 is reset to null
+ // 'method' => 'GET', // optional - HTTP method to use for the AJAX call (GET, POST)
]
```
@@ -1383,7 +1383,7 @@ Input preview:
'label' => 'Image',
'type' => 'upload',
'upload' => true,
- 'disk' => 'uploads' // if you store files in the /public folder, please ommit this; if you store them in /storage or S3, please specify it;
+ 'disk' => 'uploads' // if you store files in the /public folder, please omit this; if you store them in /storage or S3, please specify it;
],
```
@@ -1450,7 +1450,7 @@ Shows a multiple file input to the user and stores the values as a JSON array in
'label' => 'Photos',
'type' => 'upload_multiple',
'upload' => true,
- 'disk' => 'uploads' // if you store files in the /public folder, please ommit this; if you store them in /storage or S3, please specify it;
+ 'disk' => 'uploads' // if you store files in the /public folder, please omit this; if you store them in /storage or S3, please specify it;
],
```
@@ -1548,10 +1548,10 @@ An entry stored in the database will look like this:
```
$video = {
id: 234324,
- title: ‘my video title’,
- image: ‘https://provider.com/image.jpg',
- url: ‘http://provider.com/video',
- provider: ‘youtube’
+ title: 'my video title',
+ image: 'https://provider.com/image.jpg',
+ url: 'http://provider.com/video',
+ provider: 'youtube'
}
```
@@ -1604,11 +1604,11 @@ Show a wysiwyg (CKEditor) to the user.
## Overwriting Default Field Types
-The actual field types are stored in the Backpack/CRUD package in ```/resources/views/fields```. If you need to change an existing field, you don’t need to modify the package, you just need to add a blade file in your application in ```/resources/views/vendor/backpack/crud/fields```, with the same name. The package checks there first, and only if there's no file there, will it load it from the package.
+The actual field types are stored in the Backpack/CRUD package in ```/resources/views/fields```. If you need to change an existing field, you don't need to modify the package, you just need to add a blade file in your application in ```/resources/views/vendor/backpack/crud/fields```, with the same name. The package checks there first, and only if there's no file there, will it load it from the package.
To quickly publish a field blade file in your project, you can use ```php artisan backpack:crud:publish fields/field_name```. For example, to publish the number field type, you'd type ```php artisan backpack:crud:publish fields/number```
->Please keep in mind that if you're using _your_ file for a field type, you're not using the _package file_. So any updates we push to that file, you're not getting them. In most cases, it's recommended you crate a custom field type for your use case, instead of overwriting default field types.
+>Please keep in mind that if you're using _your_ file for a field type, you're not using the _package file_. So any updates we push to that file, you're not getting them. In most cases, it's recommended you create a custom field type for your use case, instead of overwriting default field types.
## Creating a Custom Field Type
@@ -1624,7 +1624,7 @@ Your field definition will be something like:
'label' => 'Home address',
'type' => 'address'
/// 'view_namespace' => 'yourpackage' // use a custom namespace of your package to load views within a custom view folder.
-]);
+],
```
And your blade file something like:
diff --git a/3.5/crud-filters.md b/3.5/crud-filters.md
index 1feb07b6..21bed0d1 100644
--- a/3.5/crud-filters.md
+++ b/3.5/crud-filters.md
@@ -55,7 +55,7 @@ function() { // if the filter is active (the GET parameter "draft" exits)
> - you can get the filter value by specifying a parameter to the function (ex: ```$value```);
> - you have access to other request variables using ```$this->crud->request```;
> - you also have read/write access to public properties using ```$this->crud```;
-> - when building complicated "OR" logic, make sure the first "where" in your closure is a "where" and only the subsequent are "orWhere"; Laravel 5.3+ no longer convers the first "orWhere" into a "where";
+> - when building complicated "OR" logic, make sure the first "where" in your closure is a "where" and only the subsequent are "orWhere"; Laravel 5.3+ no longer converts the first "orWhere" into a "where";
## Filter types
@@ -80,7 +80,7 @@ function() { // if the filter is active
### Text
-Shows a text input. Most useful for letting the user filter through information that not shown as a column in the CRUD table - otherwise they could just use the DataTables search field.
+Shows a text input. Most useful for letting the user filter through information that's not shown as a column in the CRUD table - otherwise they could just use the DataTables search field.

@@ -104,15 +104,15 @@ Show a datepicker. The user can select one day.

```php
- $this->crud->addFilter([ // date filter
- 'type' => 'date',
- 'name' => 'date',
- 'label'=> 'Date'
- ],
- false,
- function($value) { // if the filter is active, apply these constraints
- // $this->crud->addClause('where', 'date', $value);
- });
+$this->crud->addFilter([ // date filter
+ 'type' => 'date',
+ 'name' => 'date',
+ 'label'=> 'Date'
+],
+false,
+function($value) { // if the filter is active, apply these constraints
+ // $this->crud->addClause('where', 'date', $value);
+});
```
@@ -123,17 +123,17 @@ Show a daterange picker. The user can select a start date and an end date.

```php
- $this->crud->addFilter([ // daterange filter
- 'type' => 'date_range',
- 'name' => 'from_to',
- 'label'=> 'Date range'
- ],
- false,
- function($value) { // if the filter is active, apply these constraints
- // $dates = json_decode($value);
- // $this->crud->addClause('where', 'date', '>=', $dates->from);
- // $this->crud->addClause('where', 'date', '<=', $dates->to . ' 23:59:59');
- });
+$this->crud->addFilter([ // daterange filter
+ 'type' => 'date_range',
+ 'name' => 'from_to',
+ 'label'=> 'Date range'
+],
+false,
+function($value) { // if the filter is active, apply these constraints
+ // $dates = json_decode($value);
+ // $this->crud->addClause('where', 'date', '>=', $dates->from);
+ // $this->crud->addClause('where', 'date', '<=', $dates->to . ' 23:59:59');
+});
```
diff --git a/3.5/crud-how-to.md b/3.5/crud-how-to.md
index 76869dbb..b85723d0 100644
--- a/3.5/crud-how-to.md
+++ b/3.5/crud-how-to.md
@@ -37,7 +37,7 @@ If you don't find one there, you can create one, and Backpack will pick it up in
Starting with Backpack\CRUD 3.2, you can use the ```with()``` method on ```CRUD::resource``` to better organize your routes. Something like this:
```php
-CRUD::resource(‘teams’, ‘Admin\TeamCrudController’)->with(function(){
+CRUD::resource('teams', 'Admin\TeamCrudController')->with(function(){
// add extra routes to this resource
Route::get('teams/ajax-name-options', 'Admin\TeamCrudController@nameOptions');
Route::get('teams/ajax-category-options', 'Admin\TeamCrudController@categoryOptions');
@@ -103,7 +103,7 @@ class CompanyUser extends User
If you try to add multiple columns with the same ```name```, by default Backpack will only show the last one. That's because ```name``` is also used as a key in the ```$column``` array. So when you ```addColumn()``` with the same name twice, it just overwrites the previous one.
-In order to insert two column with the same name, use the ```key``` attribute on the second column (or both columns). If this attribute is present for a column, Backpack will use ```key``` instead of ```name```. Example:
+In order to insert two columns with the same name, use the ```key``` attribute on the second column (or both columns). If this attribute is present for a column, Backpack will use ```key``` instead of ```name```. Example:
```diff
$this->crud->addColumn([
@@ -133,10 +133,10 @@ In order to insert two column with the same name, use the ```key``` attribute on
## Use the Media Library (File Manager)
-If you've chosen to install [elFinder](http://elfinder.org/) when installing Backpack, you already have a media manager. And it’s integrated into:
-- TinyMCE (as “tinymce” fieldtype)
-- CKEditor (as “ckeditor” fieldtype)
-- CRUD “browse” fieldtype
+If you've chosen to install [elFinder](http://elfinder.org/) when installing Backpack, you already have a media manager. And it's integrated into:
+- TinyMCE (as "tinymce" fieldtype)
+- CKEditor (as "ckeditor" fieldtype)
+- CRUD "browse" fieldtype
- standalone, at the *your-project/admin/elfinder* route;
For the integration, barryvdh's [laravel-elfinder](https://github.com/barryvdh/laravel-elfinder) package is used.
@@ -205,9 +205,9 @@ Say you want to show two selects:
```php
$this->crud->addField([ // SELECT2
- 'label' => ‘Category',
+ 'label' => 'Category',
'type' => 'select',
- 'name' => ‘category',
+ 'name' => 'category',
'entity' => 'category',
'attribute' => 'name',
]);
@@ -221,8 +221,8 @@ Say you want to show two selects:
'data_source' => url('http://github.com/api/article'), // url to controller search function (with /{id} should return model)
'placeholder' => 'Select an article', // placeholder for the select
'minimum_input_length' => 0, // minimum characters to type before querying results
- 'dependencies' => [‘category’], // when a dependency changes, this select2 is reset to null
- // ‘method' => ‘GET’, // optional - HTTP method to use for the AJAX call (GET, POST)
+ 'dependencies' => ['category'], // when a dependency changes, this select2 is reset to null
+ // 'method' => 'GET', // optional - HTTP method to use for the AJAX call (GET, POST)
]);
```
@@ -232,7 +232,7 @@ Say you want to show two selects:
```php
Route::get('api/article', 'App\Http\Controllers\Api\ArticleController@index');
-Route::get('api/article/{id}', 'App\Http\Controllers\Api\ArticleController@show’);
+Route::get('api/article/{id}', 'App\Http\Controllers\Api\ArticleController@show');
```
**DIFFERENT HERE**: Nothing.
diff --git a/3.5/crud-operation-list-entries.md b/3.5/crud-operation-list-entries.md
index 5255371c..2f22a632 100644
--- a/3.5/crud-operation-list-entries.md
+++ b/3.5/crud-operation-list-entries.md
@@ -110,7 +110,7 @@ Exporting the DataTable to PDF, CSV, XLS is as easy as typing ```$this->crud->en
By default, all entries are shown in the ListEntries table, before filtering. If you want to restrict the entries to a subset, you can use the methods below in your EntityCrudController's ```setup()``` method:
```php
-// Change what entries are show in the table view.
+// Change what entries are shown in the table view.
// This changes all queries on the table view,
// as opposed to filters, who only change it when that filter is applied.
$this->crud->addClause('active'); // apply a local scope
@@ -130,7 +130,7 @@ $this->crud->orderBy();
#### Responsive Table
-If you CRUD table has more columns than can fit inside the viewport (on mobile / tablet or smaller desktop screens), unimportant columns will start hiding and an expansion icon (three dots) will appear to the left of each row. We call this behaviour "_responsive table_", and consider this to be the best UX. By behaviour we consider the 1st column the most important, than 2nd, than 3rd, etc; the "actions" column is considered as important as the 1st column. You can of course [change the importance of columns](/docs/{{version}}/crud-columns#define-which-columns-to-hide-in-responsive-table).
+If your CRUD table has more columns than can fit inside the viewport (on mobile / tablet or smaller desktop screens), unimportant columns will start hiding and an expansion icon (three dots) will appear to the left of each row. We call this behaviour "_responsive table_", and consider this to be the best UX. By behaviour we consider the 1st column the most important, then 2nd, then 3rd, etc; the "actions" column is considered as important as the 1st column. You can of course [change the importance of columns](/docs/{{version}}/crud-columns#define-which-columns-to-hide-in-responsive-table).
If you do not like this, you can **toggle off the responsive behaviour for all CRUD tables** by changing this config value in your ```config/backpack/crud.php``` to ```false```:
```php
diff --git a/3.5/crud-operation-revisions.md b/3.5/crud-operation-revisions.md
index 6a9210bf..b2833e4f 100644
--- a/3.5/crud-operation-revisions.md
+++ b/3.5/crud-operation-revisions.md
@@ -7,7 +7,7 @@
Revisions allows your admins to store, see and undo changes to entries on an Eloquent model.
-The operation provides you with a simple interface to work with [venturecraft/revisionable](https://github.com/VentureCraft/revisionable#implementation), which is a great pacakge that stores all changes in a separate table. It can work as an audit trail, a backup system and an accountability system for the admins.
+The operation provides you with a simple interface to work with [venturecraft/revisionable](https://github.com/VentureCraft/revisionable#implementation), which is a great package that stores all changes in a separate table. It can work as an audit trail, a backup system and an accountability system for the admins.
When enabled, ```Revisions``` will show another button in the table view, between _Edit_ and _Delete_. On click, that button opens another page which will allow an admin to see all changes and who made them:
diff --git a/3.5/crud-operation-update.md b/3.5/crud-operation-update.md
index e6477313..c7fd915f 100644
--- a/3.5/crud-operation-update.md
+++ b/3.5/crud-operation-update.md
@@ -75,7 +75,7 @@ public function update(UpdateRequest $request)
For localized apps, you can let your admins edit multi-lingual entries. Only translations stored the [spatie/laravel-translatable](https://github.com/spatie/laravel-translatable) way are supported right now, but more options will be coming soon.
In order to make one of your Models translatable (localization), you need to:
-0. Be running MySQL 5.7+ (or a PosgreSQL with JSON column support);
+0. Be running MySQL 5.7+ (or a PostgreSQL with JSON column support);
1. [Install spatie/laravel-translatable](https://github.com/spatie/laravel-translatable#installation);
2. In your database, make all translatable columns either JSON or TEXT.
3. Use Backpack's ```HasTranslations``` trait on your model (instead of using spatie's ```HasTranslations```) and define what fields are translatable, inside the ```$translatable``` property. For example:
diff --git a/3.5/crud-operations.md b/3.5/crud-operations.md
index 4ad5a4ca..bc125218 100644
--- a/3.5/crud-operations.md
+++ b/3.5/crud-operations.md
@@ -96,7 +96,7 @@ $this->crud->setHeading('some string', 'create'); // set the Heading for the cre
$this->crud->setSubheading('some string', 'create'); // set the Subheading for the create action
```
-There methods are usually useful inside actions, not in ```setup()```. Since action methods are called _after_ ```setup()```, any call to these getters and setters in ```setup()``` would get overwritten by the call in the action.
+These methods are usually useful inside actions, not in ```setup()```. Since action methods are called _after_ ```setup()```, any call to these getters and setters in ```setup()``` would get overwritten by the call in the action.
### Handling Access to Operations
diff --git a/3.5/crud-tutorial.md b/3.5/crud-tutorial.md
index 827b0696..4fa02c24 100644
--- a/3.5/crud-tutorial.md
+++ b/3.5/crud-tutorial.md
@@ -98,7 +98,7 @@ class Tag extends Model {
/*
|--------------------------------------------------------------------------
- | ACCESORS
+ | ACCESSORS
|--------------------------------------------------------------------------
*/
@@ -205,7 +205,7 @@ What we should notice inside this TagCrudController is that:
Let's move our attention to the ```setup()``` method, which is the gateway to configuring our CRUD Panel.
-As we can tell from the comments there, in most cases we _shouldn't_ use ```$this->crud->setFromDb()```, which automagically figures out which columns and fields to show. That's because for real models, in real projects, it would _never_ be able to 100% figure out which field types to use. Real projects are very custom - that's a fact. In real projects, models are complicated, use a bunch of fields types and you'll want to customize things. Instead of using ```setFromDb()``` then gradually changing what you don't like, **we heavily recommend you manually define all fields and columns you need**.
+As we can tell from the comments there, in most cases we _shouldn't_ use ```$this->crud->setFromDb()```, which automagically figures out which columns and fields to show. That's because for real models, in real projects, it would _never_ be able to 100% figure out which field types to use. Real projects are very custom - that's a fact. In real projects, models are complicated, use a bunch of field types and you'll want to customize things. Instead of using ```setFromDb()``` then gradually changing what you don't like, **we heavily recommend you manually define all fields and columns you need**.
Since our ```Tag``` model is so simple, we _can_ leave it like this - it will work perfectly, since we only need a ```text``` field and a ```text``` column. But let's not do that. Let's define our fields and columns manually, like big boys:
@@ -244,7 +244,7 @@ This will:
- add a simple ```text``` column for our ```name``` attribute to the ListEntries operation (the table view);
- add a simple ```text``` field for our ```name``` attribute to the Create and Update forms;
-It the exact same thing ```setFromDb()``` would have figured out, but done manually. This way, if we want to add [other columns](/docs/{{version}}/crud-columns)) or [other fields](/docs/{{version}}/crud-fields), we can easily do that. If we want to change the label of the ```name``` field from ```Name``` to ```Tag name```, we just make that small change. The benefits of _not_ using ```setFromDb()``` will be more obvious once you use Backpack on real models, we promise.
+It's the exact same thing ```setFromDb()``` would have figured out, but done manually. This way, if we want to add [other columns](/docs/{{version}}/crud-columns)) or [other fields](/docs/{{version}}/crud-fields), we can easily do that. If we want to change the label of the ```name``` field from ```Name``` to ```Tag name```, we just make that small change. The benefits of _not_ using ```setFromDb()``` will be more obvious once you use Backpack on real models, we promise.
Here, in the ```setup()``` method, is where you can also do a lot of other things, like enabling other operations, adding buttons, adding filters, customizing your query, etc. For a full list of the things you can do inside ```setup()``` check out our [cheat sheet](/docs/{{version}}/crud-cheat-sheet).
diff --git a/3.5/demo.md b/3.5/demo.md
index 4cec341e..eb531deb 100644
--- a/3.5/demo.md
+++ b/3.5/demo.md
@@ -2,7 +2,7 @@
---
-We've put toghether a working Laravel app (backend-only), that you can install on your machine. This should make it easier to:
+We've put together a working Laravel app (backend-only), that you can install on your machine. This should make it easier to:
- see how it looks & feels;
- see how it works;
- change stuff in code, to see how easy it is to customize Backpack;
diff --git a/3.5/getting-started-advanced-features.md b/3.5/getting-started-advanced-features.md
index 5252217a..60148539 100644
--- a/3.5/getting-started-advanced-features.md
+++ b/3.5/getting-started-advanced-features.md
@@ -4,14 +4,14 @@
**Duration:** 5 min
-Here are some other cool things Backpack makes easy for you. We recommend going through them one by one, just browsing. You might not need the feature _right now_, but when _you do_, you’ll know how to find it.
+Here are some other cool things Backpack makes easy for you. We recommend going through them one by one, just browsing. You might not need the feature _right now_, but when _you do_, you'll know how to find it.
---
## Other Operations
- [Show](/docs/{{version}}/crud-operation-show) Operation - you can let your admins preview an entry
-- [Reorder](/docs/{{version}}/crud-operation-reorder) Operation - you can reorder and nesting entries (hierarcy tree)
+- [Reorder](/docs/{{version}}/crud-operation-reorder) Operation - you can reorder and nesting entries (hierarchy tree)
- [Revisions](/docs/{{version}}/crud-operation-revisions) Operation - you can keep a record of all modifications to an entry, and let your admin revert changes
---
@@ -27,7 +27,7 @@ Here are some other cool things Backpack makes easy for you. We recommend going
--
- **ListEntries**
- - you can add a “+” button next to each entry, to allow the admin to easily preview some quick information that was too big to fit inside a columns - we call it [details row](/docs/{{version}}/crud-operation-list-entries#details-row)
+ - you can add a "+" button next to each entry, to allow the admin to easily preview some quick information that was too big to fit inside a columns - we call it [details row](/docs/{{version}}/crud-operation-list-entries#details-row)
- export all visible items in the table by adding [export buttons](/docs/{{version}}/crud-operation-list-entries#export-buttons)
- [custom search logic](/docs/{{version}}/crud-columns#custom-search-logic) for the columns in the list view
@@ -36,4 +36,4 @@ Additionally, here are a few more ways you can customize your CRUDs:
- [Custom Views for each CRUD](/docs/{{version}}/crud-how-to#customize-views-for-each-crud-panel)
- [Custom CSS or JS](/docs/{{version}}/crud-how-to#customize-css-and-js-for-default-crud-operations) for each CRUD Operation
-**That’s it for today!** Told you we’re done with long lessons :-) Hopefully some of the above have peaked your interest and you’ve clicked to see what Backpack can do. In the [next lesson](/docs/{{version}}/getting-started-license-and-support) we’ll go through a few other Backpack packages, that cover some recurring use cases.
+**That's it for today!** Told you we're done with long lessons :-) Hopefully some of the above have peaked your interest and you've clicked to see what Backpack can do. In the [next lesson](/docs/{{version}}/getting-started-license-and-support) we'll go through a few other Backpack packages that cover some recurring use cases.
diff --git a/3.5/getting-started-basics.md b/3.5/getting-started-basics.md
index bae7efde..99061791 100644
--- a/3.5/getting-started-basics.md
+++ b/3.5/getting-started-basics.md
@@ -4,14 +4,14 @@
**Duration:** 5 minutes
-> **Are you already comfortable with Laravel?** In order to understand this series and make use of Backpack, you’ll need to have a decent understanding of the Laravel framework. If you don’t, please go ahead and [watch this excellent intro series on Laracasts](https://laracasts.com/series/laravel-from-scratch-2017) and accomodate yourself with Laravel first.
+> **Are you already comfortable with Laravel?** In order to understand this series and make use of Backpack, you'll need to have a decent understanding of the Laravel framework. If you don't, please go ahead and [watch this excellent intro series on Laracasts](https://laracasts.com/series/laravel-from-scratch-2017) and accommodate yourself with Laravel first.
## What is Backpack?
A software that helps Laravel professionals build administration panels - secure areas where administrators login and create, read, update and delete application information. It is *not* a CMS, it is more a framework that lets you *build your own* CMS. You can install it in your existing project or in a totally new project.
-It’s designed to be flexible enough to allow you to **build admin panels for everything from simple presentation websites to CRMs, ERPs, eCommerce, eLearning, etc**. We can vouch for that, because we have built all that stuff using Backpack already.
+It's designed to be flexible enough to allow you to **build admin panels for everything from simple presentation websites to CRMs, ERPs, eCommerce, eLearning, etc**. We can vouch for that, because we have built all that stuff using Backpack already.
## How to use?
@@ -22,7 +22,7 @@ Backpack consists of two **core packages**:
A **CRUD** is what we call a section of your admin panel that lets the admin _Create, Read, Update or Delete_ entries of a certain entity (or Model). So you can have a CRUD for Products, a CRUD for Articles, a CRUD for Categories, or whatever else you might want to create, read, update or delete.
-For the purpose of this series, we’ll show examples on the ```Tag``` entity. This is what a Tag CRUD could look like:
+For the purpose of this series, we'll show examples on the ```Tag``` entity. This is what a Tag CRUD could look like:

@@ -38,17 +38,17 @@ Mind that you will _almost never_ use all of Backpack's features in one CRUD. Bu
### Backpack\Base
-**Backpack/Base** is the package that **will handle the authentication** and provide you with minimal admin area functionality. **Your admin will be able to login and change his password or email.** And that’s pretty much it.
+**Backpack/Base** is the package that **will handle the authentication** and provide you with minimal admin area functionality. **Your admin will be able to login and change his password or email.** And that's pretty much it.

-Thanks to Base, after you [install Backpack](/docs/{{version}}/installation) (don't do it now), you’ll be able to log into your admin panel at ```http://yourapp/admin```. You can change the URL prefix from ```admin``` to something else in your ```config/backpack/base.php``` file, along with a bunch of other configuration options. [Click here](https://github.com/Laravel-Backpack/Base/blob/master/src/config/backpack/base.php) to browse the configuration file and see what it can do for you.
+Thanks to Base, after you [install Backpack](/docs/{{version}}/installation) (don't do it now), you'll be able to log into your admin panel at ```http://yourapp/admin```. You can change the URL prefix from ```admin``` to something else in your ```config/backpack/base.php``` file, along with a bunch of other configuration options. [Click here](https://github.com/Laravel-Backpack/Base/blob/master/src/config/backpack/base.php) to browse the configuration file and see what it can do for you.
Backpack\Base pulls in the free [AdminLTE](https://adminlte.io/themes/AdminLTE/index2.html) theme and enhances the design a little bit. So any front-end block that AdminLTE has, you'll also be able to use in your custom pages. It also includes a system for bubble notifications, which you can use across the admin panel. You can easily [trigger notification bubbles in PHP](/docs/{{version}}/base-about#triggering-notification-bubbles-in-php) or [trigger notification bubbles in JavaScript](/docs/{{version}}/base-about#triggering-notification-bubbles-in-javascript).
### Backpack\CRUD
-This is where it gets interesting. As soon as you [install Backpack](/docs/{{version}}/installation) in your project, you can create **CRUDs** for your admins to easily manipulate DB information. Let’s browse through a simple example, of creating a CRUD administration panel for a Tag entity:
+This is where it gets interesting. As soon as you [install Backpack](/docs/{{version}}/installation) in your project, you can create **CRUDs** for your admins to easily manipulate DB information. Let's browse through a simple example, of creating a CRUD administration panel for a Tag entity:
```zsh
# STEP 1. create migration
@@ -67,7 +67,7 @@ php artisan backpack:base:add-sidebar-content "
## Create & Update Operations
@@ -95,7 +95,7 @@ A typical *field definition array* will need at least three things:
- ```label``` - the human-readable label for the input (will be generated from ```name``` if not given);
-You can use [one of the 44+ field types we’ve provided](/docs/{{version}}/crud-fields#default-field-types), or easily [create a custom field type](/docs/{{version}}/crud-fields#creating-a-custom-field-type) if you have some super-specific need that we haven’t covered yet, or even [overwrite how a field type works](#overwriting-default-field-types). Take a few minutes and [browse the 44+ field types](/docs/{{version}}/crud-fields#default-field-types), to understand how the definition array differs from one to another and how many use cases you have already covered.
+You can use [one of the 44+ field types we've provided](/docs/{{version}}/crud-fields#default-field-types), or easily [create a custom field type](/docs/{{version}}/crud-fields#creating-a-custom-field-type) if you have some super-specific need that we haven't covered yet, or even [overwrite how a field type works](#overwriting-default-field-types). Take a few minutes and [browse the 44+ field types](/docs/{{version}}/crud-fields#default-field-types), to understand how the definition array differs from one to another and how many use cases you have already covered.
Let's take another example, slightly more complicated than the ```text``` fields we used above. Something you'll encounter all the time is relationship fields. So let's say the ```Tag``` model has an **n-n relationship** with an Article model:
@@ -115,7 +115,7 @@ $this->crud->addField([
'entity' => 'articles', // the relationship name in your Model
'attribute' => 'title', // attribute on Article that is shown to admin
'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
-], ‘update’);
+], 'update');
```
**Notes:**
@@ -138,7 +138,7 @@ $this->crud->addField([
**Note: **Because the last parameter is missing, the field will be added to both Create and Update forms.
-> When generating a CrudController, you’ll be using the ```$this->crud->setFromDb();``` method by default, which tries to figure out what fields you might need in your create/update forms and in your list view, but - as you'd expect - only works for the simple field types. You can:
+> When generating a CrudController, you'll be using the ```$this->crud->setFromDb();``` method by default, which tries to figure out what fields you might need in your create/update forms and in your list view, but - as you'd expect - only works for the simple field types. You can:
>
> (1) choose to keep using ```setFromDb()``` and add/remove/change additional fields
>
@@ -183,7 +183,7 @@ ListEntries shows the admin a table with all entries. On the front-end, the info
### Columns
-Columns help you specify *which* attributes are shown in the table and *in which order*. **They’re defined in the ```setup()``` method, the same as fields, and their syntax is super-similar to fields too**:
+Columns help you specify *which* attributes are shown in the table and *in which order*. **They're defined in the ```setup()``` method, the same as fields, and their syntax is super-similar to fields too**:
```php
$this->crud->addColumn($column_definition_array); // add a single column, at the end of the table
@@ -240,4 +240,4 @@ $this->crud->removeButton($name);
$this->crud->removeButtonFromStack($name, $stack);
```
-**That’s it for today!** Thanks for sticking with us this long. This has been the most important and longest lesson. You can go ahead and [install Backpack](/docs/{{version}}/installation) now, as you’ve already gone through the most important features. Or [read the next lesson](/docs/{{version}}/getting-started-advanced-features), about advanced features.
\ No newline at end of file
+**That's it for today!** Thanks for sticking with us this long. This has been the most important and longest lesson. You can go ahead and [install Backpack](/docs/{{version}}/installation) now, as you've already gone through the most important features. Or [read the next lesson](/docs/{{version}}/getting-started-advanced-features), about advanced features.
\ No newline at end of file
diff --git a/3.5/getting-started-license-and-support.md b/3.5/getting-started-license-and-support.md
index 3916ffc9..7dceeb0a 100644
--- a/3.5/getting-started-license-and-support.md
+++ b/3.5/getting-started-license-and-support.md
@@ -16,7 +16,7 @@ Take a look at:
## License
-Backpack is **free for non-commercial use**, but needs a license code in order to prevent “_unlicensed use_” notification bubbles and interruption of service. You can get a license code for your project:
+Backpack is **free for non-commercial use**, but needs a license code in order to prevent "_unlicensed use_" notification bubbles and interruption of service. You can get a license code for your project:
- ```free```, if you're using it for non-commercial purposes; [apply here](https://backpackforlaravel.com/pricing);
- ```free```, if you've contributed to Backpack on Github; [apply here](https://backpackforlaravel.com/pricing);
- ```$49 EUR/project```, if you're making money using it for a project; [buy here](https://backpackforlaravel.com/pricing);
@@ -25,14 +25,14 @@ Backpack is **free for non-commercial use**, but needs a license code in order t
**Freelancers** or companies **who make money using Backpack** - for themselves, their employers or their clients, **should [purchase a commercial license here](https://backpackforlaravel.com/pricing)**.
->**You don't need a license code on LOCALHOST.** If you’re just trying Backpack on your own machine, you don’t need a license code. You only need a license code when you take your application to production.
+>**You don't need a license code on LOCALHOST.** If you're just trying Backpack on your own machine, you don't need a license code. You only need a license code when you take your application to production.
## Support
-With thousands of developers using Backpack, a lot of them non-commercial, and such a small price, **we can’t offer official support for the packages**. We've been doing this since 2016, we actively maintain the packages, we try to squash any bugs ASAP and add new features all the time, but we unfortunately can't spend time on back-and-forth on implementation issues in your project. But. We do have good documentation and have been blessed with a **great community**, where people help each other out. If Backpack becomes your tool of preference, I highly recommend you join our gang. Help others get started, create cool stuff, or even influence the direction of Backpack:
+With thousands of developers using Backpack, a lot of them non-commercial, and such a small price, **we can't offer official support for the packages**. We've been doing this since 2016, we actively maintain the packages, we try to squash any bugs ASAP and add new features all the time, but we unfortunately can't spend time on back-and-forth on implementation issues in your project. But. We do have good documentation and have been blessed with a **great community**, where people help each other out. If Backpack becomes your tool of preference, I highly recommend you join our gang. Help others get started, create cool stuff, or even influence the direction of Backpack:
-- **[StackOverflow tag](https://stackoverflow.com/questions/tagged/backpack-for-laravel) for support requests** (If you need help creating something using Backpack, post your question on StackOverflow using the ```backpack-for-laravel``` tag. We've been blessed with a great community, that is happy to help. Who doesn't like getting StackOverflow points?)
+- **[StackOverflow tag](https://stackoverflow.com/questions/tagged/backpack-for-laravel) for support requests** (If you need help creating something using Backpack, post your question on StackOverflow using the ```backpack-for-laravel``` tag. We've been blessed with a great community that is happy to help. Who doesn't like getting StackOverflow points?)
- **[Gitter Chatroom](https://gitter.im/BackpackForLaravel/Lobby) for quick questions** (If you have an urgent matter that won't take much time to answer, use our 24/7 Gitter chatroom. Be considerate, everyone's probably working on their own project right now.)
- **[Github Issues](https://github.com/laravel-backpack/) for bugs** (Found a bug? Great! Please search for it on Github first - someone might have already found it. If not, open an issue, we're happy to learn about it and make Backpack better. )
diff --git a/3.5/install-optionals.md b/3.5/install-optionals.md
index 83f82fc2..bf58fc0b 100644
--- a/3.5/install-optionals.md
+++ b/3.5/install-optionals.md
@@ -4,7 +4,7 @@
Each Backpack package has its own installation instructions in its readme file. We duplicate them here for easy access.
-Everything else is optional. Your project might use them or it might not. Only do each following steps if you need the functionality that package provides.
+Everything else is optional. Your project might use them or it might not. Only do each of the following steps if you need the functionality that package provides.
## BackupManager
diff --git a/3.5/installation.md b/3.5/installation.md
index e76efa40..c9eaa2c1 100644
--- a/3.5/installation.md
+++ b/3.5/installation.md
@@ -7,7 +7,7 @@
If you can run Laravel 5.6, you can install Backpack. Backpack does _not_ have additional requirements. For the following process, we assume:
-- you have a working installation of [Laravel 5.7](https://laravel.com/docs/5.7#installing-laravel) or [Laravel 5.6](https://laravel.com/docs/5.6#installing-laravel) (an existing project is fine, you don't need a *fresh* Laravel install);
+- you have a working installation of [Laravel 5.7](https://laravel.com/docs/5.7#installing-laravel) or [5.6](https://laravel.com/docs/5.6#installing-laravel) (an existing project is fine, you don't need a *fresh* Laravel install);
- you have put your database and email credentials in your .ENV file;
diff --git a/3.5/introduction.md b/3.5/introduction.md
index 44697be4..b639be19 100644
--- a/3.5/introduction.md
+++ b/3.5/introduction.md
@@ -32,14 +32,14 @@ php artisan backpack:base:add-sidebar-content "
### Requirements
- - Laravel 5.6 or 5.7
+ - Laravel 5.7 or 5.6
- PHP 7.1.3+
- - MySQL (recommended) / PosgreSQL / SQLite / SQL Server
+ - MySQL (recommended) / PostgreSQL / SQLite / SQL Server
### Screenshots
-Take a look at [our homepage](http://www.backpackforlaravel.com/).
+Take a look at [our homepage](https://backpackforlaravel.com/).
### Demo
@@ -54,7 +54,7 @@ Backpack has never had a critical vulnerability/hack. But there _have_ been impo
### Maintenance
-Backpack 3.5 is the current version, and is being actively maintained by Backpack's creator, [Cristian Tabacitu](http://tabacitu.ro), with the help of a wonderful community of Backpack veterans. [See all contributors](https://github.com/Laravel-Backpack/CRUD/graphs/contributors).
+Backpack 3.5 is the current version, and is being actively maintained by Backpack's creator, [Cristian Tabacitu](https://tabacitu.ro), with the help of a wonderful community of Backpack veterans. [See all contributors](https://github.com/Laravel-Backpack/CRUD/graphs/contributors).
### License
@@ -75,5 +75,5 @@ For more, please see:
We heavily recommend you spend a little time to understand Backpack, and only afterwards install and use it. Currently your options are:
- **[Text Tutorial](/docs/{{version}}/getting-started-basics)** - 23 minutes
-- **[Email Tutorial](http://backpackforlaravel.com/getting-started-emails)** - 1 email per day, for 5 days, 5 minutes each
+- **[Email Tutorial](https://backpackforlaravel.com/getting-started-emails)** - 1 email per day, for 5 days, 5 minutes each
- **Video Tutorial** - working on it
diff --git a/3.5/release-notes.md b/3.5/release-notes.md
index 9f56399f..0ccf1ed6 100644
--- a/3.5/release-notes.md
+++ b/3.5/release-notes.md
@@ -18,8 +18,8 @@ Here are the main differences between [Backpack 3.4](https://backpackforlaravel.
- added ```php artisan backpack:base:publish-middleware``` command; [details here](https://github.com/Laravel-Backpack/Base/pull/334);
- upon installation, ```BackpackUser``` model and ```CheckIfAdmin``` middleware are published by default - so they can EASILY be customized; [details here](https://github.com/Laravel-Backpack/Base/pull/334);
- two separate files: ```inc/topbar_left_content.blade.php``` and ```inc/topbar_right_content.blade.php``` where the user can specify additional content for the top menu; [details here](https://github.com/Laravel-Backpack/Base/pull/302); [documentation here](docs/{{version}}/base-how-to#use-separate-login-register-forms-for-users-and-admins);
-- error views now use a layout file, so it’s easier to customize how all error pages look; defaut error view design is now consistent with default AdminLTE design;
-- split ```layout``` into multiple views (```head```, ```scripts```), so it’s easier to customize just one part of it;
+- error views now use a layout file, so it's easier to customize how all error pages look; defaut error view design is now consistent with default AdminLTE design;
+- split ```layout``` into multiple views (```head```, ```scripts```), so it's easier to customize just one part of it;
- ```backpack_url()``` can now take parameters, just like ```url()```;
- password reset page is a clear two-step process, and pre-populates the email field; big UX improvement for something that is often used by inexperienced users (they're the ones losing their password);
@@ -29,7 +29,7 @@ Here are the main differences between [Backpack 3.4](https://backpackforlaravel.
- default CSS file now uses ```body.skin-purple``` as a selector, to fix the paint glitch, where buttons and other things were shown blue, then changed to purple, when using the purple skin;
- now using jquery and font-awesome from adminlte package instead of CDN;
- language folders like ```da_DK```, ```fr_CA``` and ```pt_br``` have been duplicated into their standardized form (```da-DK```, ```fr-CA``` and ```pt-BR```); introduced notice that the old folders will be deprecated in the next release;
-- the footer is now transparent; it is not a primary piece of content, it shouldn’t stand out;
+- the footer is now transparent; it is not a primary piece of content, it shouldn't stand out;
### Removed
- removed Laravel 5.5 support;
diff --git a/3.5/upgrade-guide.md b/3.5/upgrade-guide.md
index 01206bcc..9c1d10e9 100644
--- a/3.5/upgrade-guide.md
+++ b/3.5/upgrade-guide.md
@@ -107,7 +107,7 @@ Search any custom files you use in your admin panels for ```Auth::```. You _migh
#### Step 5
-If you haven’t created any custom **error views**, re-publish the ```resources/views/errors``` folder. Please note that this will delete your existing folder.
+If you haven't created any custom **error views**, re-publish the ```resources/views/errors``` folder. Please note that this will delete your existing folder.
```bash
php artisan vendor:publish --provider="Backpack\Base\BaseServiceProvider" --tag=errors --force
@@ -146,7 +146,7 @@ And change the overlays path in your ```config/backpack/base.php``` file (```ove
#### Step 7
-**ALL Backpack/Base views have suffered some changes**. If you’ve published/customized/overwritten any of the Backpack/Base views, please [take a look at the changes](https://github.com/Laravel-Backpack/Base/pull/324/files) and implement them in your file. To rephrase this:
+**ALL Backpack/Base views have suffered some changes**. If you've published/customized/overwritten any of the Backpack/Base views, please [take a look at the changes](https://github.com/Laravel-Backpack/Base/pull/324/files) and implement them in your file. To rephrase this:
- if you have files in you ```resources/views/vendor/backpack/base/``` it means you're actually using _that_ file, instead of the new one provided by upgrading to Base 1.0.0;
- you need to either (A) delete that file and forfeit any changes you've made (Backpack will pick up the new one) OR (B) apply the changes yourself
diff --git a/3.6/add-ons-community.md b/3.6/add-ons-community.md
new file mode 100644
index 00000000..6178e504
--- /dev/null
+++ b/3.6/add-ons-community.md
@@ -0,0 +1,17 @@
+# Community Add-ons
+
+---
+
+We've been blessed with a wonderful, supportive community, where developers help each other out. Some of them have even created add-ons, so that we can all reuse functionality across our projects:
+
+| Name | Description | License |
+| ------------- |:-------------:| --------:|
+| [AbbyJanke/BackpackBlog](https://github.com/AbbyJanke/BackpackBlog) | blog front-end and back-end | - |
+| [AbbyJanke/BackpackMeta](https://github.com/AbbyJanke/BackpackMeta) | helps create meta options for extending core functions | - |
+| [eduardoarandah/LogViewer](https://github.com/eduardoarandah/backpacklogviewer) | advanced logging interface - brings the ArcaneDev/LogViewer package to Backpack admin panels | [MIT](https://github.com/eduardoarandah/backpacklogviewer/blob/master/LICENSE.md) |
+| [eduardoarandah/UserManager](https://github.com/eduardoarandah/UserManager) | manage the default Laravel users table (no permissions, no groups) | [MIT](https://github.com/eduardoarandah/UserManager/blob/master/LICENSE) |
+| [novius/laravel-backpack-redirection-manager](https://github.com/novius/laravel-backpack-redirection-manager) | manage missing page redirections | [AGPL-3](https://github.com/eduardoarandah/backpacklogviewer/blob/master/LICENSE.md) |
+| [novius/laravel-backpack-translation-manager](https://github.com/novius/laravel-backpack-translation-manager) | manage translations stored in the database | - |
+| [updivision/estarter-ecommerce-for-laravel](https://github.com/updivision/estarter-ecommerce-for-laravel) | complete e-commerce back-end (products, categories, clients, orders) | [YUMMY](https://github.com/updivision/estarter-ecommerce-for-laravel/blob/master/LICENSE.md) |
+| [webfactor/laravel-generators](https://github.com/webfactor/laravel-generators) | CLI to generate migrations, factories, seeders, CRUDs, lang files, route files | [MIT](https://github.com/webfactor/laravel-generators/blob/master/LICENSE.md) |
+| [seandowney/laravel-backpack-gallery-crud](https://github.com/seandowney/laravel-backpack-gallery-crud) | manage photo galleries | [MIT](https://github.com/seandowney/laravel-backpack-gallery-crud/blob/master/LICENSE.md) |
diff --git a/3.6/add-ons-how-to-create-a-backpack-addon.md b/3.6/add-ons-how-to-create-a-backpack-addon.md
new file mode 100644
index 00000000..9c8baa14
--- /dev/null
+++ b/3.6/add-ons-how-to-create-a-backpack-addon.md
@@ -0,0 +1,216 @@
+# How to Create an Add-on
+
+---
+
+
+### Intro
+
+There's nothing special about add-ons. They are simple Composer packages.
+
+But for consistency, we recommend you follow our simple folder structure. Our rule of thumb: **organize your ```src``` folder like it were a Laravel application**. We do this because it's easier for users to understand how the package works, and it makes it easy to copy-paste the code inside their apps and modify, for complicated use cases. That way, add-ons can be kept super-simple, with everybody adding functionality _in their own apps_. Example folder structure:
+- [src]
+ - [app]
+ - [Http]
+ - [Models]
+ - [Requests]
+ - [database]
+ - [migrations]
+ - [seeds]
+ - [routes]
+ - YourPackageNameServiceProvider.php
+- [tests]
+- composer.json
+- CHANGELOG.md
+- LICENSE.md
+- README.md
+
+Requirements:
+- a working installation of the [Backpack demo](https://github.com/laravel-backpack/demo)
+- 1-2 hours
+
+
+## Step 1. Create a package
+
+### Install Backpack Demo
+
+We're going to use [the Backpack demo project](https://github.com/laravel-backpack/demo) to create a new package. Follow the instructions in [the Installation chapter](https://github.com/laravel-backpack/demo#install).
+
+Any Laravel & Backpack app would work. But since you're going to require packages that you only need during package development, and make various changes to app files, we recommended you _create_ the package using a Backpack demo. After the package is online (with zero functionality), you will _install_ it in a real application, and _modify_ it right there, in the ```vendor``` folder. You will then delete this Backpack demo project.
+
+
+### Install CLI tool
+
+We're going to use [Jeroen-G/laravel-packager](https://github.com/Jeroen-G/laravel-packager) to generate a new package. Follow the instructions in the Installation chapter.
+
+### Generate Package Files
+
+Next up, decide what your vendor name will be. This is NOT the package name, it's the name all your packages will reside under. For example, Laravel uses "laravel". Backpack for Laravel uses "backpack". Jeffrey Way uses "way". If unsure, use your github username for the vendor name. That's what people usually do, if they don't run a company / brand.
+
+Then decide what your package name will be. Ex: ```newscrud```, ```usermanager```, etc.
+
+Then run:
+```
+php artisan packager:new myvendor mypackage
+```
+
+This will create a ```/packages/``` folder in your root directory, where your package will be stored, so you can build it. It will also pull [a very basic package template](https://github.com/thephpleague/skeleton), created by thephpleague. Everything you have right now is in ```packages/myvendor/mypackage``` - check it out.
+
+### Customize Generated Files
+
+Now let's customise it and add some boilerplate code, everything that most Laravel Packages will need. Replace everything you need in ```composer.json```, ```CHANGELOG.md```, ```CONTRIBUTING.md```, ```LICENSE.md```, ```README.md```. Make it yours.
+
+If you want to use Laravel package auto-discovery (and why wouldn't you), make sure to include the Laravel providers section in your ```composer.json```'s ```extra``` section, like so:
+```
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ },
+ "laravel": {
+ "providers": [
+ "Backpack\\NewsCRUD\\NewsCRUDServiceProvider"
+ ]
+ }
+ }
+```
+
+In ```/src/``` you'll find your service provider. That's where your package's logic is, but it's empty. Use this Service Provider template and replace ```League``` with your ```myvendor``` and ```Skeleton``` with your ```mypackage```. Your package will probably need some Controllers, routes and config files.
+
+### Create The Files Your Package Needs
+
+Here are a few commands that could help you do that:
+
+```bash
+# make sure everything is inside your src folder
+cd src/
+
+# to create a controller
+echo "app/Http/Controllers/ControllerName.php
+
+# to create a request file
+echo "app/Http/Requests/EntityRequest.php
+
+# to create a route file
+echo "routes/mypackage.php
+
+# to create a config file
+echo "config/mypackage.php
+
+# to create a views folder
+mkdir resources/views/
+```
+
+You use the routes, config and controller files just like you use the ones in your application. Nothing changes there. But remember that all classes should have the package's namespace:
+
+```php
+namespace MyVendor\MyPackage\Http\Controllers;
+```
+
+### Make Sure Your Laravel App Loads The Package
+
+Add your service provider to your app's ```/config/app.php```
+
+If not, add it:
+```
+"MyVendor\MyPackage\MyPackageServiceProvider",
+```
+
+Check that you autoload your package in composer.json:
+```
+"autoload" : {
+ "psr-4": {
+ "Domain\\PackageName\\": "packages/Domain/PackageName/src"
+ }
+},
+```
+
+Let's recreate the autoload
+```
+cd ../../../..
+composer dump-autoload
+```
+
+If you have a config file to publish, do:
+```
+php artisan vendor:publish
+```
+
+Now test it. Start by doing a ```dd('testing)``` in your service provider's ```boot()``` method. If your package is working fine, I recommend you put it online first, even before it does _anything useful_. You'll get the setup out of the way, and be able to focus on code. Plus, you'll be able to install it in a _real_ Backpack application, and edit it from the ```vendor/myvendor/mypackage``` folder (and push to your git remote).
+
+---
+
+
+## Step 2. Put it on GitHub
+
+```
+cd packages/domain/packagename/
+git init
+git add .
+git commit -m "first commit"
+```
+
+Create [a new GitHub repository](https://github.com/new).
+
+```
+git remote add origin git@github.com:yourusername/yourrepository.git
+git push -u origin master
+git tag -a 1.0.0 -m 'First version'
+git push --tags
+```
+
+Tags are the way you will version your package, so it's important you do it. People will only be able to get updates if you tag them.
+
+---
+
+
+## Step 3. Put it on Packagist
+
+On [Packagist.org](https://packagist.org), submit a new package. Enter your package's GitHub URL and click Check. If any errors occur, follow the onscreen instructions.
+
+When you're done, you'll be taken to your packagist page, where you'll probably get a notice like this:
+
+>This package is not auto-updated. Please set up the [GitHub Service Hook](https://packagist.org/profile/) for Packagist so that it gets updated whenever you push!
+
+Let's take care of that. Click that link, get your API token and go to your package's GitHub page, in ```Settings / Webhooks & Services / Add a new service```. Search for Packagist. Enter your username and the token and hit Submit. Your error in Packagist should disappear in 5–10 minutes.
+
+Congrats! You now have a working package online. You can now require it with composer.
+
+
+---
+
+
+## Step 4. Install in a Real Project
+
+We've instructed you to create the package in a disposable backpack-demo install. If you've done so, you can now install your package **in your _real_ project**:
+
+```bash
+composer require myvendor/mypackage --prefer-source
+```
+
+Using the ```prefer-source``` flag will actually _clone the git repo_ inside your ```vendor/myvendor/mypackage``` directory. So you can do:
+
+```bash
+cd /vendor/myvendor/mypackage
+git checkout master
+```
+
+Then after each change you want to publish, you would mark that change in your ```CHANGELOG.md``` file and do:
+```bash
+git pull origin master
+git add .
+git commit -am "fixes #14189 - some problem or feature with an id"
+git tag 1.0.3
+git push origin master --tags
+```
+
+---
+
+**That's it. Go build your package!** If you end up with something you like, please share it with the community in the [Gitter Chatroom](https://gitter.im/BackpackForLaravel/Lobby), and add it to [the Community Add-Ons page](/docs/{{version}}/add-ons-community), so other people know about it (_login, then click Edit in the top-right corner of the page_).
+
+You can now delete the Backpack project, and the database you've created for it (if any).
+
+For extra reading credits, these are the resources we've used to create this guide:
+- https://laravel.com/docs/packages
+- https://laracasts.com/discuss/channels/tips/developing-your-packages-in-laravel-5
+- https://github.com/jaiwalker/setup-laravel5-package
+- https://github.com/Jeroen-G/laravel-packager
+- https://laracasts.com/lessons/package-development-101
\ No newline at end of file
diff --git a/3.6/add-ons-official.md b/3.6/add-ons-official.md
new file mode 100644
index 00000000..429a1a02
--- /dev/null
+++ b/3.6/add-ons-official.md
@@ -0,0 +1,15 @@
+# Official Add-ons
+
+In addition to our core packages (Base and CRUD), we've developed a few packages you can install or download, that treat common use cases.
+
+
+ - [PermissionManager](https://github.com/Laravel-Backpack/PermissionManager) - interface to manage users & permissions, using [spatie/laravel-permission](https://github.com/spatie/laravel-permission); ```free```
+ - [Settings](https://github.com/Laravel-Backpack/Settings) - interface to edit site-wide settings; ```free```
+ - [PageManager](https://github.com/Laravel-Backpack/PageManager) - interface to manage content for custom pages, using page templates; ```free```
+ - [MenuCRUD](https://github.com/Laravel-Backpack/MenuCRUD) - interface to create/update/reorder menu items; ```free```
+ - [NewsCRUD](https://github.com/Laravel-Backpack/NewsCRUD) - interface to manage news articles, categories and tags; ```free```
+ - [LogManager](https://github.com/Laravel-Backpack/LogManager) - interface to preview Laravel log files; ```free```
+ - [BackupManager](https://github.com/Laravel-Backpack/BackupManager) - interface to backup your files & db using [spatie/laravel-backup](https://github.com/spatie/laravel-backup); ```free```
+
+
+>**These add-ons only provide basic functionality.** What will be enough for _most_ projects. They do not intend to be a complete solution for all use cases. If you need to customize a package for your specific use case, you can easily do that, by copy-pasting their code in your project and modifying it. Every official package has been created with this in mind, has a very simple architecture, uses Backpack best practices. Find the "extend" section in each of their docs for more about this.
\ No newline at end of file
diff --git a/3.6/base-about.md b/3.6/base-about.md
new file mode 100644
index 00000000..e05c2926
--- /dev/null
+++ b/3.6/base-about.md
@@ -0,0 +1,174 @@
+# About Backpack\Base
+
+---
+
+Backpack/Base kickstarts your admin panel building by:
+- pulling in the AdminLTE HTML theme, based on Bootstrap 3;
+- providing different views and functionality for authentication;
+- integrating [prologue/alerts](https://github.com/prologuephp/alerts) and and [pnotify](https://github.com/sciactive/pnotify) for showing notification bubbles upon error/success/warning/info;
+- providing pretty error pages for most common errors;
+- providing a horizontal menu and a side menu you can customize;
+- providing a place for your admin to to change his email/name/password;
+- providing a few helpers you can use throughout your admin panel;
+
+For the simplest projects, you will never need to know how it works, never need to customize anything but the ```config/backpack/base.php``` file. But here's how everything works, below.
+
+
+## Layout & Design
+
+
+### General
+
+Backpack\Base pulls in the free [AdminLTE](https://adminlte.io/themes/AdminLTE/index2.html) theme and adds our own CSS file on top, for a few cosmetic improvements. We've chosen AdminLTE because it provides design blocks for all common features of an administration panel. When you decide to build something from scratch, you can just use its HTML blocks - no designer needed.
+
+
+### Published Views
+
+After installation, you'll notice Backpack has added one or more files to ```resources/views/vendor/backpack/base/```. By default, it only publishes:
+- ```inc/sidebar_content.blade.php```;
+- ```dashboard.blade.php```;
+
+Those files are used to show the contents of the menu to the left (sidebar), and the first page the admin sees when logging in (dashboard). They've been published there so that you can easily modify their contents.
+
+
+### Unpublished Views
+
+You can change any blade file to your own needs. Determine what file you'd need to modify if you were to edit directly in the project's vendor folder, then go to ```resources/views/vendor/backpack/base``` and create a file with the exact same name. Backpack\Base will use this new file, instead of the one in the package.
+
+For example, if you want to add an item to the top menu, you could just create a file called ```resources/views/vendor/backpack/base/inc/menu.php```. Backpack will now use this file's contents, instead of ```vendor/backpack/base/src/resources/views/inc/menu.php```
+
+
+### Folder Structure
+
+If you'll take a look inside any Backpack package, you'll notice the ```src``` directory is organised like a standard Laravel app. This is intentional. It should help you easily understand how the package works, and how you can overwrite/customize its functionality.
+
+- ```app```
+ - ```Console```
+ - ```Commands```
+ - ```Http```
+ - ```Controllers```
+ - ```Middleware```
+ - ```Requests```
+ - ```Notifications```
+- ```config```
+- ```resources```
+ - ```lang```
+ - ```views```
+- ```routes```
+
+
+## Authentication
+
+When installed, Backpack provides a way for admins to login, recover password and register (don't worry, register is only enabled on ```localhost```). It does so with its own authentication controllers, models and middleware. If you have regular end-users (not admins), you can keep the _user_ authentication completely separate from _admin_ authentication. You can change which model, middleware classes inside the ```config/backpack/base.php``` config file.
+
+
+> **The ```BackpackUser``` model extends Laravel's default ```App\User``` model**. This assumes you weren't already using this model, or the ```users``` table, for anything else. If you were, please read below.
+
+
+### Using a Different User Model
+
+If you want to use a different User model than ```App\User``` or you've changed its location, please:
+- take a look at [```\Backpack\Base\app\Models\BackpackUser::class```](https://github.com/Laravel-Backpack/Base/blob/master/src/app/Models/BackpackUser.php);
+- include the methods there in _your_ user model; they're important for password recovery;
+- tell Backpack to use _your_ model in ```config/backpack/base.php```;
+
+
+### Having Both Regular Users and Admins
+
+If you already use the ```users``` table to store end-users (not admins), you will need a way to differentiate admins from regular users. Backpack does not force one method on you. Here are two methods we recommend, below:
+- (A) adding an ```is_admin``` column to your ```users``` table, then creating a middleware that checks that that column is true. You can use ```\Backpack\Base\app\Http\Middleware\CheckIfAdmin::class``` as a starting point;
+- (B) using the [PermissionManager](https://github.com/Laravel-Backpack/PermissionManager) extension - this will also add groups and permissions;
+
+Please remember to tell Backpack to use _this new middleware_ to check if a logged in user is an admin, inside ```config/backpack/base.php```.
+
+
+### Routes
+
+By default, all administration panel routes will be behind an ```/admin/``` prefix, and under an ```admin``` middleware. You can change that inside ```config/backpack/base.php```. Inside your _custom admin pages or admin features_, please:
+- use ```backpack_auth()``` instead of ```auth()```;
+- use ```backpack_url()``` instead of ```url()```;
+
+This will make sure you're using the prefix & middleware that you've defined in ```config/backpack/base.php```. In case you decide to make changes there later, you won't need to change anything else. There are also [other backpack helpers you can use](#helpers).
+
+
+## Admin Account
+
+When logged in, the admin can click his/her name to go to his "account" page. There, they will be able to do a few basic operations: change name, email or password.
+
+
+### Change Name and Email
+
+Changing name and email is done inside ```Backpack\Base\app\Http\Controllers\Auth\MyAccountController```, using the ```getAccountInfoForm()``` and ```postAccountInfoForm()``` methods. If you want to change how this works, we recommend you create a ```routes/backpack/base.php``` file, copy-paste all Backpack\Base routes there and change whatever you need. You can then point the route to your own controller, where you can do whatever you want.
+
+If you only want to add a few new inputs, you can do that by creating a file in ```resources/views/vendor/backpack/base/auth/account/update_info.blade.php``` that uses code from the same file in the Backpack package, but adds the inputs you need. Remember to also make these fields ```$fillable``` in your User model.
+
+
+### Change Password
+
+Password changing is done inside ```Backpack\Base\app\Http\Controllers\Auth\MyAccountController```, using the ```getChangePasswordForm()``` and ```postChangePasswordForm()``` methods. If you want to change how this works, we recommend you create a ```routes/backpack/base.php``` file, copy-paste all Backpack\Base routes there and change whatever you need. You can then point the route to your own controller, where you can do whatever you want.
+
+
+## Notification Bubbles
+
+
+### Triggering Notification Bubbles in PHP
+
+We use [prologue/alerts](https://github.com/prologuephp/alerts#adding-alerts-through-alert-levels) to trigger notifications. Check out its documentation for the entire syntax. Basic examples:
+
+```php
+public function foo()
+{
+ \Alert::info('This is a blue bubble.');
+ \Alert::warning('This is a yellow/orange bubble.');
+ \Alert::error('This is a red bubble.');
+ \Alert::success('This is a green bubble.');
+ \Alert::success('Got it This is an HTML message.');
+
+
+ // the layout will make sure to show your notifications
+ return view('some_view');
+}
+
+public function bar()
+{
+ \Alert::success('You have successfully logged in')->flash();
+
+ // please note the above flash() method; this will store your notification in a session variable, so that you can redirect to another page, but the notification will still be shown (on the page you redirect to)
+ return Redirect::to('some-url');
+}
+```
+
+
+### Triggering Notification Bubbles in JavaScript
+
+We use [PNotify](https://sciactive.com/pnotify/) to show notifications from JavaScript, on the same page. Check out its page for more detailed use. Basic example:
+
+```php
+new PNotify({
+ title: "Operation successful",
+ text: "You have deleted the internet.",
+ type: "success"
+});
+
+// available types: success, info, warning, error
+// PLEASE NOTE it's "error" here, not "danger"
+```
+
+
+## Helpers
+
+You can use these helpers anywhere in your app (models, views, controllers, requests, etc), except the config files, since the config files are loaded _before_ the helpers.
+
+- **```backpack_url(http://github.com/$path)```** - Use this helper instead of ```url()``` to generate paths with the admin prefix prepended.
+- **```backpack_auth()```** - Returns the Auth facade, using the current Backpack guard. Basically a shorthand for ```\Auth::guard(backpack_guard_name())```. Use this instead of ```auth()``` inside your admin panel pages.
+- **```backpack_middleware()```** - Returns the key for the admin middleware. Default is ```admin```.
+- ```backpack_authentication_column()``` - Returns the username column. The Laravel and Backpack default is ```email```.
+- ```backpack_users_have_email()``` - Tests that the ```email``` column exists on the users table and returns true/false.
+- ```backpack_avatar($user)``` - Receives a user object and returns a path to an avatar image, according to the preferences in the config file (gravatar, placeholder or custom).
+- ```backpack_guard_name()``` - Returns the guard used for Backpack authentication.
+- ```backpack_user()``` - Returns the current Backpack user, if logged in. Basically a shorthand for ```\Auth::guard(backpack_guard_name())->user()```. Use this instead of ```auth()->user()``` inside your admin pages.
+
+
+## Error Pages
+
+When installing Backpack, a few error views are published into ```resources/views/errors```, if you don't already have other files there. This will make sure that, if a user gets an HTTP error, at least it will look decent. Error pages are provided for the following error codes: ```400```, ```401```, ```403```, ```404```, ```405```, ```408```, ```429```, ```500```, ```503```.
diff --git a/3.6/base-how-to.md b/3.6/base-how-to.md
new file mode 100644
index 00000000..7516264e
--- /dev/null
+++ b/3.6/base-how-to.md
@@ -0,0 +1,237 @@
+# How To for Backpack\Base
+
+---
+
+
+## Customize the menu or sidebar
+
+During installation, Backpack publishes a few files in you ```resources/views/vendor/backpack/base/inc``` folder. In there, you'll also find:
+- ```sidebar_content.php```
+- ```topbar_left_content.php```
+- ```topbar_right_content.php```
+
+Change those files as you please.
+
+
+## Customize the dashboard
+
+The dashboard is shown from ```Backpack\Base\app\Http\Controller\AdminController.php::dashboard()```. If you take a look at that method, you'll see that the only thing it does is to set a title from the language file, and return a view: ```backpack::dashboard```.
+
+In order to place something else inside that view, simply publish that view in your project, and Backpack will pick it up, instead of the one in the package. Create a ```resources/views/vendor/backpack/base/dashboard.blade.php``` file:
+
+```html
+@extends('backpack::layout')
+
+@section('header')
+
+
+@endsection
+```
+
+To use information from the database, [use view composers](https://laravel.com/docs/5.7/views#view-composers) to push variables inside this view, when it's loaded. Or better yet, load all your dashboard information using AJAX calls, if you're loading charts, reports, etc, and the DB queries might take a long time.
+
+Take a look at the [AdminLTE dashboards](https://adminlte.io/themes/AdminLTE/index.html) - you can easily use whatever content block you want from there.
+
+## Customizing the general layout/design
+
+See [the docs](/docs/{{version}}/base-about#layout-design).
+
+## Customizing the Auth controllers
+
+In ```config/backpack/base.php``` you'll find these configuration options:
+
+```php
+ // Set this to false if you would like to use your own AuthController and PasswordController
+ // (you then need to setup your auth routes manually in your routes.php file)
+ 'setup_auth_routes' => true,
+```
+
+You can change both ```setup_auth_routes``` to ```false```. This means Backpack\Base won't register the Auth routes any more, so you'll have to manually register them in your route file, to point to the Auth controllers you want. If you're going to use the Auth controllers that Laravel generates, these are the routes you can use:
+```php
+Route::group(['middleware' => 'web', 'prefix' => config('backpack.base.route_prefix')], function () {
+ Route::auth();
+ Route::get('logout', 'Auth\LoginController@logout');
+});
+```
+
+
+## Customize the routes
+
+### Custom routes - option 1
+
+You can place a new routes file in your ```app/routes/backpack/base.php```. If a file is present there, no default Backpack\Base routes will be loaded, only what's present in that file. You can use the routes file ```vendor/backpack/base/src/resources/views/base.php``` as an example, and customize whatever you want.
+
+### Custom routes - option 2
+
+In ```config/backpack/base.php``` you'll find these configuration options:
+
+```php
+
+ /*
+ |--------------------------------------------------------------------------
+ | Routing
+ |--------------------------------------------------------------------------
+ */
+
+ // The prefix used in all base routes (the 'admin' in admin/dashboard)
+ 'route_prefix' => 'admin',
+
+ // Set this to false if you would like to use your own AuthController and PasswordController
+ // (you then need to setup your auth routes manually in your routes.php file)
+ 'setup_auth_routes' => true,
+
+ // Set this to false if you would like to skip adding the dashboard routes
+ // (you then need to overwrite the login route on your AuthController)
+ 'setup_dashboard_routes' => true,
+```
+
+In order to completely customize the auth routes, you can change both ```setup_auth_routes``` and ```setup_dashboard_routes``` to ```false```. This means Backpack\Base won't register any routes any more, so you'll have to manually register them in your route file. Here's what you can use to get started:
+```php
+Route::group(['middleware' => 'web', 'prefix' => config('backpack.base.route_prefix', 'namespace' => 'Backpack\Base\app\Http\Controllers')], function () {
+ Route::auth();
+ Route::get('logout', 'Auth\LoginController@logout');
+ Route::get('dashboard', 'AdminController@dashboard');
+ Route::get('/', 'AdminController@redirect');
+});
+```
+
+
+## Customize the look and feel of AdminLTE (using CSS)
+
+In ```config/app.php``` you should have a config option that looks like this:
+
+```php
+ // Overlays - CSS files that change the look and feel of the admin panel
+ 'overlays' => [
+ 'vendor/backpack/base/backpack.bold.css',
+ // 'vendor/backpack/base/backpack.content.is.king.css', // opinionized borderless alternative
+ ],
+```
+
+If you don't (it was added in Base 0.9.9), you can create it.
+
+This config option allows you to add CSS files that add style _on top_ of AdminLTE, to make it look different. Our ```backpack.bold.css``` file is included by default, which makes AdminLTE look more modern. But if you want your backend to match your front-end, you can create a CSS file anywhere inside your ```public``` folder, and add it here.
+
+For example, if you're using the [Stack HTML template](https://themeforest.net/item/stack-multipurpose-html-with-page-builder/19337626?ref=medium_rare) on your front-end, you can just [add this overlay](https://gist.github.com/tabacitu/4f7eae0519e37aef46cbb959b8ab01a9) to make AdminLTE look very similar.
+
+
+## Use separate login/register forms for users and admins
+
+This is a default in Backpack\Base 1.0.0.
+
+Backpack's authentication uses a completely separate authentication driver, provider, guard and password broker. They're all named ```backpack```, and registered in the vendor folder, invisible to you.
+
+If you need a separate login for user, just go ahead and create it. [Add the Laravel authentication, like instructed in the Laravel documentation](https://laravel.com/docs/5.7/authentication#authentication-quickstart): ```php artisan make:auth```. You'll then have:
+- the user login at ```/login``` -> using the AuthenticationController Laravel provides
+- the admin login at ```/admin/login``` -> using the AuthenticationControllers Backpack provides
+
+The user login will be using Laravel's default authentication driver, provider, guard and password broker, from ```config/auth.php```.
+
+Backpack's authentication driver, provider, guard and password broker can easily be overwritten by creating a driver/provider/guard/broker with the ```backpack``` name inside your ```config/auth.php```. If one named ```backpack``` exists there, Backpack will use that instead.
+
+
+## Overwrite Backpack authentication driver, provider, guard or password broker
+
+Backpack's authentication uses a completely separate authentication driver, provider, guard and password broker. Backpack adds them to what's defined in ```config/auth.php``` on runtime, and they're all named ```backpack```.
+
+To change a setting in how Backpack's driver/provider/guard or password broker works, create a driver/provider/guard/broker with the ```backpack``` name inside your ```config/auth.php```. If one named ```backpack``` exists there, Backpack will use that instead.
+
+
+## Use separate sessions for admin&user authentication
+
+This is a default in Backpack\Base 1.0.0.
+
+
+## Login with username instead of email
+
+1. Create a ```username``` column in your users table and add it in ```$fillable``` on your ```User``` model. Best to do this with a migration.
+2. Remove tge UNIQUE and NOT NULL constraints from ```email``` on your table. Best to do this with a migration. Alternatively, delete your ```email``` column and remove it from ```$fillable``` on your ```User``` model. If you already have a CRUD for users, you might also need to delete it from the Request, and from your UserCrudController.
+3. Change your ```config/backpack/base.php``` config options:
+```php
+ // Username column for authentication
+ // The Backpack default is the same as the Laravel default (email)
+ // If you need to switch to username, you also need to create that column in your db
+ 'authentication_column' => 'username',
+ 'authentication_column_name' => 'Username',
+```
+That's it. This will:
+- use ```username``` for login;
+- use ```username``` for registration;
+- use ```username``` in My Account, when a user wants to change his info;
+- completely disable the password recovery (if you've deleted the ```email``` db column);
+
+
+
+## Use your own User model instead of BackpackUser
+
+By default, authentication and everything else inside Backpack is done using the ```Backpack\Base\app\Models\BackpackUser``` model, which extends Laravel's default ```App\User``` model. If you change the location of ```App\User```, or want to use a different User model for whatever other reason, you can do so by
+- changing ```user_model_fqn``` in ```config/backpack/base.php``` to your new class;
+- making sure everything inside ```BackpackUser``` is also inside your new model (this is important for recovering password, etc);
+
+
+
+## Use your own profile image (avatar)
+
+By default, Backpack will use Gravatar to show the profile image for the currently logged in backpack user. In order to change this, you can use the option in ```config/backpack/base.php```:
+```php
+// What kind of avatar will you like to show to the user?
+// Default: gravatar (automatically use the gravatar for his email)
+//
+// Other options:
+// - placehold (generic image with his first letter)
+// - example_method_name (specify the method on the User model that returns the URL)
+'avatar_type' => 'gravatar',
+```
+
+Please note that this does not allow the user to change his profile image.
+
+
+
+## Manually install Base
+
+If for any reason the Backpack/Base installation process fails for you, you can manually run all the commands in the installer, which are listed below. Failure to install can happens sometimes if the user does not have enough permissions (sudo access is needed) or if the composer command is not registered (and ```php composer``` needs to be run instead).
+
+```bash
+# Install backpack/generators
+composer require backpack/generators --dev
+
+# Install laracasts/generators
+composer require laracasts/generators:dev-master --dev
+
+# Publish configs, langs, views and AdminLTE files
+php artisan vendor:publish --provider="Backpack\Base\BaseServiceProvider" --tag="minimum"
+
+# Publish config for notifications - prologue/alerts
+php artisan vendor:publish --provider="Prologue\Alerts\AlertsServiceProvider"
+
+# Generate users table (using Laravel's default migrations)
+php artisan migrate
+
+# Publish the BackpackUser model inside your app/Models directory
+php artisan backpack:base:publish-user-model
+
+# Publish the CheckIfAdmin middleware inside your app/Http/Middleware directory
+php artisan backpack:base:publish-middleware
+```
diff --git a/3.6/crud-api.md b/3.6/crud-api.md
new file mode 100644
index 00000000..1c22bb4a
--- /dev/null
+++ b/3.6/crud-api.md
@@ -0,0 +1,476 @@
+# API
+
+---
+
+Here are all the functions you will be using **inside your EntityCrudController's ```setup()``` method**, grouped by the operation you will most likely use them for.
+
+## Operations
+
+
+### ListEntries
+
+
+#### Columns
+
+Manipulate what columns are shown in the table view.
+
+- **addColumn()** - add a column, at the end of the stack
+```php
+$this->crud->addColumn($column_definition_array);
+```
+
+- **addColumns()** - add multiple columns, at the end of the stack
+```php
+$this->crud->addColumns([$column_definition_array, $another_column_definition_array]);
+```
+
+- **modifyColumn()** - change column attributes
+```php
+$this->crud->modifyColumn($name, $modifs_array);
+```
+
+- **removeColumn()** - remove one column from all operations
+```php
+$this->crud->removeColumn('column_name');
+```
+
+- **removeColumns()** - remove multiple columns from all operations
+```php
+$this->crud->removeColumns(['column_name_1', 'column_name_2']); // remove an array of columns from the stack
+```
+
+- **setColumnDetails()** - change the attributes of one column; alias of ```modifyColumn()```;
+```php
+$this->crud->setColumnDetails('column_name', ['attribute' => 'value']);
+```
+
+- **setColumnsDetails()** - change the attributes of multiple columns; alias of ```modifyColumn()```;
+```php
+$this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
+```
+
+- **setColumns()** - remove previously set columns and only use the ones give now;
+```php
+$this->crud->setColumns();
+// sets the columns you want in the table view, either as array of column names, or multidimensional array with all columns detailed with their types
+```
+
+- **Chained - beforeColumn()** - insert current column _before_ the given column
+```php
+// ------ REORDER COLUMNS
+$this->crud->addColumn()->beforeColumn('name');
+```
+
+- **Chained - afterColumn()** - insert current column _after_ the given column
+```php
+$this->crud->addColumn()->afterColumn('name');
+```
+
+- **Chained - makeFirstColumn()** - make this column the first one in the list
+```php
+$this->crud->addColumn()->makeFirstColumn();
+// Please note: you need to also specify priority 1 in your addColumn statement for details_row or responsive expand buttons to show
+```
+
+
+#### Buttons
+
+- **addButton()** - add a button in the given stack
+```php
+$this->crud->addButton($stack, $name, $type, $content, $position);
+// stacks: top, line, bottom
+// types: view, model_function
+// positions: beginning, end (defaults to 'beginning' for the 'line' stack, 'end' for the others);
+```
+
+- **addButtonFromModelFunction()** - add a button whose HTML is returned by a method in the CRUD model
+```php
+$this->crud->addButtonFromModelFunction($stack, $name, $model_function_name, $position);
+```
+
+- **addButtonFromView()** - add a button whose HTML is in a view placed at ```resources\views\vendor\backpack\crud\buttons```
+```php
+$this->crud->addButtonFromView($stack, $name, $view, $position);
+```
+
+- **removeButton()** - remove a button from whatever stack it's in
+```php
+$this->crud->removeButton($name);
+```
+
+- **removeButtonFromStack()** - remove a button from a particular stack
+```php
+$this->crud->removeButtonFromStack($name, $stack);
+```
+
+
+#### Filters
+
+Manipulate what filters are shown in the table view. Check out [CRUD > Operations > ListEntries > Filters](/docs/{{version}}/crud-filters) to see examples of ```$filter_definition_array```
+
+- **addFilter()** - add a filter to the list view
+```php
+$this->crud->addFilter($filter_definition_array, $values, $filter_logic);
+```
+
+- **modifyFilter()** - change the attributes of a filter
+```php
+$this->crud->modifyFilter($name, $modifs_array);
+```
+
+- **removeFilter()** - remove a certain filter from the list view
+```php
+$this->crud->removeFilter($name);
+```
+
+- **removeAllFilters()** - remove all filters from the list view
+```php
+$this->crud->removeAllFilters();
+```
+
+- **filters()** - get all the registered filters for the list view
+```php
+$this->crud->filters();
+```
+
+
+#### Details Row
+
+Shows a ```+``` (plus sign) next to each table row, so that the user can expand that row and reveal details. You are responsible for creating the view with those details.
+
+- **enableDetailsRow()** - show the + sign in the table view
+```php
+$this->crud->enableDetailsRow();
+// NOTE: you also need to do allow access to the right users:
+$this->crud->allowAccess('details_row');
+// NOTE: you also need to do overwrite the showDetailsRow($id) method in your EntityCrudController to show whatever you'd like in the details row OR overwrite the views/backpack/crud/details_row.blade.php
+$this->crud->setDetailsRowView('your-view');
+```
+
+- **disableDetailsRow()** - hide the + sign in the table view
+```php
+$this->crud->disableDetailsRow();
+```
+
+
+#### Export Buttons
+
+Please note it will only export the current _page_ of results. So in order to export all entries the user needs to make the current page show "All" entries from the top-left picker.
+
+- **enableExportButtons()** - Show export to PDF, CSV, XLS and Print buttons on the table view
+```php
+$this->crud->enableExportButtons();
+```
+
+
+#### Responsive Table
+
+- **disableResponsiveTable()** - stop the listEntries view from showing/hiding columns depending on viewport width
+```php
+$this->crud->disableResponsiveTable();
+```
+
+- **enableResponsiveTable()** - make the listEntries view show/hide columns depending on viewport width
+```php
+$this->crud->enableResponsiveTable();
+```
+
+
+#### Persistent Table
+
+- **enablePersistentTable()** - make the listEntries remember the filters, search and pagination for a user, even if he leaves the page, for 2 hours
+```php
+$this->crud->enablePersistentTable();
+```
+
+- **disablePersistentTable()** - stop the listEntries from remembering the filters, search and pagination for a user, even if he leaves the page
+```php
+$this->crud->disablePersistentTable();
+```
+
+
+#### Page Length
+
+- **setDefaultPageLength()** - change the number of items per page in the list view
+```php
+$this->crud->setDefaultPageLength(10);
+```
+
+- **setPageLengthMenu()** - change the entire page length menu in the list view
+```php
+$this->crud->setPageLengthMenu([100, 200, 300]);
+```
+
+
+#### Actions Column
+
+- **setActionsColumnPriority()** - make the actions column (in the table view) hide when not enough space is available, by giving it an unreasonable priority
+```php
+$this->crud->setActionsColumnPriority(10000);
+```
+
+
+#### Custom / Advanced Queries
+
+- **addClause()** - change what entries are shown in the table view; this allows _developers_ to forcibly change the query used by the table view, as opposed to filters, that allow _users_ to change the query with new inputs;
+```php
+$this->crud->addClause('active'); // apply local scope
+$this->crud->addClause('type', 'car'); // apply local dynamic scope
+$this->crud->addClause('where', 'name', '=', 'car');
+$this->crud->addClause('whereName', 'car');
+$this->crud->addClause('whereHas', 'posts', function($query) {
+ $query->activePosts();
+ });
+```
+
+- **groupBy()** - shorthand to add a **groupBy** clause to the query
+```php
+$this->crud->groupBy();
+```
+
+- **limit()** - shorthand to add a **limit** clause to the query
+```php
+$this->crud->limit();
+```
+
+- **orderBy()** - shorthand to add an **orderBy** clause to the query
+```php
+$this->crud->orderBy();
+```
+
+
+### Show
+
+Use [the same Columns API as for the ListEntries operation](#columns-api), but inside your ```show()``` method.
+
+
+### Create & Update Operations
+
+Manipulate what fields are shown in the create / update forms. Check out [CRUD > Operations > Create & Update > Fields](/docs/{{version}}/crud-fields) in the docs to see examples of ```$field_definition_array```.
+
+**Note:** The last parameter is always the form - ```create``` or ```update```. If missing, it's assumed ```both```.
+
+- **addField()** - add one field to the create / update or both forms
+```php
+$this->crud->addField($field_definition_array, 'update/create/both');
+$this->crud->addField('db_column_name', 'update/create/both'); // a lazy way to add fields: let the CRUD decide what field type it is and set it automatically, along with the field label
+```
+
+- **addFields()** - add multiple fields to the create / update or both forms
+```php
+$this->crud->addFields($array_of_fields_definition_arrays, 'update/create/both');
+```
+
+- **modifyField()** - change the attributes of an existing field
+```php
+$this->crud->modifyField($name, $modifs_array, 'update/create/both');
+```
+
+- **removeField()** - remove a given field from a given operation
+```php
+$this->crud->removeField('name', 'update/create/both');
+```
+
+- **removeFields()** - remove multiple fields from a given operation
+```php
+$this->crud->removeFields($array_of_names, 'update/create/both');
+```
+
+- **removeAllFields()** - remove all registered fields from both create and update operations
+```php
+$this->crud->removeAllFields();
+```
+- **Chained - beforeField()** - add a field _before_ a given field
+```php
+$this->crud->addField()->beforeField('name');
+```
+
+- **Chained - afterField()** - add a field _after_ a given field
+```php
+$this->crud->addField()->afterField('name');
+```
+
+- **setRequiredFields()** - check the FormRequests used in this EntityCrudController for required fields, and add an asterisk to them in the create or edit forms
+```php
+$this->crud->setRequiredFields(StoreRequest::class, 'create');
+$this->crud->setRequiredFields(UpdateRequest::class, 'edit');
+```
+
+
+### Reorder
+
+Show a reorder button in the table view, next to Add. Provides an interface to reorder & nest elements, provided the ```parent_id```, ```lft```, ```rgt```, ```depth``` columns are in the database, and ```$fillable``` on the model.
+
+- **enableReorder()** - enable the Reorder functionality
+```php
+$this->crud->enableReorder('label_name', 3);
+// NOTE: the second parameter is the maximum nesting depth; this example will prevent the user from creating trees deeper than 3 levels;
+// NOTE: you also need to do allow access to the right users:
+$this->crud->allowAccess('reorder');
+```
+
+- **disableReorder()** - disable the Reorder functionality
+```php
+$this->crud->disableReorder();
+```
+
+- **isReorderEnabled()** - returns ```true```/```false``` if the Reorder operation is enabled or not
+```php
+$this->crud->isReorderEnabled();
+```
+
+
+### Revisions
+
+A.k.a. Audit Trail. Tracks all changes to an entry and provides an interface to revert to a previous state. In order to use this, you also need to ```use \Venturecraft\Revisionable\RevisionableTrait;```. Please check out the [Revision Operation](/docs/{{version}}/crud-operation-revisions) for more info.
+
+```php
+$this->crud->allowAccess('revisions');
+```
+
+
+## All Operations
+
+### Access
+
+Prevent or allow users from accessing different CRUD operations.
+
+- **allowAccess()** - give users access to one or multiple operations
+```php
+$this->crud->allowAccess('list');
+$this->crud->allowAccess(['list', 'create', 'delete']);
+```
+
+- **denyAccess()** - prevent users from accessing one or multiple operations
+```php
+$this->crud->denyAccess('list');
+$this->crud->denyAccess(['list', 'create', 'delete']);
+```
+
+- **hasAccess()** - check if the current user has access to one or multiple operations
+```php
+$this->crud->hasAccess('add'); // returns true/false
+$this->crud->hasAccessOrFail('add'); // throws 403 error
+$this->crud->hasAccessToAll(['create', 'update']); // returns true/false
+$this->crud->hasAccessToAny(['create', 'update']); // returns true/false
+```
+
+### Eager Loading Relationships
+
+- **with()** - when the current entry is loaded (in any operation) also get its relationships, so that only one query is made to the database per entry
+```php
+$this->crud->with('relationship_name');
+```
+
+### Custom Views
+
+- **setShowView()**, **setEditView()**, **setCreateView()**, **setListView()**, **setReorderView()**, **setRevisionsView()**, **setRevisionsTimelineView()**, **setDetailsRowView()** - set the view for a certain CRUD operation or feature
+```php
+// use a custom view for a CRUD operation
+$this->crud->setShowView('your-view');
+$this->crud->setEditView('your-view');
+$this->crud->setCreateView('your-view');
+$this->crud->setListView('your-view');
+$this->crud->setReorderView('your-view');
+$this->crud->setRevisionsView('your-view');
+$this->crud->setRevisionsTimelineView('your-view');
+$this->crud->setDetailsRowView('your-view');
+```
+
+### Getters
+
+- **getEntry()** - get a certain entry of the current model type
+```php
+$this->crud->getEntry($entry_id);
+```
+- **getEntries()** - get all entries using the current CRUD query
+```php
+$this->crud->getEntries();
+```
+
+- **getFields()** - get all fields for a certain operation, or for both
+```php
+$this->crud->getFields('create/update/both');
+```
+
+- **getCurrentEntry()** - get the current entry, for operations that work on a single entry
+```php
+$this->crud->getCurrentEntry();
+// ex: in your update() method, after calling parent::updateCrud()
+```
+
+### Operations
+
+- **getOperation()** - get the name of the operation that is currently being performed
+```php
+$this->crud->getOperation();
+```
+
+- **setOperation()** - set the name of the operation that is currently being performed
+```php
+$this->crud->setOperation('ListEntries');
+```
+
+### Actions
+
+An action is the controller method that is currently being run.
+
+- **getActionMethod()** - returns the method on the controller that was called by the route; ex: ```create()```, ```update()```, ```edit()``` etc;
+```php
+$this->crud->getActionMethod();
+```
+
+- **actionIs()** - checks if the given controller method is the one called by the route
+```php
+$this->crud->actionIs('create');
+```
+
+### Title, Heading, Subheading
+
+- **getTitle()** - get the Title for the create action
+```php
+$this->crud->getTitle('create');
+```
+
+- **getHeading()** - get the Heading for the create action
+```php
+$this->crud->getHeading('create');
+```
+
+- **getSubheading()** - get the Subheading for the create action
+```php
+$this->crud->getSubheading('create');
+```
+
+- **setTitle()** - set the Title for the create action
+```php
+$this->crud->setTitle('some string', 'create');
+```
+
+- **setHeading()** - set the Heading for the create action
+```php
+$this->crud->setHeading('some string', 'create');
+```
+
+- **setSubheading()** - set the Subheading for the create action
+```php
+$this->crud->setSubheading('some string', 'create');
+```
+
+### CrudPanel Basic Info
+
+- **setModel()** - set the Eloquent object that should be used for all operations
+```php
+$this->crud->setModel("App\Models\Example");
+```
+
+- **setRoute()** - set the main route to this CRUD
+```php
+$this->crud->setRoute("admin/example");
+// OR $this->crud->setRouteName("admin.example");
+```
+
+- **setEntityNameStrings()** - set how the entity name should be shown to the user, in singular and in plural
+```php
+$this->crud->setEntityNameStrings("example", "examples");
+```
\ No newline at end of file
diff --git a/3.6/crud-basics.md b/3.6/crud-basics.md
new file mode 100644
index 00000000..a629169e
--- /dev/null
+++ b/3.6/crud-basics.md
@@ -0,0 +1,46 @@
+# Basics
+
+---
+
+Backpack\CRUD provides a fast way to build administration panels - places where your administrators can Create, Read, Update, Delete entries for a specific Eloquent model. **One CRUD Panel provides functionality for one Eloquent Model.**
+
+
+## Requirements
+
+In order to create a CRUD Panel, you'll need:
+- **a table in the database** (and maybe connection tables for relationships);
+- **an Eloquent Model** that points to that db table;
+
+If you don't already have the models, don't worry, Backpack also includes a faster way to generate database migrations and models.
+
+
+## Architecture
+
+A Backpack CRUD Panel uses _the same elements_ you would have created for an administration panel, if you were doing it from scratch:
+- a **controller** - holds the logic for the all operations an admin can perform on that Eloquent model; will be generated in ```app/Http/Controllers/Admin```;
+- a **request** file - used to validate Create and Update forms; will be generated in ```app/Http/Requests```;
+- a resource **route** - points to the controller above; will be generated in ```routes/backpack/custom.php```;
+
+**The only difference** between building it from scratch and using Backpack\CRUD** is that:
+- your controller will be extending ```Backpack\CRUD\app\Http\Controllers\CrudController```**, which already has the logic for a few operations: Create, Update, Delete, ListEntries, Show, Reorder, Revisions.
+- your model will ```use \Backpack\CRUD\CrudTrait```;
+
+This simple architecture (```ProductCrudController extends CrudController```) means:
+- **your CRUD Panel will not be a _black box_**; you can easily see the logic for each operation, by checking the methods on this controller;
+- **you can _easily_ overwrite what happens inside each default operation**;
+- **you can _easily_ add custom operations**;
+
+For example:
+- want to change how a single ```Product``` is shown to the admin? just create a method called ```show()``` in your ```ProductCrudController```; simple OOP dictates that your method will be picked up, instead of the one in CrudController; some goes for ```create()```, ```store()```, etc - you have complete control;
+- want to create a new "Publish" operation on a ```Product```? your ```ProductCrudController``` is a great place for that logic; just create a custom ```publish()``` method and a route that points to it;
+
+
+## Files
+
+For a ```Tag``` entity, your CRUD Panel would consist of:
+- a controller (```app/Http/Controllers/Admin/TagCrudController.php```);
+- a request (```app/Http/Requests/TagCrudRequest.php```);
+- a route inside ```routes/backpack/custom.php```;
+- your existing model (```app/Models/Tag.php```);
+
+To further your understanding of how a CRUD Panel works, [read more about this example in the tutorial](/docs/{{version}}/crud-tutorial).
diff --git a/3.6/crud-buttons.md b/3.6/crud-buttons.md
new file mode 100644
index 00000000..090d9bd4
--- /dev/null
+++ b/3.6/crud-buttons.md
@@ -0,0 +1,201 @@
+# Buttons
+
+---
+
+
+## About
+
+Buttons are used inside the ListEdit operation, to allow the admin to trigger other operations. Some point to entirely new routes (```create```, ```update```, ```show```), others perform the operation on the current page using AJAX (```delete```).
+
+
+### Button Stacks
+
+The ShowList operation has 3 places where buttons can be placed:
+ - ```top``` (where the Add button is)
+ - ```line``` (where the Edit and Delete buttons are)
+ - ```bottom``` (after the table)
+
+When adding a button to the stack, you can choose whether to insert it at the ```beginning``` or ```end``` of the stack by specifying that as a last parameter.
+
+
+### Default Buttons
+
+Backpack adds a few buttons by default:
+- ```create``` to the ```top``` stack;
+- ```update``` and ```delete``` to the ```line``` stack;
+
+Default buttons are invisible if an operation has been disabled. For example, you can:
+- hide the "delete" button using ```$this->crud->denyAccess('delete')```;
+- show a "preview" button by using ```$this->crud->allowAccess('show')```;
+
+
+### Buttons API
+
+Here are a few things you can call in your EntityCrudController's ```setup()``` method, to manipulate buttons:
+
+```php
+// possible positions: 'beginning' and 'end'; defaults to 'beginning' for the 'line' stack, 'end' for the others;
+
+// add a button; possible types are: view, model_function
+$this->crud->addButton($stack, $name, $type, $content, $position);
+
+// add a button whose HTML is returned by a method in the CRUD model
+$this->crud->addButtonFromModelFunction($stack, $name, $model_function_name, $position);
+
+// add a button whose HTML is in a view placed at resources\views\vendor\backpack\crud\buttons
+$this->crud->addButtonFromView($stack, $name, $view, $position);
+
+// remove a button
+$this->crud->removeButton($name);
+
+// remove a button for a certain stack (top, line, bottom)
+$this->crud->removeButtonFromStack($name, $stack);
+```
+
+### Overwriting a Default Button
+
+Before showing any buttons, Backpack will check your ```resources\views\vendor\backpack\crud\buttons``` directory, to see if you've overwritten any default buttons. If it finds a blade file with the same name there as the default buttons, it will use your blade file, instead of the default.
+
+That means **you can overwrite an existing button simply by creating a blade file with the same name inside this directory**.
+
+
+### Creating a Custom Button
+
+To create a custom button:
+- create a new blade file in ```resources\views\vendor\backpack\crud\buttons```;
+- add that button using the ```addButton()``` syntax above, in the EntityCrudControllers you want, inside the ```setup()``` method;
+
+In this blade file, you can use:
+- ```$entry``` - the database entry you're showing (only inside the ```line``` stack);
+- ```$crud``` - the entire CrudPanel object;
+- ```$button``` - the button you're currently showing;
+
+
+## Examples
+
+
+### Adding a Custom Button with a Blade File
+
+Let's say we want to create a simple ```moderate.blade.php``` button. This button would just open a ```user/{id}/moderate/``` route, which would point to ```UserCrudController::moderate()```. The steps would be:
+
+- Create the ```resources\views\vendor\backpack\crud\buttons\moderate.blade.php``` file:
+```php
+@if ($crud->hasAccess('update'))
+ Moderate
+@endif
+```
+- Add the new route, next to ```UserCrudController```'s route (most likely inside ```routes/backpack/custom.php```):
+```php
+Route::get('user/{id}/moderate', 'UserCrudController@moderate');
+```
+
+- We can now add a ```moderate()``` method to our ```UserCrudController```, which would moderate the user, and redirect back.
+```php
+public function moderate()
+{
+ // show a form that does something
+}
+```
+
+- Now we can actually add this button to any of ```UserCrudController::setup()```:
+```php
+$this->crud->addButtonFromView('line', 'moderate', 'moderate', 'beginning');
+```
+
+
+### Adding a Custom Button without a Blade File
+
+Instead of creating a blade file for your button, you can use a function on your model to output the button's HTML.
+
+In your ```ArticleCrudController::setup()```:
+```php
+// add a button whose HTML is returned by a method in the CRUD model
+$this->crud->addButtonFromModelFunction('line', 'open_google', 'openGoogle', 'beginning');
+```
+
+In your ```Article``` model:
+
+```php
+ public function openGoogle($crud = false)
+ {
+ return ' Google it';
+ }
+```
+
+
+
+### Adding a Custom Button with Javascript to the "top" stack
+
+Let's say we want to create an ```import.blade.php``` button. For simplicity, this button would just run an AJAX call which handles everything, and shows a status report to the user through notification bubbles.
+
+The "top" buttons are not bound to any certain entry, like buttons from the "list" stack. They can only do general things. And if they do general things, it's _generally_ recommended that you move their javascript to the bottom of the page. You can easily do that with ```@push('after_javascript')```, because the Backpack default layout has an ```after_javascript``` stack. This way, you can make sure your Javascript is moved at the bottom of the page, after all other Javascript has been loaded (jQuery, DataTables, etc). Check out the example below.
+
+The steps would be:
+
+- Create the ```resources\views\vendor\backpack\crud\buttons\import.blade.php``` file:
+```php
+@if ($crud->hasAccess('create'))
+
+ Import {{ $crud->entity_name }}
+
+@endif
+
+@push('after_scripts')
+
+@endpush
+```
+- Add the new route, next to ```UserCrudController```'s route (most likely inside ```routes/backpack/custom.php```):
+```php
+Route::get('user/import', 'UserCrudController@import');
+```
+
+- We can now add a ```import()``` method to our ```UserCrudController```, which would import the users.
+```php
+public function import()
+{
+ // whatever you decide to do
+}
+```
+
+- Now we can actually add this button to any of ```UserCrudController::setup()```:
+```php
+$this->crud->addButtonFromView('top', 'import', 'view', 'crud::buttons.import', 'end');
+```
diff --git a/3.6/crud-cheat-sheet.md b/3.6/crud-cheat-sheet.md
new file mode 100644
index 00000000..60174261
--- /dev/null
+++ b/3.6/crud-cheat-sheet.md
@@ -0,0 +1,307 @@
+# Crud API Cheat Sheet
+
+---
+
+Here are all the functions you will be using **inside your EntityCrudController's ```setup()``` method**, grouped by the operation you will most likely use them for.
+
+## Operations
+
+
+### ListEntries
+
+
+#### Columns
+
+Methods: addColumn(), addColumns(), modifyColumn(), removeColumn(), removeColumns(), setColumnDetails(), setColumnsDetails(), setColumns(), beforeColumn(), afterColumn(), makeFirstColumn()
+
+```php
+// Manipulate what columns are shown in the table view.
+$this->crud->addColumn($column_definition_array); // add a column, at the end of the stack
+$this->crud->addColumns([$column_definition_array, $another_column_definition_array]); // add multiple columns, at the end of the stack
+$this->crud->modifyColumn($name, $modifs_array);
+$this->crud->removeColumn('column_name'); // remove a column from the stack
+$this->crud->removeColumns(['column_name_1', 'column_name_2']); // remove an array of columns from the stack
+$this->crud->setColumnDetails('column_name', ['attribute' => 'value']);
+$this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
+
+$this->crud->setColumns(); // set the columns you want in the table view, either as array of column names, or multidimensional array with all columns detailed with their types
+
+// ------ REORDER COLUMNS
+$this->crud->addColumn()->beforeColumn('name'); // will show this before the given column
+$this->crud->addColumn()->afterColumn('name'); // will show this after the given column
+
+$this->crud->addColumn()->makeFirstColumn();
+ // will make this column the first one in the list
+ // you need to also specify priority 1 in your addColumn statement for details_row or responsive expand buttons to show
+```
+
+
+#### Buttons
+
+Methods: addButton(), addButtonFromModelFunction(), addButtonFromView(), removeButton(), removeButtonFromStack()
+
+```php
+// possible positions: 'beginning' and 'end'; defaults to 'beginning' for the 'line' stack, 'end' for the others;
+$this->crud->addButton($stack, $name, $type, $content, $position); // add a button; possible types are: view, model_function
+$this->crud->addButtonFromModelFunction($stack, $name, $model_function_name, $position); // add a button whose HTML is returned by a method in the CRUD model
+$this->crud->addButtonFromView($stack, $name, $view, $position); // add a button whose HTML is in a view placed at resources\views\vendor\backpack\crud\buttons
+$this->crud->removeButton($name);
+$this->crud->removeButtonFromStack($name, $stack);
+```
+
+
+#### Filters
+
+Methods: addFilter(), modifyFilter(), removeFilter(), removeAllFilters(), filters()
+
+```php
+// Manipulate what filters are shown in the table view.
+//
+// Note: check out CRUD > Features > Filters in the docs to see examples of $filter_definition_array
+$this->crud->addFilter($filter_definition_array, $values, $filter_logic);
+$this->crud->modifyFilter($name, $modifs_array);
+$this->crud->removeFilter($name);
+$this->crud->removeAllFilters();
+$this->crud->filters(); // gets all the filters
+```
+
+
+#### Details Row
+
+Methods: enableDetailsRow(), disableDetailsRow()
+
+```php
+// Shows a + sign next to each table row, so that the user can expand that row and reveal details. You are responsible for creating the view with those details.
+$this->crud->enableDetailsRow();
+// NOTE: you also need to do allow access to the right users: $this->crud->allowAccess('details_row');
+// NOTE: you also need to do overwrite the showDetailsRow($id) method in your EntityCrudController to show whatever you'd like in the details row OR overwrite the views/backpack/crud/details_row.blade.php
+
+$this->crud->disableDetailsRow();
+```
+
+
+#### Export Buttons
+
+Methods: enableExportButtons()
+
+```php
+// Show export to PDF, CSV, XLS and Print buttons on the table view. Please note it will only export the current _page_ of results. So in order to export all entries the user needs to make the current page show "All" entries from the top-left picker.
+$this->crud->enableExportButtons();
+```
+
+
+#### Responsive Table
+
+Methods: enableResponsiveTable(), disableResponsiveTable()
+
+```php
+$this->crud->disableResponsiveTable();
+$this->crud->enableResponsiveTable();
+```
+
+
+#### Persistent Table
+
+Methods: enablePersistenTable(), disablePersistenTable()
+
+```php
+$this->crud->disablePersistentTable();
+$this->crud->enablePersistentTable();
+```
+
+
+#### Page Length
+
+Methods: setDetaultPageLength(), setPageLengthMenu()
+
+```php
+$this->crud->setDefaultPageLength(10); // number of rows shown in list view
+$this->crud->setPageLengthMenu([100, 200, 300]); // page length menu to show in the list view
+```
+
+
+#### Actions Column
+
+Methods: setActionColumnPriority()
+
+```php
+// make the actions column (in the table view) hide when not enough space is available, by giving it an unreasonable priority
+$this->crud->setActionsColumnPriority(10000);
+```
+
+
+#### Custom / Advanced Queries
+
+Methods: addClause(), groupBy(), limit(), orderBy()
+
+```php
+// Change what entries are shown in the table view.
+// This changes all queries on the table view,
+// as opposed to filters, who only change it when that filter is applied.
+$this->crud->addClause('active'); // apply local scope
+$this->crud->addClause('type', 'car'); // apply local dynamic scope
+$this->crud->addClause('where', 'name', '=', 'car');
+$this->crud->addClause('whereName', 'car');
+$this->crud->addClause('whereHas', 'posts', function($query) {
+ $query->activePosts();
+ });
+$this->crud->groupBy();
+$this->crud->limit();
+
+$this->crud->orderBy();
+// please note it's generally a good idea to use crud->orderBy() inside "if (!$this->request->has('order')) {}"; that way, your custom order is applied ONLY IF the user hasn't forced another order (by clicking a column heading)
+```
+
+
+### Show
+
+Use the same Columns API as for the ListEntries operation, but inside your ```show()``` method.
+
+
+### Create & Update Operations
+
+Methods: addField(), addFields(), modifyField(), modifyFields(), removeField(), removeFields(), removeAllFields(), beforeField(), afterField()
+
+```php
+// ------
+// FIELDS
+// ------
+// Manipulate what fields are shown in the create / update forms.
+//
+// Note: check out CRUD > Features > Field Types in the docs to see examples of $field_definition_array
+
+$this->crud->addField($field_definition_array, 'update/create/both');
+$this->crud->addField('db_column_name', 'update/create/both'); // a lazy way to add fields: let the CRUD decide what field type it is and set it automatically, along with the field label
+$this->crud->addFields($array_of_fields_definition_arrays, 'update/create/both');
+$this->crud->modifyField($name, $modifs_array, 'update/create/both');
+$this->crud->removeField('name', 'update/create/both');
+$this->crud->removeFields($array_of_names, 'update/create/both');
+$this->crud->removeAllFields();
+
+// Note: the last parameter is always the form - create or update; if missing, it's assumed 'both';
+
+
+// ------ REORDER FIELDS
+$this->crud->addField()->beforeField('name'); // will show this before the given field
+$this->crud->addField()->afterField('name'); // will show this after the given field
+```
+
+
+### Reorder
+
+Methods: enableReorder(), disableReorder(), isReorderEnabled()
+
+```php
+// Show a reorder button in the table view, next to Add
+// Provide an interface to reorder & nest elements, provided the parent_id, lft, rgt, depth columns are in the database, and fillable on the model.
+$this->crud->enableReorder('label_name', 3);
+// NOTE: the second parameter is the maximum nesting depth; this example will prevent the user from creating trees deeper than 3 levels;
+// NOTE: you also need to do allow access to the right users: $this->crud->allowAccess('reorder');
+
+$this->crud->disableReorder();
+$this->crud->isReorderEnabled(); // return true/false
+
+```
+
+
+### Revisions
+
+```php
+// -------------------------
+// REVISIONS aka Audit Trail
+// -------------------------
+// Tracks all changes to an entry and provides an interface to revert to a previous state.
+//
+// IMPORTANT: You also need to use \Venturecraft\Revisionable\RevisionableTrait;
+// Please check out: https://backpackforlaravel.com/docs/crud-operation-revisions
+$this->crud->allowAccess('revisions');
+```
+
+
+## All Operations
+
+Methods: allowAccess(), denyAccess(), hasAccess(), hasAccessOrFail(), hasAccessToAll(), hasAccessToAny(), setShowView(), setEditView(), setCreateView(), setListView(), setReorderView(), setRevisionsView, setRevisionsTimelineView(), setDetailsRowView(), getEntry(), getFields(), getColumns(), getCurrentEntry(), getTitle(), setTitle(), getHeading(), setHeading(), getSubheading(), setSubheading(),
+
+```php
+// ------
+// ACCESS
+// ------
+// Prevent or allow users from accessing different CRUD operations.
+
+$this->crud->allowAccess('list');
+$this->crud->allowAccess(['list', 'create', 'delete']);
+$this->crud->denyAccess('list');
+$this->crud->denyAccess(['list', 'create', 'delete']);
+
+$this->crud->hasAccess('add'); // returns true/false
+$this->crud->hasAccessOrFail('add'); // throws 403 error
+$this->crud->hasAccessToAll(['create', 'update']); // returns true/false
+$this->crud->hasAccessToAny(['create', 'update']); // returns true/false
+
+// -------------
+// EAGER LOADING
+// -------------
+
+// eager load a relationship
+$this->crud->with('relationship_name');
+
+// ------------
+// CUSTOM VIEWS
+// ------------
+
+// use a custom view for a CRUD operation
+$this->crud->setShowView('your-view');
+$this->crud->setEditView('your-view');
+$this->crud->setCreateView('your-view');
+$this->crud->setListView('your-view');
+$this->crud->setReorderView('your-view');
+$this->crud->setRevisionsView('your-view');
+$this->crud->setRevisionsTimelineView('your-view');
+$this->crud->setDetailsRowView('your-view');
+
+// -------
+// GETTERS
+// -------
+
+$this->crud->getEntry($entry_id);
+$this->crud->getEntries();
+
+$this->crud->getFields('create/update/both');
+
+// in your update() method, after calling parent::updateCrud()
+$this->crud->getCurrentEntry();
+
+// -------
+// OPERATIONS
+// -------
+
+$this->crud->setOperation('ListEntries');
+$this->crud->getOperation();
+
+// -------
+// ACTIONS
+// -------
+
+$this->crud->getActionMethod(); // returns the method on the controller that was called by the route; ex: create(), update(), edit() etc;
+$this->crud->actionIs('create'); // checks if the controller method given is the one called by the route
+
+$this->crud->getTitle('create'); // get the Title for the create action
+$this->crud->getHeading('create'); // get the Heading for the create action
+$this->crud->getSubheading('create'); // get the Subheading for the create action
+
+$this->crud->setTitle('some string', 'create'); // set the Title for the create action
+$this->crud->setHeading('some string', 'create'); // set the Heading for the create action
+$this->crud->setSubheading('some string', 'create'); // set the Subheading for the create action
+
+// ---------------------------
+// CrudPanel Basic Information
+// ---------------------------
+$this->crud->setModel("App\Models\Example");
+$this->crud->setRoute("admin/example");
+// OR $this->crud->setRouteName("admin.example");
+$this->crud->setEntityNameStrings("example", "examples");
+
+// check the FormRequests used in that EntityCrudController for required fields, and add an asterisk to them in the create/edit form
+$this->crud->setRequiredFields(StoreRequest::class, 'create');
+$this->crud->setRequiredFields(UpdateRequest::class, 'edit');
+```
diff --git a/3.6/crud-columns.md b/3.6/crud-columns.md
new file mode 100644
index 00000000..a835fb3c
--- /dev/null
+++ b/3.6/crud-columns.md
@@ -0,0 +1,701 @@
+# Columns
+
+---
+
+
+## About
+
+A column shows the information of an Eloquent attribute, in a user-friendly format.
+
+It's used inside default operations to:
+- show a table cell in **ListEntries**;
+- show an attribute value in **Show**;
+
+A column consists of only one file - a blade file with the same name as the column type (ex: ```text.blade.php```). Backpack provides you with [default column types](#default-column-types) for the common use cases, but you can easily [change how a default field type works](#overwriting-default-column-types), or [create an entirely new field type](#creating-a-custom-column-type).
+
+
+### Mandatory Attributes
+
+When passing a column array, you need to specify at least these attributes:
+```php
+[
+ 'name' => 'options', // the db column name (attribute name)
+ 'label' => "Options", // the human-readable label for it
+ 'type' => 'text' // the kind of column to show
+],
+```
+
+
+### Optional Attributes
+
+- [```searchLogic```](#custom-search-logic)
+- [```orderLogic```](#custom-order-logic)
+- [```orderable```](#custom-order-logic)
+- [```visibleInTable```](#choose-where-columns-are-visible)
+- [```visibleInModal```](#choose-where-columns-are-visible)
+- [```visibleInExport```](#choose-where-columns-are-visible)
+- [```visibleInShow```](#choose-where-columns-are-visible)
+- [```priority```](#define-which-columns-to-hide-in-responsive-table)
+
+
+### Columns API
+
+Inside your ```setup()``` method there are a few calls you can make to configure or manipulate columns:
+
+```php
+// add a column, at the end of the stack
+$this->crud->addColumn($column_definition_array);
+
+// add multiple columns, at the end of the stack
+$this->crud->addColumns([$column_definition_array, $another_column_definition_array]);
+
+// remove a column from the stack
+$this->crud->removeColumn('column_name');
+
+// remove an array of columns from the stack
+$this->crud->removeColumns(['column_name_1', 'column_name_2']);
+
+// change the attributes of a column
+$this->crud->modifyColumn($name, $modifs_array);
+$this->crud->setColumnDetails('column_name', ['attribute' => 'value']);
+
+// change the attributes of multiple columns
+$this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
+
+// forget what columns have been previously defined, only use these columns
+$this->crud->setColumns([$column_definition_array, $another_column_definition_array]);
+```
+
+In addition, to manipulate the order columns are shown in, you can:
+
+```php
+// add this column before a given column
+$this->crud->addColumn('text')->beforeColumn('name');
+
+// add this column after a given column
+$this->crud->addColumn()->afterColumn('name');
+
+// make this column the first one in the list
+$this->crud->addColumn()->makeFirstColumn();
+```
+
+
+## Default Column Types
+
+
+### array
+
+Enumerate an array stored in the db column as JSON.
+```php
+[
+ 'name' => 'options', // The db column name
+ 'label' => "Options", // Table column heading
+ 'type' => 'array'
+],
+```
+
+
+### array_count
+
+Count the items in an array stored in the db column as JSON.
+
+```php
+[
+ 'name' => 'options', // The db column name
+ 'label' => "Options", // Table column heading
+ 'type' => 'array_count',
+ // 'suffix' => 'options', // if you want it to show "2 options" instead of "2 items"
+],
+```
+
+
+### boolean
+
+Show Yes/No (or custom text) instead of 1/0.
+
+```php
+[
+ 'name' => 'name',
+ 'label' => 'Status',
+ 'type' => 'boolean',
+ // optionally override the Yes/No texts
+ // 'options' => [0 => 'Active', 1 => 'Inactive']
+],
+```
+
+
+### check
+
+Show a favicon with a checked or unchecked box, depending on the given boolean.
+```php
+[
+ 'name' => 'featured', // The db column name
+ 'label' => "Featured", // Table column heading
+ 'type' => 'check'
+],
+```
+
+
+
+### checkbox
+
+Shows a checkbox (the form element), and inserts the js logic needed to select/deselect multiple entries. It is mostly used for [the Bulk Delete action](/docs/{{version}}/crud-operation-delete#delete-multiple-items-bulk-delete), and [custom bulk actions](/docs/{{version}}/crud-operations#creating-a-new-operation-with-a-bulk-action-no-interface).
+
+Shorthand:
+```php
+$this->crud->enableBulkActions();
+```
+(will also add an empty custom_html column)
+
+Verbose:
+```php
+$this->crud->addColumn([
+ 'type' => 'checkbox',
+ 'name' => 'bulk_actions',
+ 'label' => ' ',
+ 'priority' => 1,
+ 'searchLogic' => false,
+ 'orderable' => false,
+ 'visibleInModal' => false,
+])->makeFirstColumn();
+```
+
+
+### closure
+
+
+Show custom HTML based on a closure you specify in your EntityCrudController. Please note this column does not escape HTML before rendering. You need to do that yourself, if you consider it necessary.
+
+```php
+[
+ 'name' => 'created_at',
+ 'label' => 'Created At',
+ 'type' => 'closure',
+ 'function' => function($entry) {
+ return 'Created on '.$entry->created_at;
+ }
+],
+```
+
+
+### date
+
+
+The date column will show a localized date in the default date format (as specified in the ```config/backpack/base.php``` file), whether the attribute is casted as date in the model or not.
+
+Note that the ```format``` attribute uses ISO date formatting parameters and not PHP ```date()``` formatters. See for more information.
+
+```php
+[
+ 'name' => "name", // The db column name
+ 'label' => "Tag Name", // Table column heading
+ 'type' => "date",
+ // 'format' => 'l j F Y', // use something else than the base.default_date_format config value
+],
+```
+
+
+### datetime
+
+
+The date column will show a localized datetime in the default datetime format (as specified in the ```config/backpack/base.php``` file), whether the attribute is casted as datetime in the model or not.
+
+Note that the ```format``` attribute uses ISO date formatting parameters and not PHP ```date()``` formatters. See for more information.
+
+
+```php
+[
+ 'name' => "name", // The db column name
+ 'label' => "Tag Name", // Table column heading
+ 'type' => "datetime",
+ // 'format' => 'l j F Y H:i:s', // use something else than the base.default_datetime_format config value
+],
+```
+
+
+### email
+
+The email column will output the email address in the database (truncated to 254 characters if needed), with a ```mailto:``` link towards the full email. Its definition is:
+```php
+[
+ 'name' => 'email', // The db column name
+ 'label' => "Email Address", // Table column heading
+ 'type' => 'email',
+ // 'limit' => 500, // if you want to truncate the text to a different number of characters
+],
+```
+
+
+### image
+
+
+Show a thumbnail image.
+
+```php
+[
+ 'name' => 'profile_image', // The db column name
+ 'label' => "Profile image", // Table column heading
+ 'type' => 'image',
+ // 'prefix' => 'folder/subfolder/',
+ // optional width/height if 25px is not ok with you
+ // 'height' => '30px',
+ // 'width' => '30px',
+],
+```
+
+
+### markdown
+
+
+Convert a markdown string to HTML, using ```Illuminate\Mail\Markdown```. Since Markdown is usually used for long texts, this column is most helpful in the "Show" operation - not so much in the "ListEntries" operation, where only short snippets make sense.
+
+```php
+[
+ 'name' => 'text', // The db column name
+ 'label' => "Text", // Table column heading
+ 'type' => 'markdown',
+],
+```
+
+
+### model_function
+
+
+The model_function column will output a function on your main model. Its definition is:
+```php
+[
+ // run a function on the CRUD model and show its return value
+ 'name' => "url",
+ 'label' => "URL", // Table column heading
+ 'type' => "model_function",
+ 'function_name' => 'getSlugWithLink', // the method in your Model
+ // 'function_parameters' => [$one, $two], // pass one/more parameters to that method
+ // 'limit' => 100, // Limit the number of characters shown
+],
+```
+For this example, if your model would feature this method, it would return the link to that entity:
+```php
+public function getSlugWithLink() {
+ return ''.$this->slug.'';
+}
+```
+
+**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent JS and CSS from reaching your DB in the first place.
+
+
+### model_function_attribute
+
+
+If the function you're trying to use returns an object, not a string, you can use the model_function_attribute column, which will output the attribute on the function result. Its definition is:
+```php
+[
+ 'name' => "url",
+ 'label' => "URL", // Table column heading
+ 'type' => "model_function_attribute",
+ 'function_name' => 'getSlugWithLink', // the method in your Model
+ // 'function_parameters' => [$one, $two], // pass one/more parameters to that method
+ 'attribute' => 'route',
+ // 'limit' => 100, // Limit the number of characters shown
+],
+```
+
+**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent JS and CSS from reaching your DB in the first place.
+
+
+### multidimensional_array
+
+
+Enumerate the values in a multidimensional array, stored in the db as JSON.
+
+```php
+[
+ 'name' => 'options', // The db column name
+ 'label' => "Options", // Table column heading
+ 'type' => 'multidimensional_array',
+ 'visible_key' => 'name' // The key to the attribute you would like shown in the enumeration
+],
+```
+
+
+### number
+
+
+The text column will just output the number value of a db column (or model attribute). Its definition is:
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => "Tag Name", // Table column heading
+ 'type' => "number",
+ // 'prefix' => "$",
+ // 'suffix' => " EUR",
+ // 'decimals' => 2,
+ // 'dec_point' => ',',
+ // 'thousands_sep' => '.',
+ // decimals, dec_point and thousands_sep are used to format the number;
+ // for details on how they work check out PHP's number_format() method, they're passed directly to it;
+ // https://www.php.net/manual/en/function.number-format.php
+],
+```
+
+
+### radio
+
+
+Show a pretty text instead of the database value, according to an associative array. Usually used as a column for the "radio" field type.
+
+```php
+[
+ 'name' => 'status',
+ 'label' => 'Status',
+ 'type' => 'radio',
+ 'options' => [
+ 0 => "Draft",
+ 1 => "Published"
+ ]
+],
+```
+
+This example will show:
+- "Draft" when the value stored in the db is 0;
+- "Published" when the value stored in the db is 1;
+
+
+### row_number
+
+
+Show the row number (index). The number depends strictly on the result set (x records per page, pagination, search, filters, etc). It does not get any information from the database. It is not searchable. It is only useful to show the current row number.
+
+```
+$this->crud->addColumn([
+ 'name' => 'row_number',
+ 'type' => 'row_number',
+ 'label' => '#',
+ 'orderable' => false,
+])->makeFirstColumn();
+```
+
+Notes:
+- you can have a different ```name```; just make sure your model doesn't have that attribute;
+- you can have a different label;
+- you can place the column as second / third / etc if you remove ```makeFirstColumn()```;
+- this column type allows the use of suffix/prefix just like the text column type;
+- if upon placement you notice it always shows ```false``` then please note there have been changes in the ```search()``` method - you need to add another parameter to your ```getEntriesAsJsonForDatatables()``` call;
+
+
+### text
+
+The text column will just output the text value of a db column (or model attribute). Its definition is:
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => "Tag Name", // Table column heading
+ // 'prefix' => "Name: ",
+ // 'suffix' => "(user)",
+ // 'limit' => 120, // character limit; default is 50;
+],
+```
+
+**Advanced use case:** The ```text``` column type can also show the attribute of a 1-1 relationship. If you have a relationship (like ```parent()```) set up in your Model, you can use relationship and attribute in the ```name```, using dot notation:
+```php
+[
+ 'name' => 'parent.title',
+ 'label' => 'Title',
+ 'type' => 'text'
+],
+```
+
+
+### select
+
+The select column will output its connected entity. Used for relationships like hasOne() and belongsTo(). Its name and definition is the same as for the select *field type*:
+```php
+[
+ // 1-n relationship
+ 'label' => "Parent", // Table column heading
+ 'type' => "select",
+ 'name' => 'parent_id', // the column that contains the ID of that connected entity;
+ 'entity' => 'parent', // the method that defines the relationship in your Model
+ 'attribute' => "name", // foreign key attribute that is shown to user
+ 'model' => "App\Models\Category", // foreign key model
+],
+```
+
+
+### select_from_array
+
+Show a particular text depending on the value of the attribute.
+
+```php
+[ // select_from_array
+ 'name' => 'status',
+ 'label' => "Status",
+ 'type' => 'select_from_array',
+ 'options' => ['draft' => 'Draft (invisible)', 'published' => 'Published (visible)'],
+],
+```
+
+
+### select_multiple
+
+The select_multiple column will output a comma separated list of its connected entities. Used for relationships like hasMany() and belongsToMany(). Its name and definition is the same as the select_multiple field:
+```php
+[
+ // n-n relationship (with pivot table)
+ 'label' => "Tags", // Table column heading
+ 'type' => "select_multiple",
+ 'name' => 'tags', // the method that defines the relationship in your Model
+ 'entity' => 'tags', // the method that defines the relationship in your Model
+ 'attribute' => "name", // foreign key attribute that is shown to user
+ 'model' => "App\Models\Tag", // foreign key model
+],
+```
+
+
+### table
+
+
+The ```table``` column will output a condensed table, when used on an attribute that stores a JSON array or object. It is meant to be used inside the show functionality (not list, though it also works there).
+
+Its definition is very similar to the [table *field type*](/docs/{{version}}/crud-fields#table).
+
+```php
+[
+ 'name' => 'features',
+ 'label' => 'Features',
+ 'type' => 'table',
+ 'columns' => [
+ 'name' => 'Name',
+ 'description' => 'Description',
+ 'price' => 'Price',
+ 'obs' => 'Observations'
+ ]
+],
+```
+
+
+### upload_multiple
+
+
+The ```table``` column will output a list of files and links, when used on an attribute that stores a JSON array of file paths. It is meant to be used inside the show functionality (not list, though it also works there), to preview files uploaded with the ```upload_multiple``` field type.
+
+Its definition is very similar to the [upload_multiple *field type*](/docs/{{version}}/crud-fields#upload_multiple).
+
+```php
+[
+ 'name' => 'photos',
+ 'label' => 'Photos',
+ 'type' => 'upload_multiple',
+ // 'disk' => 'public', // filesystem disk if you're using S3 or something custom
+],
+```
+
+
+### video
+
+
+Display a small screenshot for a Youtube or Vimeo video, stored in the database as JSON using the "video" field type.
+
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => "Tag Name", // Table column heading
+ 'type' => 'video',
+],
+```
+
+
+### view
+
+Display any custom column type you want. Usually used by Backpack package developers, to use views from within their packages, instead of having to publish the views.
+
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => "Tag Name", // Table column heading
+ 'type' => 'view',
+ 'view' => 'package::columns.column_type_name', // or path to blade file
+],
+```
+
+
+## Overwriting Default Column Types
+
+You can overwrite a column type by placing a file with the same name in your ```resources\views\vendor\backpack\crud\columns``` directory. When a file is there, Backpack will pick that one up, instead of the one in the package. You can do that from command line using ```php artisan backpack:crud:publish columns/column-file-name```
+
+Examples:
+- creating a ```resources\views\vendor\backpack\crud\columns\number.blade.php``` file would overwrite the ```number``` column functionality;
+- ```php artisan backpack:crud:publish columns/text``` will take the view from the package and copy it to the directory above, so you can edit it;
+
+>Keep in mind that when you're overwriting a default column type, you're forfeiting any future updates for that column. We can't push updates to a file that you're no longer using.
+
+
+## Creating a Custom Column Type
+
+Columns consist of only one file - a blade file with the same name as the column type (ex: ```text.blade.php```). You can create one by placing a new blad file inside ```resources\views\vendor\backpack\crud\columns```. Be careful to choose a distinctive name, otherwise you might be overwriting a default column type (see above).
+
+For example, you can create a ```markdown.blade.php```:
+```php
+{!! \Markdown::convertToHtml($entry->{$column['name']}) !!}
+```
+
+The most useful variables you'll have in this file here are:
+- ```$entry``` - the database entry you're showing (Eloquent object);
+- ```$crud``` - the entire CrudPanel object, with settings, options and variables;
+
+By default, custom columns are not searchable. In order to make your column searchable you need to [specify a custom ```searchLogic``` in your declaration](#custom-search-logic).
+
+
+
+## Advanced Columns Use
+
+
+### Custom Search Logic for Columns
+
+If your column points to something atypical (not a value that is stored as plain text in the database column, maybe a model function, or a JSON, or something else), you might find that the search doesn't work for that column. You can choose which columns are searchable, and what those columns actually search, by using the column's ```searchLogic``` attribute:
+
+```php
+// column with custom search logic
+$this->crud->addColumn([
+ 'name' => 'slug_or_title',
+ 'label' => 'Title',
+ 'searchLogic' => function ($query, $column, $searchTerm) {
+ $query->orWhere('title', 'like', '%'.$searchTerm.'%');
+ }
+]);
+
+
+// 1-n relationship column with custom search logic
+$this->crud->addColumn([
+ 'label' => "Cruise Ship",
+ 'type' => "select",
+ 'name' => 'cruise_ship_id',
+ 'entity' => 'cruise_ship',
+ 'attribute' => "cruise_ship_name_date", // combined name & date column
+ 'model' => "App\Models\CruiseShip",
+ 'searchLogic' => function ($query, $column, $searchTerm) {
+ $query->orWhereHas('cruise_ship', function ($q) use ($column, $searchTerm) {
+ $q->where('name', 'like', '%'.$searchTerm.'%')
+ ->orWhereDate('depart_at', '=', date($searchTerm));
+ });
+ }
+]);
+
+
+// column that doesn't need to be searchable
+$this->crud->addColumn([
+ 'name' => 'slug_or_title',
+ 'label' => 'Title',
+ 'searchLogic' => false
+]);
+
+// column whose search logic should behave like it were a 'text' column type
+$this->crud->addColumn([
+ 'name' => 'slug_or_title',
+ 'label' => 'Title',
+ 'searchLogic' => 'text'
+]);
+```
+
+
+### Custom Order Logic for Columns
+
+If your column points to something atypical (not a value that is stored as plain text in the database column, maybe a model function, or a JSON, or something else), you might find that the ordering doesn't work for that column. You can choose which columns are orderable, and how those columns actually get ordered, by using the column's ```orderLogic``` attribute.
+
+For example, to order Articles not by its Category ID (as default, but by the Category Name), you can do:
+
+```php
+$this->crud->addColumn([ // Select
+ 'label' => "Category",
+ 'type' => 'select',
+ 'name' => 'category_id', // the db column for the foreign key
+ 'entity' => 'category', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'orderable' => true,
+ 'orderLogic' => function ($query, $column, $columnDirection) {
+ return $query->leftJoin('categories', 'categories.id', '=', 'articles.select')
+ ->orderBy('categories.name', $columnDirection)->select('articles.*');
+ }
+]);
+```
+
+If you want a column to not be orderable at all, just pass ```'orderable' => false```
+
+
+### Choose Where Columns are Visible
+
+Starting with Backpack\CRUD 3.5.0, you can choose to show/hide columns in different contexts. You can pass ```true``` / ```false``` to the column attributes below, and Backpack will know to show the column or not, in different contexts:
+
+```php
+$this->crud->addColumn([
+ 'name' => 'description',
+ 'visibleInTable' => false, // no point, since it's a large text
+ 'visibleInModal' => false, // would make the modal too big
+ 'visibleInExport' => false, // not important enough
+ 'visibleInShow' => true, // sure, why not
+]);
+```
+
+This also allows you to do tricky things like:
+- add a column that's hidden from the table view, but WILL get exported;
+- adding a column that's hidden everywhere, but searchable (even with a custom ```searchLogic```);
+
+
+### Multiple Columns With the Same Name
+
+Starting with Backpack\CRUD 3.3 (Nov 2017), you can have multiple columns with the same name, by specifying a unique ```key``` property. So if you want to use the same column name twice, you can do that. Notice below we have the same name for both columns, but one of them has a ```key```. This additional key will be used as an array key, if provided.
+
+```php
+// column that shows the parent's first name
+$this->crud->addColumn([
+ 'label' => "Parent First Name", // Table column heading
+ 'type' => "select",
+ 'name' => 'parent_id', // the column that contains the ID of that connected entity;
+ 'entity' => 'parent', // the method that defines the relationship in your Model
+ 'attribute' => "first_name", // foreign key attribute that is shown to user
+ 'model' => "App\Models\User", // foreign key model
+]);
+
+// column that shows the parent's last name
+$this->crud->addColumn([
+ 'label' => "Parent Last Name", // Table column heading
+ 'type' => "select",
+ 'name' => 'parent_id', // the column that contains the ID of that connected entity;
+ 'key' => 'parent_last_name', // the column that contains the ID of that connected entity;
+ 'entity' => 'parent', // the method that defines the relationship in your Model
+ 'attribute' => "last_name", // foreign key attribute that is shown to user
+ 'model' => "App\Models\User", // foreign key model
+]);
+```
+
+
+### Define which columns to show or hide in the responsive table
+
+By default, DataTables-responsive will try his best to show:
+- **the first column** (since that usually is the most important for the user, plus it holds the modal button and the details_row button so it's crucial for usability);
+- **the last column** (the actions column, where the action buttons reside);
+
+When giving priorities, lower is better. So a column with priority 4 will be hidden BEFORE a column with priority 2. The first and last columns have a priority of 1. You can define a different priority for a column using the ```priority``` attribute. For example:
+
+```php
+$this->crud->addColumn([
+ 'name' => 'details',
+ 'type' => 'text',
+ 'label' => 'Details',
+ 'priority' => 2,
+ ]);
+$this->crud->addColumn([
+ 'name' => 'obs',
+ 'type' => 'text',
+ 'label' => 'Observations',
+ 'priority' => 3,
+ ]);
+```
+In the example above, depending on how much space it's got in the viewport, DataTables will first hide the ```obs``` column, then ```details```, then the last column, then the first column.
+
+You can make the last column be less important (and hide) by giving it an unreasonable priority:
+
+```php
+$this->crud->setActionsColumnPriority(10000);
+```
+
+>Note that responsive tables adopt special behavior if the table is not able to show all columns. This includes displaying a vertical ellipsis to the left of the row, and making the row clickable to reveal more detail. This behavior is automatic and is not manually controllable via a field property.
diff --git a/3.6/crud-fields.md b/3.6/crud-fields.md
new file mode 100644
index 00000000..e2e889b1
--- /dev/null
+++ b/3.6/crud-fields.md
@@ -0,0 +1,1686 @@
+# Fields
+
+---
+
+
+## About
+
+Field types define how the admin can manipulate an entry's values. They're used by the Create and Update operations.
+
+Think of the field type as the type of input: ``````. But for most entities, you won't just need text inputs - you'll need datepickers, upload buttons, 1-n relationship, n-n relationships, textareas, etc.
+
+We have a lot of default field types, detailed below. If you don't find what you're looking for, you can [create a custom field type](/docs/{{version}}/crud-fields#creating-a-custom-field-type). Or if you just want to tweak a default field type a little bit, you can [overwrite default field types](/docs/{{version}}/crud-fields#overwriting-default-field-types).
+
+
+### Mandatory Field Attributes
+
+For each of them, you only need to define it properly in the Controller. All field types will need at least three things:
+- the ```name``` of the column in the database (ex: "title")
+- the human-readable ```label``` for the input (ex: "Title")
+- the ```type``` of the input (ex: "text")
+
+So at minimum, your field definition array should look like:
+```php
+[
+ 'name' => 'description',
+ 'type' => 'textarea',
+ 'label' => 'Article Description',
+]
+```
+
+
+### Optional Field Attributes
+
+There are a few optional attributes on all default field types, that you can use to easily achieve a few common cutomizations:
+
+```php
+[
+ 'prefix' => '',
+ 'suffix' => '',
+ 'default' => 'some value', // set a default value
+ 'hint' => 'Some hint text', // helpful text, shows up after the input
+ 'attributes' => [
+ 'placeholder' => 'Some text when empty',
+ 'class' => 'form-control some-class',
+ 'readonly'=>'readonly',
+ 'disabled'=>'disabled',
+ ], // change the HTML attributes of your input
+ 'wrapperAttributes' => [
+ 'class' => 'form-group col-md-12'
+ ], // change the HTML attributes for the field wrapper - mostly for resizing fields
+]
+```
+
+These will help you:
+
+- **prefix** - add a text or icon _before_ the actual input;
+- **suffix** - add a text or icon _after_ the actual input;
+- **default** - specify a default value for the input, on create;
+- **hint** - add descriptive text for this input;
+- **attributes** - change or add actual HTML attributes of the input (ex: readonly, disabled, class, placeholder, etc);
+- **wrapperAttributes** - change or add actual HTML attributes to the div that contains the input;
+
+
+### Fields API
+
+To manipulate fields, you can use the methods below. As a second parameter, you can specify the operation you want that to work for (```create``` or ```update```). If you want it to work for both, don't use the second parameter.
+
+```php
+// add a field to both Create and Update operation
+$this->crud->addField($field_definition_array);
+
+// add a field only to the Update operation
+$this->crud->addField($field_definition_array, 'update');
+
+// shorthand: add a text field to both Create and Update operations
+$this->crud->addField('db_column_name');
+
+// add multiple fields
+$this->crud->addFields([$field_definition_array_1, $field_definition_array_2]);
+
+// change the attributes of a field
+$this->crud->modifyField($name, $modifs_array);
+
+// remove a field from both operations
+$this->crud->removeField('name');
+
+// remove multiple fields from both operations
+$this->crud->removeFields($array_of_names);
+
+// remove all fields from all operations
+$this->crud->removeAllFields();
+
+// FIELD ORDER
+
+// add a field before a given field
+$this->crud->addField($field_definition_array)->beforeField('name');
+
+// add a field after a given field
+$this->crud->addField($field_definition_array)->afterField('name');
+```
+
+
+### Extra Fields Features
+
+
+#### Fake Fields (all stored as JSON in the database)
+
+In case you want to store insignificant information for an entry that doesn't need a database column, you can add any number of Fake Fields, and all their information will be stored inside one column in the db, as JSON. By default, an ```extras``` column is assumed on the database table, but you can change that.
+
+**Step 1.** Use the fake attribute on your field:
+```php
+[
+ 'name' => 'name', // JSON variable name
+ 'label' => "Tag Name", // human-readable label for the input
+
+ 'fake' => true, // show the field, but don't store it in the database column above
+ 'store_in' => 'extras' // [optional] the database column name where you want the fake fields to ACTUALLY be stored as a JSON array
+],
+```
+
+**Step 2.** On your model, make sure the db columns where you store the JSONs (by default only ```extras```):
+- are in your ```$fillable``` property;
+- are on a new ```$fakeColumns``` property (create it now);
+- are casted as array in ```$casts```;
+
+>If you need your fakes to also be translatable, remember to also place ```extras``` in your model's ```$translatable``` property.
+
+Example:
+```php
+[
+ 'name' => 'meta_title',
+ 'label' => "Meta Title",
+ 'fake' => true,
+ 'store_in' => 'metas' // [optional]
+],
+[
+ 'name' => 'meta_description',
+ 'label' => "Meta Description",
+ 'fake' => true,
+ 'store_in' => 'metas' // [optional]
+],
+[
+ 'name' => 'meta_keywords',
+ 'label' => "Meta Keywords",
+ 'fake' => true,
+ 'store_in' => 'metas' // [optional]
+],
+```
+
+In this example, these 3 fields will show up in the create & update forms, the CRUD will process as usual, but in the database these values won't be stored in the ```meta_title```, ```meta_description``` and ```meta_keywords``` columns. They will be stored in the ```metas``` column as a JSON array:
+
+```php
+{"meta_title":"title","meta_description":"desc","meta_keywords":"keywords"}
+```
+
+If the ```store_in``` attribute wasn't used, they would have been stored in the ```extras``` column.
+
+
+#### Split Fields into Tabs
+
+You can now split your create/edit inputs into multiple tabs.
+
+
+
+In order to use this feature, you just need to specify the tab name for each of your fields. Example:
+
+```php
+$this->crud->addField([ // select_from_array
+ 'name' => 'select_from_array',
+ 'label' => "Select from array",
+ 'type' => 'select_from_array',
+ 'options' => ['one' => 'One', 'two' => 'Two', 'three' => 'Three'],
+ 'allows_null' => false,
+ 'allows_multiple' => true,
+ 'tab' => 'Tab name here',
+]);
+```
+
+If you forget to specify a tab name for a field, Backpack will place it above all tabs.
+
+
+
+## Default Field Types
+
+
+### address_algolia
+
+Use [Algolia Places autocomplete](https://community.algolia.com/places/) to help users type their address faster. With the ```store_as_json``` option, it will store the address, postcode, city, country, latitude and longitude in a JSON in the database. Without it, it will just store the address string.
+
+```php
+[ // Address
+ 'name' => 'address',
+ 'label' => 'Address',
+ 'type' => 'address_algolia',
+ // optional
+ 'store_as_json' => true
+],
+```
+
+> **Use attribute casting.** For information stored as JSON in the database, it's recommended that you use [attribute casting](https://laravel.com/docs/eloquent-mutators#attribute-casting) to ```array``` or ```object```. That way, every time you get the info from the database you'd get it in a usable format.
+
+
+Input preview:
+
+
+
+
+### address_google
+
+Use [Google Places Search](https://developers.google.com/places/web-service/search) to help users type their address faster. With the ```store_as_json``` option, it will store the address, postcode, city, country, latitude and longitude in a JSON in the database. Without it, it will just store the complete address string.
+
+```php
+[ // Address
+ 'name' => 'address',
+ 'label' => 'Address',
+ 'type' => 'address_google',
+ // optional
+ 'store_as_json' => true
+],
+```
+
+Using Google Places API is dependant on using an API Key. Please [get an API key](https://console.cloud.google.com/apis/credentials) - you do have to configure billing, but you qualify for $200/mo free usage, which covers most use cases. Then copy-paste that key as your ```services.google_places.key``` value. So inside your ```config/services.php``` please add the items below:
+
+```php
+ 'google_places' => [
+ 'key' => 'the-key-you-got-from-google-places'
+ ],
+```
+
+> **Use attribute casting.** For information stored as JSON in the database, it's recommended that you use [attribute casting](https://laravel.com/docs/eloquent-mutators#attribute-casting) to ```array``` or ```object```. That way, every time you get the info from the database you'd get it in a usable format.
+
+Input preview:
+
+
+
+
+### browse
+
+If you've chosen to use [elFinder](http://elfinder.org/) upon Backpack installation, this button allows the admin to open [elFinder](http://elfinder.org/) and select a file from there.
+
+```php
+[ // Browse
+ 'name' => 'image',
+ 'label' => 'Image',
+ 'type' => 'browse'
+],
+```
+
+
+Input preview:
+
+
+
+Onclick preview:
+
+
+
+
+### browse_multiple
+
+Open elFinder and select multiple files from there.
+
+```php
+[ // Browse multiple
+ 'name' => 'files',
+ 'label' => 'Files',
+ 'type' => 'browse_multiple',
+ // 'multiple' => true, // enable/disable the multiple selection functionality
+ // 'mime_types' => null, // visible mime prefixes; ex. ['image'] or ['application/pdf']
+],
+```
+
+We recommend you cast your attribute as ```array``` on your model. That way, when you do ```$entry->files``` you get a nice array. The field will work even if you don't cast.
+
+Input preview:
+
+
+
+
+### base64_image
+
+Upload an image and store it in the database as Base64. Notes:
+- make sure the column type is LONGBLOB;
+- detailed [instructions and customizations here](https://github.com/Laravel-Backpack/CRUD/pull/56#issue-164712261);
+
+```php
+$this->crud->addField([ // base64_image
+ 'label' => "Profile Image",
+ 'name' => "image",
+ 'filename' => "image_filename", // set to null if not needed
+ 'type' => 'base64_image',
+ 'aspect_ratio' => 1, // set to 0 to allow any aspect ratio
+ 'crop' => true, // set to true to allow cropping, false to disable
+ 'src' => NULL, // null to read straight from DB, otherwise set to model accessor function
+]);
+```
+
+Input preview:
+
+
+
+
+### checkbox
+
+Checkbox for true/false.
+
+```php
+[ // Checkbox
+ 'name' => 'active',
+ 'label' => 'Active',
+ 'type' => 'checkbox'
+],
+```
+
+Input preview:
+
+
+
+
+### checklist
+
+```php
+[
+ 'label' => 'Roles',
+ 'type' => 'checklist',
+ 'name' => 'roles',
+ 'entity' => 'roles',
+ 'attribute' => 'name',
+ 'model' => "Backpack\PermissionManager\app\Models\Role",
+ 'pivot' => true,
+]);
+```
+
+Input preview:
+
+
+
+
+### checklist_dependency
+
+```php
+
+// two interconnected entities
+'label' => 'User Role Permissions',
+'field_unique_name' => 'user_role_permission',
+'type' => 'checklist_dependency',
+'name' => 'roles_and_permissions', // the methods that defines the relationship in your Model
+'subfields' => [
+ 'primary' => [
+ 'label' => 'Roles',
+ 'name' => 'roles', // the method that defines the relationship in your Model
+ 'entity' => 'roles', // the method that defines the relationship in your Model
+ 'entity_secondary' => 'permissions', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'model' => "Backpack\PermissionManager\app\Models\Role", // foreign key model
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?]
+ 'number_columns' => 3, //can be 1,2,3,4,6
+ ],
+ 'secondary' => [
+ 'label' => 'Permission',
+ 'name' => 'permissions', // the method that defines the relationship in your Model
+ 'entity' => 'permissions', // the method that defines the relationship in your Model
+ 'entity_primary' => 'roles', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'model' => "Backpack\PermissionManager\app\Models\Permission", // foreign key model
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?]
+ 'number_columns' => 3, //can be 1,2,3,4,6
+ ],
+ ],
+],
+```
+
+Input preview:
+
+
+
+
+### ckeditor
+
+Show a wysiwyg CKEditor to the user.
+
+```php
+[ // CKEditor
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'ckeditor',
+ // optional:
+ 'extra_plugins' => ['oembed', 'widget'],
+ 'options' => [
+ 'autoGrow_minHeight' => 200,
+ 'autoGrow_bottomSpace' => 50,
+ 'removePlugins' => 'resize,maximize',
+ ]
+],
+```
+
+Input preview:
+
+
+
+
+### color
+
+```php
+[ // Color
+ 'name' => 'background_color',
+ 'label' => 'Background Color',
+ 'type' => 'color'
+],
+```
+
+Input preview:
+
+
+
+
+### color_picker
+
+Show a pretty colour picker using [Bootstrap Colorpicker](https://itsjavi.com/bootstrap-colorpicker/).
+
+```php
+[ // color_picker
+ 'label' => 'Background Color',
+ 'name' => 'background_color',
+ 'type' => 'color_picker',
+ 'color_picker_options' => ['customClass' => 'custom-class']
+]
+```
+
+Input preview:
+
+
+
+
+### custom_html
+
+Allows you to insert custom HTML in the create/update forms. Usually used in forms with a lot of fields, to separate them using h1-h5, hr, etc, but can be used for any HTML.
+
+```php
+[ // CustomHTML
+ 'name' => 'separator',
+ 'type' => 'custom_html',
+ 'value' => ''
+],
+```
+
+
+### date
+
+```php
+[ // Date
+ 'name' => 'birthday',
+ 'label' => 'Birthday',
+ 'type' => 'date'
+],
+```
+
+Input preview:
+
+
+
+
+### date_picker
+
+Show a pretty [Bootstrap Datepicker](http://bootstrap-datepicker.readthedocs.io/en/latest/).
+
+```php
+[ // date_picker
+ 'name' => 'date',
+ 'type' => 'date_picker',
+ 'label' => 'Date',
+ // optional:
+ 'date_picker_options' => [
+ 'todayBtn' => 'linked',
+ 'format' => 'dd-mm-yyyy',
+ 'language' => 'fr'
+ ],
+],
+```
+
+Please note it is recommended that you use [attribute casting](https://laravel.com/docs/eloquent-mutators#attribute-casting) on your model (cast to date).
+
+
+Input preview:
+
+
+
+
+### date_range
+
+Starting with Backpack\CRUD 3.1.59
+
+Show a DateRangePicker and let the user choose a start date and end date.
+
+```php
+ [
+ 'name' => 'event_date_range', // a unique name for this field
+ 'start_name' => 'start_date', // the db column that holds the start_date
+ 'end_name' => 'end_date', // the db column that holds the end_date
+ 'label' => 'Event Date Range',
+ 'type' => 'date_range',
+ // OPTIONALS
+ 'start_default' => '1991-03-28 01:01', // default value for start_date
+ 'end_default' => '1991-04-05 02:00', // default value for end_date
+ 'date_range_options' => [ // options sent to daterangepicker.js
+ 'timePicker' => true,
+ 'locale' => ['format' => 'DD/MM/YYYY HH:mm']
+ ]
+ ]
+```
+
+Please note it is recommended that you use [attribute casting](https://laravel.com/docs/eloquent-mutators#attribute-casting) on your model (cast to date).
+
+Your end result will look like this:
+
+Input preview:
+
+
+
+
+### datetime
+
+```php
+[ // DateTime
+ 'name' => 'start',
+ 'label' => 'Event start',
+ 'type' => 'datetime'
+],
+```
+
+**Please note:** if you're using datetime [attribute casting](https://laravel.com/docs/eloquent-mutators#attribute-casting) on your model, you also need to place this mutator inside your model:
+```php
+ public function setDatetimeAttribute($value) {
+ $this->attributes['datetime'] = \Carbon\Carbon::parse($value);
+ }
+```
+Otherwise the input's datetime-local formal will cause some errors.
+
+Input preview:
+
+
+
+
+### datetime_picker
+
+Show a [Bootstrap Datetime Picker](https://eonasdan.github.io/bootstrap-datetimepicker/).
+
+```php
+[ // DateTime
+ 'name' => 'start',
+ 'label' => 'Event start',
+ 'type' => 'datetime_picker',
+ // optional:
+ 'datetime_picker_options' => [
+ 'format' => 'DD/MM/YYYY HH:mm',
+ 'language' => 'fr'
+ ],
+ 'allows_null' => true,
+ // 'default' => '2017-05-12 11:59:59',
+],
+```
+
+Input preview:
+
+
+
+
+### email
+
+```php
+[ // Email
+ 'name' => 'email',
+ 'label' => 'Email Address',
+ 'type' => 'email'
+],
+```
+
+Input preview:
+
+
+
+
+
+### enum
+
+Show a select with the values in the database for that ENUM field. Requires that the db column type is "enum". If the db column allows null, the " - " value will also show up in the select.
+
+```php
+[ // Enum
+ 'name' => 'status',
+ 'label' => 'Status',
+ 'type' => 'enum'
+],
+```
+
+PLEASE NOTE the enum field only works for MySQL databases.
+
+Input preview:
+
+
+
+
+### hidden
+
+Include an in the form.
+
+```php
+[ // Hidden
+ 'name' => 'status',
+ 'type' => 'hidden'
+],
+```
+
+
+### icon_picker
+
+[/block]
+Show an icon picker. Supported icon sets are fontawesome, glyphicon, ionicon, weathericon, mapicon, octicon, typicon, elusiveicon, materialdesign as per the jQuery plugin, [bootstrap-iconpicker](http://victor-valencia.github.io/bootstrap-iconpicker/).
+
+The stored value will be the class name (ex: fa-home).
+
+```php
+[
+ 'label' => "Icon",
+ 'name' => 'icon',
+ 'type' => 'icon_picker',
+ 'iconset' => 'fontawesome' // options: fontawesome, glyphicon, ionicon, weathericon, mapicon, octicon, typicon, elusiveicon, materialdesign
+],
+```
+
+Your input will look like button, with a dropdown where the user can search or pick an icon:
+
+Input preview:
+
+
+
+
+### image
+
+Upload an image and store it on the disk.
+
+**Step 1.** Show the field.
+```php
+$this->crud->addField([ // image
+ 'label' => "Profile Image",
+ 'name' => "image",
+ 'type' => 'image',
+ 'upload' => true,
+ 'crop' => true, // set to true to allow cropping, false to disable
+ 'aspect_ratio' => 1, // omit or set to 0 to allow any aspect ratio
+ // 'disk' => 's3_bucket', // in case you need to show images from a different disk
+ // 'prefix' => 'uploads/images/profile_pictures/' // in case your db value is only the file name (no path), you can use this to prepend your path to the image src (in HTML), before it's shown to the user;
+]);
+```
+
+**Step 2.** Set a mutator on your Model, so that the file can be stored. You can use this boilerplate code and modify it to match your use case:
+
+```php
+// ..
+
+use Illuminate\Support\Str;
+
+// ..
+
+Class Product extends Model
+{
+ // ..
+
+ public function setImageAttribute($value)
+ {
+ $attribute_name = "image";
+ $disk = config('backpack.base.root_disk_name'); // or use your own disk, defined in config/filesystems.php
+ $destination_path = "public/uploads/folder_1/folder_2"; // path relative to the disk above
+
+ // if the image was erased
+ if ($value==null) {
+ // delete the image from disk
+ \Storage::disk($disk)->delete($this->{$attribute_name});
+
+ // set null in the database column
+ $this->attributes[$attribute_name] = null;
+ }
+
+ // if a base64 was sent, store it in the db
+ if (starts_with($value, 'data:image'))
+ {
+ // 0. Make the image
+ $image = \Image::make($value)->encode('jpg', 90);
+ // 1. Generate a filename.
+ $filename = md5($value.time()).'.jpg';
+ // 2. Store the image on disk.
+ \Storage::disk($disk)->put($destination_path.'/'.$filename, $image->stream());
+ // 3. Save the public path to the database
+ // but first, remove "public/" from the path, since we're pointing to it from the root folder
+ // that way, what gets saved in the database is the user-accesible URL
+ $public_destination_path = Str::replaceFirst('public/', '', $destination_path);
+ $this->attributes[$attribute_name] = $public_destination_path.'/'.$filename;
+ }
+ }
+
+// ..
+```
+> **The uploaded images are not deleted for you.** If you delete an entry (using the CRUD or anywhere inside your app), the image file won't be deleted from the disk.
+> If you're NOT using soft deletes on that Model and want the image to be deleted at the same time the entry is, just specify that in your Model's ```deleting``` event:
+> ```php
+ public static function boot()
+ {
+ parent::boot();
+ static::deleting(function($obj) {
+ \Storage::disk('public_folder')->delete($obj->image);
+ });
+ }
+ ```
+
+**A note about aspect_ratio**
+The value for aspect ratio is a float that represents the ratio of the cropping rectangle height and width. By way of example,
+
+- Square = 1
+- Landscape = 2
+- Portrait = 0.5
+
+And you can, of course, use any value for more extreme rectangles.
+
+Input preview:
+
+
+
+
+
+### month
+
+```php
+[ // Month
+ 'name' => 'month',
+ 'label' => 'Month',
+ 'type' => 'month'
+],
+```
+
+Input preview:
+
+
+
+
+### number
+
+Shows an input type=number to the user, with optional prefix and suffix:
+
+```php
+[ // Number
+ 'name' => 'number',
+ 'label' => 'Number',
+ 'type' => 'number',
+ // optionals
+ // 'attributes' => ["step" => "any"], // allow decimals
+ // 'prefix' => "$",
+ // 'suffix' => ".00",
+],
+```
+
+Input preview:
+
+
+
+
+### page_or_link
+
+Select an existing page from PageManager or an internal or external link. It's used in the MenuManager package, but can be used in any other model just as well. Its definition looks like this:
+```php
+[ // PageOrLink
+ 'name' => 'type',
+ 'label' => "Type",
+ 'type' => 'page_or_link',
+ 'page_model' => '\Backpack\PageManager\app\Models\Page'
+],
+```
+
+Input preview:
+
+
+
+
+### password
+
+```php
+[ // Password
+ 'name' => 'password',
+ 'label' => 'Password',
+ 'type' => 'password'
+],
+```
+
+Input preview:
+
+
+
+
+### radio
+
+Show radios according to an associative array you give the input and let the user pick from them. You can choose for the radio options to be displayed inline or one-per-line.
+
+```php
+[
+ 'name' => 'status', // the name of the db column
+ 'label' => 'Status', // the input label
+ 'type' => 'radio',
+ 'options' => [ // the key will be stored in the db, the value will be shown as label;
+ 0 => "Draft",
+ 1 => "Published"
+ ],
+ // optional
+ //'inline' => false, // show the radios all on the same line?
+],
+```
+
+Input preview:
+
+
+
+
+### range
+
+```php
+[ // Range
+ 'name' => 'range',
+ 'label' => 'Range',
+ 'type' => 'range'
+],
+```
+
+Input preview:
+
+
+
+
+### select (1-n relationship)
+
+Show a Select with the names of the connected entity and let the user select one of them.
+Your relationships should already be defined on your models as hasOne() or belongsTo().
+
+```php
+[ // Select
+ 'label' => "Category",
+ 'type' => 'select',
+ 'name' => 'category_id', // the db column for the foreign key
+ 'entity' => 'category', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'model' => "App\Models\Tag",
+
+ // optional
+ 'options' => (function ($query) {
+ return $query->orderBy('name', 'ASC')->where('depth', 1)->get();
+ }), // force the related options to be a custom query, instead of all(); you can use this to filter the results show in the select
+],
+```
+
+Input preview:
+
+
+
+
+
+### select_grouped
+
+Display a select where the options are grouped by a second entity (like Categories).
+
+```php
+[ // select_grouped
+ 'label' => 'Articles grouped by categories',
+ 'type' => 'select_grouped', //https://github.com/Laravel-Backpack/CRUD/issues/502
+ 'name' => 'article_id',
+ 'entity' => 'article',
+ 'attribute' => 'title',
+ 'group_by' => 'category', // the relationship to entity you want to use for grouping
+ 'group_by_attribute' => 'name', // the attribute on related model, that you want shown
+ 'group_by_relationship_back' => 'articles', // relationship from related model back to this model
+],
+```
+
+Input preview:
+
+
+
+
+### select2 (1-n relationship)
+
+Works just like the SELECT field, but prettier. Shows a Select2 with the names of the connected entity and let the user select one of them.
+Your relationships should already be defined on your models as hasOne() or belongsTo().
+
+```php
+[ // Select2
+ 'label' => "Category",
+ 'type' => 'select2',
+ 'name' => 'category_id', // the db column for the foreign key
+ 'entity' => 'category', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'model' => "App\Models\Tag", // foreign key model
+
+ // optional
+ 'default' => 2, // set the default value of the select2
+ 'options' => (function ($query) {
+ return $query->orderBy('name', 'ASC')->where('depth', 1)->get();
+ }), // force the related options to be a custom query, instead of all(); you can use this to filter the results show in the select
+],
+```
+
+Input preview:
+
+
+
+
+### select_multiple (n-n relationship)
+
+Show a Select with the names of the connected entity and let the user select any number of them.
+Your relationships should already be defined on your models as hasMany() or belongsToMany().
+
+```php
+[ // SelectMultiple = n-n relationship (with pivot table)
+ 'label' => "Tags",
+ 'type' => 'select_multiple',
+ 'name' => 'tags', // the method that defines the relationship in your Model
+ 'entity' => 'tags', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'model' => "App\Models\Tag", // foreign key model
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
+
+ // optional
+ 'options' => (function ($query) {
+ return $query->orderBy('name', 'ASC')->where('depth', 1)->get();
+ }), // force the related options to be a custom query, instead of all(); you can use this to filter the results show in the select
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### select2_multiple (n-n relationship)
+
+[Works just like the SELECT field, but prettier]
+
+Shows a Select2 with the names of the connected entity and let the user select any number of them.
+Your relationships should already be defined on your models as hasMany() or belongsToMany().
+
+```php
+[ // Select2Multiple = n-n relationship (with pivot table)
+ 'label' => "Tags",
+ 'type' => 'select2_multiple',
+ 'name' => 'tags', // the method that defines the relationship in your Model
+ 'entity' => 'tags', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'model' => "App\Models\Tag", // foreign key model
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
+ // 'select_all' => true, // show Select All and Clear buttons?
+
+ // optional
+ 'options' => (function ($query) {
+ return $query->orderBy('name', 'ASC')->where('depth', 1)->get();
+ }), // force the related options to be a custom query, instead of all(); you can use this to filter the results show in the select
+],
+```
+
+Input preview:
+
+
+
+
+### select2_nested
+
+Display a select2 with the values ordered hierarchically and indented, for an entity where you use Reorder. Please mind that the connected model needs:
+- a ```children()``` relationship pointing to itself;
+- the usual ```lft```, ```rgt```, ```depth``` attributes;
+
+```php
+[ // select2_nested
+ 'name' => 'category_id',
+ 'label' => "Category",
+ 'type' => 'select2_nested',
+ 'entity' => 'category', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ // 'model' => "App\Models\Category", // force foreign key model
+],
+```
+
+Input preview:
+
+
+
+
+
+### select2_grouped
+
+Display a select2 where the options are grouped by a second entity (like Categories).
+
+```php
+[ // select2_grouped
+ 'label' => 'Articles grouped by categories',
+ 'type' => 'select2_grouped', //https://github.com/Laravel-Backpack/CRUD/issues/502
+ 'name' => 'article_id',
+ 'entity' => 'article',
+ 'attribute' => 'title',
+ 'group_by' => 'category', // the relationship to entity you want to use for grouping
+ 'group_by_attribute' => 'name', // the attribute on related model, that you want shown
+ 'group_by_relationship_back' => 'articles', // relationship from related model back to this model
+],
+```
+
+Input preview:
+
+
+
+
+
+### select_and_order
+
+Display items on two columns and let the user drag&drop between them to choose which items are selected and which are not, and reorder the selected items with drag&drop.
+
+Its definition is exactly as ```select_from_array```, but the value will be stored as JSON in the database: ```["3","5","7","6"]```, so it needs the attribute to be cast to array on the Model:
+
+```php
+protected $casts = [
+ 'featured' => 'array'
+];
+```
+
+Definition:
+
+```php
+[ // select_and_order
+ 'name' => 'featured',
+ 'label' => "Featured",
+ 'type' => 'select_and_order',
+ 'options' => [
+ 1 => "Option 1",
+ 2 => "Option 2"
+ ]
+],
+```
+
+Also possible:
+
+```php
+[
+ 'name' => 'featured',
+ 'label' => 'Featured',
+ 'type' => 'select_and_order',
+ 'options' => Product::get()->pluck('title','id')->toArray(),
+],
+```
+
+Input preview:
+
+
+
+
+
+### select_from_array
+
+Display a select with the values you want:
+
+```php
+[ // select_from_array
+ 'name' => 'template',
+ 'label' => "Template",
+ 'type' => 'select_from_array',
+ 'options' => ['one' => 'One', 'two' => 'Two'],
+ 'allows_null' => false,
+ 'default' => 'one',
+ // 'allows_multiple' => true, // OPTIONAL; needs you to cast this to array in your model;
+],
+```
+
+Input preview:
+
+
+
+
+### select2_from_array
+
+Display a select2 with the values you want:
+
+```php
+[ // select_from_array
+ 'name' => 'template',
+ 'label' => "Template",
+ 'type' => 'select2_from_array',
+ 'options' => ['one' => 'One', 'two' => 'Two'],
+ 'allows_null' => false,
+ 'default' => 'one',
+ // 'allows_multiple' => true, // OPTIONAL; needs you to cast this to array in your model;
+],
+```
+
+Input preview:
+
+
+
+
+### select2_from_ajax
+
+Display a select2 that takes its values from an AJAX call.
+
+```
+[
+ // 1-n relationship
+ 'label' => "End", // Table column heading
+ 'type' => "select2_from_ajax",
+ 'name' => 'category_id', // the column that contains the ID of that connected entity
+ 'entity' => 'city', // the method that defines the relationship in your Model
+ 'attribute' => "name", // foreign key attribute that is shown to user
+ 'model' => "App\Models\Category", // foreign key model
+ 'data_source' => url("http://github.com/api/category"), // url to controller search function (with /{id} should return model)
+ 'placeholder' => "Select a category", // placeholder for the select
+ 'minimum_input_length' => 2, // minimum characters to type before querying results
+ // 'dependencies' => ['category'], // when a dependency changes, this select2 is reset to null
+ // 'method' => 'GET', // optional - HTTP method to use for the AJAX call (GET, POST)
+ // 'include_all_form_fields' => false, // optional - only send the current field through AJAX (for a smaller payload if you're not using multiple chained select2s)
+ ]
+```
+
+Of course, you also need to create a controller and routes for the data_source above. Here's an example:
+
+```
+Route::get('/api/category', 'Api\CategoryController@index');
+Route::get('/api/category/{id}', 'Api\CategoryController@show');
+```
+
+```
+input('q');
+ $page = $request->input('page');
+
+ if ($search_term)
+ {
+ $results = Category::where('name', 'LIKE', '%'.$search_term.'%')->paginate(10);
+ }
+ else
+ {
+ $results = Category::paginate(10);
+ }
+
+ return $results;
+ }
+
+ public function show($id)
+ {
+ return Category::find($id);
+ }
+}
+```
+
+Input preview:
+
+
+
+
+### select2_from_ajax_multiple
+
+Display a select2 that takes its values from an AJAX call. Same as [select2_from_ajax](#section-select2_from_ajax) above, but allows for multiple items to be selected. The only difference in the field definition is the "pivot" attribute.
+
+```
+[
+ // n-n relationship
+ 'label' => "End", // Table column heading
+ 'type' => "select2_from_ajax_multiple",
+ 'name' => 'city_id', // the column that contains the ID of that connected entity
+ 'entity' => 'city', // the method that defines the relationship in your Model
+ 'attribute' => "name", // foreign key attribute that is shown to user
+ 'model' => "App\Models\City", // foreign key model
+ 'data_source' => url("http://github.com/api/cities"), // url to controller search function (with /{id} should return model)
+ 'placeholder' => "Select a city", // placeholder for the select
+ 'minimum_input_length' => 2, // minimum characters to type before querying results
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
+ // 'include_all_form_fields' => false, // optional - only send the current field through AJAX (for a smaller payload if you're not using multiple chained select2s)
+ ]
+```
+
+Of course, you also need to create a controller and routes for the data_source above. Here's an example:
+
+```
+Route::get('/api/category', 'Api\CategoryController@index');
+Route::get('/api/category/{id}', 'Api\CategoryController@show');
+```
+
+```
+input('q');
+ $page = $request->input('page');
+
+ if ($search_term)
+ {
+ $results = Category::where('name', 'LIKE', '%'.$search_term.'%')->paginate(10);
+ }
+ else
+ {
+ $results = Category::paginate(10);
+ }
+
+ return $results;
+ }
+
+ public function show($id)
+ {
+ return Category::find($id);
+ }
+}
+```
+
+Input preview:
+
+
+
+
+### simplemde
+
+Show a [SimpleMDE markdown editor](https://simplemde.com/) to the user.
+
+```php
+[ // SimpleMDE
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'simplemde',
+ // optional
+ // 'simplemdeAttributes' => [
+ // 'promptURLs' => true,
+ // 'status' => false,
+ // 'spellChecker' => false,
+ // 'forceSync' => true,
+ // ],
+ // 'simplemdeAttributesRaw' => $some_json
+],
+```
+
+Input preview:
+
+
+
+
+### summernote
+
+Show a [Summernote wysiwyg editor](http://summernote.org/) to the user.
+
+```php
+[ // Summernote
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'summernote',
+ // 'options' => [], // easily pass parameters to the summernote JS initialization
+],
+```
+
+Input preview:
+
+
+
+
+### table
+
+Show a table with multiple inputs per row and store the values as JSON in the database. The user can add more rows and reorder the rows as they please.
+
+```php
+[ // Table
+ 'name' => 'options',
+ 'label' => 'Options',
+ 'type' => 'table',
+ 'entity_singular' => 'option', // used on the "Add X" button
+ 'columns' => [
+ 'name' => 'Name',
+ 'desc' => 'Description',
+ 'price' => 'Price'
+ ],
+ 'max' => 5, // maximum rows allowed in the table
+ 'min' => 0, // minimum rows allowed in the table
+],
+```
+
+>It's highly recommended that you use [attribute casting](https://laravel.com/docs/eloquent-mutators#attribute-casting) on your model when working with JSON stored in database columns, and cast your this attribute to either ```object``` or ```array```.
+
+Input preview:
+
+
+
+
+### text
+
+The basic field type, all it needs is the two mandatory parameters: name and label.
+
+```php
+[ // Text
+ 'name' => 'title',
+ 'label' => "Title",
+ 'type' => 'text',
+
+ // optional
+ //'prefix' => '',
+ //'suffix' => '',
+ //'default' => 'some value', // default value
+ //'hint' => 'Some hint text', // helpful text, show up after input
+ //'attributes' => [
+ //'placeholder' => 'Some text when empty',
+ //'class' => 'form-control some-class'
+ //], // extra HTML attributes and values your input might need
+ //'wrapperAttributes' => [
+ //'class' => 'form-group col-md-12'
+ //], // extra HTML attributes for the field wrapper - mostly for resizing fields
+ //'readonly'=>'readonly',
+],
+```
+
+You can use the optional 'prefix' and 'suffix' attributes to display something before and after the input, like icons, path prefix, etc:
+
+Input preview:
+
+
+
+
+### textarea
+
+Show a textarea to the user.
+
+```php
+[ // Textarea
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'textarea'
+],
+```
+
+Input preview:
+
+
+
+
+### time
+
+```php
+[ // Time
+ 'name' => 'start',
+ 'label' => 'Start time',
+ 'type' => 'time'
+],
+```
+
+
+### tinymce
+
+Show a wysiwyg (TinyMCE) to the user.
+
+```php
+[ // TinyMCE
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'tinymce',
+ // optional overwrite of the configuration array
+ // 'options' => [ 'selector' => 'textarea.tinymce', 'skin' => 'dick-light', 'plugins' => 'image,link,media,anchor' ],
+],
+```
+
+Input preview:
+
+
+
+
+### upload
+
+**Step 1.** Show a file input to the user:
+```php
+[ // Upload
+ 'name' => 'image',
+ 'label' => 'Image',
+ 'type' => 'upload',
+ 'upload' => true,
+ 'disk' => 'uploads' // if you store files in the /public folder, please omit this; if you store them in /storage or S3, please specify it;
+],
+```
+
+**Step 2.** In order to save/update/delete the file from disk&db, we need to create [a mutator](https://laravel.com/docs/5.3/eloquent-mutators#defining-a-mutator) on your model:
+```php
+public function setImageAttribute($value)
+ {
+ $attribute_name = "image";
+ $disk = "public";
+ $destination_path = "folder_1/subfolder_1";
+
+ $this->uploadFileToDisk($value, $attribute_name, $disk, $destination_path);
+
+ // return $this->{$attribute_name}; // uncomment if this is a translatable field
+ }
+```
+
+**How it works:**
+
+The field sends the file, through a Request, to the Controller. The Controller then tries to create/update the Model. That's when the mutator on your model will run. That also means we can do any [file validation](https://laravel.com/docs/5.3/validation#rule-file) (```file```, ```image```, ```mimetypes```, ```mimes```) in the Request, before the file is stored on the disk.
+
+[The ```uploadFileToDisk()``` method](https://github.com/Laravel-Backpack/CRUD/blob/master/src/CrudTrait.php#L108-L129) will take care of everything for most use cases:
+
+```php
+/**
+ * Handle file upload and DB storage for a file:
+ * - on CREATE
+ * - stores the file at the destination path
+ * - generates a name
+ * - stores the full path in the DB;
+ * - on UPDATE
+ * - if the value is null, deletes the file and sets null in the DB
+ * - if the value is different, stores the different file and updates DB value
+ * /
+public function uploadFileToDisk($value, $attribute_name, $disk, $destination_path) {}
+```
+
+If you wish to have a different functionality, you can delete the method call from your mutator and do your own thing.
+
+>**The uploaded files are not deleted for you.** When you delete an entry (wether through CRUD or the application), the uploaded files will not be deleted.
+
+If you're NOT using soft deletes on that Model and want the file to be deleted at the same time the entry is, just specify that in your Model's ```deleting``` event:
+```php
+ public static function boot()
+ {
+ parent::boot();
+ static::deleting(function($obj) {
+ \Storage::disk('public_folder')->delete($obj->image);
+ });
+ }
+```
+
+Input preview:
+
+
+
+
+### upload_multiple
+
+Shows a multiple file input to the user and stores the values as a JSON array in the database.
+
+**Step 1.** Show a multiple file input to the user:
+```php
+[ // Upload
+ 'name' => 'photos',
+ 'label' => 'Photos',
+ 'type' => 'upload_multiple',
+ 'upload' => true,
+ 'disk' => 'uploads' // if you store files in the /public folder, please omit this; if you store them in /storage or S3, please specify it;
+],
+```
+
+**Step 2.** In order to save/update/delete the files from disk&db, we need to create [a mutator](https://laravel.com/docs/5.3/eloquent-mutators#defining-a-mutator) on your model:
+```php
+public function setPhotosAttribute($value)
+ {
+ $attribute_name = "photos";
+ $disk = "public";
+ $destination_path = "folder_1/subfolder_1";
+
+ $this->uploadMultipleFilesToDisk($value, $attribute_name, $disk, $destination_path);
+ }
+```
+
+**Step 3.** Since the filenames are stored in the database as a JSON array, we're going to use [attribute casting](https://laravel.com/docs/eloquent-mutators#attribute-casting) on your model, so every time we get the filenames array from the database it's converted from a JSON array to a PHP array:
+```php
+ protected $casts = [
+ 'photos' => 'array'
+ ];
+```
+
+**How it works:**
+
+The field sends the files, through a Request, to the Controller. The Controller then tries to create/update the Model. That's when the mutator on your model will run. That also means we can do any [file validation](https://laravel.com/docs/5.3/validation#rule-file) (```file```, ```image```, ```mimetypes```, ```mimes```) in the Request, before the files are stored on the disk.
+
+[The ```uploadMultipleFilesToDisk()``` method](https://github.com/Laravel-Backpack/CRUD/blob/master/src/CrudTrait.php#L154-L189) will take care of everything for most use cases:
+
+```
+/**
+ * Handle multiple file upload and DB storage:
+ * - if files are sent
+ * - stores the files at the destination path
+ * - generates random names
+ * - stores the full path in the DB, as JSON array;
+ * - if a hidden input is sent to clear one or more files
+ * - deletes the file
+ * - removes that file from the DB.
+ * /
+public function uploadMultipleFilesToDisk($value, $attribute_name, $disk, $destination_path) {}
+```
+
+If you wish to have a different functionality, you can delete the method call from your mutator and do your own thing.
+
+>**The uploaded files are not deleted for you.** When you delete an entry (wether through CRUD or the application), the uploaded files will not be deleted.
+
+If you're NOT using soft deletes on that Model and want the files to be deleted at the same time the entry is, just specify that in your Model's ```deleting``` event:
+```php
+ public static function boot()
+ {
+ parent::boot();
+ static::deleting(function($obj) {
+ if (count((array)$obj->photos)) {
+ foreach ($obj->photos as $file_path) {
+ \Storage::disk('public_folder')->delete($file_path);
+ }
+ }
+ });
+ }
+```
+
+You might notice the field is using a ```clear_photos``` variable. Don't worry, you don't need it in your db table. That's just used to delete photos upon "update". If you use ```$fillable``` on your model, just don't include it. If you use ```$guarded``` on your model, place it in guarded.
+
+Input preview:
+
+
+
+
+### url
+
+[/block]
+```php
+[ // URL
+ 'name' => 'link',
+ 'label' => 'Link to video file',
+ 'type' => 'url'
+],
+```
+
+
+### video
+
+Allow the user to paste a Youtube/Vimeo link. That will get the video information with Javascript and store it as a JSON in the database.
+
+Field definition:
+```php
+[ // URL
+ 'name' => 'video',
+ 'label' => 'Link to video file on Youtube or Vimeo',
+ 'type' => 'video',
+],
+```
+
+An entry stored in the database will look like this:
+```
+$video = {
+ id: 234324,
+ title: 'my video title',
+ image: 'https://provider.com/image.jpg',
+ url: 'http://provider.com/video',
+ provider: 'youtube'
+}
+```
+
+So you should use [attribute casting](https://laravel.com/docs/eloquent-mutators#attribute-casting) in your model, to cast the video as ```array``` or ```object```.
+
+
+
+### view
+
+Load a custom view in the form.
+
+```php
+[
+ 'name' => 'custom-ajax-button',
+ 'type' => 'view',
+ 'view' => 'partials/custom-ajax-button'
+],
+```
+
+**Note:** the same functionality can be achieved using a [custom field type](/docs/{{version}}/crud-fields#creating-a-custom-field-type), or using the [custom_html field type](/docs/{{version}}/crud-fields#custom-html) (if the content is really simple).
+
+
+### week
+
+```php
+[ // Week
+ 'name' => 'first_week',
+ 'label' => 'First week',
+ 'type' => 'week'
+],
+```
+
+Input preview:
+
+
+
+
+### wysiwyg
+
+Show a wysiwyg (CKEditor) to the user.
+
+```php
+[ // WYSIWYG Editor
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'wysiwyg'
+],
+```
+
+
+## Overwriting Default Field Types
+
+The actual field types are stored in the Backpack/CRUD package in ```/resources/views/fields```. If you need to change an existing field, you don't need to modify the package, you just need to add a blade file in your application in ```/resources/views/vendor/backpack/crud/fields```, with the same name. The package checks there first, and only if there's no file there, will it load it from the package.
+
+To quickly publish a field blade file in your project, you can use ```php artisan backpack:crud:publish fields/field_name```. For example, to publish the number field type, you'd type ```php artisan backpack:crud:publish fields/number```
+
+>Please keep in mind that if you're using _your_ file for a field type, you're not using the _package file_. So any updates we push to that file, you're not getting them. In most cases, it's recommended you create a custom field type for your use case, instead of overwriting default field types.
+
+
+## Creating a Custom Field Type
+
+If you need to extend the CRUD with a new field type, you create a new file in your application in ```/resources/views/vendor/backpack/crud/fields```. Use a name that's different from all default field types. That's it, you'll now be able to use it just like a default field type.
+
+Your field definition will be something like:
+
+```php
+[
+ // Custom Field
+ 'name' => 'address',
+ 'label' => 'Home address',
+ 'type' => 'address'
+ /// 'view_namespace' => 'yourpackage' // use a custom namespace of your package to load views within a custom view folder.
+],
+```
+
+And your blade file something like:
+```php
+
+
+
+
+@if ($crud->checkIfFieldIsFirstOfItsType($field))
+ {{-- FIELD EXTRA CSS --}}
+ {{-- push things in the after_styles section --}}
+
+ @push('crud_fields_styles')
+
+ @endpush
+
+
+ {{-- FIELD EXTRA JS --}}
+ {{-- push things in the after_scripts section --}}
+
+ @push('crud_fields_scripts')
+
+ @endpush
+@endif
+
+// Note: most of the times you'll want to use @if ($crud->checkIfFieldIsFirstOfItsType($field, $fields)) to only load CSS/JS once, even though there are multiple instances of it.
+```
+
+Inside your custom field type, you can use these variables:
+- ```$crud``` - all the CRUD Panel settings, options and variables;
+- ```$entry``` - in the Update operation, the current entry being modified (the actual values);
+- ```$field``` - all attributes that have been passed for this field;
diff --git a/3.6/crud-filters.md b/3.6/crud-filters.md
new file mode 100644
index 00000000..21bed0d1
--- /dev/null
+++ b/3.6/crud-filters.md
@@ -0,0 +1,457 @@
+# Filters
+
+---
+
+
+## About
+
+Backpack CRUD allows you to show a filters bar right above the entries table. When selected or modified, they reload the DataTables results. The search will then search within the filtered elements.
+
+
+
+Just like with fields, columns or buttons, you can add existing filters or create a custom filter that fits to your particular needs. Everything's done inside your ```EntityCrudController::setup()```.
+
+
+### Filters API
+
+In order to manipulate filters, you can use:
+
+```php
+$this->crud->addFilter($options, $values, $filter_logic);
+
+$this->crud->removeFilter($name);
+$this->crud->removeAllFilters();
+
+$this->crud->filters(); // gets all the filters
+```
+
+
+### Adding a filter
+
+When adding a filter you need to specify the 3 parameters of the ```addFilter()``` method:
+- $options - an array of options (name, type, label are most important)
+- $values - filter values - can be an array or a closure
+- $filter_logic - what should happen if the filter is applied (usually add a clause to the query) - can be a closure, a string for a simple operation or false for a simple "where";
+
+Here's a simple example, with comments that explain what we're doing:
+```php
+$this->crud->addFilter([ // add a "simple" filter called Draft
+ 'type' => 'simple',
+ 'name' => 'draft',
+ 'label'=> 'Draft'
+],
+false, // the simple filter has no values, just the "Draft" label specified above
+function() { // if the filter is active (the GET parameter "draft" exits)
+ $this->crud->addClause('where', 'draft', '1');
+ // we've added a clause to the CRUD so that only elements with draft=1 are shown in the table
+ // an alternative syntax to this would have been
+ // $this->crud->query = $this->crud->query->where('draft', '1');
+ // another alternative syntax, in case you had a scopeDraft() on your model:
+ // $this->crud->addClause('draft');
+});
+```
+> Notes about the filter logic closure
+> - the code will only be run on the controller's ```index()``` or ```search()``` methods;
+> - you can get the filter value by specifying a parameter to the function (ex: ```$value```);
+> - you have access to other request variables using ```$this->crud->request```;
+> - you also have read/write access to public properties using ```$this->crud```;
+> - when building complicated "OR" logic, make sure the first "where" in your closure is a "where" and only the subsequent are "orWhere"; Laravel 5.3+ no longer converts the first "orWhere" into a "where";
+
+
+## Filter types
+
+
+### Simple
+
+Only shows a label and can be toggled on/off. Useful for things like active/inactive and easily paired with [Eloquent Scopes](https://laravel.com/docs/5.3/eloquent#local-scopes). The "Draft" and "Has Video" filters in the screenshot above are simple filters.
+
+```php
+$this->crud->addFilter([ // simple filter
+ 'type' => 'simple',
+ 'name' => 'active',
+ 'label'=> 'Active'
+],
+false,
+function() { // if the filter is active
+ // $this->crud->addClause('active'); // apply the "active" eloquent scope
+} );
+```
+
+
+### Text
+
+Shows a text input. Most useful for letting the user filter through information that's not shown as a column in the CRUD table - otherwise they could just use the DataTables search field.
+
+
+
+```php
+$this->crud->addFilter([ // simple filter
+ 'type' => 'text',
+ 'name' => 'description',
+ 'label'=> 'Description'
+],
+false,
+function($value) { // if the filter is active
+ // $this->crud->addClause('where', 'description', 'LIKE', "%$value%");
+} );
+```
+
+
+### Date
+
+Show a datepicker. The user can select one day.
+
+
+
+```php
+$this->crud->addFilter([ // date filter
+ 'type' => 'date',
+ 'name' => 'date',
+ 'label'=> 'Date'
+],
+false,
+function($value) { // if the filter is active, apply these constraints
+ // $this->crud->addClause('where', 'date', $value);
+});
+```
+
+
+### Date range
+
+Show a daterange picker. The user can select a start date and an end date.
+
+
+
+```php
+$this->crud->addFilter([ // daterange filter
+ 'type' => 'date_range',
+ 'name' => 'from_to',
+ 'label'=> 'Date range'
+],
+false,
+function($value) { // if the filter is active, apply these constraints
+ // $dates = json_decode($value);
+ // $this->crud->addClause('where', 'date', '>=', $dates->from);
+ // $this->crud->addClause('where', 'date', '<=', $dates->to . ' 23:59:59');
+});
+```
+
+
+### Dropdown
+
+Shows a list of elements (that you provide) in a dropdown. The user can only select one of these elements.
+
+
+
+```php
+$this->crud->addFilter([ // dropdown filter
+ 'name' => 'status',
+ 'type' => 'dropdown',
+ 'label'=> 'Status'
+], [
+ 1 => 'In stock',
+ 2 => 'In provider stock',
+ 3 => 'Available upon ordering',
+ 4 => 'Not available',
+], function($value) { // if the filter is active
+ // $this->crud->addClause('where', 'status', $value);
+});
+```
+
+
+### Select2
+
+Shows a select2 and allows the user to select one item from the list or search for an item. Useful when the values list is long (over 10 elements).
+
+
+
+```php
+$this->crud->addFilter([ // select2 filter
+ 'name' => 'status',
+ 'type' => 'select2',
+ 'label'=> 'Status'
+], function() {
+ return [
+ 1 => 'In stock',
+ 2 => 'In provider stock',
+ 3 => 'Available upon ordering',
+ 4 => 'Not available',
+ ];
+}, function($value) { // if the filter is active
+ // $this->crud->addClause('where', 'status', $value);
+});
+```
+
+**Note:** If you want to pass all entries of a Laravel model to your filter, you can do it in the second parameter (the closure), with something like ```return \Backpack\NewsCRUD\app\Models\Category::all()->keyBy('id')->pluck('name', 'id')->toArray();```;
+
+
+### Select2_multiple
+
+Shows a select2 and allows the user to select one or more items from the list or search for an item. Useful when the values list is long (over 10 elements) and your user should be able to select multiple elements. You can decide yourself if the query for each element should use 'where' or 'orWhere', in the third parameter of the ```addFilter()``` method.
+
+
+
+```php
+$this->crud->addFilter([ // select2_multiple filter
+ 'name' => 'status',
+ 'type' => 'select2_multiple',
+ 'label'=> 'Status'
+], function() {
+ return [
+ 1 => 'In stock',
+ 2 => 'In provider stock',
+ 3 => 'Available upon ordering',
+ 4 => 'Not available',
+ ];
+}, function($values) { // if the filter is active
+ // foreach (json_decode($values) as $key => $value) {
+ // $this->crud->addClause('where', 'published', $value);
+ // }
+});
+```
+
+
+### Select2_ajax
+
+Shows a select2 and allows the user to select one item from the list or search for an item. This list is fetched through an AJAX call by the select2. Useful when the values list is long (over 1000 elements).
+
+
+
+1. Add a route for the ajax search, right above your usual ```CRUD::resource()``` route. Example:
+
+```php
+Route::get('test/ajax-category-options', 'TestCrudController@categoryOptions');
+CRUD::resource('test', 'TestCrudController');
+```
+
+2. Add a method to your EntityCrudController that responds to a search term. The result should be an array with ```id => value```. Example for a 1-n relationship:
+
+```php
+public function categoryOptions(Request $request) {
+ $term = $request->input('term');
+ $options = App\Models\Category::where('name', 'like', '%'.$term.'%')->get()->pluck('name', 'id');
+ return $options;
+}
+```
+
+3. Add the select2_ajax filter and for the second parameter ("values") specify the exact route.
+
+```php
+$this->crud->addFilter([ // select2_ajax filter
+ 'name' => 'category_id',
+ 'type' => 'select2_ajax',
+ 'label'=> 'Category',
+ 'placeholder' => 'Pick a category'
+],
+url('http://github.com/admin/test/ajax-category-options'), // the ajax route
+function($value) { // if the filter is active
+ // $this->crud->addClause('where', 'category_id', $value);
+});
+```
+
+
+### Range
+
+Shows two number inputs, for min and max.
+
+
+
+```php
+$this->crud->addFilter([
+ 'name' => 'number',
+ 'type' => 'range',
+ 'label'=> 'Range',
+ 'label_from' => 'min value',
+ 'label_to' => 'max value'
+],
+false,
+function($value) { // if the filter is active
+ $range = json_decode($value);
+ if ($range->from) {
+ $this->crud->addClause('where', 'number', '>=', (float) $range->from);
+ }
+ if ($range->to) {
+ $this->crud->addClause('where', 'number', '<=', (float) $range->to);
+ }
+});
+```
+
+### View
+
+Display any custom column filter you want. Usually used by Backpack package developers, to use views from within their packages, instead of having to publish them.
+
+```php
+$this->crud->addFilter([ // custom filter view
+ 'name' => 'category_id',
+ 'type' => 'view',
+ 'view' => 'package::columns.column_type_name', // or path to blade file
+ 'label'=> 'Category',
+ 'placeholder' => 'Pick a category',
+],
+false,
+function($value) { // if the filter is active
+ // $this->crud->addClause('where', 'category_id', $value);
+});
+```
+
+
+## Creating custom filters
+
+Creating a new filter type is as easy as using the template below and placing a new view in your ```resources/views/vendor/backpack/crud/filters``` folder. You can then call this new filter by its view's name (ex: ```custom_select.blade.php``` will mean your filter type is called ```custom_select```).
+
+The filters bar is actually a [bootstrap navbar](http://getbootstrap.com/components/#navbar) at its core, but slimmer. So adding a new filter will be just like adding a menu item (for the HTML). Start from the ```text``` filter below and build your functionality.
+
+Inside this file, you'll have:
+- ```$filter``` object - includes everything you've defined on the current field;
+- ```$crud``` - the CrudPanel object;
+
+```php
+{{-- Text Backpack CRUD filter --}}
+
+
+
+{{-- ########################################### --}}
+{{-- Extra CSS and JS for this particular filter --}}
+
+
+{{-- FILTERS EXTRA JS --}}
+{{-- push things in the after_scripts section --}}
+
+@push('crud_list_scripts')
+
+
+@endpush
+{{-- End of Extra CSS and JS --}}
+{{-- ########################################## --}}
+```
+
+
+## Examples
+
+Use a dropdown to filter by the values of a MySQL ENUM column:
+
+```php
+$this->crud->addFilter([ // select2 filter
+ 'name' => 'published',
+ 'type' => 'select2',
+ 'label'=> 'Published'
+], function() {
+ return \App\Models\Test::getEnumValuesAsAssociativeArray('published');
+}, function($value) { // if the filter is active
+ $this->crud->addClause('where', 'published', $value);
+});
+```
+
+Use a select2 to filter by a 1-n relationship:
+```php
+$this->crud->addFilter([ // select2 filter
+ 'name' => 'category_id',
+ 'type' => 'select2',
+ 'label'=> 'Category'
+], function() {
+ return \App\Models\Category::all()->pluck('name', 'id')->toArray();
+}, function($value) { // if the filter is active
+ $this->crud->addClause('where', 'category_id', $value);
+});
+```
+
+Use a select2_multiple to filter Products by an n-n relationship:
+```php
+$this->crud->addFilter([ // select2_multiple filter
+ 'name' => 'tags',
+ 'type' => 'select2_multiple',
+ 'label'=> 'Tags'
+], function() { // the options that show up in the select2
+ return Product::all()->pluck('name', 'id')->toArray();
+}, function($values) { // if the filter is active
+ foreach (json_decode($values) as $key => $value) {
+ $this->crud->query = $this->crud->query->whereHas('tags', function ($query) use ($value) {
+ $query->where('tag_id', $value);
+ });
+ }
+});
+```
+
+Use a simple filter to add a scope if the filter is active:
+```php
+$this->crud->addFilter([ // add a "simple" filter called Published
+ 'type' => 'simple',
+ 'name' => 'published',
+ 'label'=> 'Published'
+],
+false,
+function() { // if the filter is active (the GET parameter "published" exits)
+ $this->crud->addClause('published');
+});
+```
+
+Use a simple filter to show the softDeleted items (trashed):
+```php
+ $this->crud->addFilter([
+ 'type' => 'simple',
+ 'name' => 'trashed',
+ 'label'=> 'Trashed'
+ ],
+ false,
+ function($values) { // if the filter is active
+ $this->crud->query = $this->crud->query->onlyTrashed();
+ });
+```
diff --git a/3.6/crud-how-to.md b/3.6/crud-how-to.md
new file mode 100644
index 00000000..b85723d0
--- /dev/null
+++ b/3.6/crud-how-to.md
@@ -0,0 +1,331 @@
+# How To for Backpack\CRUD
+
+---
+
+In addition the usual CRUD functionality, Backpack also allows you to do a few more complicated things:
+
+
+## Customize Views for each CRUD Panel
+
+Backpack loads its views through a double-fallback mechanism:
+- by default, it will load the views in the vendor folder (the package views);
+- if you've included views with the exact same name in your ```resources/views/vendor/backpack/crud``` folder, it will pick up those instead; you can use this method to overwrite a blade file for all CRUDs;
+- alternatively, if you only want to change a blade file for one CRUD, you can use the methods below in your ```setup()``` method, to change a particular view:
+```php
+$this->crud->setShowView('your-view');
+$this->crud->setEditView('your-view');
+$this->crud->setCreateView('your-view');
+$this->crud->setListView('your-view');
+$this->crud->setReorderView('your-view');
+$this->crud->setRevisionsView('your-view');
+$this->crud->setRevisionsTimelineView('your-view');
+$this->crud->setDetailsRowView('your-view');
+```
+
+
+## Customize CSS and JS for Default CRUD Operations
+
+Each default Backpack operation has its own CSS and JS file, in:
+- ```public/vendor/backpack/crud/css```
+- ```public/vendor/backpack/crud/js```
+
+If you don't find one there, you can create one, and Backpack will pick it up in that operation's view (ex: ```create.css``` or ```list.js```).
+
+
+## Add Extra CRUD Routes
+
+Starting with Backpack\CRUD 3.2, you can use the ```with()``` method on ```CRUD::resource``` to better organize your routes. Something like this:
+
+```php
+CRUD::resource('teams', 'Admin\TeamCrudController')->with(function(){
+ // add extra routes to this resource
+ Route::get('teams/ajax-name-options', 'Admin\TeamCrudController@nameOptions');
+ Route::get('teams/ajax-category-options', 'Admin\TeamCrudController@categoryOptions');
+});
+```
+
+
+## Publish a column / field / filter / button and modify it
+
+All Backpack packages allow you to easily overwrite and customize the views. If you want Backpack to pick up _your_ file, instead of the one in the package, you can do that by just placing a file with the same name in your views. So if you want to overwrite the select2 field (```vendor/backpack/crud/src/resources/views/fields/select2.blade.php```) to change some functionality, you need to create ```resources/views/vendor/backpack/crud/fields/select2.blade.php```. You can do that manually, or use this command:
+```shell
+php artisan backpack:crud:publish fields/select2
+```
+This will look for the blade file and copy it inside the folder, so you can edit it.
+
+>**Please note:** Once you place a file with the same name inside your project, Backpack will pick that one up instead of the one in the package. That means that even though the file in the package is updated, you won't be getting those updates, since you're not using that file. Blade modifications are almost never breaking changes, but it's a good thing to receive updates with zero effort. Even small ones. So please overwrite the files as little as possible. Best to create your own custom fields/column/filters/buttons, whenever you can.
+
+
+## Filter the options in a select field
+
+This also applies to: select2, select2_multiple, select2_from_ajax, select2_from_ajax_multiple.
+
+There are 3 possible solutions:
+1. If there will be few options (dozens), the easiest way would be to use ```select_from_array``` or ```select2_from_array``` instead. Since you tell it what the options are, you can do any filtering you want there.
+2. If there are a lot of options (100+), best to use ```select2_from_ajax``` instead. You'll be able to filter the results any way you want in the controller method (the one that responds with the results to the AJAX call).
+3. If you can't use ```select2_from_array``` for ```select2_from_ajax```, you can create another model and add a global scope to it. For example, say you only want to show the users that belong to the user's company. You can create ```App\Models\CompanyUser``` and use that in your ```select2``` field instead of ```App\Models\User```:
+
+```php
+company_id) {
+ $companyId = Auth::user()->company->id;
+
+ static::addGlobalScope('company_id', function (Builder $builder) use ($companyId) {
+ $builder->where('company_id', $companyId);
+ });
+ }
+ }
+}
+```
+
+
+## Use the same column name multiple times in a CRUD
+
+If you try to add multiple columns with the same ```name```, by default Backpack will only show the last one. That's because ```name``` is also used as a key in the ```$column``` array. So when you ```addColumn()``` with the same name twice, it just overwrites the previous one.
+
+In order to insert two columns with the same name, use the ```key``` attribute on the second column (or both columns). If this attribute is present for a column, Backpack will use ```key``` instead of ```name```. Example:
+
+```diff
+ $this->crud->addColumn([
+ 'label' => "Location",
+ 'type' => 'select',
+ 'name' => 'location_id',
+ 'entity' => 'location',
+ 'attribute' => 'title',
+ 'model' => "App\Models\Location"
+ ]);
+
+ $this->crud->addColumn([
+ 'label' => "Location Type",
+ 'type' => 'radio_location_type',
+ 'options' => [
+ 1 => "Country",
+ 2 => "Region"
+ ],
+ 'name' => 'location_id',
++ 'key' => 'location_type',
+ 'entity' => 'location',
+ 'attribute' => 'type',
+ 'model' => "App\Models\Location"
+ ]);
+```
+
+
+## Use the Media Library (File Manager)
+
+If you've chosen to install [elFinder](http://elfinder.org/) when installing Backpack, you already have a media manager. And it's integrated into:
+- TinyMCE (as "tinymce" fieldtype)
+- CKEditor (as "ckeditor" fieldtype)
+- CRUD "browse" fieldtype
+- standalone, at the *your-project/admin/elfinder* route;
+
+For the integration, barryvdh's [laravel-elfinder](https://github.com/barryvdh/laravel-elfinder) package is used.
+
+
+
+
+## Manually install Backpack/CRUD
+
+If the automatic installation doesn't work for you and you need to manually install CRUD, here are all the commands it is running:
+
+1) In your terminal:
+
+``` bash
+composer require backpack/crud
+```
+
+2) If you'd also like a file manager, run:
+```bash
+composer require barryvdh/laravel-elfinder
+mkdir -p public/uploads
+php artisan elfinder:publish
+php artisan vendor:publish --provider="Backpack\CRUD\CrudServiceProvider" --tag="elfinder"
+php artisan backpack:base:add-sidebar-content '
'
+```
+
+3) Actually install CRUD:
+```bash
+php artisan vendor:publish --provider="Backpack\CRUD\CrudServiceProvider" --tag="public"
+php artisan vendor:publish --provider="Backpack\CRUD\CrudServiceProvider" --tag="lang"
+php artisan vendor:publish --provider="Backpack\CRUD\CrudServiceProvider" --tag="config"
+```
+
+
+## Load fields from a different folder
+
+If you're developing a package, you might need Backpack to pick up fields from your package folder, instead of having to publish them upon installation.
+
+Fields, Columns and Filters all have a ```view_namespace``` parameter you can use. Type your folder there, and Backpack will check that folder first, then where the views are published, then Backpack's package folder. Example:
+
+```php
+$this->crud->addFilter([ // add a "simple" filter called Draft
+ 'type' => 'complex',
+ 'name' => 'checkbox',
+ 'label' => 'Checked',
+ 'view_namespace' => 'custom_filters'
+ ],
+ false, // the simple filter has no values, just the "Draft" label specified above
+ function () { // if the filter is active (the GET parameter "draft" exits)
+ $this->crud->addClause('where', 'checkbox', '1');
+ });
+```
+This will make Backpack look for the ```resources/views/custom_filters/complex.blade.php```, and pick that up before anything else.
+
+
+## Add a select2 field that depends on another field
+
+The ```select2_from_ajax``` and ```select2_from_ajax_multiple``` fields allow you to filter the results of a select2, depending on what has already been selected in a form. Say you have to select2 fields. When the AJAX call is made to the second field, all other variables in the page also get passed - that means you can filter the results of the second select2.
+
+Say you want to show two selects:
+- the first one shows Categories
+- the second one shows Articles, but only from the category above
+
+1. In you CrudController you would do:
+
+```php
+
+ $this->crud->addField([ // SELECT2
+ 'label' => 'Category',
+ 'type' => 'select',
+ 'name' => 'category',
+ 'entity' => 'category',
+ 'attribute' => 'name',
+ ]);
+
+ $this->crud->addField([ // select2_from_ajax: 1-n relationship
+ 'label' => "Article", // Table column heading
+ 'type' => 'select2_from_ajax_multiple',
+ 'name' => 'articles', // the column that contains the ID of that connected entity;
+ 'entity' => 'article', // the method that defines the relationship in your Model
+ 'attribute' => 'title', // foreign key attribute that is shown to user
+ 'data_source' => url('http://github.com/api/article'), // url to controller search function (with /{id} should return model)
+ 'placeholder' => 'Select an article', // placeholder for the select
+ 'minimum_input_length' => 0, // minimum characters to type before querying results
+ 'dependencies' => ['category'], // when a dependency changes, this select2 is reset to null
+ // 'method' => 'GET', // optional - HTTP method to use for the AJAX call (GET, POST)
+ ]);
+```
+
+**DIFFERENT HERE**: ```minimum_input_length``` and ```dependencies```.
+
+2. That second select points to routes that need to be registered:
+
+```php
+Route::get('api/article', 'App\Http\Controllers\Api\ArticleController@index');
+Route::get('api/article/{id}', 'App\Http\Controllers\Api\ArticleController@show');
+```
+
+**DIFFERENT HERE**: Nothing.
+
+3. Then that controller would look something like this:
+
+```php
+input('q');
+ $form = collect($request->input('form'))->pluck('value', 'name');
+
+ $options = Article::query();
+
+ // if no category has been selected, show no options
+ if (! $form['category']) {
+ return [];
+ }
+
+ // if a category has been selected, only show articles in that category
+ if ($form['category']) {
+ $options = $options->where('category_id', $form['category']);
+ }
+
+ if ($search_term) {
+ $results = $options->where('title', 'LIKE', '%'.$search_term.'%')->paginate(10);
+ } else {
+ $results = $options->paginate(10);
+ }
+
+ return $options->paginate(10);
+ }
+
+ public function show($id)
+ {
+ return Article::find($id);
+ }
+}
+```
+
+**DIFFERENT HERE**: We use ```$form``` to determine what other variables have been selected in the form, and modify the result accordingly.
+
+
+
+## Change the content class for an operation
+
+If you want to make the contents of an operation take more / less space from the window, you can do that:
+
+(A) for all CRUDs by specifying the custom content class in your ```config/backpack/crud.php```:
+
+```php
+ // Here you may override the css-classes for the content section of the create view globally
+ // To override per view use $this->crud->setCreateContentClass('class-string')
+ 'create_content_class' => 'col-md-8 col-md-offset-2',
+
+ // Here you may override the css-classes for the content section of the edit view globally
+ // To override per view use $this->crud->setEditContentClass('class-string')
+ 'edit_content_class' => 'col-md-8 col-md-offset-2',
+
+ // Here you may override the css-classes for the content section of the revisions timeline view globally
+ // To override per view use $this->crud->setRevisionsTimelineContentClass('class-string')
+ 'revisions_timeline_content_class' => 'col-md-10 col-md-offset-1',
+
+ // Here you may override the css-class for the content section of the list view globally
+ // To override per view use $this->crud->setListContentClass('class-string')
+ 'list_content_class' => 'col-md-12',
+
+ // Here you may override the css-classes for the content section of the show view globally
+ // To override per view use $this->crud->setShowContentClass('class-string')
+ 'show_content_class' => 'col-md-8 col-md-offset-2',
+
+ // Here you may override the css-classes for the content section of the reorder view globally
+ // To override per view use $this->crud->setReorderContentClass('class-string')
+ 'reorder_content_class' => 'col-md-8 col-md-offset-2',
+```
+
+(B) for a single CRUD, by using:
+
+```php
+$this->crud->setCreateContentClass('col-md-8 col-md-offset-2');
+$this->crud->setUpdateContentClass('col-md-8 col-md-offset-2');
+$this->crud->setListContentClass('col-md-8 col-md-offset-2');
+$this->crud->setShowContentClass('col-md-8 col-md-offset-2');
+$this->crud->setReorderContentClass('col-md-8 col-md-offset-2');
+$this->crud->setRevisionsTimelineContentClass('col-md-8 col-md-offset-2');
+```
diff --git a/3.6/crud-operation-clone.md b/3.6/crud-operation-clone.md
new file mode 100644
index 00000000..d5f20552
--- /dev/null
+++ b/3.6/crud-operation-clone.md
@@ -0,0 +1,91 @@
+# Clone
+
+--
+
+
+## About
+
+This CRUD operation allows your admins to duplicate one or more entries from the database.
+
+>**IMPORTANT:** The clone operation does NOT duplicate related entries. So n-n relationships will be unaffected. However, this also means that n-n relationships are ignored. So when you clone an entry, the new entry:
+>- will NOT have the same 1-1 relationships
+>- will have the same 1-n relationships
+>- will NOT have the same n-1 relationships
+>- will NOT have the same n-n relationships
+>
+>This might be somewhat counterintuitive for end users - though it should make perfect sense for us developers. This is why the Clone operation is NOT enabled by default.
+
+
+## Clone a Single Item
+
+
+### How it Works
+
+Using AJAX, a POST request is performed towards ```/entity-name/{id}```, which points to the ```clone()``` method in your EntityCrudController.
+
+
+### How to Use
+
+The ```clone()``` action is **disabled by default**. To enable it, you should use ```$this->crud->allowAccess('clone');``` inside your ```setup()``` method. This will make the Clone button appear in the table view, and will allow access to the controller method if manually accessed.
+
+
+### How to Overwrite
+
+In case you need to change how this operation works, just create a ```clone()``` method in your EntityCrudController:
+
+```php
+public function clone($id)
+{
+ $this->crud->hasAccessOrFail('clone');
+ $this->crud->setOperation('clone');
+
+ // whatever you want
+}
+```
+
+You can also overwrite the clone button by creating a file with the same name inside your ```resources/views/vendor/backpack/crud/buttons/```. You can easily publish the clone button there to make changes using:
+
+```zsh
+php artisan backpack:crud:publish buttons/clone
+```
+
+
+## Clone Multiple Items (Bulk Clone)
+
+In addition to the button for each entry, you can show checkboxes next to each element, and allow your admin to clone multiple entries at once.
+
+
+
+### How it Works
+
+Using AJAX, a POST request is performed towards ```/entity-name/bulk-clone```, which points to the ```bulkClone()``` method in your EntityCrudController.
+
+
+### How to Use
+
+The ```bulkClone()``` action is **disabled by default**, and there are no buttons using it. To make the buttons show up, inside your ```setup()``` method you should:
+
+```php
+$this->crud->enableBulkActions(); // if you haven't already
+
+$this->crud->allowAccess('clone');
+$this->crud->addButton('bottom', 'bulk_clone', 'view', 'crud::buttons.bulk_clone', 'beginning');
+```
+
+
+### How to Overwrite
+
+In case you need to change how this operation works, just create a ```bulkClone()``` method in your EntityCrudController:
+
+```php
+public function bulkClone($id)
+{
+ // your custom code here
+}
+```
+
+You can also overwrite the bulk clone button by creating a file with the same name inside your ```resources/views/vendor/backpack/crud/buttons/```. You can easily publish the clone button there to make changes using:
+
+```zsh
+php artisan backpack:crud:publish buttons/bulk_clone
+```
diff --git a/3.6/crud-operation-create.md b/3.6/crud-operation-create.md
new file mode 100644
index 00000000..855b7b11
--- /dev/null
+++ b/3.6/crud-operation-create.md
@@ -0,0 +1,88 @@
+# Create
+
+---
+
+
+## About
+
+This operation allows your admins to add new entries to a database table.
+
+
+
+
+## Requirements
+
+All editable attributes should be ```$fillable``` on your Model.
+
+
+## How to Use
+
+The ```Create``` operation is **enabled by default**. To disable it, you should use ```$this->crud->denyAccess('create');``` inside your ```setup()``` method. This will make the Add button disappear in ListEntries, in the ```top``` button stack.
+
+To use the Create operation, you must:
+
+**Step 1. Specify what field types** you'd like to show for each editable attribute, in your EntityCrudController's ```setup()``` method. You can do that using the [Fields API](/docs/{{version}}/crud-fields#fields-api). In short you can:
+
+```php
+// add a field only to the Create operation
+$this->crud->addField($field_definition_array, 'create');
+// add a field to both the Create and Update operations
+$this->crud->addField($field_definition_array);
+```
+
+**Step 2. Specify validation rules, in your the EntityCrudRequest file** that you are typehinting on your ```EntityCrudController::store()``` method. If you need separate validation for Create and Update [look here](#separate-validation).
+
+For more on how to manipulate fields, please read the [Fields documentation page](/docs/{{version}}/crud-fields). For more on validation rules, check out [Laravel's validation docs](https://laravel.com/docs/master/validation#available-validation-rules).
+
+
+## How It Works
+
+CrudController is a RESTful controller, so the ```Create``` operation uses two routes:
+- GET to ```/entity-name/create``` - points to ```create()``` which shows the Add New Entry form (```create.blade.php```);
+- POST to ```/entity-name``` - points to ```store()``` which does the actual storing operation;
+
+The ```create()``` method will show all the fields you've defined for this operation using the [Fields API](/docs/{{version}}/crud-fields#fields-api), then upon Save the ```store()``` method will first check the validation from the typehinted FormRequest, then create the entry using the Eloquent model. Only attributes that are ```$fillable``` on the model will actually be stored in the database.
+
+
+## Callbacks
+
+Developers coming from GroceryCRUD or other CRUD systems will be looking for callbacks to run before_insert, before_update, after_insert, after_update. **There are no callbacks in Backpack**, because there's no need. The code for the insert&update operations is out in the open for you to customize. Notice your ```EntityCrudController``` **already** has the following methods, which you can modify as you wish:
+```php
+public function store(StoreRequest $request)
+{
+ // <--------- here is where a before_insert callback logic would be
+ $response = parent::storeCrud();
+ // <--------- here is where a after_insert callback logic would be
+ return $response;
+}
+
+public function update(UpdateRequest $request)
+{
+ // <--------- here is where a before_update callback logic would be
+ $response = parent::updateCrud();
+ // <--------- here is where a after_update callback logic would be
+ return $response;
+}
+```
+
+>But before you do that, ask yourself - **_is this something that should be done when an entry is added/updated/deleted from the application, too_**? Not just the admin admin? If so, a better place for it would be the Model. Remember your Model is a pure Eloquent Model, so the cleanest way might be to use [Eloquent Event Observers](https://laravel.com/docs/5.5/eloquent#events) or [accessors and mutators](https://laravel.com/docs/master/eloquent-mutators#accessors-and-mutators).
+
+
+## Translatable models and multi-language CRUDs
+
+For UX purposes, when creating multi-language entries, the Create form will only allow the admin to add an entry in one language, the default one. The admin can then edit that entry in all available languages, to translate it. Check out [this same section in the Update operation](/docs/{{version}}/crud-operation-update#translatable-models) for how to enable multi-language functionality.
+
+
+## Separate Validation Rules for Create and Update
+
+**Differences between the Create and Update validations?** If your Update operation requires a different validation than the Create operation, just:
+- create a separate request file for each operation;
+- instruct your EntityCrudController to use separate files, in the "use" section;
+
+For example, we could create ```UpdateTagRequest.php``` and ```CreateTagRequest.php```, with different validations, then in TagCrudController just do:
+```diff
+- use App\Http\Requests\TagRequest as StoreRequest;
++ use App\Http\Requests\CreateTagRequest as StoreRequest;
+- use App\Http\Requests\TagRequest as UpdateRequest;
++ use App\Http\Requests\UpdateTagRequest as UpdateRequest;
+```
\ No newline at end of file
diff --git a/3.6/crud-operation-delete.md b/3.6/crud-operation-delete.md
new file mode 100644
index 00000000..8a661cd9
--- /dev/null
+++ b/3.6/crud-operation-delete.md
@@ -0,0 +1,82 @@
+# Delete
+
+--
+
+
+## About
+
+This CRUD operation allows your admins to remove one or more entries from the table.
+
+>In case your entity has SoftDeletes, it will perform a soft delete. The admin will _not_ know that his entry has been hard or soft deleted, since it will no longer show up in the ListEntries view.
+
+
+## Delete a Single Item
+
+
+### How it Works
+
+Using AJAX, a DELETE request is performed towards ```/entity-name/{id}```, which points to the ```destroy()``` method in your EntityCrudController.
+
+
+### How to Use
+
+The ```Delete``` action is **enabled by default**. To disable it, you should use ```$this->crud->denyAccess('delete');``` inside your ```setup()``` method. This will prevent the Delete button from appearing in the table view, and will deny access to the controller method if manually accessed.
+
+
+### How to Overwrite
+
+In case you need to change how this operation works, just create a ```destroy()``` method in your EntityCrudController:
+
+```php
+public function destroy($id)
+{
+ $this->crud->hasAccessOrFail('delete');
+
+ return $this->crud->delete($id);
+}
+```
+
+You can also overwrite the delete button by creating a file with the same name inside your ```resources/views/vendor/backpack/crud/buttons/```. You can easily publish the delete button there to make changes using:
+
+```zsh
+php artisan backpack:crud:publish buttons/delete
+```
+
+
+## Delete Multiple Items (Bulk Delete)
+
+In addition to the button for each entry, you can show checkboxes next to each element, and allow your admin to delete multiple entries at once.
+
+
+
+### How it Works
+
+Using AJAX, a DELETE request is performed towards ```/entity-name/bulk-delete```, which points to the ```bulkDelete()``` method in your EntityCrudController.
+
+
+### How to Use
+
+The ```bulkDelete()``` action is **enabled by default**, but there are no buttons using it. To make the buttons show up, inside your ```setup()``` method you should:
+
+```php
+$this->crud->enableBulkActions();
+$this->crud->addBulkDeleteButton();
+```
+
+
+### How to Overwrite
+
+In case you need to change how this operation works, just create a ```bulkDelete()``` method in your EntityCrudController:
+
+```php
+public function bulkDelete($id)
+{
+ // your custom code here
+}
+```
+
+You can also overwrite the bulk delete button by creating a file with the same name inside your ```resources/views/vendor/backpack/crud/buttons/```. You can easily publish the delete button there to make changes using:
+
+```zsh
+php artisan backpack:crud:publish buttons/bulk_delete
+```
\ No newline at end of file
diff --git a/3.6/crud-operation-list-entries.md b/3.6/crud-operation-list-entries.md
new file mode 100644
index 00000000..2f22a632
--- /dev/null
+++ b/3.6/crud-operation-list-entries.md
@@ -0,0 +1,189 @@
+# ListEntries
+
+---
+
+
+## About
+
+This operation shows a table with all database entries. It's the first page the admin lands on (for an entity), and it's usually the gateway to all other operations, because it holds all the buttons.
+
+A simple ListEntries view might look like this:
+
+
+
+But a complex implementation of the ListEntries operation, using Columns, Filters, custom Buttons, custom Operations, responsive table, Details Row, Export Buttons will still look pretty good:
+
+
+
+You can easily customize [columns](#columns), [buttons](#buttons), [filters](#filters), [enable/disable additional features we've built](#other-features), or [overwrite the view and build your own features](#how-to-overwrite).
+
+
+## How It Works
+
+The main route leads to ```EntityCrudController::index()```, which shows the table view (```list.blade.php```. Inside that table view, we're using AJAX to fetch the entries and place them inside DataTables. That AJAX points to the same controller, ```EntityCrudController::search()```.
+
+Actions:
+- ```index()```
+- ```search()```
+
+For views, it uses:
+- ```list.blade.php```
+- ```columns/```
+- ```buttons/```
+
+
+## How to Use
+
+The ```ListEntries``` operation is **enabled by default**. To disable it, you can use ```$this->crud->denyAccess('list');``` inside your ```setup()``` method.
+
+Configuration for this operation is usually done inside your ```setup()``` method. That's recommended, because the columns you define here are used by a few actions (```index()```, ```search()```, ```show()```).
+
+**For a minimum setup, you only need to define the columns you need to show in the table.**
+
+
+### Columns
+
+Columns represent the way your information is shown in the table view. All column types must have their ```name```, ```label``` and ```type``` specified, but some could require some other attributes too.
+
+```php
+$this->crud->addColumn([
+ 'name' => 'name', // The db column name
+ 'label' => "Tag Name", // Table column heading
+ 'type' => 'Text'
+ ]);
+```
+
+Backpack has 22+ [column types](/docs/{{version}}/crud-columns) you can use. Plus, you can easily [create your own type of column](/docs/{{version}}/crud-columns##creating-a-custom-column-type). **Check out the [Columns](/docs/{{version}}/crud-columns##creating-a-custom-column-type) documentation page** for a detailed look at column types, API and usage.
+
+
+### Buttons
+
+Buttons are used to trigger other operations. Some point to entirely new routes (```create```, ```update```, ```show```), others perform the operation on the current page using AJAX (```delete```).
+
+The ShowList operation has 3 places where buttons can be placed:
+ - ```top``` (where the Add button is)
+ - ```line``` (where the Edit and Delete buttons are)
+ - ```bottom``` (after the table)
+
+Backpack adds a few buttons by default:
+- ```add``` to the ```top``` stack;
+- ```edit``` and ```delete``` to the ```line``` stack;
+
+To learn more about buttons, **check out the [Buttons](/docs/{{version}}/crud-buttons) documentation page**.
+
+
+### Filters
+
+Filters show up right before the actual table, and provide a way for the admin to filter the results in the ListEntries table. To learn more about filters, **check out the [Filters](/docs/{{version}}/crud-filters) documentation page**.
+
+
+### Other Features
+
+
+#### Details Row
+
+The details row functionality allows you to present more information in the table view of a CRUD. When enabled, a "+" button will show up next to every row, which on click will expand a "details row" below it, showing additional information.
+
+
+
+On click, an AJAX request is sent to the ```entity/{id}/details``` route, which calls the ```showDetailsRow()``` method on your EntityCrudController. Everything returned by that method is then shown in the details row. You'll want to overwrite that method to show anything you'd like in the details row.
+
+To use, inside your ```EntityCrudController```:
+1. Enable the functionality: ```$this->crud->enableDetailsRow();```
+2. Allow access to all admins: ```$this->crud->allowAccess('details_row');```; Wrap an "if" statement around this if you don't want everybody to be able to see it.
+3. Overwrite the ```showDetailsRow($id)``` method;
+
+Alternative for the 3rd step: overwrite ```views/backpack/crud/details_row.blade.php``` which is called by the default ```showDetailsRow($id)``` functionality.
+
+
+#### Export Buttons
+
+Exporting the DataTable to PDF, CSV, XLS is as easy as typing ```$this->crud->enableExportButtons();``` in your constructor.
+
+
+
+>**Please note that when clicked, each button will export the _currently visible_ table.** You can use the "visibility" button, and the "Items per page" dropdown to manipulate what is inside the export.
+
+
+#### Custom Query
+
+By default, all entries are shown in the ListEntries table, before filtering. If you want to restrict the entries to a subset, you can use the methods below in your EntityCrudController's ```setup()``` method:
+
+```php
+// Change what entries are shown in the table view.
+// This changes all queries on the table view,
+// as opposed to filters, who only change it when that filter is applied.
+$this->crud->addClause('active'); // apply a local scope
+$this->crud->addClause('type', 'car'); // apply local dynamic scope
+$this->crud->addClause('where', 'name', '=', 'car');
+$this->crud->addClause('whereName', 'car');
+$this->crud->addClause('whereHas', 'posts', function($query) {
+ $query->activePosts();
+ });
+$this->crud->groupBy();
+$this->crud->limit();
+
+$this->crud->orderBy();
+// please note it's generally a good idea to use crud->orderBy() inside "if (!$this->request->has('order')) {}"; that way, your custom order is applied ONLY IF the user hasn't forced another order (by clicking a column heading)
+```
+
+
+#### Responsive Table
+
+If your CRUD table has more columns than can fit inside the viewport (on mobile / tablet or smaller desktop screens), unimportant columns will start hiding and an expansion icon (three dots) will appear to the left of each row. We call this behaviour "_responsive table_", and consider this to be the best UX. By behaviour we consider the 1st column the most important, then 2nd, then 3rd, etc; the "actions" column is considered as important as the 1st column. You can of course [change the importance of columns](/docs/{{version}}/crud-columns#define-which-columns-to-hide-in-responsive-table).
+
+If you do not like this, you can **toggle off the responsive behaviour for all CRUD tables** by changing this config value in your ```config/backpack/crud.php``` to ```false```:
+```php
+ // enable the datatables-responsive plugin, which hides columns if they don't fit?
+ // if not, a horizontal scrollbar will be shown instead
+ 'responsive_table' => true
+```
+
+To turn off the responsive table behaviour for _just one CRUD panel_, you can use ```$this->crud->disableResponsiveTable()``` in your ```setup()``` method.
+
+
+#### Persistent Table
+
+By default, ListEntries will NOT remember your filtering, search and pagination when you leave the page. If you want ListEntries to do that, you can enable a ListEntries feature we call ```persistent_table```.
+
+**This will take the user back to the _filtered table_ after adding an item, previewing an item, creating an item or just browsing around**, preserving the table just like he/she left it - with the same filtering, pagination and search applied. It does so by saving the pagination, search and filtering for 2 hours in local storage.
+
+To use ```persistent_table``` you can:
+- enable it for all CRUDs with the config option ```'persistent_table' => true``` in your ```config/backpack/crud.php```;
+- enable it inside a particular crud controller with ```$this->crud->enablePersistentTable();```
+- disable it inside a particular crud controller with ```$this->crud->disablePersistentTable();```
+
+
+
+## How to Overwrite
+
+The main route leads to ```EntityCrudController::index()```, which loads ```list.blade.php```. Inside that table view, we're using AJAX to fetch the entries and place them inside a DataTables. The AJAX points to the same controller, ```EntityCrudController::search()```.
+
+
+### The View
+
+You can change how the ```list.blade.php``` file looks and works, by just placing a file with the same name in your ```resources/views/vendor/backpack/crud/list.blade.php```. To quickly do that, run:
+
+```zsh
+php artisan backpack:crud:publish list
+```
+
+Keep in mind that by publishing this file, you won't be getting any updates we'll be pushing to it.
+
+
+### The Operation Logic
+
+Getting and showing the information is done inside the ```index()``` method. Take a look at the ```CrudController::index()``` method (your EntityCrudController is extending this CrudController) to see how it works.
+
+To overwrite it, just create an ```index()``` method in your ```EntityCrudController```.
+
+
+### The Search Logic
+
+An AJAX call is made to the ```search()``` method:
+- when entries are shown in the table;
+- when entries are filtered in the table;
+- when search is performed on the table;
+- when pagination is performed on the table;
+
+You can of course overwrite this ```search()``` method by just creating one with the same name in your ```EntityCrudController```. In addition, you can overwrite what a specific column is searching through (and how), by [using the searchLogic attribute](/docs/{{version}}/crud-columns#custom-search-logic) on columns.
diff --git a/3.6/crud-operation-reorder.md b/3.6/crud-operation-reorder.md
new file mode 100644
index 00000000..dd70a0a2
--- /dev/null
+++ b/3.6/crud-operation-reorder.md
@@ -0,0 +1,34 @@
+# Reorder
+
+---
+
+
+## About
+
+This operation allows your admins to reoder & nest entries.
+
+
+
+
+## Requirements
+
+Your model should have the following integer fields, with a default value of 0: ```parent_id```, ```lft```, ```rgt```, ```depth```.
+
+Additionnaly, the `parent_id` field has to be nullable.
+
+
+## How to Use
+
+The ```Reorder``` operation is **disabled by default**. To enable it, you should use ```$this->crud->allowAccess('reorder');``` inside your ```setup()``` method. This will make a Reorder button appear in ListEntries, in the ```top``` button stack. Then, in your EntityCrudController's ```setup()``` method:
+
+```php
+$this->crud->enableReorder('attribute_name', ALLOWED_DEPTH);
+```
+Where:
+- ```attribute_name``` should be the attribute you want shown on the draggable elements (ex: ```name```);
+- ```ALLOWED_DEPTH``` should be an integer, how many levels deep would you allow your admin to go when nesting; for infinit levels, you should set it to ```0```;
+
+
+## How It Works
+
+The ```/reorder``` route points to a ```reorder()``` method in your ```EntityCrudController```.
diff --git a/3.6/crud-operation-revisions.md b/3.6/crud-operation-revisions.md
new file mode 100644
index 00000000..b2833e4f
--- /dev/null
+++ b/3.6/crud-operation-revisions.md
@@ -0,0 +1,58 @@
+# Revisions
+
+---
+
+
+## About
+
+Revisions allows your admins to store, see and undo changes to entries on an Eloquent model.
+
+The operation provides you with a simple interface to work with [venturecraft/revisionable](https://github.com/VentureCraft/revisionable#implementation), which is a great package that stores all changes in a separate table. It can work as an audit trail, a backup system and an accountability system for the admins.
+
+When enabled, ```Revisions``` will show another button in the table view, between _Edit_ and _Delete_. On click, that button opens another page which will allow an admin to see all changes and who made them:
+
+
+
+
+
+
+## How to Use
+
+The ```Revision``` operation is **disabled by default**. In order to enable this functionality for a CRUD panel, you need to:
+
+1. Create the revisions table:
+
+```bash
+cp vendor/venturecraft/revisionable/src/migrations/2013_04_09_062329_create_revisions_table.php database/migrations/ && php artisan migrate
+```
+
+2. Use [venturecraft/revisionable](https://github.com/VentureCraft/revisionable#implementation) on your model. If you are using another bootable trait be sure to override the boot method in your model.
+
+```php
+namespace MyApp\Models;
+
+class Article extends Eloquent {
+ use \Backpack\CRUD\CrudTrait, \Venturecraft\Revisionable\RevisionableTrait;
+
+ // If you are using another bootable trait
+ // be sure to override the boot method in your model
+ public static function boot()
+ {
+ parent::boot();
+ }
+}
+```
+
+3. In your EntityCrudController's ```setup()``` method, enable access to the Revisions operation:
+
+```php
+$this->crud->allowAccess('revisions');
+```
+
+4. [optional] If you want the table view to load faster (and why wouldn't you?), you should eager-load the revisions, so there won't be any extra DB queries for the revisions:
+
+```php
+$this->crud->with('revisionHistory');
+```
+
+For complex usage, head on over to [VentureCraft/revisionable](https://github.com/VentureCraft/revisionable) to see the full documentation and extra configuration options.
diff --git a/3.6/crud-operation-show.md b/3.6/crud-operation-show.md
new file mode 100644
index 00000000..724528a2
--- /dev/null
+++ b/3.6/crud-operation-show.md
@@ -0,0 +1,64 @@
+# Show
+
+--
+
+
+## About
+
+This CRUD operation allows your admins to preview an entry. When enabled, it will add a "Preview" button in the ListEntries view, that points to a show page:
+
+
+
+In case your entity is translatable, it will show a multi-language dropdown, just like Edit.
+
+
+## How it Works
+
+The ```/entity-name/{id}``` route points to the ```show()``` method in your EntityCrudController. Inside this method, it uses ```setFromDb()``` to try to magically figure out all attributes you would like shown for this Model, and shows them using [Column types](/docs/{{version}}/crud-columns) inside ```show.blade.php```.
+
+
+## How to Use
+
+The ```ListEntries``` operations is **disabled by default**. To enable it, you should use ```$this->crud->allowAccess('show');``` inside your ```setup()``` method.This will make a Preview button appear in the table view, and allow access to the show view.
+
+This view uses the same column types you've defined in ```setup()``` and adds all other **fillable** attributes on the model. If you need to hide a ListEntries column from the Show operation, you can specify ```'visibleInShow' => false,``` to the column in ```setup()```, and it will be hidden from the preview page.
+
+If you need more customization (add/change/remove columns), check out [How to Overwrite](#how-to-overwrite).
+
+
+## How to Overwrite
+
+In case you need to add/change/remove any columns, create a ```show()``` method in your EntityCrudController. Using the ```addColumn()``` you're already familiar with, you can change how those attributes are shown to the admin. For example:
+
+```php
+public function show($id)
+{
+ $content = parent::show($id);
+
+ $this->crud->addColumn([
+ 'name' => 'table',
+ 'label' => 'Table',
+ 'type' => 'table',
+ 'columns' => [
+ 'name' => 'Name',
+ 'desc' => 'Description',
+ 'price' => 'Price',
+ ]
+ ]);
+ $this->crud->addColumn([
+ 'name' => 'fake_table',
+ 'label' => 'Fake Table',
+ 'type' => 'table',
+ 'columns' => [
+ 'name' => 'Name',
+ 'desc' => 'Description',
+ 'price' => 'Price',
+ ],
+ ]);
+ $this->crud->addColumn('text');
+ $this->crud->removeColumn('date');
+ $this->crud->removeColumn('extras');
+
+ return $content;
+}
+```
diff --git a/3.6/crud-operation-update.md b/3.6/crud-operation-update.md
new file mode 100644
index 00000000..c7fd915f
--- /dev/null
+++ b/3.6/crud-operation-update.md
@@ -0,0 +1,178 @@
+# Update
+
+---
+
+
+## About
+
+This operation allows your admins to add new entries to a database table.
+
+
+
+
+## Requirements
+
+All editable attributes should be ```$fillable``` on your Model.
+
+
+## How to Use
+
+The ```Update``` operation is **enabled by default**. To disable it, you should use ```$this->crud->denyAccess('update');``` inside your ```setup()``` method. This will make the Update button disappear in ListEntries, in the ```line``` stack.
+
+To use the Update operation, you must:
+
+**Step 1. Specify what field types** you'd like to show for each attribute, in your EntityCrudController's ```setup()``` method. You can do that using the [Fields API](/docs/{{version}}/crud-fields#fields-api). In short you can:
+
+```php
+// add a field only to the Update operation
+$this->crud->addField($field_definition_array, 'update');
+// add a field to both the Update and Update operations
+$this->crud->addField($field_definition_array);
+```
+
+**Step 2. Specify validation rules, in your the EntityCrudRequest file** that you are typehinting on your ```EntityCrudController::update()``` method. If you need separate validation for Create and Update [look here](#separate-validation).
+
+For more on how to manipulate fields, please read the [Fields documentation page](/docs/{{version}}/crud-fields). For more on validation rules, check out [Laravel's validation docs](https://laravel.com/docs/master/validation#available-validation-rules).
+
+
+## How It Works
+
+CrudController is a RESTful controller, so the ```Update``` operation uses two routes:
+- GET to ```/entity-name/{id}/edit``` - points to ```edit()``` which shows the Edit form (```edit.blade.php```);
+- POST to ```/entity-name/{id}/edit``` - points to ```store()``` which uses Eloquent to update the entry in the database;
+
+The ```edit()``` method will show all the fields you've defined for this operation using the [Fields API](/docs/{{version}}/crud-fields#fields-api), then upon Save the ```update()``` method will first check the validation from the typehinted FormRequest, then create the entry using the Eloquent model. Only attributes that are ```$fillable``` on the model will actually be updated in the database.
+
+
+## Callbacks
+
+Developers coming from GroceryCRUD or other CRUD systems will be looking for callbacks to run before_insert, before_update, after_insert, after_update. **There are no callbacks in Backpack**, because there's no need. The code for the insert&update operations is out in the open for you to customize. Notice your ```EntityCrudController``` **already** has the following methods, which you can modify as you wish:
+```php
+public function store(StoreRequest $request)
+{
+ // <--------- here is where a before_insert callback logic would be
+ $response = parent::storeCrud();
+ // <--------- here is where a after_insert callback logic would be
+ return $response;
+}
+
+public function update(UpdateRequest $request)
+{
+ // <--------- here is where a before_update callback logic would be
+ $response = parent::updateCrud();
+ // <--------- here is where a after_update callback logic would be
+ return $response;
+}
+```
+
+>But before you do that, ask yourself - **_is this something that should be done when an entry is added/updated/deleted from the application, too_**? Not just the admin admin? If so, a better place for it would be the Model. Remember your Model is a pure Eloquent Model, so the cleanest way might be to use [Eloquent Event Observers](https://laravel.com/docs/5.5/eloquent#events) or [accessors and mutators](https://laravel.com/docs/master/eloquent-mutators#accessors-and-mutators).
+
+
+## Translatable models and multi-language CRUDs
+
+
+
+For localized apps, you can let your admins edit multi-lingual entries. Only translations stored the [spatie/laravel-translatable](https://github.com/spatie/laravel-translatable) way are supported right now, but more options will be coming soon.
+
+In order to make one of your Models translatable (localization), you need to:
+0. Be running MySQL 5.7+ (or a PostgreSQL with JSON column support);
+1. [Install spatie/laravel-translatable](https://github.com/spatie/laravel-translatable#installation);
+2. In your database, make all translatable columns either JSON or TEXT.
+3. Use Backpack's ```HasTranslations``` trait on your model (instead of using spatie's ```HasTranslations```) and define what fields are translatable, inside the ```$translatable``` property. For example:
+
+```php
+ You DO NOT need to cast translatable string columns as array/json/object in the Eloquent model. From Eloquent's perspective they're strings. So:
+> - you _should NOT_ cast ```name```; it's a string in Eloquent, even though it's stored as JSON in the db by SpatieTranslatable;
+> - you _should_ cast ```extras``` to ```array```, if each translation stores an array of some sort;
+
+Change the languages available to translate to/from, in your crud config file (```config/backpack/crud.php```). By default there are quite a few enabled (English, French, German, Italian, Romanian).
+
+Additionally, if you have slugs, you'll need to use backpack's classes instead of the ones provided by cviebrock/eloquent-sluggable:
+
+```php
+ [
+ 'source' => 'slug_or_name',
+ ],
+ ];
+ }
+}
+```
+
+
+## Separate Validation Rules for Create and Update
+
+**Differences between the Create and Update validations?** If your Update operation requires a different validation than the Create operation, just:
+- create a separate request file for each operation;
+- instruct your EntityCrudController to use separate files, in the "use" section;
+
+For example, we could create ```UpdateTagRequest.php``` and ```CreateTagRequest.php```, with different validations, then in TagCrudController just do:
+```diff
+- use App\Http\Requests\TagRequest as StoreRequest;
++ use App\Http\Requests\CreateTagRequest as StoreRequest;
+- use App\Http\Requests\TagRequest as UpdateRequest;
++ use App\Http\Requests\UpdateTagRequest as UpdateRequest;
+```
diff --git a/3.6/crud-operations.md b/3.6/crud-operations.md
new file mode 100644
index 00000000..bc125218
--- /dev/null
+++ b/3.6/crud-operations.md
@@ -0,0 +1,573 @@
+# Operations
+
+---
+
+When creating a CRUD Panel, your ```EntityCrudController``` (where Entity = your model name) is extending ```CrudController```. Inside it, we've already provided the logic for [the most important operations](/#supported-operations), you just need to enable or configure them. Also, you can easily [add custom operations](/#creating-a-custom-operation).
+
+
+## Standard Operations
+
+Operations enabled by default:
+- [ListEntries](/docs/{{version}}/crud-operation-list-entries) - allows the admin to see all entries for an Eloquent model, with pagination, search, filters;
+- [Create](/docs/{{version}}/crud-operation-create) - allows the admin to add a new entry;
+- [Update](/docs/{{version}}/crud-operation-update) - allows the admin to edit an existing entry;
+- [Delete](/docs/{{version}}/crud-operation-delete) - allows the admin to remove and entry;
+
+Operations disabled by default:
+- [Show](/docs/{{version}}/crud-operation-show) - allows the admin to preview an entry;
+- [Reorder](/docs/{{version}}/crud-operation-reorder) - allows the admin to reorder all entries of a model;
+- [Revisions](/docs/{{version}}/crud-operation-revisions) - shows an audit log of all changes to an entry, and allows the admin to undo modifications;
+
+
+
+### Operation Actions
+
+Each Operation is actually _a trait_, which can be used on CrudControllers. This trait can contain one or more methods (or functions). Since Laravel calls each Controller method an _action_, that means each _Operation_ can have one or many _actions_. For example, we have the ```clone``` operation and two actions: ```clone``` and ```bulkClone```.
+
+```php
+trait CloneOperation
+{
+ public function clone($id)
+ {
+ // ...
+ }
+
+ public function bulkClone()
+ {
+ // ...
+ }
+}
+```
+
+An action can do something with AJAX and return true/false, it can return an AJAX, or it can return a view - or whatever else you can do inside a controller method.
+
+You can check which action is currently being performed using the [standard Laravel Route API](https://laravel.com/api/5.7/Illuminate/Routing/Route.html):
+
+- ```\Route::getCurrentRoute()->getAction()``` or ```$this->request->route()->getAction()```:
+```
+array:7 [▼
+ "middleware" => array:2 [▼
+ 0 => "web"
+ 1 => "admin"
+ ]
+ "as" => "crud.monster.index"
+ "uses" => "App\Http\Controllers\Admin\MonsterCrudController@index"
+ "controller" => "App\Http\Controllers\Admin\MonsterCrudController@index"
+ "namespace" => "App\Http\Controllers\Admin"
+ "prefix" => "admin"
+ "where" => []
+]
+```
+- ```\Route::getCurrentRoute()->getActionName()``` or ```$this->request->route()->getActionName()```:
+```
+App\Http\Controllers\Admin\MonsterCrudController@index
+```
+- ```\Route::getCurrentRoute()->getActionMethod()``` or ```$this->request->route()->getActionMethod()```:
+```
+index
+```
+
+You can also use the shortcuts on the CrudPanel object:
+```php
+$this->crud->getActionMethod(); // returns the method on the controller that was called by the route; ex: create(), update(), edit() etc;
+$this->crud->actionIs('create'); // checks if the controller method given is the one called by the route
+```
+
+
+### Titles, Headings and Subheadings
+
+For standard CRUD operations, each _action_ that shows an interface uses some texts to show the user what page, operation or action he is currently performing:
+- **Title** - page title, shown in the browser's title bar;
+- **Heading** - biggest heading on page;
+- **Subheading** - short description of the current page, sits beside the heading;
+
+
+
+You can get and set the above using:
+```php
+// Getters
+$this->crud->getTitle('create'); // get the Title for the create action
+$this->crud->getHeading('create'); // get the Heading for the create action
+$this->crud->getSubheading('create'); // get the Subheading for the create action
+
+// Setters
+$this->crud->setTitle('some string', 'create'); // set the Title for the create action
+$this->crud->setHeading('some string', 'create'); // set the Heading for the create action
+$this->crud->setSubheading('some string', 'create'); // set the Subheading for the create action
+```
+
+These methods are usually useful inside actions, not in ```setup()```. Since action methods are called _after_ ```setup()```, any call to these getters and setters in ```setup()``` would get overwritten by the call in the action.
+
+
+### Handling Access to Operations
+
+Admins are allowed to do an operation or not using a very simple system: ```$crud``` holds an array with all operations they can perform. By default it will look like this:
+
+```php
+public $access = [
+ 'list',
+ 'create',
+ 'update',
+ 'delete'
+ /* 'revisions', reorder', 'show', 'clone' */
+];
+```
+
+You can easily add or remove elements to this access array in your ```setup()``` method, or your custom methods, using:
+```php
+$this->crud->allowAccess('operation');
+$this->crud->allowAccess(['list', 'update', 'delete']);
+$this->crud->denyAccess('operation');
+$this->crud->denyAccess(['update', 'create', 'delete']);
+
+$this->crud->hasAccess('operation'); // returns true/false
+$this->crud->hasAccessOrFail('create'); // throws 403 error
+$this->crud->hasAccessToAll(['create', 'update']); // returns true/false
+$this->crud->hasAccessToAny(['create', 'update']); // returns true/false
+```
+
+
+
+### Getting and Setting an Operation Name
+
+Inside a CrudController method all default operations use ```$this->crud->setOperation('show')``` to define which operation is currently being performed. So you can do ```$crud->getOperation()``` inside your views and do things according to this.
+
+When you create custom operation, it's recommended that you also do ```$this->crud->setOperation('show')``` in each custom method, so that have the ability to check later on.
+
+
+### Adding Methods to the CrudPanel Object
+
+Every time you call ```$this->crud```, you're referring to a ```CrudPanel``` object, where we store all information about the current CRUD and perform all computation.
+
+Starting with CRUD 3.5 you can add static methods to this ```CrudPanel``` object with ```$this->crud->macro()```, because the object is [macroable](https://unnikked.ga/understanding-the-laravel-macroable-trait-dab051f09172). So you can do:
+
+```php
+class MonsterCrudController extends CrudController
+{
+ public function setup()
+ {
+ $this->crud->macro('doStuff', function($something) {
+ echo '
'; var_dump($something); echo '
';
+ dd($this);
+ });
+ $this->crud->macro('getColumnsInTheFormatIWant', function() {
+ $columns = $this->columns;
+ // ... do something to $columns;
+ return $columns;
+ });
+
+ // bla-bla-bla the actual setup code
+ }
+ public function sendEmail()
+ {
+ // ...
+ $this->crud->doStuff();
+ dd($this->crud->getColumnsInTheFormatIWant());
+ // ...
+ }
+ public function markPending()
+ {
+ // ...
+ $this->crud->doStuff();
+ dd($this->crud->getColumnsInTheFormatIWant());
+ // ...
+ }
+}
+```
+
+So if you define a custom operation that needs some static methods, you can add them. You can also use the ```$this->crud->settings``` object, to store various settings. Use it as an associative array, with the operation as key:
+
+```php
+$this->crud->settings['moderate']['show_title'] = false;
+```
+
+
+## Creating a Custom Operation
+
+Thanks to [Backpack's simple architecture](/docs/{{version}}/crud-basics#architecture), each CRUD panel uses a controller and a route, that are placed inside your project. That means you hold the keys to how this controller works.
+
+To add an operation to an ```EntityCrudController```, you can just:
+- create a new route in ```routes/backpack/custom.php``` that points to a new method in that controller;
+- create that method inside your ```EntityCrudController```;
+- [add a new button for this operation to the ListEntries view](/docs/{{version}}/crud-buttons#creating-a-custom-button);
+
+Take a look at the examples below for a better picture and code examples.
+
+
+### Access to Custom Operations
+
+Since you're creating a new operation, in terms of restricting access you can:
+1. allow access to this new operation depending on access to a default operation (usually if the admin can ```update```, he's ok to perform custom operations);
+2. customize access to this particular operation, by just using a different key than the default ones; for example, you can allow access by using ```$this->crud->allowAccess('moderate')``` in your ```setup()``` method, then check for access to that operation using ```$this->crud->hasAccess('moderate')```;
+
+
+### Examples
+
+
+#### Creating a New Operation With No Interface
+
+Let's say we have a ```UserCrudController``` and we want to create a simple ```Clone``` operation, which would create another entry with the same info. So very similar to ```Delete```. What we need to do is:
+
+1. Create a route for this operation - we can add it anywhere, but it's recommended we keep all admin routes within ```routes/backpack/custom.php```:
+
+```php
+Route::post('user/{id}/clone', 'UserCrudController@clone');
+```
+
+2. Add the method inside ```UserCrudController```:
+
+```php
+public function clone($id)
+{
+ $this->crud->hasAccessOrFail('create');
+ $this->crud->setOperation('Clone');
+
+ $clonedEntry = $this->crud->model->findOrFail($id)->replicate();
+
+ return (string) $clonedEntry->push();
+}
+```
+
+3. Create a button for this method. Since our operation is similar to "Delete", lets start from that one and customize what we need. The button should clone the entry using an AJAX call. No need to load another page for an operation this simple. We'll create a ```resources\views\vendor\backpack\crud\buttons\clone.blade.php``` file:
+
+```php
+@if ($crud->hasAccess('create'))
+ Clone
+@endif
+
+
+```
+
+4. We can now actually add this button to our ```UserCrudController::setup()```:
+
+```php
+$this->crud->addButtonFromView('line', 'clone', 'clone', 'beginning');
+```
+
+>Of course, **if you plan to re-use this operation on another EntityCrudController**, it's a good idea to isolate the method inside a trait, then use that trait on each EntityCrudController where you want the operation to work.
+
+
+#### Creating a New Operation With An Interface
+
+Let's say we have a ```UserCrudController``` and we want to create a simple ```Moderate``` operation, where we show a form where the admin can add his observations and what not. In this respect, it should be similar to ```Update``` - the button should lead to a separate form, then that form will probably have a Save button. So when creating the methods, we should look at ```CrudController::edit()``` and ```CrudController::updateCrud()``` for working examples.
+
+What we need to do is:
+
+1. Create a route for this operation - we can add it anywhere, but it's recommended we keep all admin routes within ```routes/backpack/custom.php```:
+
+```php
+Route::get('user/{id}/moderate', 'UserCrudController@getModerateForm');
+Route::post('user/{id}/moderate', 'UserCrudController@postModerateForm');
+```
+
+2. Add the methods inside ```UserCrudController```:
+
+```php
+public function getModerateForm($id)
+{
+ $this->crud->hasAccessOrFail('update');
+ $this->crud->setOperation('Moderate');
+
+ // get the info for that entry
+ $this->data['entry'] = $this->crud->getEntry($id);
+ $this->data['crud'] = $this->crud;
+ $this->data['title'] = 'Moderate '.$this->crud->entity_name;
+
+ return view('vendor.backpack.crud.moderate', $this->data);
+}
+
+public function postModerateForm(Request $request = null)
+{
+ $this->crud->hasAccessOrFail('update');
+
+ // TODO: do whatever logic you need here
+ // ...
+ // You can use
+ // - $this->crud
+ // - $this->crud->getEntry($id)
+ // - $request
+ // ...
+
+ // show a success message
+ \Alert::success('Moderation saved for this entry.')->flash();
+
+ return \Redirect::to($this->crud->route);
+}
+```
+
+3. Create the ```/resources/views/vendor/backpack/crud/moderate.php``` blade file, which shows the moderate form and what not. Best to start from the ```edit.blade.php``` file and customize:
+
+```html
+@extends('backpack::layout')
+
+@section('header')
+
+
+@endsection
+
+```
+
+4. Create a button for this operation. Since our operation is similar to "Update", lets start from that one and customize what we need. The button should just take the admin to the route that shows the Moderate form. Nothing fancy. We'll create a ```resources\views\vendor\backpack\crud\buttons\moderate.blade.php``` file:
+
+```php
+@if ($crud->hasAccess('update'))
+ Moderate
+@endif
+```
+
+4. We can now actually add this button to our ```UserCrudController::setup()```:
+
+```php
+$this->crud->addButtonFromView('line', 'moderate', 'moderate', 'beginning');
+```
+
+>Of course, **if you plan to re-use this operation on another EntityCrudController**, it's a good idea to isolate the method inside a trait, then use that trait on each EntityCrudController where you want the operation to work.
+
+
+#### Creating a New Operation With a Bulk Action (No Interface)
+
+Say we want to create a ```Clone``` button which clones multiple entries at the same time. So very similar to our ```Bulk Delete```. What we need to do is:
+
+1. ```$this->crud->enableBulkActions()``` to make the checkboxes show up;
+
+2. Create a new button and add it to our buttom stack:
+
+```html
+@if ($crud->hasAccess('create') && $crud->bulk_actions)
+ Clone
+@endif
+
+@push('after_scripts')
+
+@endpush
+```
+
+3. In our ```setup()``` method, add this button to the bottom stack:
+
+```php
+$this->crud->addButtonFromView('bottom', 'bulk_clone', 'bulk_clone', 'end');
+```
+
+4. Create a method in your EntityCrudController (or in a trait, if you want to re-use it for multiple CRUDs):
+
+```php
+ public function bulkClone()
+ {
+ $this->crud->hasAccessOrFail('create');
+
+ $entries = $this->request->input('entries');
+ $clonedEntries = [];
+
+ foreach ($entries as $key => $id) {
+ if ($entry = $this->crud->model->find($id)) {
+ $clonedEntries[] = $entry->replicate()->push();
+ }
+ }
+
+ return $clonedEntries;
+ }
+```
+
+5. Add a route to point to this new method:
+
+```php
+CRUD::resource('monster', 'MonsterCrudController')->with(function() {
+ Route::post('monster/bulk-clone', 'MonsterCrudController@bulkClone');
+});
+```
+
+Now there's a Clone button on our bottom stack, that works as expected for multiple entries.
+
+The button makes one call for all entries, and only triggers one notification. If you would rather make a call for each entry, you can use something like below:
+
+```html
+@if ($crud->hasAccess('create') && $crud->bulk_actions)
+ Clone
+@endif
+
+@push('after_scripts')
+
+@endpush
+```
\ No newline at end of file
diff --git a/3.6/crud-tutorial.md b/3.6/crud-tutorial.md
new file mode 100644
index 00000000..4fa02c24
--- /dev/null
+++ b/3.6/crud-tutorial.md
@@ -0,0 +1,389 @@
+# CRUD Tutorial
+
+---
+
+What's the simplest entity you can think of? It will probably be something like ```Tag```, which only holds an ```id``` and a ```name```. Let's create this new entity in the database, the model for it, then create a CRUD Panel to let admins manage entries for this entity.
+
+We assume:
+- you've [installed Backpack](/docs/{{version}}/installation);
+- you don't already have a ```Tag``` model in your project;
+
+
+## Generate Files
+
+Since we don't have an Eloquent model for it already, we're going to use [Jeffrey Way's Generators](https://github.com/laracasts/Laravel-5-Generators-Extended) package, which is installed along with Backpack, to generate the migration.
+
+```zsh
+# STEP 0. create migration
+php artisan make:migration:schema create_tags_table --model=0 --schema="name:string:unique"
+php artisan migrate
+```
+
+Now that we have the ```tags``` table in the database, let's generate the actual files we'll be using:
+
+```zsh
+# STEP 1. create a model, a request and a controller for the admin panel
+php artisan backpack:crud tag #use singular, not plural
+
+# STEP 2. add a route for the crud panel (under the admin prefix and auth middleware):
+php artisan backpack:base:add-custom-route "CRUD::resource('tag', 'TagCrudController');"
+
+# STEP 3. add an item to the sidebar menu
+php artisan backpack:base:add-sidebar-content "
"
+```
+
+The code above will have generated:
+- a migration (```database/migrations/yyyy_mm_dd_xyz_create_tags_table.php```);
+- a database table (```tags``` with just two columns: ```id``` and ```name```);
+- a model (```app/Models/Tag.php```);
+- a controller (```app/Http/Controllers/Admin/TagCrudController.php```);
+- a request (```app/Http/Requests/TagCrudRequest.php```);
+- a resource route, as a line inside ```routes/backpack/custom.php```;
+
+**Next up:** we'll need to go through the generated files, and customize for our needs.
+
+
+## Customize Generated Files
+
+We'll skip the migration and database table, since there's nothing there specific to Backpack, nothing to customize, and we've already run the migration.
+
+
+### The Model
+
+Let's take a look at the generated model:
+
+```php
+
+### The Controller
+
+Let's take a look at ```app/Http/Controllers/Admin/TagCrudController.php```. It should look something like this:
+
+```php
+crud->setModel('App\Models\Tag');
+ $this->crud->setRoute(config('backpack.base.route_prefix') . '/tag');
+ $this->crud->setEntityNameStrings('tag', 'tags');
+
+ /*
+ |--------------------------------------------------------------------------
+ | CrudPanel Configuration
+ |--------------------------------------------------------------------------
+ */
+
+ // TODO: remove setFromDb() and manually define Fields and Columns
+ $this->crud->setFromDb();
+ }
+
+ public function store(StoreRequest $request)
+ {
+ // your additional operations before save here
+ $redirect_location = parent::storeCrud($request);
+ // your additional operations after save here
+ // use $this->data['entry'] or $this->crud->entry
+ return $redirect_location;
+ }
+
+ public function update(UpdateRequest $request)
+ {
+ // your additional operations before save here
+ $redirect_location = parent::updateCrud($request);
+ // your additional operations after save here
+ // use $this->data['entry'] or $this->crud->entry
+ return $redirect_location;
+ }
+}
+
+```
+
+What we should notice inside this TagCrudController is that:
+- ```TagCrudController extends CrudController```, which, if we drill down, is a RESTful controller that already has a few methods we will be using - ```create()```, ```edit()```, ```show()```, ```destroy()```, etc.;
+- ```TagCrudController``` has a ```setup()``` method, where can configure how the CRUD panel works;
+- ```TagCrudController``` has its ```store()``` and ```update()``` methods with ```StoreRequest``` and ```UpdateRequest``` typehinted; which means those classes will be used for form validation; if we take a look at the top of the file, those Requests both lead to our newly generated ```app/Http/Requests/TagRequest.php```;
+
+Let's move our attention to the ```setup()``` method, which is the gateway to configuring our CRUD Panel.
+
+As we can tell from the comments there, in most cases we _shouldn't_ use ```$this->crud->setFromDb()```, which automagically figures out which columns and fields to show. That's because for real models, in real projects, it would _never_ be able to 100% figure out which field types to use. Real projects are very custom - that's a fact. In real projects, models are complicated, use a bunch of field types and you'll want to customize things. Instead of using ```setFromDb()``` then gradually changing what you don't like, **we heavily recommend you manually define all fields and columns you need**.
+
+Since our ```Tag``` model is so simple, we _can_ leave it like this - it will work perfectly, since we only need a ```text``` field and a ```text``` column. But let's not do that. Let's define our fields and columns manually, like big boys:
+
+```diff
+ public function setup()
+ {
+ /*
+ |--------------------------------------------------------------------------
+ | CrudPanel Basic Information
+ |--------------------------------------------------------------------------
+ */
+ $this->crud->setModel('App\Models\Tag');
+ $this->crud->setRoute(config('backpack.base.route_prefix') . '/tag');
+ $this->crud->setEntityNameStrings('tag', 'tags');
+
+ /*
+ |--------------------------------------------------------------------------
+ | CrudPanel Configuration
+ |--------------------------------------------------------------------------
+ */
+
+- // TODO: remove setFromDb() and manually define Fields and Columns
+- $this->crud->setFromDb();
+
++ // Columns
++ $this->crud->addColumn(['name' => 'name', 'type' => 'text', 'label' => 'Name']);
++
++ // Fields
++ $this->crud->addField(['name' => 'name', 'type' => 'text', 'label' => 'Name']);
+ }
+}
+```
+
+This will:
+- disable the ```setFromDb()``` functionality;
+- add a simple ```text``` column for our ```name``` attribute to the ListEntries operation (the table view);
+- add a simple ```text``` field for our ```name``` attribute to the Create and Update forms;
+
+It's the exact same thing ```setFromDb()``` would have figured out, but done manually. This way, if we want to add [other columns](/docs/{{version}}/crud-columns)) or [other fields](/docs/{{version}}/crud-fields), we can easily do that. If we want to change the label of the ```name``` field from ```Name``` to ```Tag name```, we just make that small change. The benefits of _not_ using ```setFromDb()``` will be more obvious once you use Backpack on real models, we promise.
+
+Here, in the ```setup()``` method, is where you can also do a lot of other things, like enabling other operations, adding buttons, adding filters, customizing your query, etc. For a full list of the things you can do inside ```setup()``` check out our [cheat sheet](/docs/{{version}}/crud-cheat-sheet).
+
+But for now, let's continue to our next generated file.
+
+
+### The Request
+
+Backpack will also generate a [standard FormRequest file](https://laravel.com/docs/master/validation#form-request-validation), that you can use for validation of the Create and Update forms. There is nothing Backpack-specific in here, but let's take a look at the generated ```app/Http/Requests/TagCrudRequest.php``` file:
+
+```php
+ 'required|min:5|max:255'
+ ];
+ }
+
+ /**
+ * Get the validation attributes that apply to the request.
+ *
+ * @return array
+ */
+ public function attributes()
+ {
+ return [
+ //
+ ];
+ }
+
+ /**
+ * Get the validation messages that apply to the request.
+ *
+ * @return array
+ */
+ public function messages()
+ {
+ return [
+ //
+ ];
+ }
+}
+
+```
+
+This file is a 100% pure FormRequest file - all Laravel, nothing particular to Backpack. In generated FormRequest files, no validation rules are imposed by default. But we do want ```name``` to be ```required``` and ```unique```, so let's do that, using the [standard Laravel validation rules](https://laravel.com/docs/master/validation#available-validation-rules):
+
+```diff
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules()
+ {
+ return [
+- // 'name' => 'required|min:5|max:255'
++ 'name' => 'required|min:5|max:255|unique:tags,name'
+ ];
+ }
+```
+
+> If your validation needs to be different between the Create and Update operations, [you can easily do that too](/docs/{{version}}/crud-operation-create#separate-requests-for-create-and-update).
+
+
+### The Route
+
+We have already generated our CRUD route, and we don't need to do anything about it, but let's check our ```routes/backpack/custom.php```. It should look like this:
+
+```php
+ config('backpack.base.route_prefix', 'admin'),
+ 'middleware' => ['web', config('backpack.base.middleware_key', 'admin')],
+ 'namespace' => 'App\Http\Controllers\Admin',
+], function () { // custom admin routes
+ // CRUD resources and other admin routes
+ CRUD::resource('tag', 'Admin\TagCrudController');
+}); // this should be the absolute last line of this file
+```
+
+Here, we can see that our routes have been placed:
+- under a prefix that we can change in ```config/backpack/base.php```;
+- under a middleware we can change in ```config/backpack/base.php```;
+- inside the ```App\Http\Controllers\Admin``` namespace, because that's where our custom CrudControllers will be generated;
+
+**It's generally a good idea to have the all admin routes in this separate file.** If you edit this file in the future, make sure you leave the last line intact, so that other routes can be automatically generated inside this file. And of course, add your routes inside this route group, so that:
+- you have a single prefix for your admin routes (ex: ```admin/tag```, ```admin/product```, ```admin/dashboard```);
+- all your admin panel functionality is protected by the same middleware;
+- all your admin panel controllers live in one place (```App\Http\Controllers\Admin```);
+
+
+### The Menu Item
+
+We've previously generated a menu item in the ```views/vendor/backpack/base/inc/sidebar_content.php``` file. You'll see this file is pure HTML. This will allow you to customize the menu as much as you want. The "active" state of the menu is done with JavaScript, based on the ```href``` attribute.
+
+This is the bit that has been generated for you:
+
+```php
+
+```
+
+You can of course change anything here, if you want.
+
+
+## The result
+
+You are now ready to go to ```your-app-name.domain/admin/tag``` and see your fully functional admin panel for ```Tags```.
+
+**Congratulations, you should now have a good understanding of how Backpack\CRUD works!** This is a very very basic example, but the process will be identical for Models with 50+ attributes, complicated logic, etc.
diff --git a/3.6/demo.md b/3.6/demo.md
new file mode 100644
index 00000000..eb531deb
--- /dev/null
+++ b/3.6/demo.md
@@ -0,0 +1,61 @@
+# Demo
+
+---
+
+We've put together a working Laravel app (backend-only), that you can install on your machine. This should make it easier to:
+- see how it looks & feels;
+- see how it works;
+- change stuff in code, to see how easy it is to customize Backpack;
+
+In this [Demo repository](https://github.com/laravel-backpack/demo), we've:
+- installed Laravel 5.6;
+- installed Backpack\Base and Backpack\CRUD on top;
+- created a few demo models (Monsters, Icons, Products) and admin panels for them, using dozens of field types, column types, filters, etc - to show off most of Backpack's default features;
+- installed a few Backpack extensions: PermissionManager, PageManager, LogManager, BackupManager, Settings, MenuCRUD, NewsCRUD;
+
+
+>**Don't use this demo to start your real projects.** Please use [the recommended installation procedure](/docs/{{version}}/installation). You don't want all the bogus entities we've created. You don't want all the packages we've used. And you _definitely_ don't want the default admin user. Start from scratch.
+
+
+## Demo Installation
+
+1) In your ```Projects``` or ```www``` directory, wherever you host your apps:
+
+```zsh
+git clone https://github.com/Laravel-Backpack/demo.git backpack-demo
+```
+
+2) Set your database information in your ```.env``` file (use ```.env.example``` as an example);
+
+3) Install all the requirements:
+``` zsh
+cd backpack-demo
+composer install
+```
+
+4) Populate the database and stuff:
+```zsh
+php artisan key:generate
+php artisan migrate
+php artisan db:seed --class="Backpack\Settings\database\seeds\SettingsTableSeeder"
+php artisan db:seed
+```
+
+
+## Usage
+
+Once everything's installed, and your database has been set up:
+
+- Your admin panel is available at http://localhost/backpack-demo/admin
+- Login with email ```admin@example.com```, password ```admin```
+- You can register a different account, to check out the process and see your gravatar inside the admin panel.
+- By default, registration is open only in your local environment. Check out ```config/backpack/base.php``` to change this and other preferences.
+- Check out the Monsters admin panel - it features over 40 field types.
+- The magic of Backpack is not in its standard functionality, but in how easy it is to code your own, or customize every little bit of it. Our recommendation:
+ - Go through the [CRUD Tutorial](/docs/{{version}}/crud-tutorial) to understand it;
+ - Create a new CRUD panel for an entity, using the faster procedure outlined at the end of that page; say... ```car```;
+
+
+>**vhost configurations**
+>
+>Depending on your vhost configuration you might need to access the application via a different url, for example if you're using ```artisan serve``` you can access it on http://127.0.0.1:8000/admin - if you're using Laravel Valet, then it may look like http://backpack-demo.test/admin - you will need to access the url which matches your systems configuration. If you do not understand how to configure your virtual hosts, we suggest [watching Laracasts Episode #1](https://laracasts.com/series/laravel-from-scratch/episodes/1) to quickly get started.
\ No newline at end of file
diff --git a/3.6/getting-started-advanced-features.md b/3.6/getting-started-advanced-features.md
new file mode 100644
index 00000000..60148539
--- /dev/null
+++ b/3.6/getting-started-advanced-features.md
@@ -0,0 +1,39 @@
+# 3. Advanced Features
+
+---
+
+**Duration:** 5 min
+
+Here are some other cool things Backpack makes easy for you. We recommend going through them one by one, just browsing. You might not need the feature _right now_, but when _you do_, you'll know how to find it.
+
+---
+
+
+## Other Operations
+- [Show](/docs/{{version}}/crud-operation-show) Operation - you can let your admins preview an entry
+- [Reorder](/docs/{{version}}/crud-operation-reorder) Operation - you can reorder and nesting entries (hierarchy tree)
+- [Revisions](/docs/{{version}}/crud-operation-revisions) Operation - you can keep a record of all modifications to an entry, and let your admin revert changes
+
+---
+
+
+## Other Features
+- **Create & Update**
+ - [Manage files on disk](/docs/{{version}}/crud-how-to#use-the-media-library-file-manager) (media library)
+ - [Fake fields](/docs/{{version}}/crud-fields#fake-fields-all-stored-as-json-in-the-database)
+ - Translatable models and [multi-language CRUDs](/docs/{{version}}/crud-operation-update#translatable-models)
+ - [Tabs in create/update forms](/docs/{{version}}/crud-fields#split-fields-into-tabs)
+
+--
+
+- **ListEntries**
+ - you can add a "+" button next to each entry, to allow the admin to easily preview some quick information that was too big to fit inside a columns - we call it [details row](/docs/{{version}}/crud-operation-list-entries#details-row)
+ - export all visible items in the table by adding [export buttons](/docs/{{version}}/crud-operation-list-entries#export-buttons)
+ - [custom search logic](/docs/{{version}}/crud-columns#custom-search-logic) for the columns in the list view
+
+
+Additionally, here are a few more ways you can customize your CRUDs:
+- [Custom Views for each CRUD](/docs/{{version}}/crud-how-to#customize-views-for-each-crud-panel)
+- [Custom CSS or JS](/docs/{{version}}/crud-how-to#customize-css-and-js-for-default-crud-operations) for each CRUD Operation
+
+**That's it for today!** Told you we're done with long lessons :-) Hopefully some of the above have peaked your interest and you've clicked to see what Backpack can do. In the [next lesson](/docs/{{version}}/getting-started-license-and-support) we'll go through a few other Backpack packages that cover some recurring use cases.
diff --git a/3.6/getting-started-basics.md b/3.6/getting-started-basics.md
new file mode 100644
index 00000000..64507b5e
--- /dev/null
+++ b/3.6/getting-started-basics.md
@@ -0,0 +1,128 @@
+# 1. Basics
+
+---
+
+**Duration:** 5 minutes
+
+> **Are you already comfortable with Laravel?** In order to understand this series and make use of Backpack, you'll need to have a decent understanding of the Laravel framework. If you don't, please go ahead and [watch this excellent intro series on Laracasts](https://laracasts.com/series/laravel-from-scratch-2017) and accommodate yourself with Laravel first.
+
+
+
+## What is Backpack?
+A software that helps Laravel professionals build administration panels - secure areas where administrators login and create, read, update and delete application information. It is *not* a CMS, it is more a framework that lets you *build your own* CMS. You can install it in your existing project or in a totally new project.
+
+It's designed to be flexible enough to allow you to **build admin panels for everything from simple presentation websites to CRMs, ERPs, eCommerce, eLearning, etc**. We can vouch for that, because we have built all that stuff using Backpack already.
+
+
+## How to use?
+
+Backpack consists of two **core packages**:
+- **Backpack\Base** - provides the design of the admin area (based on [AdminLTE](https://adminlte.io/themes/AdminLTE/index2.html))
+- **Backpack\CRUD** - empowers you to create **CRUDs**, really fast
+
+A **CRUD** is what we call a section of your admin panel that lets the admin _Create, Read, Update or Delete_ entries of a certain entity (or Model). So you can have a CRUD for Products, a CRUD for Articles, a CRUD for Categories, or whatever else you might want to create, read, update or delete.
+
+For the purpose of this series, we'll show examples on the ```Tag``` entity. This is what a Tag CRUD could look like:
+
+
+
+But Backpack is fully prepared for feature-packed CRUDs - since it's a good tool for very complex projects too. Here's what a CRUD that uses all of Backpack's features could look like:
+
+
+
+Mind that you will _almost never_ use all of Backpack's features in one CRUD. But if you do... it still looks good, and it'll be intuitive to use.
+
+
+## Core Packages
+
+
+### Backpack\Base
+
+**Backpack/Base** is the package that **will handle the authentication** and provide you with minimal admin area functionality. **Your admin will be able to login and change his password or email.** And that's pretty much it.
+
+
+
+Thanks to Base, after you [install Backpack](/docs/{{version}}/installation) (don't do it now), you'll be able to log into your admin panel at ```http://yourapp/admin```. You can change the URL prefix from ```admin``` to something else in your ```config/backpack/base.php``` file, along with a bunch of other configuration options. [Click here](https://github.com/Laravel-Backpack/Base/blob/master/src/config/backpack/base.php) to browse the configuration file and see what it can do for you.
+
+Backpack\Base pulls in the free [AdminLTE](https://adminlte.io/themes/AdminLTE/index2.html) theme and enhances the design a little bit. So any front-end block that AdminLTE has, you'll also be able to use in your custom pages. It also includes a system for bubble notifications, which you can use across the admin panel. You can easily [trigger notification bubbles in PHP](/docs/{{version}}/base-about#triggering-notification-bubbles-in-php) or [trigger notification bubbles in JavaScript](/docs/{{version}}/base-about#triggering-notification-bubbles-in-javascript).
+
+
+### Backpack\CRUD
+This is where it gets interesting. As soon as you [install Backpack](/docs/{{version}}/installation) in your project, you can create **CRUDs** for your admins to easily manipulate DB information. Let's browse through a simple example, of creating a CRUD administration panel for a Tag entity:
+
+```zsh
+# STEP 1. create migration
+php artisan make:migration:schema create_tags_table --model=0 --schema="name:string:unique"
+php artisan migrate
+
+# STEP 2. create a model, a request and a controller for the admin panel
+php artisan backpack:crud tag #use singular, not plural
+
+# STEP 3. add a route to routes/backpack/custom.php (under the admin prefix and auth middleware):
+php artisan backpack:base:add-custom-route "CRUD::resource('tag', 'TagCrudController');"
+
+# STEP 4. add a sidebar item
+php artisan backpack:base:add-sidebar-content "
"
+```
+
+This will create a simple CRUD panel, which you should now be able to see in the Sidebar.
+
+For a simple entry like this, the generated CRUD panel will even work "as is", no need for customizations. But don't expect this for more complex entities. They will usually have particularities and need customization. That's where Backpack shines - modifying anything in the CRUD Panel is easy and intuitive, once you understand how it works.
+
+The code above would generate:
+- a **migration** file
+- a **model** (```app\Models\Tag.php```)
+- a **request** file, for form validation (```app\Http\Requests\TagCrudRequest.php```)
+- a **controller** file, where you can customize how the CrudPanel looks and feels (```app\Http\Controllers\Admin\TagCrudController.php```)
+- a **route**, as a line inside ```routes/backpack/custom.php```
+
+We won't be covering the **migration**, **model** and **request** files here, as they are in no way custom. The only thing you need to make sure is that the Model is properly configured (db table, relationships, ```$fillable``` or ```$guarded``` properties, etc) and that it uses our ```CrudTrait```. What we _will_ be covering is ```TagCrudController``` - which is where most of your logic will reside. Here's a copy of a simple one you might use to achieve the above:
+
+```php
+crud->setModel("App\Models\Tag");
+ $this->crud->setRoute("admin/tag");
+ $this->crud->setEntityNameStrings('tag', 'tags');
+
+ $this->crud->setColumns(['name', 'slug']);
+ $this->crud->addField([
+ 'name' => 'name',
+ 'type' => 'text',
+ 'label' => "Tag name"
+ ]);
+ $this->crud->addField([
+ 'name' => 'slug',
+ 'type' => 'text',
+ 'label' => "URL Segment (slug)"
+ ]);
+ }
+
+ public function store(StoreRequest $request)
+ {
+ return parent::storeCrud();
+ }
+
+ public function update(UpdateRequest $request)
+ {
+ return parent::updateCrud();
+ }
+}
+```
+
+You should notice:
+- It uses basic inheritance (```TagCrudController extends CrudController```); so if you want to modify a behaviour (save, update, reorder, etc), you can easily do that by overwriting the corresponding method in your ```TagCrudController```;
+- The request file is typehinted in the ```store()``` and ```update()``` methods; Since in case form validation fails, the information won't even reach these methods;
+- All the CRUD setup is usually done in the ```setup()``` method;
+
+**That's all for today! **If you want to learn more, go ahead and [read the next lesson](/docs/{{version}}/getting-started-crud-operations) of this series.
diff --git a/3.6/getting-started-crud-operations.md b/3.6/getting-started-crud-operations.md
new file mode 100644
index 00000000..42735246
--- /dev/null
+++ b/3.6/getting-started-crud-operations.md
@@ -0,0 +1,243 @@
+# 2. CRUD Operations
+
+---
+
+**Duration:** 10 minutes
+
+Let's bring back the example in our first lesson. The Tags CRUD:
+
+
+
+With its ```TagCrudController```:
+
+```php
+crud->setModel("App\Models\Tag");
+ $this->crud->setRoute("admin/tag");
+ $this->crud->setEntityNameStrings('tag', 'tags');
+
+ $this->crud->setColumns(['name', 'slug']);
+ $this->crud->addField([
+ 'name' => 'name',
+ 'type' => 'text',
+ 'label' => "Tag name"
+ ]);
+ $this->crud->addField([
+ 'name' => 'slug',
+ 'type' => 'text',
+ 'label' => "URL Segment (slug)"
+ ]);
+ }
+
+ public function store(StoreRequest $request)
+ {
+ return parent::storeCrud();
+ }
+
+ public function update(UpdateRequest $request)
+ {
+ return parent::updateCrud();
+ }
+}
+```
+
+By default, CRUDs have these operations already enabled:
+- **Create** - using a create form (aka "*add form*")
+- **ListEntries** - using AJAX DataTables (aka "*list view*", aka "*table view*")
+- **Update** - using an update form (aka "*edit form*")
+- **Delete** - using a *button* in the *list view*
+
+These are the basic operations an admin can execute on an Eloquent model, thanks to Backpack. We do have additional operations (Preview, Reorder, Revisions), and you can easily _create a custom operation_, but let's not get ahead of ourselves. Baby steps. **Let's go through the most important features of the operations you'll be using _all the time_: ListEntries, Create and Update**.
+
+
+## Create & Update Operations
+
+
+
+
+### Fields
+
+Inside your Controller's ```setup()``` method, you'll be able to define what fields you want the admin to see, when creating/updating entries. In the example above, we only have two fields, both using the ```text``` field type. So that's what's shown to the admin. When the admin presses _Save_, assuming your model has those two attributes as ```$fillable```, Backpack will save the entry and take you back to the ListEntries view. Keep in mind we're using a _pure_ Eloquent model. So of course, inside the model you could use accessors, mutators, events, etc.
+
+
+But a lot of times, you won't just need text inputs. You'll need datepickers, upload buttons, 1-n relationship, n-n relationships, textareas, etc. For each field, you only need to define it properly in the Controller's ```setup()``` method. Here are the most used methods to manipulate fields:
+
+```php
+// You can pass a second parameter with the operation:
+// - "create" for Create
+// - "update" for Update
+// - nothing (missing) for both Create and Update
+
+$this->crud->addField($field_definition_array);
+$this->crud->addFields([$field_definition_array_1, $field_definition_array_2]);
+$this->crud->removeField('name');
+$this->crud->removeFields(['name_1', 'name_2']);
+
+// pro tip:
+// a quick way to add simple fields: let the CRUD decide what field type it is
+$this->crud->addField('db_column_name');
+```
+
+A typical *field definition array* will need at least three things:
+- ```name``` - the attribute (column in the database), which will also become the name of the input;
+- ```type``` - the kind of field we'd like to use (text, number, select2, etc);
+- ```label``` - the human-readable label for the input (will be generated from ```name``` if not given);
+
+
+You can use [one of the 44+ field types we've provided](/docs/{{version}}/crud-fields#default-field-types), or easily [create a custom field type](/docs/{{version}}/crud-fields#creating-a-custom-field-type) if you have some super-specific need that we haven't covered yet, or even [overwrite how a field type works](#overwriting-default-field-types). Take a few minutes and [browse the 44+ field types](/docs/{{version}}/crud-fields#default-field-types), to understand how the definition array differs from one to another and how many use cases you have already covered.
+
+Let's take another example, slightly more complicated than the ```text``` fields we used above. Something you'll encounter all the time is relationship fields. So let's say the ```Tag``` model has an **n-n relationship** with an Article model:
+
+```php
+ public function articles()
+ {
+ return $this->belongsToMany('App\Models\Article', 'article_tag');
+ }
+```
+
+We could use the code below to add a ```select2_multiple``` field to the Tag update forms:
+
+```php
+$this->crud->addField([
+ 'type' => 'select2_multiple',
+ 'name' => 'articles', // the relationship name in your Model
+ 'entity' => 'articles', // the relationship name in your Model
+ 'attribute' => 'title', // attribute on Article that is shown to admin
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
+], 'update');
+```
+
+**Notes:**
+- Because of the last parameter ("_update_"), the field will only be added on the Update form (not on the Create);
+- Because we haven't specified a ```label```, Backpack will take the "_articles_" name and turn it into a label: "_Articles_";
+
+If we had an Articles CRUD, and the reverse relationship defined on the ```Article``` model too, we could also add a ```select2_multiple``` field in the Article CRUD, to allow the admin to choose which tags apply to each article. This actually makes more sense than the above :-)
+
+```php
+$this->crud->addField([
+ 'label' => "Tags",
+ 'type' => 'select2_multiple',
+ 'name' => 'tags', // the method that defines the relationship in your Model
+ 'entity' => 'tags', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
+]);
+```
+
+**Note: **Because the last parameter is missing, the field will be added to both Create and Update forms.
+
+
+> When generating a CrudController, you'll be using the ```$this->crud->setFromDb();``` method by default, which tries to figure out what fields you might need in your create/update forms and in your list view, but - as you'd expect - only works for the simple field types. You can:
+>
+> (1) choose to keep using ```setFromDb()``` and add/remove/change additional fields
+>
+> or
+>
+> (2) delete ```setFromDb()``` and manually define each field and column;
+>
+> **Our recommendation**, for anything but the simplest CRUDs, **is to manually define each field** - much easier to understand and customize, for your future self and any other developer that comes after you.
+
+
+### Callbacks
+
+Developers coming from GroceryCRUD on CodeIgniter or other CRUD systems will be looking for callbacks to run ```before_insert```, ```before_update```, ```after_insert```, ```after_update```.
+
+**There are no callbacks in Backpack**, because there's no need. The code for the create & update operations is out in the open for you to customize. Notice your EntityCrudController already has the following methods, which you can modify as you wish:
+
+```php
+public function store(StoreRequest $request)
+{
+ // <--------- here is where a before_insert callback logic would be
+ $response = parent::storeCrud();
+ // <--------- here is where a after_insert callback logic would be
+ return $response;
+}
+
+public function update(UpdateRequest $request)
+{
+ // <--------- here is where a before_update callback logic would be
+ $response = parent::updateCrud();
+ // <--------- here is where a after_update callback logic would be
+ return $response;
+}
+```
+
+But before you do that, ask yourself - *is this something that should be done when an entry is added/updated/deleted from the application, too*? Not just the admin admin? If so, a better place for it would be the Model. Remember your Model is a pure Eloquent Model, so the cleanest way might be to use [Eloquent Event Observers](https://laravel.com/docs/5.5/eloquent#events) or [accessors and mutators](https://laravel.com/docs/master/eloquent-mutators#accessors-and-mutators).
+
+
+## ListEntries Operation
+
+ListEntries shows the admin a table with all entries. On the front-end, the information is pulled using AJAX calls, and shown using DataTables. It's the most feature-packed operation in Backpack, but right now we're just going through the most important features you need to know about: columns, filters and buttons.
+
+
+### Columns
+
+Columns help you specify *which* attributes are shown in the table and *in which order*. **They're defined in the ```setup()``` method, the same as fields, and their syntax is super-similar to fields too**:
+
+```php
+$this->crud->addColumn($column_definition_array); // add a single column, at the end of the table
+$this->crud->addColumns([$column_definition_array_1, $column_definition_array_2]); // add multiple columns, at the end of the table
+$this->crud->removeColumn('column_name'); // remove a column from the table
+$this->crud->removeColumns(['column_name_1', 'column_name_2']); // remove an array of columns from the table
+$this->crud->setColumnDetails('column_name', ['attribute' => 'value']);
+$this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
+
+$this->crud->setColumns([$column_definition_array_1, $column_definition_array_2]); // make these the only columns in the table
+```
+
+You can use one of the [14+ column types](/docs/{{version}}/crud-columns#default-column-types) to show information to the user in the table, or easily [create a custom column type](/docs/{{version}}/crud-columns#creating-a-custom-column-type), if you have a super-specific need. Here's an example of using the methods above:
+
+```php
+$this->crud->addColumn([
+ 'name' => 'published_at',
+ 'type' => 'date',
+ 'label' => 'Publish_date',
+ ]);
+
+// PRO TIP: to quickly add a text column, just pass the name string instead of an array
+$this->crud->addColumn('text'); // adds a text column, at the end of the stack
+```
+
+
+### Filters
+
+
+
+Filters provide an easy way for the admin to well… _filter_ the ListEntries table. The syntax is very similar to Fields and Columns and you can use one of the [existing 8 filter types](/docs/{{version}}/crud-filters) or easily [create a custom filter](/docs/{{version}}/crud-filters#creating-custom-filters).
+
+```php
+$this->crud->addFilter($options, $values, $filter_logic);
+$this->crud->removeFilter($name);
+$this->crud->removeAllFilters();
+```
+
+For more on this, check out the [filters documentation page](/docs/{{version}}/crud-filters), when you need them.
+
+
+### Buttons
+
+
+
+If you want to add a custom button to an entry, you can do that. If you want to remove a button, you can also do that. Look for the [buttons documentation](/docs/{{version}}/crud-buttons) when you need it.
+
+```php
+// positions: 'beginning' and 'end'
+// stacks: 'line', 'top', 'bottom'
+// types: view, model_function
+$this->crud->addButton($stack, $name, $type, $content, $position);
+$this->crud->removeButton($name);
+$this->crud->removeButtonFromStack($name, $stack);
+```
+
+**That's it for today!** Thanks for sticking with us this long. This has been the most important and longest lesson. You can go ahead and [install Backpack](/docs/{{version}}/installation) now, as you've already gone through the most important features. Or [read the next lesson](/docs/{{version}}/getting-started-advanced-features), about advanced features.
\ No newline at end of file
diff --git a/3.6/getting-started-license-and-support.md b/3.6/getting-started-license-and-support.md
new file mode 100644
index 00000000..7dceeb0a
--- /dev/null
+++ b/3.6/getting-started-license-and-support.md
@@ -0,0 +1,43 @@
+# 4. Add-ons, License & Support
+
+---
+
+**Duration:** 3 minutes
+
+
+## Add-ons
+
+In addition to our core packages (Base and CRUD), we have quite a few packages you can install or download, that treat common use cases. Some have been developed by our core team, some by our wonderful community. For example, we have plug&play interfaces to manage [site-wide settings](https://github.com/Laravel-Backpack/Settings), [the default Laravel users table](https://github.com/eduardoarandah/UserManager), [users, groups & permissions](https://github.com/Laravel-Backpack/PermissionManager), [content for custom pages, using page templates](https://github.com/Laravel-Backpack/PageManager), [news articles, categories and tags](https://github.com/Laravel-Backpack/NewsCRUD), etc.
+
+Take a look at:
+- [all official add-ons](/docs/{{version}}/add-ons-official)
+- [all community add-ons](/docs/{{version}}/add-ons-community)
+
+
+## License
+
+Backpack is **free for non-commercial use**, but needs a license code in order to prevent "_unlicensed use_" notification bubbles and interruption of service. You can get a license code for your project:
+- ```free```, if you're using it for non-commercial purposes; [apply here](https://backpackforlaravel.com/pricing);
+- ```free```, if you've contributed to Backpack on Github; [apply here](https://backpackforlaravel.com/pricing);
+- ```$49 EUR/project```, if you're making money using it for a project; [buy here](https://backpackforlaravel.com/pricing);
+- ```$299 EUR for unlimited projects```, if you use Backpack a lot; [buy here](https://backpackforlaravel.com/pricing);
+
+**Freelancers** or companies **who make money using Backpack** - for themselves, their employers or their clients, **should [purchase a commercial license here](https://backpackforlaravel.com/pricing)**.
+
+
+>**You don't need a license code on LOCALHOST.** If you're just trying Backpack on your own machine, you don't need a license code. You only need a license code when you take your application to production.
+
+
+## Support
+
+With thousands of developers using Backpack, a lot of them non-commercial, and such a small price, **we can't offer official support for the packages**. We've been doing this since 2016, we actively maintain the packages, we try to squash any bugs ASAP and add new features all the time, but we unfortunately can't spend time on back-and-forth on implementation issues in your project. But. We do have good documentation and have been blessed with a **great community**, where people help each other out. If Backpack becomes your tool of preference, I highly recommend you join our gang. Help others get started, create cool stuff, or even influence the direction of Backpack:
+
+- **[StackOverflow tag](https://stackoverflow.com/questions/tagged/backpack-for-laravel) for support requests** (If you need help creating something using Backpack, post your question on StackOverflow using the ```backpack-for-laravel``` tag. We've been blessed with a great community that is happy to help. Who doesn't like getting StackOverflow points?)
+- **[Gitter Chatroom](https://gitter.im/BackpackForLaravel/Lobby) for quick questions** (If you have an urgent matter that won't take much time to answer, use our 24/7 Gitter chatroom. Be considerate, everyone's probably working on their own project right now.)
+- **[Github Issues](https://github.com/laravel-backpack/) for bugs** (Found a bug? Great! Please search for it on Github first - someone might have already found it. If not, open an issue, we're happy to learn about it and make Backpack better. )
+
+Thank you for sticking up with us for so long. This is the last Backpack lesson we can give you. **Now you have absolutely no excuse not to start your first Backpack project :-)** Here are a few links for if you still don't think you're ready:
+
+- [Go through the demo](/docs/{{version}}/demo) and play around
+- Read this [CRUD Tutorial](/docs/{{version}}/crud-tutorial)
+- Take a look at the [CrudController API Cheat Sheet](/docs/{{version}}/crud-cheat-sheet)
\ No newline at end of file
diff --git a/3.6/index.md b/3.6/index.md
new file mode 100644
index 00000000..c4b04116
--- /dev/null
+++ b/3.6/index.md
@@ -0,0 +1,44 @@
+#### About
+
+- [Getting Started](/docs/{{version}}/introduction)
+ - [1. Basics](/docs/{{version}}/getting-started-basics)
+ - [2. CRUD Operations](/docs/{{version}}/getting-started-crud-operations)
+ - [3. Advanced Features](/docs/{{version}}/getting-started-advanced-features)
+ - [4. Add-ons, License & Support](/docs/{{version}}/getting-started-license-and-support)
+- [Demo](/docs/{{version}}/demo)
+- [Installation](/docs/{{version}}/installation)
+- [Release Notes](/docs/{{version}}/release-notes)
+- [Upgrade Guide](/docs/{{version}}/upgrade-guide)
+
+#### Backpack\Base 1.1.x
+
+- [About](/docs/{{version}}/base-about)
+- [How To](/docs/{{version}}/base-how-to)
+
+#### Backpack\CRUD 3.6.x
+
+- [Basics](/docs/{{version}}/crud-basics)
+- [Tutorial](/docs/{{version}}/crud-tutorial)
+- [API](/docs/{{version}}/crud-api)
+- [Cheat Sheet](/docs/{{version}}/crud-cheat-sheet)
+- [Operations](/docs/{{version}}/crud-operations)
+ + [ListEntries](/docs/{{version}}/crud-operation-list-entries)
+ + [Columns](/docs/{{version}}/crud-columns)
+ + [Buttons](/docs/{{version}}/crud-buttons)
+ + [Filters](/docs/{{version}}/crud-filters)
+ + [Create](/docs/{{version}}/crud-operation-create) & [Update](/docs/{{version}}/crud-operation-update)
+ + [Fields](/docs/{{version}}/crud-fields)
+ + [Delete](/docs/{{version}}/crud-operation-delete)
+ + [Clone](/docs/{{version}}/crud-operation-clone)
+ + [Show](/docs/{{version}}/crud-operation-show)
+ + [Columns](/docs/{{version}}/crud-columns)
+ + [Reorder](/docs/{{version}}/crud-operation-reorder)
+ + [Revisions](/docs/{{version}}/crud-operation-revisions)
+- [How To](/docs/{{version}}/crud-how-to)
+
+
+#### Add-ons
+
+- [Official Add-ons](/docs/{{version}}/add-ons-official)
+- [Community Add-ons](/docs/{{version}}/add-ons-community)
+- [How to Create an Add-on](/docs/{{version}}/add-ons-how-to-create-a-backpack-addon)
diff --git a/3.6/install-optionals.md b/3.6/install-optionals.md
new file mode 100644
index 00000000..bf58fc0b
--- /dev/null
+++ b/3.6/install-optionals.md
@@ -0,0 +1,165 @@
+# Install Optional Packages
+
+---
+
+Each Backpack package has its own installation instructions in its readme file. We duplicate them here for easy access.
+
+Everything else is optional. Your project might use them or it might not. Only do each of the following steps if you need the functionality that package provides.
+
+
+## BackupManager
+
+[>> See screenshots and installation](https://github.com/Laravel-Backpack/BackupManager)
+
+1) In your terminal
+
+``` bash
+# Install the package
+composer require backpack/backupmanager
+
+# Publish the config file and lang files:
+php artisan vendor:publish --provider="Backpack\BackupManager\BackupManagerServiceProvider"
+
+# [optional] Add a sidebar_content item for it
+php artisan backpack:base:add-sidebar-content "
"
+```
+
+2) Add a new "disk" to config/filesystems.php:
+
+```php
+ // used for Backpack/BackupManager
+ 'backups' => [
+ 'driver' => 'local',
+ 'root' => storage_path('backups'), // that's where your backups are stored by default: storage/backups
+ ],
+```
+This is where you choose a different driver if you want your backups to be stored somewhere else (S3, Dropbox, Google Drive, Box, etc).
+
+3) [optional] Modify your backup options in config/backup.php
+
+4) [optional] Instruct Laravel to run the backups automatically in your console kernel:
+
+```php
+// app/Console/Kernel.php
+
+protected function schedule(Schedule $schedule)
+{
+ $schedule->command('backup:clean')->daily()->at('04:00');
+ $schedule->command('backup:run')->daily()->at('05:00');
+}
+```
+
+5) [optional] If you need to change the path to the mysql_dump command, you can do that in your config/database.php file. For MAMP on Mac OS, add these to your mysql connection:
+```
+ 'dump_command_path' => '/Applications/MAMP/Library/bin/', // only the path, so without 'mysqldump' or 'pg_dump'
+ 'dump_command_timeout' => 60 * 5, // 5 minute timeout
+ 'dump_using_single_transaction' => true,
+```
+
+
+## LogManager
+
+[>> See screenshots and installation](https://github.com/Laravel-Backpack/logmanager)
+
+
+1) Install via composer:
+
+``` bash
+composer require backpack/logmanager
+```
+
+2) Add a "storage" filesystem disk in config/filesystems.php:
+
+```
+// used for Backpack/LogManager
+'storage' => [
+ 'driver' => 'local',
+ 'root' => storage_path(),
+ ],
+```
+
+3) Configure Laravel to create a new log file for every day, in your .ENV file, if it's not already. Otherwise there will only be one file at all times.
+
+```
+ APP_LOG=daily
+```
+
+or directly in your config/app.php file:
+```
+ 'log' => env('APP_LOG', 'daily'),
+```
+
+4) [optional] Add a menu item for it in resources/views/vendor/backpack/base/inc/sidebar_content.blade.php or menu.blade.php:
+
+```bash
+php artisan backpack:base:add-sidebar-content "
"
+```
+
+## Settings
+
+An interface for the administrator to easily change application settings. Uses Laravel Backpack.
+
+[>> See screenshots and installation](https://github.com/Laravel-Backpack/settings)
+
+Installation:
+
+``` bash
+# install the package
+composer require backpack/settings
+
+# run the migration
+php artisan vendor:publish --provider="Backpack\Settings\SettingsServiceProvider"
+php artisan migrate
+
+# [optional] add a menu item for it to the sidebar_content file
+php artisan backpack:base:add-sidebar-content "
"
+
+# [optional] insert some example dummy data to the database
+php artisan db:seed --class="Backpack\Settings\database\seeds\SettingsTableSeeder"
+```
+
+
+## PageManager
+
+[>> See screenshots and installation](https://github.com/Laravel-Backpack/pagemanager)
+
+1) In your terminal
+
+``` bash
+composer require backpack/pagemanager
+```
+
+2) Publish the views, migrations and the PageTemplates trait; run the migrations:
+
+```
+php artisan vendor:publish --provider="Backpack\PageManager\PageManagerServiceProvider"
+php artisan migrate
+```
+
+3) [optional] Add a menu item for it in resources/views/vendor/backpack/base/inc/sidebar_content.blade.php or menu.blade.php:
+
+```bash
+php artisan backpack:base:add-sidebar-content "
"
+```
+
+
+## PermissionManager
+
+An admin panel for user authentication on Laravel 5, using Backpack\CRUD. Add, edit, delete users, roles and permission.
+
+[>> Installation](https://github.com/Laravel-Backpack/PermissionManager#install)
+[>> Github](https://github.com/Laravel-Backpack/PermissionManager)
+
+
+## MenuCrud
+
+An admin panel for menu items on Laravel 5, using Backpack\CRUD. Add, edit, reorder, nest, rename menu items and link them to Backpack\PageManager pages, external link or custom internal link.
+
+[>> Github](https://github.com/Laravel-Backpack/MenuCRUD)
+
+
+## NewsCrud
+
+Since NewsCRUD does not provide any extra functionality other than Backpack\CRUD, it is not a package. It's just a tutorial to show you how this can be achieved. In the future, CRUD examples like this one will be easily installed from the command line, from a central repository. Until then, you will need to manually create the files.
+
+[>> Github](https://github.com/Laravel-Backpack/NewsCRUD)
diff --git a/3.6/installation.md b/3.6/installation.md
new file mode 100644
index 00000000..48d6c9bc
--- /dev/null
+++ b/3.6/installation.md
@@ -0,0 +1,71 @@
+# Installation
+
+---
+
+
+## Requirements
+
+If you can run Laravel 6 or 5.8, you can install Backpack. Backpack does _not_ have additional requirements. For the following process, we assume:
+
+- you have a working installation of [Laravel 6](https://laravel.com/docs/6.0#installing-laravel) or [Laravel 5.8](https://laravel.com/docs/5.8#installing-laravel) (an existing project is fine, you don't need a *fresh* Laravel install);
+
+- you have put your database and email credentials in your .ENV file;
+
+- you can run the ```composer``` command from any directory (you have ```composer``` registered as a global command); if you need to run ```php composer.phar``` or reference another directory, please remember to adapt the commands below to your configuration;
+
+
+## Installation
+
+
+### Install Core Packages
+
+0) Open your project folder in your terminal:
+
+```bash
+cd your-laravel-project-name
+```
+
+1) In your project's main directory, install CRUD using composer:
+
+``` bash
+composer require backpack/crud
+```
+
+2) Now run the installation commands for each of the core packages (Base has also been installed, as a dependency):
+
+``` bash
+php artisan backpack:base:install
+php artisan backpack:crud:install
+```
+
+Note: If you'd also like to enable the [file manager functionality](https://backpackforlaravel.com/uploads/home_slider/4.png), reply "yes" when the installer asks you. By default it lets users manage the ```public/uploads``` directory, but you can change that in the ```elfinder.php``` config file. Most of the times it is _not_ recommended to give your admins power over file structure - not even their uploads alone. So ```elfinder``` does not come installed by default.
+
+
+3) [Optional] You should now:
+- Change configuration values in ```config/backpack/base.php``` to make the admin panel your own. Backpack is white label, so you can change everything: menu color, project name, developer name etc.
+- If your User model has been moved (it is not ```App\User.php```, please go change ```App\Models\BackpackUser.php``` and make sure it extends the correct user model;
+- If you have separate admin panels for Users and Administrators, and already have a way to differentiate between the two, please change ```app/Http/Middleware/CheckIfAdmin.php```, particularly ```checkIfUserIsAdmin($user)```, to make sure all users who get log into the admin panel have a right to do that;
+- If your application has only one login screen (for the admins), that means you're not going to use the auth controllers that Laravel provided by default. You're only going to use Backpack's auth controllers. You can keep the Laravel ones in your project, of course. But some people like to delete them to not get confused later on:
+
+``` bash
+# OPTIONAL! Please read the notice above.
+rm -rf app/Http/Controllers/Auth #deletes laravel's demo auth controllers
+```
+
+That's it. If you already know how to use Backpack, next up you'll probably want to [create CRUD Panels](/docs/{{version}}/crud-tutorial#generate-files).
+
+> If it's your first time installing Backpack, it is **highly recommended** that you go through our [Getting Started series](/docs/{{version}}/getting-started-basics), to understand how Backpack works. That's why we created it - to help you learn how to use this admin panel framework. In ~23 minutes we'll teach you 80% of what you can do, and how.
+
+
+### Install Add-ons
+
+In case you want to add extra functionality that's already been built, check out [the installation steps for the add-ons we've developed](/docs/{{version}}/install-optionals).
+
+
+## Frequently Asked Questions
+
+- **Error: The process X exceeded the timeout of 60 seconds.** It might mean Github or Packagist is unavailable at the moment. This usually doesn't last for more than a few minutes, so you can run ```php artisan backpack:base:install --timeout=600``` to increase the timeout to 10 minutes. If this doesn't work either, take a look behind the scenes with ```php artisan backpack:base:install --timeout=600 --debug```, and refer to [this thread](https://github.com/Laravel-Backpack/Base/issues/217).
+
+- **Error: SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long**. Your MySQL version might be a bit old. Please [apply this quick fix](https://laravel-news.com/laravel-5-4-key-too-long-error), then run ```php artisan migrate:fresh```.
+
+- **Any other installation error?** If you can't install Backpack\\Base because of a different error, you can [try the manual installation process](/docs/{{version}}/base-how-to#manually-install-base), which you can tweak to your needs.
diff --git a/3.6/introduction.md b/3.6/introduction.md
new file mode 100644
index 00000000..81bd4d44
--- /dev/null
+++ b/3.6/introduction.md
@@ -0,0 +1,79 @@
+# Getting Started
+
+---
+
+Backpack is a collection of Laravel packages that help you **build custom administration panels**, for anything from presentation websites to complex web applications. You can drop it on existing Laravel installations _or_ fresh projects.
+
+In a nutshell:
+
+- **Backpack\Base** will provide you with a _visual interface_ for the admin panel (the HTML, the CSS, the JS); it pulls in the excellent [AdminLTE](https://adminlte.io/themes/AdminLTE/index2.html) theme, adds authentication functionality & bubble notifications; when you decide to build a custom feature for your admin panel, you already have the HTML blocks for the UI, and it will look good;
+- **Backpack\CRUD** will help you build _sections where your admins can manipulate entries for Eloquent models_; we call them _CRUD Panels_ after the most basic operations: Create/Read/Update/Delete; after [understanding Backpack](/docs/{{version}}/getting-started-basics), you'll be able to create a CRUD panel for each entity in about 10 minutes / model:
+
+```bash
+# STEP 0. create migration (in case you're starting from scratch)
+php artisan make:migration:schema create_tags_table --model=0 --schema="name:string:unique"
+php artisan migrate
+
+# STEP 1. create a model, a request and a controller for the admin panel
+php artisan backpack:crud tag #use singular, not plural
+
+# STEP 2. add a route for this admin panel to routes/backpack/custom.php
+php artisan backpack:base:add-custom-route "CRUD::resource('tag', 'TagCrudController');"
+
+# STEP 3. add sidebar item to resources/views/vendor/backpack/base/inc/sidebar_content.blade.php
+php artisan backpack:base:add-sidebar-content "
"
+
+# STEP 4. go through the generated files, customize according to your needs
+```
+
+
+## Need to Know
+
+
+### Requirements
+
+ - Laravel 5.8
+ - PHP 7.1.3+
+ - MySQL (recommended) / PostgreSQL / SQLite / SQL Server
+
+
+### Screenshots
+
+Take a look at [our homepage](https://backpackforlaravel.com/).
+
+
+### Demo
+
+You can easily [install a demo Laravel project with Backpack installed](/docs/{{version}}/demo) and play around.
+
+
+### Security
+
+Backpack has never had a critical vulnerability/hack. But there _have_ been important security updates for dependencies (including Laravel). Please [login with Github](/auth/github) or [subscribe to our monthly newsletter](https://backpackforlaravel.com/newsletter), so we can reach you in case anything bad happens. No spam, no marketing emails, we promise. We only send one email per month, with Backpack updates.
+
+
+### Maintenance
+
+Backpack 3.5 is the current version, and is being actively maintained by Backpack's creator, [Cristian Tabacitu](http://tabacitu.ro), with the help of a wonderful community of Backpack veterans. [See all contributors](https://github.com/Laravel-Backpack/CRUD/graphs/contributors).
+
+
+### License
+
+Backpack is under a license we call "_You make money, I make money_" (YummY). Backpack's source is public, and you can use it for free for non-commercial purposes (testing, non-profits, personal use, etc), but if you make money using it you need to purchase a commercial license. Please see [the pricing section](https://backpackforlaravel.com/pricing) for more details. In production, you need a license code for both commercial and non-commercial use, to prevent nagging notification bubbles. On localhost, you don't need a license code.
+
+
+### Add-ons
+
+In addition to our core packages (Base and CRUD), there are a few packages you can install or download, that treat common use cases. Some have been developed by our core team, some by our wonderful community. You can just install interfaces to manage [site-wide settings](https://github.com/Laravel-Backpack/Settings), [the default Laravel users table](https://github.com/eduardoarandah/UserManager), [users, groups & permissions](https://github.com/Laravel-Backpack/PermissionManager), [content for custom pages, using page templates](https://github.com/Laravel-Backpack/PageManager), [news articles, categories and tags](https://github.com/Laravel-Backpack/NewsCRUD), etc.
+
+For more, please see:
+- [all official add-ons](/docs/{{version}}/add-ons-official)
+- [all community add-ons](/docs/{{version}}/add-ons-community)
+
+
+## How to Start
+
+We heavily recommend you spend a little time to understand Backpack, and only afterwards install and use it. Currently your options are:
+- **[Text Tutorial](/docs/{{version}}/getting-started-basics)** - 23 minutes
+- **[Email Tutorial](https://backpackforlaravel.com/getting-started-emails)** - 1 email per day, for 5 days, 5 minutes each
+- **Video Tutorial** - working on it
diff --git a/3.6/release-notes.md b/3.6/release-notes.md
new file mode 100644
index 00000000..395ab383
--- /dev/null
+++ b/3.6/release-notes.md
@@ -0,0 +1,27 @@
+# Release Notes
+
+---
+
+**Launch date:** March 1st 2019
+
+**Backpack 3.6 has no new features**. It is just a maintenance upgrade, which adds support for Laravel 5.8 and removes support for Laravel 5.7 and 5.6.
+
+Here are the main differences between [Backpack 3.5](https://backpackforlaravel.com/docs/3.5) and Backpack 3.6.
+
+
+## Backpack\Base 1.1.x
+
+### Added
+- support for Laravel 5.8;
+
+### Removed
+- removed Laravel 5.6 and 5.7 support;
+- ```jenssegers/date``` dependency, since Carbon v2 can now do the same thing well;
+- ```Tightenco\Parental``` dependency, since it proved unstable; the trait we were using is now included in Base as ```Backpack\Base\app\Models\Traits\InheritsRelationsFromParentModel;```;
+
+
+## Backpack\CRUD 3.6.x
+
+### Fixed
+
+- ```date``` and ```datetime``` column use Carbon localized dates, instead of ```jenssegers/date``` ;
diff --git a/3.6/upgrade-guide.md b/3.6/upgrade-guide.md
new file mode 100644
index 00000000..f768f2d9
--- /dev/null
+++ b/3.6/upgrade-guide.md
@@ -0,0 +1,31 @@
+# Upgrade Guide
+
+---
+
+This will guide you through upgrading from Backpack 3.5 to 3.6. For upgrading from 3.4 to 3.5 [check out the previous upgrade guide](https://backpackforlaravel.com/docs/3.5/upgrade-guide).
+
+
+## Requirements
+
+- Backpack\Base 1.0.x installed
+- Backpack\CRUD 3.5.x installed
+- Laravel 5.8 installed
+- PHP 7.1.3+
+- 5 minutes on top of your normal [Laravel 5.8 upgrade](https://laravel.com/docs/5.8/upgrade)
+
+
+## Upgrade Steps
+
+1. Update your ```composer.json``` file to require ```"backpack/crud": "3.6.*"``` along with ```"laravel/framework": "5.8.*"```. Remove ```backpack/base``` from your requirements - backpack/crud will take care of that. Then run ```composer update```.
+
+2. In your ```App\Models\BackpackUser``` instead of ```Tightenco\Parental\HasParent```, please use ```Backpack\Base\app\Models\Traits\InheritsRelationsFromParentModel```; [here's the diff](https://github.com/Laravel-Backpack/Base/pull/362/files#diff-f075b83ebb2b1ef3ba84dec14b395607);
+
+3. In your ```app/config/backpack/base.php``` please change your ```default_date_format``` and ```default_datetime_format``` to ```Do MMMM YYYY``` and ```Do MMMM YYYY, HH:mm``` respectively;
+
+4. If you've overwritten ```inc/head.blade.php``` or ```inc/scripts.blade.php```, please make sure you [use the newest version of Bootstrap](https://github.com/Laravel-Backpack/Base/pull/362/files#diff-96ac3ea4d0cb85053acf44e3772eb5f1); they've fixed a security vulnerability (XSS);
+
+5. Run ```php artisan view:clear```
+
+---
+
+**That's it**. Thank you for taking the time to upgrade.
diff --git a/4.0/add-ons-community.md b/4.0/add-ons-community.md
new file mode 100644
index 00000000..6e9bc673
--- /dev/null
+++ b/4.0/add-ons-community.md
@@ -0,0 +1,16 @@
+# Community Add-ons
+
+---
+
+We've been blessed with a wonderful, supportive community, where developers help each other out. Some of them have even created add-ons, so that we can all reuse functionality across our projects:
+
+| Name | Description | License |
+| ------------- |:-------------:| --------:|
+| [AbbyJanke/Expensed](https://github.com/AbbyJanke/expensed) | income and expense tracker | MIT |
+| [eduardoarandah/LogViewer](https://github.com/eduardoarandah/backpacklogviewer) | advanced logging interface - brings the ArcaneDev/LogViewer package to Backpack admin panels | [MIT](https://github.com/eduardoarandah/backpacklogviewer/blob/master/LICENSE.md) |
+| [eduardoarandah/UserManager](https://github.com/eduardoarandah/UserManager) | manage the default Laravel users table (no permissions, no groups) | [MIT](https://github.com/eduardoarandah/UserManager/blob/master/LICENSE) |
+| [novius/laravel-backpack-redirection-manager](https://github.com/novius/laravel-backpack-redirection-manager) | manage missing page redirections | [AGPL-3](https://github.com/eduardoarandah/backpacklogviewer/blob/master/LICENSE.md) |
+| [novius/laravel-backpack-translation-manager](https://github.com/novius/laravel-backpack-translation-manager) | manage translations stored in the database | - |
+| [updivision/estarter-ecommerce-for-laravel](https://github.com/updivision/estarter-ecommerce-for-laravel) | complete e-commerce back-end (products, categories, clients, orders) | [YUMMY](https://github.com/updivision/estarter-ecommerce-for-laravel/blob/master/LICENSE.md) |
+| [webfactor/laravel-generators](https://github.com/webfactor/laravel-generators) | CLI to generate migrations, factories, seeders, CRUDs, lang files, route files | [MIT](https://github.com/webfactor/laravel-generators/blob/master/LICENSE.md) |
+| [seandowney/laravel-backpack-gallery-crud](https://github.com/seandowney/laravel-backpack-gallery-crud) | manage photo galleries | [MIT](https://github.com/seandowney/laravel-backpack-gallery-crud/blob/master/LICENSE.md) |
diff --git a/4.0/add-ons-how-to-create-a-backpack-addon.md b/4.0/add-ons-how-to-create-a-backpack-addon.md
new file mode 100644
index 00000000..9c8baa14
--- /dev/null
+++ b/4.0/add-ons-how-to-create-a-backpack-addon.md
@@ -0,0 +1,216 @@
+# How to Create an Add-on
+
+---
+
+
+### Intro
+
+There's nothing special about add-ons. They are simple Composer packages.
+
+But for consistency, we recommend you follow our simple folder structure. Our rule of thumb: **organize your ```src``` folder like it were a Laravel application**. We do this because it's easier for users to understand how the package works, and it makes it easy to copy-paste the code inside their apps and modify, for complicated use cases. That way, add-ons can be kept super-simple, with everybody adding functionality _in their own apps_. Example folder structure:
+- [src]
+ - [app]
+ - [Http]
+ - [Models]
+ - [Requests]
+ - [database]
+ - [migrations]
+ - [seeds]
+ - [routes]
+ - YourPackageNameServiceProvider.php
+- [tests]
+- composer.json
+- CHANGELOG.md
+- LICENSE.md
+- README.md
+
+Requirements:
+- a working installation of the [Backpack demo](https://github.com/laravel-backpack/demo)
+- 1-2 hours
+
+
+## Step 1. Create a package
+
+### Install Backpack Demo
+
+We're going to use [the Backpack demo project](https://github.com/laravel-backpack/demo) to create a new package. Follow the instructions in [the Installation chapter](https://github.com/laravel-backpack/demo#install).
+
+Any Laravel & Backpack app would work. But since you're going to require packages that you only need during package development, and make various changes to app files, we recommended you _create_ the package using a Backpack demo. After the package is online (with zero functionality), you will _install_ it in a real application, and _modify_ it right there, in the ```vendor``` folder. You will then delete this Backpack demo project.
+
+
+### Install CLI tool
+
+We're going to use [Jeroen-G/laravel-packager](https://github.com/Jeroen-G/laravel-packager) to generate a new package. Follow the instructions in the Installation chapter.
+
+### Generate Package Files
+
+Next up, decide what your vendor name will be. This is NOT the package name, it's the name all your packages will reside under. For example, Laravel uses "laravel". Backpack for Laravel uses "backpack". Jeffrey Way uses "way". If unsure, use your github username for the vendor name. That's what people usually do, if they don't run a company / brand.
+
+Then decide what your package name will be. Ex: ```newscrud```, ```usermanager```, etc.
+
+Then run:
+```
+php artisan packager:new myvendor mypackage
+```
+
+This will create a ```/packages/``` folder in your root directory, where your package will be stored, so you can build it. It will also pull [a very basic package template](https://github.com/thephpleague/skeleton), created by thephpleague. Everything you have right now is in ```packages/myvendor/mypackage``` - check it out.
+
+### Customize Generated Files
+
+Now let's customise it and add some boilerplate code, everything that most Laravel Packages will need. Replace everything you need in ```composer.json```, ```CHANGELOG.md```, ```CONTRIBUTING.md```, ```LICENSE.md```, ```README.md```. Make it yours.
+
+If you want to use Laravel package auto-discovery (and why wouldn't you), make sure to include the Laravel providers section in your ```composer.json```'s ```extra``` section, like so:
+```
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ },
+ "laravel": {
+ "providers": [
+ "Backpack\\NewsCRUD\\NewsCRUDServiceProvider"
+ ]
+ }
+ }
+```
+
+In ```/src/``` you'll find your service provider. That's where your package's logic is, but it's empty. Use this Service Provider template and replace ```League``` with your ```myvendor``` and ```Skeleton``` with your ```mypackage```. Your package will probably need some Controllers, routes and config files.
+
+### Create The Files Your Package Needs
+
+Here are a few commands that could help you do that:
+
+```bash
+# make sure everything is inside your src folder
+cd src/
+
+# to create a controller
+echo "app/Http/Controllers/ControllerName.php
+
+# to create a request file
+echo "app/Http/Requests/EntityRequest.php
+
+# to create a route file
+echo "routes/mypackage.php
+
+# to create a config file
+echo "config/mypackage.php
+
+# to create a views folder
+mkdir resources/views/
+```
+
+You use the routes, config and controller files just like you use the ones in your application. Nothing changes there. But remember that all classes should have the package's namespace:
+
+```php
+namespace MyVendor\MyPackage\Http\Controllers;
+```
+
+### Make Sure Your Laravel App Loads The Package
+
+Add your service provider to your app's ```/config/app.php```
+
+If not, add it:
+```
+"MyVendor\MyPackage\MyPackageServiceProvider",
+```
+
+Check that you autoload your package in composer.json:
+```
+"autoload" : {
+ "psr-4": {
+ "Domain\\PackageName\\": "packages/Domain/PackageName/src"
+ }
+},
+```
+
+Let's recreate the autoload
+```
+cd ../../../..
+composer dump-autoload
+```
+
+If you have a config file to publish, do:
+```
+php artisan vendor:publish
+```
+
+Now test it. Start by doing a ```dd('testing)``` in your service provider's ```boot()``` method. If your package is working fine, I recommend you put it online first, even before it does _anything useful_. You'll get the setup out of the way, and be able to focus on code. Plus, you'll be able to install it in a _real_ Backpack application, and edit it from the ```vendor/myvendor/mypackage``` folder (and push to your git remote).
+
+---
+
+
+## Step 2. Put it on GitHub
+
+```
+cd packages/domain/packagename/
+git init
+git add .
+git commit -m "first commit"
+```
+
+Create [a new GitHub repository](https://github.com/new).
+
+```
+git remote add origin git@github.com:yourusername/yourrepository.git
+git push -u origin master
+git tag -a 1.0.0 -m 'First version'
+git push --tags
+```
+
+Tags are the way you will version your package, so it's important you do it. People will only be able to get updates if you tag them.
+
+---
+
+
+## Step 3. Put it on Packagist
+
+On [Packagist.org](https://packagist.org), submit a new package. Enter your package's GitHub URL and click Check. If any errors occur, follow the onscreen instructions.
+
+When you're done, you'll be taken to your packagist page, where you'll probably get a notice like this:
+
+>This package is not auto-updated. Please set up the [GitHub Service Hook](https://packagist.org/profile/) for Packagist so that it gets updated whenever you push!
+
+Let's take care of that. Click that link, get your API token and go to your package's GitHub page, in ```Settings / Webhooks & Services / Add a new service```. Search for Packagist. Enter your username and the token and hit Submit. Your error in Packagist should disappear in 5–10 minutes.
+
+Congrats! You now have a working package online. You can now require it with composer.
+
+
+---
+
+
+## Step 4. Install in a Real Project
+
+We've instructed you to create the package in a disposable backpack-demo install. If you've done so, you can now install your package **in your _real_ project**:
+
+```bash
+composer require myvendor/mypackage --prefer-source
+```
+
+Using the ```prefer-source``` flag will actually _clone the git repo_ inside your ```vendor/myvendor/mypackage``` directory. So you can do:
+
+```bash
+cd /vendor/myvendor/mypackage
+git checkout master
+```
+
+Then after each change you want to publish, you would mark that change in your ```CHANGELOG.md``` file and do:
+```bash
+git pull origin master
+git add .
+git commit -am "fixes #14189 - some problem or feature with an id"
+git tag 1.0.3
+git push origin master --tags
+```
+
+---
+
+**That's it. Go build your package!** If you end up with something you like, please share it with the community in the [Gitter Chatroom](https://gitter.im/BackpackForLaravel/Lobby), and add it to [the Community Add-Ons page](/docs/{{version}}/add-ons-community), so other people know about it (_login, then click Edit in the top-right corner of the page_).
+
+You can now delete the Backpack project, and the database you've created for it (if any).
+
+For extra reading credits, these are the resources we've used to create this guide:
+- https://laravel.com/docs/packages
+- https://laracasts.com/discuss/channels/tips/developing-your-packages-in-laravel-5
+- https://github.com/jaiwalker/setup-laravel5-package
+- https://github.com/Jeroen-G/laravel-packager
+- https://laracasts.com/lessons/package-development-101
\ No newline at end of file
diff --git a/4.0/add-ons-official.md b/4.0/add-ons-official.md
new file mode 100644
index 00000000..429a1a02
--- /dev/null
+++ b/4.0/add-ons-official.md
@@ -0,0 +1,15 @@
+# Official Add-ons
+
+In addition to our core packages (Base and CRUD), we've developed a few packages you can install or download, that treat common use cases.
+
+
+ - [PermissionManager](https://github.com/Laravel-Backpack/PermissionManager) - interface to manage users & permissions, using [spatie/laravel-permission](https://github.com/spatie/laravel-permission); ```free```
+ - [Settings](https://github.com/Laravel-Backpack/Settings) - interface to edit site-wide settings; ```free```
+ - [PageManager](https://github.com/Laravel-Backpack/PageManager) - interface to manage content for custom pages, using page templates; ```free```
+ - [MenuCRUD](https://github.com/Laravel-Backpack/MenuCRUD) - interface to create/update/reorder menu items; ```free```
+ - [NewsCRUD](https://github.com/Laravel-Backpack/NewsCRUD) - interface to manage news articles, categories and tags; ```free```
+ - [LogManager](https://github.com/Laravel-Backpack/LogManager) - interface to preview Laravel log files; ```free```
+ - [BackupManager](https://github.com/Laravel-Backpack/BackupManager) - interface to backup your files & db using [spatie/laravel-backup](https://github.com/spatie/laravel-backup); ```free```
+
+
+>**These add-ons only provide basic functionality.** What will be enough for _most_ projects. They do not intend to be a complete solution for all use cases. If you need to customize a package for your specific use case, you can easily do that, by copy-pasting their code in your project and modifying it. Every official package has been created with this in mind, has a very simple architecture, uses Backpack best practices. Find the "extend" section in each of their docs for more about this.
\ No newline at end of file
diff --git a/4.0/add-ons-tutorial.md b/4.0/add-ons-tutorial.md
new file mode 100644
index 00000000..b488415f
--- /dev/null
+++ b/4.0/add-ons-tutorial.md
@@ -0,0 +1,232 @@
+# How to Create a Backpack Add-on
+
+---
+
+
+### Intro
+
+So you've created a custom field, column, filter, or an entire CRUD. Great! If you want to re-use it across projects, or you think _other people_ would like to use it too, there's a good way to do that.
+
+The process below will involve creating a new package on Github, Composer & Packagist - which is a little challenging to wrap your head around, the first time you do it. But if you were able to create a custom field, you will be able to do that too. And in doing this, you'll learn the basics of creating and maintaining a PHP package. That's something that not all PHP developers can do, so it's pretty cool, I think.
+
+> If you already know how to create & maintain a PHP package, this tutorial might be too easy for you. Try to skim it, because we give useful tips. But you can also just go to [:DigitallyHappy/toggle-field-for-backpack](https://github.com/DigitallyHappy/toggle-field-for-backpack), clone the repo and make the changes you see fit.
+
+Requirements:
+- a working installation of Laravel & Backpack 4 (alternative: you can install the [Backpack demo](https://github.com/laravel-backpack/demo));
+- a Github account (free or paid);
+- 15-30 minutes;
+
+
+
+## Step 0. Scope and Constants
+
+**Decide what your package is going to do.** Try to keep the package as small as possible. If you're trying to share multiple fields/columns/etc, we recommend you create a different package for each field type. This will make it:
+- easier for you to communicate what the package does;
+- easier for you to maintain a field type (or abandon it);
+- more likely for people to install & use your package;
+
+In the tutorial below, we'll assume you're trying to share one custom field - ```dummy.blade.php```. But the process will be the same no matter what you're building, starting from the skeletons packages below.
+
+Once you know what you're building, there are a few constants which you need to decide upon. Names that once you've chosen, it will be _possible_, but _very difficult_ to change:
+
+**Package Name.** Try to find a name that is as explicit as possible. So that users, just by reading the name, will pretty much understand what the package does. Also, try to include "_for Backpack_" - that way it will stand out to developers who use Backpack (your target audience).
+- Good Examples: ```json-editor-field-for-backpack```, ```user-column-for-backpack```, ```users-crud-for-backpack```;
+- Bad Examples: ```custom-field``` (too general), ```cbf``` (too cryptic), ```aurora``` (this is not the place to be creative :smile: );
+Since in this example we're trying to build a package for the new ```dummy``` field type, we'll choose ```dummy-field-for-backpack``` as the package name.
+
+**Vendor Name.** You noticed how every time you install a composer package, it's ```composer install something/package-name```? Well that's what that "something" is - the _vendor name_. It's usually the name of the company or person behind the project. The easiest to remember would be your github username, or your company's github username. But, if you're not happy with those, you _can_ choose a different vendor name - basically a brand name, under which you build packages. This could be the place to be creative :smile:, if you don't have a company name already. In the example below we'll use ```company-name```.
+
+**Class Namespace.** When people reference your package's classes, this is what they see first. It's a good practice to use VendorName/PackageName as the namespace for your package. But notice it's no longer kebab-case (using dashes - ```my-company/dummy-field-for-backpack```), it is PascalCase (```MyCompany/DummyFieldForBackpack```).
+
+
+
+## Step 1. Clone the skeleton package
+
+To get your package online ASAP, we've prepared a few "skeleton" packages, that you can fork and modify:
+- [:DigitallyHappy/toggle-field-for-backpack](https://github.com/DigitallyHappy/toggle-field-for-backpack) - field add-on example;
+- TODO - column add-on example;
+- TODO - filter add-on example;
+- TODO - button add-on example;
+- TODO - CRUD add-on example;
+- TODO - multiple CRUD add-on example;
+- TODO - CRUD with dependencies add-on example;
+
+Pick the skeleton package that's as similar as possible to what you want to build. On its Github page, under if you click the green **Clone or Download** button, you'll get the path to that repo. In your project, let's clone that repo:
+```bash
+# git clone {REPO URL} packages/{VENDOR NAME}/{PACKAGE NAME}
+git clone git@github.com:DigitallyHappy/toggle-field-for-backpack.git packages/my-company/dummy-field-for-backpack
+```
+
+
+## Step 2. Make it your own
+
+Take a look at the files you've copied - it's a very simple package. In you package's root folder we have:
+- ```README.md``` - your package's "home page" on Github; this should hold all the information needed to use your package;
+- ```composer.json``` - configuration file that tells Composer (the PHP package installer) more about your package;
+- ```CHANGELOG.md``` - where you should write every time you make changes to the field;
+- ```LICENSE.md``` - so that people know how they're allowed to use your package (MIT is the default);
+
+Take a look at all of them and modify to fit your needs. It should be faster to modify by hand, and pretty intuitive. But, if it's the first time you create a PHP package, you can use the process below, to make sure you don't mess up anything, since making a casing mistake somewhere (```my-vendor``` instead of ```MyVendor```) could take you very long to debug:
+- **namespace** - find ```DigitallyHappy\ToggleFieldForBackpack``` and replace with your _VendorName\PackageName_ (ex: ```MyCompany\DummyFieldForBackpack```);
+- **escaped namespace** - find ```DigitallyHappy\\ToggleFieldForBackpack``` and replace with your _VendorName\\PackageName_ (ex: ```MyCompany\\DummyFieldForBackpack```);
+- **vendor and package name** - find ```digitallyhappy/toggle-field-for-backpack``` and replace with your _vendor-name/package-name_ (ex: ```my-company/dummy-field-for-backpack```);
+- **package name** - find ```toggle-field-for-backpack``` and replace with your _package-name_ (ex: ```dummy-field-for-backpack```);
+- **vendor name** - find ```digitallyhappy``` and replace with your _vendor-name_ (ex: ```my-company```);
+- **author name** - find ```Cristian Tabacitu``` and replace with your name (ex: ```John Doe```);
+- **author email** - find ```hello@tabacitu.ro``` and replace with your email (ex: ```john@example.com```);
+- **author website** - find ```https://tabacitu.ro``` and replace with your website or Github page (ex: ```http://example.com```);
+- open ```changelog.md``` and keep only the 1.0.0 version; put today's date;
+- open ```composer.json``` and change the description of your package;
+- open ```readme.md``` and change the text to better describe _your_ package; don't worry about the screenshot, we'll change that one in a future step;
+
+In ```/src/``` you'll find your service provider, which does one thing: it loads the views in your ```src/resources/views``` under the ```dummy-field-for-backpack``` view namespace. So that anybody who installs your package can use a view that your package includes, by referencing ```dummy-field-for-backpack::path.to.view```.
+
+Also in ```/src/``` you'll notice ```src/resources/views/fields/toggle.blade.php```. This is the example field, which you can rename and use to start coding you field. Or if you already have your field ready, you can just delete this file, and copy-paste the finished blade file from your project
+
+
+## Step 3. Put it on GitHub
+
+```
+# make sure you replace the below with your actual vendor name and package name
+cd packages/my-company/dummy-field-for-backpack/
+git add .
+git commit -m "turned sthe keleton package into dummy-field package"
+```
+
+Create [a new GitHub repository](https://github.com/new). Then get the Git URL the same way you did for the Toggle package, from the green "Clone or Download" button. With that Git URL:
+
+```
+# remove the old origin (pointing to the toggle package)
+git remote rm origin
+
+# add a remote pointing to YOUR github repo
+git remote add origin git@github.com:yourusername/yourrepository.git
+
+# refresh the new origin remote everywhere
+git config master.remote origin
+git config master.merge refs/heads/master
+
+# push your code to your github repo
+git push -u origin master
+
+# tag your release as 1.0.0
+git tag -a 1.0.0 -m 'First version'
+
+# push your tags to the Repo - this is very important to Packagist;
+git push --tags
+```
+
+You might not have used git tags until now. Tags are the way you will version your package, so it's important you do it. For every new version, you need to:
+- write your changes inside the ```changelog.md``` file, so people can easily see what's new;
+- tag your release with the proper tag, so that Packagist will know you've pushed a new version;
+
+---
+
+
+## Step 4. Put it on Packagist
+
+On [Packagist.org](https://packagist.org), create an account if you don't have one already, then click "Submit package" in the top-right corner. Enter your package's GitHub URL and click Check. If any errors occur, follow the onscreen instructions.
+
+When you're done, you'll be taken to your packagist page, where you'll probably get a notice like this:
+
+>This package is not auto-updated. Please set up the [GitHub Service Hook](https://packagist.org/profile/) for Packagist so that it gets updated whenever you push!
+
+Let's take care of that. Click [that link](https://packagist.org/profile/), click "Show API Token", copy it and go to _your package's GitHub page_, in ```Settings / Webhooks & Services / Add a new service```. Search for Packagist. Enter your username and the token and hit Submit. Your error in Packagist should disappear in 5–10 minutes.
+
+Congrats! You now have a working package online. You can now require it with composer.
+
+
+---
+
+
+## Step 5. Install it
+
+Since your package is now online, you can now install it using composer.
+
+```bash
+# go to the root of you Laravel app
+cd ../../..
+
+# delete the folder from packages
+rm -r packages
+
+composer require my-company/dummy-field-for-backpack --prefer-source
+```
+
+Notice we've installed it using the ```prefer-source``` flag. This will actually _clone the git repo_ inside your ```vendor/myvendor/mypackage``` directory. So you can do:
+
+```bash
+cd /vendor/my-company/dummy-field-for-backpack
+git checkout master
+```
+
+**That's it. Your package is online and installable!** You have most of the knowledge needed to build and maintain a PHP package.
+
+
+
+## Step 6. Double-check, then triple-check
+
+### Are you sure it's working?
+After your package is online and ready to use, double-check that it's working well. Then triple-check.
+
+### Your README is your home page
+Afterwards go to your README file again, and make sure it's the best it can be. Remember, your README file is the first thing people see when they find your package. If it's not appealing, they won't use it. If it doesn't do a good job of explaining how to use it, they won't use it. Take this seriously. This is where A LOT of packages go wrong - the authors do not spend the right amount of time on their README page.
+
+IMPORTANT. Make sure your README has a nice screenshot of the functionality you're offering. The easier it is for a developer to see the benefit of using your package, the more likely it is for them to install it. There's a trick in uploading images to Github, then using them in your README file. Go to your package's Github page, and add an issue. In that issue's body, drag&drop the screenshot image. Github will upload it, and give it an URL. Copy-paste that URL, submit the issue (you can also already close the issue), then use that image URL inside your README file. Boom! Free image hosting.
+
+By now you should have made some changes to your files, inside your ```vendor/my-company/dummy-field-for-backpack``` directory.
+
+After each change you want to publish, you should:
+1. Write about that change in your ```CHANGELOG.md``` file. Increment the version sticking to SEMVER.
+
+2. Commit and push your changes, remembering to also create a new tag with the version.
+```bash
+git pull origin master
+git add .
+git commit -am "fixes #14189 - some problem or feature with an id from Github"
+git tag 1.0.1
+git push origin master --tags
+```
+
+
+## Step 7. Feedback and Promotion
+
+Congratulations on your new Backpack addon!
+
+To get feedback, ask people to try it on:
+- [our subredddit](https://www.reddit.com/r/BackpackForLaravel/)
+- [our Gitter chatroom](https://gitter.im/BackpackForLaravel/Lobby)
+
+Make sure you write something nice, so people are interested to click.
+
+After you've got some feedback, and a few users have installed your package and everything seems fine, time to promote it big time:
+- post it to [laravel-news.com/links](https://laravel-news.com/links)
+- show it off in the [Laracasts forum](https://laracasts.com/discuss)
+- ask people to try it in [laravel.io](https://laravel.io/forum)
+
+
+## Extra Credits
+
+If you're building a bigger package, with one CRUD or more, we recommend you follow the simple folder structure we use across all Backpack packages. Our rule of thumb: **organize your ```src``` folder like it were a Laravel application**. We do this because it's easier for developers to understand how the package works, and it makes it easy to copy-paste the code inside their apps and modify, for complicated use cases. That way, add-ons can be kept super-simple, with everybody adding functionality _in their own apps_. Example folder structure:
+- [src]
+ - [app]
+ - [Http]
+ - [Models]
+ - [Requests]
+ - [database]
+ - [migrations]
+ - [seeds]
+ - [routes]
+ - AddonServiceProvider.php
+- [tests]
+- composer.json
+- CHANGELOG.md
+- LICENSE.md
+- README.md
+
+For extra reading credits, these are the resources we've used to create this guide:
+- https://laravel.com/docs/packages
+- https://laracasts.com/discuss/channels/tips/developing-your-packages-in-laravel-5
+- https://github.com/jaiwalker/setup-laravel5-package
+- https://github.com/Jeroen-G/laravel-packager
+- https://laracasts.com/lessons/package-development-101
diff --git a/4.0/base-about.md b/4.0/base-about.md
new file mode 100644
index 00000000..cee5c5c9
--- /dev/null
+++ b/4.0/base-about.md
@@ -0,0 +1,201 @@
+# About Backpack's User Interface
+
+---
+
+Backpack helps you build admin panels faster by:
+- installing our custom HTML theme, [Backstrap](https://backstrap.net), based on Bootstrap 4 and [CoreUI](https://coreui.io);
+- installing [sweetalert](https://sweetalert.js.org/) for triggering pretty Confirm modals;
+- installing [noty](https://ned.im/noty/#/) to show notification bubbles upon error/success/warning/info - triggered from Javascript;
+- installing [prologue/alerts](https://github.com/prologuephp/alerts) for triggering notification bubbles from PHP (both on the same page and using flashdata);
+- providing a separate authentication system for your admins;
+- providing pretty error pages for most common errors;
+- providing a horizontal menu and a side menu you can customize;
+- providing a place for your admin to to change his email/name/password;
+- providing a few helpers you can use throughout your admin panel;
+
+For the simplest projects, you will never need to know how it works, never need to customize anything but the ```config/backpack/base.php``` file. But here's how everything works, below.
+
+
+## Layout & Design
+
+
+### General
+
+Backpack pulls in our custom HTML template, [Backstrap](https://www.npmjs.com/package/@digitallyhappy/backstrap), and adds our own CSS file on top, for a few cosmetic improvements. We've chosen to base Backstrap on [CoreUI](https://coreui.io), because it provides design blocks for all common features of an administration panel. When you decide to build custom pages for your Admin Panel, you can just use Backstrap's HTML blocks - no designer needed. You can see all the HTML components Backstrap provides on [backstrap.net](https://backstrap.net), and copy-paste HTML from there, or use [CoreUI](https://coreui.io)'s documentation for details.
+
+
+### New Files in Your App
+
+After installation, you'll notice Backpack has added a few files:
+
+**1) Views to ```resources/views/vendor/backpack/base/```**
+ - ```inc/sidebar_content.blade.php```;
+ - ```dashboard.blade.php```;
+
+Those files are used to show the contents of the menu to the left (sidebar), and the first page the admin sees when logging in (dashboard). They've been published there so that you can easily modify their contents, by editing their HTML or adding dynamic content through [widgets](/docs/{{version}}/base-widgets).
+
+**2) Model to ```app/Models/BackpackUser.php```**
+
+Notice that ```BackpackUser``` extends your own user model. Backpack will be using ```BackpackUser``` for authentication and management, not your ```User```, so if there's anything that's specific to your admins (accessors, mutators, methods), you can use this model to define them.
+
+**3) Middleware to ```app/Http/Middleware/CheckIfAdmin.php```**
+
+This middleware is used to test if users have access to admin panel pages. You can (and should customize it) if you have both users and admins in your app.
+
+**4) Route file to ```routes/backpack/custom.php**```**
+
+This route file is for convenience and convention. We recommend you place all your admin panel routes here.
+
+
+
+### Published Views
+
+After installation, you'll notice Backpack has added a few blade files in ```resources/views/vendor/backpack/base/```:
+ - ```inc/sidebar_content.blade.php```;
+ - ```dashboard.blade.php```;
+
+Those files are used to show the contents of the menu to the left (sidebar), and the first page the admin sees when logging in (dashboard). They've been published there so that you can easily modify their contents, by editing their HTML or adding dynamic content through [widgets](/docs/{{version}}/base-widgets).
+
+
+### Unpublished Views
+
+You can change any blade file to your own needs. Determine what file you'd need to modify if you were to edit directly in the project's vendor folder, then go to ```resources/views/vendor/backpack/base``` and create a file with the exact same name. Backpack\Base will use this new file, instead of the one in the package.
+
+For example, if you want to add an item to the top menu, you could just create a file called ```resources/views/vendor/backpack/base/inc/topbar_left_content.php```. Backpack will now use this file's contents, instead of ```vendor/backpack/base/src/resources/views/inc/topbar_left_content.php```
+
+
+### Folder Structure
+
+If you'll take a look inside any Backpack package, you'll notice the ```src``` directory is organised like a standard Laravel app. This is intentional. It should help you easily understand how the package works, and how you can overwrite/customize its functionality.
+
+- ```app```
+ - ```Console```
+ - ```Commands```
+ - ```Http```
+ - ```Controllers```
+ - ```Middleware```
+ - ```Requests```
+ - ```Notifications```
+- ```config```
+- ```resources```
+ - ```lang```
+ - ```views```
+- ```routes```
+
+
+## Authentication
+
+When installed, Backpack provides a way for admins to login, recover password and register (don't worry, register is only enabled on ```localhost```). It does so with its own authentication controllers, models and middleware. If you have regular end-users (not admins), you can keep the _user_ authentication completely separate from _admin_ authentication. You can change which model, middleware classes Backpack uses, inside the ```config/backpack/base.php``` config file.
+
+> **The ```BackpackUser``` model extends Laravel's default ```App\User``` model**. This assumes you weren't already using this model, or the ```users``` table, for anything else. If you were, please read below.
+
+
+### Using a Different User Model
+
+If you want to use a different User model than ```App\User``` or you've changed its location, please:
+- tell Backpack to use _your_ model in ```config/backpack/base.php``` instead of the ```BackpackUser``` model Backpack has published to your app;
+- take a look at [```\Backpack\Base\app\Models\BackpackUser::class```](https://github.com/Laravel-Backpack/Base/blob/master/src/app/Models/BackpackUser.php);
+- include the methods there in _your_ user model; they're important for password recovery;
+
+
+
+### Having Both Regular Users and Admins
+
+If you already use the ```users``` table to store end-users (not admins), you will need a way to differentiate admins from regular users. Backpack does not force one method on you. Here are two methods we recommend, below:
+- (A) adding an ```is_admin``` column to your ```users``` table, then changing the ```app/Http/Middleware/CheckIfAdmin::checkIfUserIsAdmin()``` method to test that attribute exists, and is true;
+- (B) using the [PermissionManager](https://github.com/Laravel-Backpack/PermissionManager) extension - this will also add groups and permissions; Then tell Backpack to use _your new permission middleware_ to check if a logged in user is an admin, inside ```config/backpack/base.php```;
+
+
+### Routes
+
+By default, all administration panel routes will be behind an ```/admin/``` prefix, and under an ```CheckIfAdmin``` middleware. You can change that inside ```config/backpack/base.php```.
+
+Inside your _admin controllers or views_, please:
+- use ```backpack_auth()``` instead of ```auth()```;
+- use ```backpack_user()``` instead of ```auth()->user```;
+- use ```backpack_url()``` instead of ```url()```;
+
+This will make sure you're using the model, prefix & middleware that you've defined in ```config/backpack/base.php```. In case you decide to make changes there later, you won't need to change anything else. There are also [other backpack helpers you can use](#helpers).
+
+
+## Admin Account
+
+When logged in, the admin can click his/her name to go to his "account" page. There, they will be able to do a few basic operations: change name, email or password.
+
+
+### Change Name and Email
+
+Changing name and email is done inside ```Backpack\Base\app\Http\Controllers\Auth\MyAccountController```, using the ```getAccountInfoForm()``` and ```postAccountInfoForm()``` methods. If you want to change how this works, we recommend you create a ```routes/backpack/base.php``` file, copy-paste all Backpack\Base routes there and change whatever routes you need, to point to _your own controller_, where you can do whatever you want.
+
+If you only want to add a few new inputs, you can do that by creating a file in ```resources/views/vendor/backpack/base/my_account.blade.php``` that uses code from the same file in the Backpack package, but adds the inputs you need. Remember to also make these fields ```$fillable``` in your User model.
+
+
+### Change Password
+
+Password changing is done inside ```Backpack\Base\app\Http\Controllers\Auth\MyAccountController```. If you want to change how this works, we recommend you create a ```routes/backpack/base.php``` file, copy-paste all Backpack\Base routes there and change whatever you need. You can then point the route to your own controller, where you can do whatever you want.
+
+
+## Notification Bubbles
+
+
+### Triggering Notification Bubbles in PHP
+
+We use [prologue/alerts](https://github.com/prologuephp/alerts#adding-alerts-through-alert-levels) to trigger notifications. Check out its documentation for the entire syntax. Basic examples:
+
+```php
+public function foo()
+{
+ \Alert::add('info', 'This is a blue bubble.');
+ \Alert::add('warning', 'This is a yellow/orange bubble.');
+ \Alert::add('error', 'This is a red bubble.');
+ \Alert::add('success', 'Got it This is HTML in a green bubble.');
+ \Alert::add('primary', 'This is a dark blue bubble.');
+ \Alert::add('secondary', 'This is a grey bubble.');
+ \Alert::add('light', 'This is a light grey bubble.');
+ \Alert::add('dark', 'This is a black bubble.');
+
+ // the layout will make sure to show your notifications
+ return view('some_view');
+}
+
+public function bar()
+{
+ \Alert::add('success', 'You have successfully logged in')->flash();
+
+ // please note the above flash() method; this will store your notification in a session variable, so that you can redirect to another page, but the notification will still be shown (on the page you redirect to)
+ return Redirect::to('some-url');
+}
+```
+
+
+### Triggering Notification Bubbles in JavaScript
+
+We use [Noty](https://ned.im/noty/#/) to show notifications from JavaScript, on the same page. Check out its page for more detailed use. Basic example:
+
+```php
+new Noty({
+ type: "success",
+ text: 'Some notification text',
+}).show();
+
+// available types: success, info, warning/notice, error/danger, primary, secondary, dark, light
+```
+
+
+## Helpers
+
+You can use these helpers anywhere in your app (models, views, controllers, requests, etc), except the config files, since the config files are loaded _before_ the helpers.
+
+- **```backpack_url(http://github.com/$path)```** - Use this helper instead of ```url()``` to generate paths with the admin prefix prepended.
+- **```backpack_auth()```** - Returns the Auth facade, using the current Backpack guard. Basically a shorthand for ```\Auth::guard(backpack_guard_name())```. Use this instead of ```auth()``` inside your admin panel pages.
+- **```backpack_middleware()```** - Returns the key for the admin middleware. Default is ```admin```.
+- ```backpack_authentication_column()``` - Returns the username column. The Laravel and Backpack default is ```email```.
+- ```backpack_users_have_email()``` - Tests that the ```email``` column exists on the users table and returns true/false.
+- ```backpack_avatar($user)``` - Receives a user object and returns a path to an avatar image, according to the preferences in the config file (gravatar, placeholder or custom).
+- ```backpack_guard_name()``` - Returns the guard used for Backpack authentication.
+- ```backpack_user()``` - Returns the current Backpack user, if logged in. Basically a shorthand for ```\Auth::guard(backpack_guard_name())->user()```. Use this instead of ```auth()->user()``` inside your admin pages.
+
+
+## Error Pages
+
+When installing Backpack, a few error views are published into ```resources/views/errors```, if you don't already have other files there. This is because Laravel does not provide error pages for all HTTP error codes. Having these files in your project will make sure that, if a user gets an HTTP error, at least it will look decent. Error pages are provided for the following error codes: ```400```, ```401```, ```403```, ```404```, ```405```, ```408```, ```429```, ```500```, ```503```.
diff --git a/4.0/base-breadcrumbs.md b/4.0/base-breadcrumbs.md
new file mode 100644
index 00000000..a3a7d5ad
--- /dev/null
+++ b/4.0/base-breadcrumbs.md
@@ -0,0 +1,89 @@
+# Breadcrumbs
+
+---
+
+
+## About
+
+Breadcrumbs show a path to the current page in the top-right corner of the screen, and can be a useful part of the UI for deeply nested admin panels.
+
+Breadcrumbs are loaded in the default layout _before_ the ```header``` section.
+
+
+## Enable / Disable Breadcrumbs
+
+You can hide or show breadcrumbs on ALL of your admin panel pages by changing a boolean variable in your ```config/backpack/base.php```:
+
+```php
+ // Show / hide breadcrumbs on admin panel pages.
+ 'breadcrumbs' => true,
+```
+
+
+## How Breadcrumbs Work
+
+The ```inc.breadcrumbs``` view will show all breadcrumbs from the ```$breadcrumbs``` variable, if it's present on the page. The ```$breadcrumbs``` variable should be a simple associative array ```[ $label1 => $link1, $label2 => $link2 ]```. Examples:
+
+```php
+ $breadcrumbs = [
+ trans('backpack::crud.admin') => backpack_url('http://github.com/dashboard'),
+ trans('backpack::base.dashboard') => false,
+ ];
+
+ $breadcrumbs = [
+ trans('backpack::crud.admin') => backpack_url('http://github.com/dashboard'),
+ trans('backpack::base.dashboard') => false,
+ ];
+
+ $breadcrumbs = [
+ 'Admin' => route('dashboard'),
+ 'Dashboard' => false,
+ ];
+```
+
+Notice the last item should NOT have a link, it should be ```false```.
+
+
+## How to Define Breadcrumbs
+
+
+### Define Breadcrumbs Inside the Controller
+
+Make sure a ```$breadcrumbs``` variable is present inside your views:
+```php
+ /**
+ * Show the admin dashboard.
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function dashboard()
+ {
+ $this->data['title'] = trans('backpack::base.dashboard'); // set the page title
+ $this->data['breadcrumbs'] = [
+ trans('backpack::crud.admin') => backpack_url('http://github.com/dashboard'),
+ trans('backpack::base.dashboard') => false,
+ ];
+
+ return view('backpack::dashboard', $this->data);
+ }
+```
+
+
+### Define Breadcrumbs Inside the View
+
+Make sure a ```$breadcrumbs``` variable is present:
+
+```php
+@extends('backpack::layout')
+
+@php
+ $breadcrumbs = [
+ 'Admin' => backpack_url('http://github.com/dashboard'),
+ 'Dashboard' => false,
+ ];
+@endphp
+
+@section('content')
+ some other content here
+@endsection
+```
\ No newline at end of file
diff --git a/4.0/base-how-to.md b/4.0/base-how-to.md
new file mode 100644
index 00000000..d952b684
--- /dev/null
+++ b/4.0/base-how-to.md
@@ -0,0 +1,509 @@
+# How To Customize the UI
+
+---
+
+
+
+## Look and feel
+
+
+### Customize the menu or sidebar
+
+During installation, Backpack publishes a few files in you ```resources/views/vendor/backpack/base/inc``` folder. In there, you'll also find:
+- ```sidebar_content.php```
+- ```topbar_left_content.php```
+- ```topbar_right_content.php```
+
+Change those files as you please.
+
+
+### Customize the dashboard
+
+The dashboard is shown from ```Backpack\Base\app\Http\Controller\AdminController.php::dashboard()```. If you take a look at that method, you'll see that the only thing it does is to set a title, breadcrumbs, and return a view: ```backpack::dashboard```.
+
+In order to place something else inside that view, like [widgets](/docs/{{version}}/base-widgets), simply publish that view in your project, and Backpack will pick it up, instead of the one in the package. Create a ```resources/views/vendor/backpack/base/dashboard.blade.php``` file:
+
+```html
+@extends(backpack_view('blank'))
+
+@php
+ $widgets['before_content'][] = [
+ 'type' => 'jumbotron',
+ 'heading' => trans('backpack::base.welcome'),
+ 'content' => trans('backpack::base.use_sidebar'),
+ 'button_link' => backpack_url('http://github.com/logout'),
+ 'button_text' => trans('backpack::base.logout'),
+ ];
+@endphp
+
+@section('content')
+
Your custom HTML can live here
+@endsection
+```
+
+To use information from the database, you can:
+- [use view composers](https://laravel.com/docs/5.7/views#view-composers) to push variables inside this view, when it's loaded;
+- load all your dashboard information using AJAX calls, if you're loading charts, reports, etc, and the DB queries might take a long time;
+- use the full namespace for your models, like ```\App\Models\Product::count()```;
+
+Take a look at the [widgets](/docs/{{version}}/base-widgets) we have - you can easily use those in your dashboard. You can also add whatever HTML you want inside the content block - check the [Backstrap HTML Template](https://backstrap.net/widgets.html) for design components you can copy-paste to speed up your custom HTML.
+
+
+### Customizing the design of the menu / sidebar / footer
+
+In ```config/backpack/base.php``` you'll notice there are variables where you can change exactly what CSS classes are placed on the HTML elements that represent the header, body, sidebar and footer:
+
+```php
+ // Horizontal navbar classes. Helps make the admin panel look similar to your project's design.
+ 'header_class' => 'app-header bg-light border-0 navbar',
+ // Try adding bg-dark, bg-primary, bg-secondary, bg-danger, bg-warning, bg-success, bg-info, bg-blue, bg-light-blue, bg-indigo, bg-purple, bg-pink, bg-red, bg-orange, bg-yellow, bg-green, bg-teal, bg-cyan
+ // You might need to add "navbar-dark" too if the background color is a dark one.
+ // Add header-fixed if you want the header menu to be sticky
+
+ // Body element classes.
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ // Try sidebar-hidden, sidebar-fixed, sidebar-compact, sidebar-lg-show
+
+
+ // Sidebar element classes.
+ 'sidebar_class' => 'sidebar sidebar-pills bg-light',
+ // Remove "sidebar-transparent" for standard sidebar look
+ // Try "sidebar-light" or "sidebar-dark" for dark/light links
+ // You can also add a background class like bg-dark, bg-primary, bg-secondary, bg-danger, bg-warning, bg-success, bg-info, bg-blue, bg-light-blue, bg-indigo, bg-purple, bg-pink, bg-red, bg-orange, bg-yellow, bg-green, bg-teal, bg-cyan
+
+ // Footer element classes.
+ 'footer_class' => 'app-footer',
+```
+
+Our default design might not be pleasant for your, or you might need to make the UI integrate better into your project. We totally understand. You can use the classes above to make it look considerably different.
+
+You'll find a few examples below - but you should use which classes you want to get the result you need.
+
+
+#### Backstrap
+
+Transparent top menu, transparent sidebar, transparent footer. This is the default. This is what _we_ think is best for most users, from our 8+ years of experience building admin panels. Prioritising _content_ over _menus_.
+
+
+
+```php
+ 'header_class' => 'app-header bg-light border-0 navbar',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar sidebar-pills bg-light',
+ 'footer_class' => 'app-footer',
+```
+
+
+#### Inspired by CoreUI
+
+White top menu, dark sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar',
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+#### Inspired by Github
+
+Black top menu, white sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header bg-dark navbar',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar bg-white sidebar-pills',
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+#### Blue Top Menu
+
+Blue top menu, dark sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar navbar-color bg-primary border-0',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar', // add "bg-white sidebar-pills" for light sidebar
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+
+#### Construction / Warning
+
+Yellow top menu, dark sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar navbar-light bg-warning',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar', // add "bg-white sidebar-pills" for light sidebar
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+#### Red Top Menu
+
+Red top menu, dark sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar navbar-color bg-error border-0',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar', // add "bg-white sidebar-pills" for light sidebar
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+#### Pink Top Menu
+
+Pink top menu, transparent sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar navbar-color bg-error border-0',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar sidebar-pills bg-light',
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+
+#### Green Top Menu
+
+Green top menu, white sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar navbar-color bg-green border-0',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar sidebar-pills bg-white',
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+### Create a new theme / child theme
+
+You can create a theme with your own HTML. Create a folder with all the views you want to overwrite, then change ```view_namespace``` inside your ```config/backpack/base.php``` to point to that folder. All views will be loaded from _that_ folder if they exist, then from ```resources/views/vendor/backpack/base```, then from the Base package.
+
+You can use child themes to:
+- create packages for your Backpack admin panels to look different (and re-use across projects)
+- use a different CSS framework (ex: Tailwind, Bulma)
+
+
+
+### Add custom Javascript to all admin panel pages
+
+In ```config/backpack/base.php``` you'll notice this config option:
+
+```php
+ // JS files that are loaded in all pages, using Laravel's asset() helper
+ 'scripts' => [
+ // Backstrap includes jQuery, Bootstrap, CoreUI, PNotify, Popper
+ 'packages/backpack/base/js/bundle.js?v='.\PackageVersions\Versions::getVersion('backpack/base'),
+
+ // examples (everything inside the bundle, loaded from CDN)
+ // 'https://code.jquery.com/jquery-3.4.1.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js',
+ // 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js',
+ // 'https://unpkg.com/@coreui/coreui/dist/js/coreui.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/pace/1.0.2/pace.min.js',
+ // 'https://unpkg.com/sweetalert/dist/sweetalert.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/noty/3.1.4/noty.min.js'
+
+ // examples (VueJS or React)
+ // 'https://unpkg.com/vue@2.4.4/dist/vue.min.js',
+ // 'https://unpkg.com/react@16/umd/react.production.min.js',
+ // 'https://unpkg.com/react-dom@16/umd/react-dom.production.min.js',
+ ],
+```
+
+You can add files to this array, and they'll be loaded in all admin panels pages.
+
+
+### Add custom CSS to all admin panel pages
+
+In ```config/backpack/base.php``` you'll notice this config option:
+
+```php
+ // CSS files that are loaded in all pages, using Laravel's asset() helper
+ 'styles' => [
+ 'packages/@digitallyhappy/backstrap/css/style.min.css',
+
+ // Examples (the fonts above, loaded from CDN instead)
+ // 'https://maxcdn.icons8.com/fonts/line-awesome/1.1/css/line-awesome-font-awesome.min.css',
+ // 'https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic',
+ ],
+```
+
+You can add files to this array, and they'll be loaded in all admin panels pages.
+
+
+### Customize the look and feel of the admin panel (using CSS)
+
+If you want to change the look and feel of the admin panel, you can create a custom CSS file wherever you want. We recommend you do it inside ```public/packages/myname/mycustomthemename/css/style.css``` folder so that it's easier to turn into a theme, if you decide later to share or re-use your CSS in other projects.
+
+In ```config/backpack/base.php``` add your file to this config option:
+
+```php
+ // CSS files that are loaded in all pages, using Laravel's asset() helper
+ 'styles' => [
+ 'packages/@digitallyhappy/backstrap/css/style.min.css',
+ // ...
+ 'packages/myname/mycustomthemename/css/style.css',
+ ],
+```
+
+This config option allows you to add CSS files that add style _on top_ of Backstrap, to make it look different. You can create a CSS file anywhere inside your ```public``` folder, and add it here.
+
+
+### How to add VueJS to all Backpack pages
+
+You can add any script you want inside all Backpack's pages by just adding it in your ```config/backpack/base.php``` file:
+
+```php
+
+ // JS files that are loaded in all pages, using Laravel's asset() helper
+ 'scripts' => [
+ // Backstrap includes jQuery, Bootstrap, CoreUI, PNotify, Popper
+ 'packages/backpack/base/js/bundle.js',
+
+ // examples (everything inside the bundle, loaded from CDN)
+ // 'https://code.jquery.com/jquery-3.4.1.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js',
+ // 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js',
+ // 'https://unpkg.com/@coreui/coreui/dist/js/coreui.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/pace/1.0.2/pace.min.js',
+ // 'https://unpkg.com/sweetalert/dist/sweetalert.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/noty/3.1.4/noty.min.js'
+
+ // examples (VueJS or React)
+ // 'https://unpkg.com/vue@2.4.4/dist/vue.min.js',
+ // 'https://unpkg.com/react@16/umd/react.production.min.js',
+ // 'https://unpkg.com/react-dom@16/umd/react-dom.production.min.js',
+ ],
+```
+
+You should be able to load Vue.JS by just uncommenting that one line. Or providing a link to a locally stored VueJS file.
+
+
+## Authentication
+
+
+### Customizing the Auth controllers
+
+In ```config/backpack/base.php``` you'll find these configuration options:
+
+```php
+ // Set this to false if you would like to use your own AuthController and PasswordController
+ // (you then need to setup your auth routes manually in your routes.php file)
+ 'setup_auth_routes' => true,
+```
+
+You can change both ```setup_auth_routes``` to ```false```. This means Backpack\Base won't register the Auth routes any more, so you'll have to manually register them in your route file, to point to the Auth controllers you want. If you're going to use the Auth controllers that Laravel generates, these are the routes you can use:
+```php
+Route::group(['middleware' => 'web', 'prefix' => config('backpack.base.route_prefix')], function () {
+ Route::auth();
+ Route::get('logout', 'Auth\LoginController@logout');
+});
+```
+
+
+### Customize the routes
+
+#### Custom routes - option 1
+
+You can place a new routes file in your ```app/routes/backpack/base.php```. If a file is present there, no default Backpack\Base routes will be loaded, only what's present in that file. You can use the routes file ```vendor/backpack/base/src/resources/views/base.php``` as an example, and customize whatever you want.
+
+#### Custom routes - option 2
+
+In ```config/backpack/base.php``` you'll find these configuration options:
+
+```php
+
+ /*
+ |--------------------------------------------------------------------------
+ | Routing
+ |--------------------------------------------------------------------------
+ */
+
+ // The prefix used in all base routes (the 'admin' in admin/dashboard)
+ 'route_prefix' => 'admin',
+
+ // Set this to false if you would like to use your own AuthController and PasswordController
+ // (you then need to setup your auth routes manually in your routes.php file)
+ 'setup_auth_routes' => true,
+
+ // Set this to false if you would like to skip adding the dashboard routes
+ // (you then need to overwrite the login route on your AuthController)
+ 'setup_dashboard_routes' => true,
+```
+
+In order to completely customize the auth routes, you can change both ```setup_auth_routes``` and ```setup_dashboard_routes``` to ```false```. This means Backpack\Base won't register any routes any more, so you'll have to manually register them in your route file. Here's what you can use to get started:
+```php
+Route::group(['middleware' => 'web', 'prefix' => config('backpack.base.route_prefix', 'namespace' => 'Backpack\Base\app\Http\Controllers')], function () {
+ Route::auth();
+ Route::get('logout', 'Auth\LoginController@logout');
+ Route::get('dashboard', 'AdminController@dashboard');
+ Route::get('/', 'AdminController@redirect');
+});
+```
+
+
+### Use separate login/register forms for users and admins
+
+This is a default in Backpack v4.
+
+Backpack's authentication uses a completely separate authentication driver, provider, guard and password broker. They're all named ```backpack```, and registered in the vendor folder, invisible to you.
+
+If you need a separate login for user, just go ahead and create it. [Add the Laravel authentication, like instructed in the Laravel documentation](https://laravel.com/docs/5.7/authentication#authentication-quickstart): ```php artisan make:auth```. You'll then have:
+- the user login at ```/login``` -> using the AuthenticationController Laravel provides
+- the admin login at ```/admin/login``` -> using the AuthenticationControllers Backpack provides
+
+The user login will be using Laravel's default authentication driver, provider, guard and password broker, from ```config/auth.php```.
+
+Backpack's authentication driver, provider, guard and password broker can easily be overwritten by creating a driver/provider/guard/broker with the ```backpack``` name inside your ```config/auth.php```. If one named ```backpack``` exists there, Backpack will use that instead.
+
+
+### Overwrite Backpack authentication driver, provider, guard or password broker
+
+Backpack's authentication uses a completely separate authentication driver, provider, guard and password broker. Backpack adds them to what's defined in ```config/auth.php``` on runtime, and they're all named ```backpack```.
+
+To change a setting in how Backpack's driver/provider/guard or password broker works, create a driver/provider/guard/broker with the ```backpack``` name inside your ```config/auth.php```. If one named ```backpack``` exists there, Backpack will use that instead.
+
+
+### Use separate sessions for admin&user authentication
+
+This is a default in Backpack v4.
+
+
+### Login with username instead of email
+
+1. Create a ```username``` column in your users table and add it in ```$fillable``` on your ```User``` model. Best to do this with a migration.
+2. Remove the UNIQUE and NOT NULL constraints from ```email``` on your table. Best to do this with a migration. Alternatively, delete your ```email``` column and remove it from ```$fillable``` on your ```User``` model. If you already have a CRUD for users, you might also need to delete it from the Request, and from your UserCrudController.
+3. Change your ```config/backpack/base.php``` config options:
+```php
+ // Username column for authentication
+ // The Backpack default is the same as the Laravel default (email)
+ // If you need to switch to username, you also need to create that column in your db
+ 'authentication_column' => 'username',
+ 'authentication_column_name' => 'Username',
+```
+That's it. This will:
+- use ```username``` for login;
+- use ```username``` for registration;
+- use ```username``` in My Account, when a user wants to change his info;
+- completely disable the password recovery (if you've deleted the ```email``` db column);
+
+
+
+### Use your own User model instead of BackpackUser
+
+By default, authentication and everything else inside Backpack is done using the ```Backpack\Base\app\Models\BackpackUser``` model, which extends Laravel's default ```App\User``` model. If you change the location of ```App\User```, or want to use a different User model for whatever other reason, you can do so by
+- changing ```user_model_fqn``` in ```config/backpack/base.php``` to your new class;
+- making sure everything inside ```BackpackUser``` is also inside your new model (this is important for recovering password, etc);
+
+
+
+### Use your own profile image (avatar)
+
+By default, Backpack will use Gravatar to show the profile image for the currently logged in backpack user. In order to change this, you can use the option in ```config/backpack/base.php```:
+```php
+// What kind of avatar will you like to show to the user?
+// Default: gravatar (automatically use the gravatar for his email)
+//
+// Other options:
+// - placehold (generic image with his first letter)
+// - example_method_name (specify the method on the User model that returns the URL)
+'avatar_type' => 'gravatar',
+```
+
+Please note that this does not allow the user to change his profile image.
+
+
+
+### Add one or more fields to the Register form
+
+To add a new field to the Registration page, you should:
+
+**Step 1.** Overwrite the registration route, so it leads to _your_ controller, instead of the one in the package. We recommend you add it your ```routes/backpack/custom.php```, BEFORE the route group where you define your CRUDs:
+
+```php
+Route::get('admin/register', 'App\Http\Controllers\Admin\Auth\RegisterController')->name('backpack.auth.register');
+```
+
+**Step 2.** Create the new RegisterController somewhere in your project, that extends the RegisterController in the package, and overwrites the validation & user creation methods. For example:
+
+```php
+getTable();
+ $email_validation = backpack_authentication_column() == 'email' ? 'email|' : '';
+
+ return Validator::make($data, [
+ 'name' => 'required|max:255',
+ backpack_authentication_column() => 'required|'.$email_validation.'max:255|unique:'.$users_table,
+ 'password' => 'required|min:6|confirmed',
+ ]);
+ }
+
+ /**
+ * Create a new user instance after a valid registration.
+ *
+ * @param array $data
+ *
+ * @return User
+ */
+ protected function create(array $data)
+ {
+ $user_model_fqn = config('backpack.base.user_model_fqn');
+ $user = new $user_model_fqn();
+
+ return $user->create([
+ 'name' => $data['name'],
+ backpack_authentication_column() => $data[backpack_authentication_column()],
+ 'password' => bcrypt($data['password']),
+ ]);
+ }
+}
+```
+Add whatever validation rules & inputs you want, in addition to name and password.
+
+**Step 3.** Add the actual inputs to your HTML. You can easily overwrite the register view by adding this method to the same RegisterController:
+
+```php
+ public function showRegistrationForm()
+ {
+
+ return backpack_view('auth.register');
+ }
+```
+This will make the registration process pick up a view you can create, in ```resources/views/vendor/backpack/base/auth/register.blade.php```. You can copy-paste the original view, and modify as you please. Including adding your own custom inputs.
diff --git a/4.0/base-widgets.md b/4.0/base-widgets.md
new file mode 100644
index 00000000..0f4ab0f7
--- /dev/null
+++ b/4.0/base-widgets.md
@@ -0,0 +1,341 @@
+# Widgets
+
+---
+
+
+## About
+
+Widgets (aka cards, aka charts, aka graphs) provide a simple way to insert blade files into admin panel pages. You can use them to insert cards, charts, notices or custom content into pages.
+
+
+
+### How to Use
+
+The default layout that Backpack uses has two widget sections:
+- ```before_content```
+- ```after_content```
+
+You can easily push widgets to these sections, by making sure a ```$widgets['before_content']``` or ```$widgets['after_content']``` variable will be present in the main view.
+
+1) From the controller:
+```php
+ /**
+ * Show the admin dashboard.
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function dashboard()
+ {
+ $this->data['title'] = trans('backpack::base.dashboard'); // set the page title
+ $this->data['widgets']['before_content'] = [
+ [
+ 'type' => 'card',
+ 'wrapperClass' => 'col-sm-6 col-md-4',
+ 'content' => [
+ 'header' => 'Some card title',
+ 'body' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non mi nec orci euismod venenatis. Integer quis sapien et diam facilisis facilisis ultricies quis justo. Phasellus sem turpis.',
+ ]
+ ],
+ ];
+
+ return view(backpack_view('dashboard'), $this->data);
+ }
+```
+
+2) From the view:
+```php
+@extends(backpack_view('blank'))
+
+@php
+ $widgets['before_content'][] = [
+ 'type' => 'card',
+ 'wrapperClass' => 'col-sm-6 col-md-4',
+ 'content' => [
+ 'header' => 'Some card title',
+ 'body' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non mi nec orci euismod venenatis. Integer quis sapien et diam facilisis facilisis ultricies quis justo. Phasellus sem turpis.',
+ ]
+ ];
+@endphp
+
+@section('content')
+@endsection
+```
+
+Both of the options above will produce the same result. You can use both options above together, pushing some widgets from the controller, and some from the view.
+
+
+
+### Mandatory Attributes
+
+When passing a widget array, you need to specify at least these attributes:
+```php
+[
+ 'type' => 'card' // the kind of widget to show
+ 'content' => null // the content of that widget (some are string, some are array)
+],
+```
+
+
+### Optional Attributes
+
+Most widget types also have these attributes present, which you can use to tweak how the widget looks inside the page:
+```php
+ 'wrapperClass' => 'col-sm-6 col-md-4', // customize the class on the parent element (wrapper)
+```
+
+
+
+## Default Widget Types
+
+
+### Alert
+
+Shows a notification bubble, with the heading and text you specify:
+
+```php
+[
+ 'type' => 'alert',
+ 'class' => 'alert alert-danger mb-2',
+ 'heading' => 'Important information!',
+ 'content' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Corrupti nulla quas distinctio veritatis provident mollitia error fuga quis repellat, modi minima corporis similique, quaerat minus rerum dolorem asperiores, odit magnam.',
+ 'close_button' => true, // show close button or not
+]
+```
+
+For different colors, you can use the following classes: ```alert-success```, ```alert-warning```, ```alert-info```, ```alert-danger``` ```alert-primary```, ```alert-secondary```, ```alert-light```, ```alert-dark```.
+
+Widget Preview:
+
+
+
+
+### Card
+
+Shows a Bootstrap card, with the heading and body you specify. You can customize the class name to get cards of different color, size, etc.
+
+```php
+[
+ 'type' => 'card',
+ // 'wrapperClass' => 'col-sm-6 col-md-4', // optional
+ // 'class' => 'card bg-dark text-white', // optional
+ 'content' => [
+ 'header' => 'Some card title', // optional
+ 'body' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non mi nec orci euismod venenatis. Integer quis sapien et diam facilisis facilisis ultricies quis justo. Phasellus sem turpis, ornare quis aliquet ut, volutpat et lectus. Aliquam a egestas elit. Nulla posuere, sem et porttitor mollis, massa nibh sagittis nibh, id porttitor nibh turpis sed arcu.',
+ ]
+]
+```
+
+For different background colors, you can use the following classes: ```bg-success```, ```bg-warning```, ```bg-info```, ```bg-danger``` ```bg-primary```, ```bg-secondary```, ```bg-light```, ```bg-dark```.
+
+Other useful helper classes: ```text-center```, ```text-white```.
+
+Widget Preview:
+
+
+
+
+### Div
+
+Allows you to include multiple widgets in the div attributes of your choice. For example, you can include multiple widgets in a `````` with the code below:
+
+```php
+[
+ 'type' => 'div',
+ 'class' => 'row',
+ 'content' => [ // widgets
+ [ 'type' => 'card', 'content' => ['body' => 'One'] ],
+ [ 'type' => 'card', 'content' => ['body' => 'Two'] ],
+ [ 'type' => 'card', 'content' => ['body' => 'Three'] ],
+ ]
+]
+```
+
+Anything you specify on this widget, other than ```type``` and ```content```, has to be a string, and will be considered an attribute of the "div" element.
+
+
+### Jumbotron
+
+Shows a Bootstrap jumbotron component, with the heading and body you specify.
+
+```php
+[
+ 'type' => 'jumbotron',
+ 'wrapperClass'=> '',
+ 'heading' => 'Welcome!',
+ 'content' => 'Use the sidebar to the left to create, edit or delete content.',
+ 'button_link' => backpack_url('http://github.com/logout'),
+ 'button_text' => 'Logout',
+]
+```
+
+Widget Preview:
+
+
+
+
+### Progress
+
+Shows a colorful card to signify the progress towards a goal. You can customize the class name to get cards of different color, size, etc.
+
+```php
+[
+ 'type' => 'progress',
+ 'class' => 'card text-white bg-primary mb-2',
+ 'value' => '11.456',
+ 'description' => 'Registered users.',
+ 'progress' => 57, // integer
+ 'hint' => '8544 more until next milestone.',
+]
+```
+
+For different background colors, you can use the following classes: ```bg-success```, ```bg-warning```, ```bg-info```, ```bg-danger``` ```bg-primary```, ```bg-secondary```, ```bg-light```, ```bg-dark```.
+
+Other useful helper classes: ```text-center```, ```text-white```.
+
+Widget Preview:
+
+
+
+
+### Progress White
+
+Shows a white card to signify the progress towards a goal. You can customize the class name to get progress bars of different color.
+
+```php
+[
+ 'type' => 'progress_white',
+ 'class' => 'card mb-2',
+ 'value' => '11.456',
+ 'description' => 'Registered users.',
+ 'progress' => 57, // integer
+ 'progressClass' => 'progress-bar bg-primary',
+ 'hint' => '8544 more until next milestone.',
+]
+```
+
+For different progress bar colors, you can use the following classes: ```bg-success```, ```bg-warning```, ```bg-info```, ```bg-danger``` ```bg-primary```, ```bg-secondary```, ```bg-light```, ```bg-dark```.
+
+Widget Preview:
+
+
+
+
+### View
+
+Loads a blade view from a location you specify. Any attributes you give it will be available in the ```$widget``` variable inside that view.
+
+```php
+[
+ 'type' => 'view',
+ 'view' => 'path.to.custom.view',
+ 'someAttr' => 'some value',
+]
+```
+
+It helps load blade files that are not specifically created to be widgets, that live in a different path than ```resources/views/vendor/backpack/base/widgets```, as if they were widgets.
+
+
+## Overwriting Default Widget Types
+
+You can overwrite a widget type by placing a file with the same name in your ```resources\views\vendor\backpack\base\widgets``` directory. When a file is there, Backpack will pick that one up, instead of the one in the package. You can do that from command line using ```php artisan backpack:base:publish widgets/widget-name```
+
+Examples:
+- creating a ```resources\views\vendor\backpack\base\widgets\card.blade.php``` file would overwrite the ```card``` widget functionality;
+- ```php artisan backpack:base:publish widgets/card``` will take the view from the package and copy it to the directory above, so you can edit it;
+
+>Keep in mind that when you're overwriting a default widget type, you're forfeiting any future updates for that widget. We can't push updates to a file that you're no longer using.
+
+
+## Creating a Custom Widget Type
+
+Widgets consist of only one file - a blade file with the same name as the widget type (ex: ```card.blade.php```). You can create one by placing a new blade file inside ```resources\views\vendor\backpack\base\widgets```. Be careful to choose a distinctive name, otherwise you might be overwriting a default widget type (see above).
+
+For example, you can create a ```well.blade.php```:
+```php
+
+
+ {!! $widget['content'] !!}
+
+
+```
+
+You can then use the ```well``` widget in a Controller or View:
+```php
+@extends(backpack_view('blank'))
+
+@php
+ $widgets['before_content'][] = [
+ 'type' => 'well',
+ 'wrapperClass' => 'col-sm-12',
+ 'content' => 'This text will be in a div with the class "well".',
+ ];
+@endphp
+
+@section('content')
+@endsection
+```
+
+To use information from the database, you can:
+- use the full namespace for your models, like ```\App\Models\Product::count()```;
+- load all your dashboard information using AJAX calls, if you're loading charts, reports, etc, and the DB queries might take a long time;
+- [use view composers](https://laravel.com/docs/5.7/views#view-composers) to push variables inside this view when it's loaded, Like. ```View::composer('backpack::widgets.well, 'App\Http\View\Composers\WellComposer');```
+
+Inside the widget blade files, you include custom CSS and JS, by pushing to the stacks in the layout:
+```php
+
+
+ {!! $widget['content'] !!}
+
+
+
+@push('after_styles')
+
+
+@endpush
+
+
+@push('after_scripts')
+
+
+@endpush
+```
+
+
+
+## Using a Widget Type from a Package
+
+You can choose the view namespace when loading a widget:
+
+```diff
+ $this->data['widgets']['after_content'] = [
+ [
+ 'type' => 'card',
++ 'viewNamespace' => 'package::widgets',
+ 'wrapperClass' => 'col-sm-6 col-md-4',
+ 'class' => 'card text-white bg-primary text-center',
+
+ 'content' => [
+ // 'header' => 'Another card title',
+ 'body' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non mi nec orci euismod venenatis. Integer quis sapien et diam facilisis facilisis ultricies quis justo. Phasellus sem turpis, ornare quis aliquet ut, volutpat et lectus. Aliquam a egestas elit.',
+ ]
+ ],
+ ];
+```
+
+Similarly, if you want to create widgets somewhere else than in ```resources/views/vendor/backpack/base/widgets```, you can pass that directory as the namespace of your widget. For example, ```resources/views/admin/widgets``` would have ```admin.widgets``` as the namespace.
diff --git a/4.0/crud-api.md b/4.0/crud-api.md
new file mode 100644
index 00000000..db12a2a3
--- /dev/null
+++ b/4.0/crud-api.md
@@ -0,0 +1,514 @@
+# API
+
+---
+
+Here are all the features you will be using **inside your EntityCrudController**, grouped by the operation you will most likely use them for.
+
+## Operations
+
+- **operation()** - allows you to add a set of instructions inside ```setup()```, that only only get called when a certain operation is being performed;
+```php
+public function setup() {
+ // ...
+ $this->crud->operation('list', function() {
+ $this->crud->addColumn('name');
+ });
+}
+```
+
+
+### ListEntries
+
+
+#### Columns
+
+Manipulate what columns are shown in the table view.
+
+- **addColumn()** - add a column, at the end of the stack
+```php
+$this->crud->addColumn($column_definition_array);
+```
+
+- **addColumns()** - add multiple columns, at the end of the stack
+```php
+$this->crud->addColumns([$column_definition_array, $another_column_definition_array]);
+```
+
+- **modifyColumn()** - change column attributes
+```php
+$this->crud->modifyColumn($name, $modifs_array);
+```
+
+- **removeColumn()** - remove one column from all operations
+```php
+$this->crud->removeColumn('column_name');
+```
+
+- **removeColumns()** - remove multiple columns from all operations
+```php
+$this->crud->removeColumns(['column_name_1', 'column_name_2']); // remove an array of columns from the stack
+```
+
+- **setColumnDetails()** - change the attributes of one column; alias of ```modifyColumn()```;
+```php
+$this->crud->setColumnDetails('column_name', ['attribute' => 'value']);
+```
+
+- **setColumnsDetails()** - change the attributes of multiple columns; alias of ```modifyColumn()```;
+```php
+$this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
+```
+
+- **setColumns()** - remove previously set columns and only use the ones give now;
+```php
+$this->crud->setColumns();
+// sets the columns you want in the table view, either as array of column names, or multidimensional array with all columns detailed with their types
+```
+
+- **Chained - beforeColumn()** - insert current column _before_ the given column
+```php
+// ------ REORDER COLUMNS
+$this->crud->addColumn()->beforeColumn('name');
+```
+
+- **Chained - afterColumn()** - insert current column _after_ the given column
+```php
+$this->crud->addColumn()->afterColumn('name');
+```
+
+- **Chained - makeFirstColumn()** - make this column the first one in the list
+```php
+$this->crud->addColumn()->makeFirstColumn();
+// Please note: you need to also specify priority 1 in your addColumn statement for details_row or responsive expand buttons to show
+```
+
+
+#### Buttons
+
+- **addButton()** - add a button in the given stack
+```php
+$this->crud->addButton($stack, $name, $type, $content, $position);
+// stacks: top, line, bottom
+// types: view, model_function
+// positions: beginning, end (defaults to 'beginning' for the 'line' stack, 'end' for the others);
+```
+
+- **addButtonFromModelFunction()** - add a button whose HTML is returned by a method in the CRUD model
+```php
+$this->crud->addButtonFromModelFunction($stack, $name, $model_function_name, $position);
+```
+
+- **addButtonFromView()** - add a button whose HTML is in a view placed at ```resources\views\vendor\backpack\crud\buttons```
+```php
+$this->crud->addButtonFromView($stack, $name, $view, $position);
+```
+
+- **removeButton()** - remove a button from whatever stack it's in
+```php
+$this->crud->removeButton($name);
+```
+
+- **removeButtonFromStack()** - remove a button from a particular stack
+```php
+$this->crud->removeButtonFromStack($name, $stack);
+```
+
+
+#### Filters
+
+Manipulate what filters are shown in the table view. Check out [CRUD > Operations > ListEntries > Filters](/docs/{{version}}/crud-filters) to see examples of ```$filter_definition_array```
+
+- **addFilter()** - add a filter to the list view
+```php
+$this->crud->addFilter($filter_definition_array, $values, $filter_logic);
+```
+
+- **modifyFilter()** - change the attributes of a filter
+```php
+$this->crud->modifyFilter($name, $modifs_array);
+```
+
+- **removeFilter()** - remove a certain filter from the list view
+```php
+$this->crud->removeFilter($name);
+```
+
+- **removeAllFilters()** - remove all filters from the list view
+```php
+$this->crud->removeAllFilters();
+```
+
+- **filters()** - get all the registered filters for the list view
+```php
+$this->crud->filters();
+```
+
+
+#### Details Row
+
+Shows a ```+``` (plus sign) next to each table row, so that the user can expand that row and reveal details. You are responsible for creating the view with those details.
+
+- **enableDetailsRow()** - show the + sign in the table view
+```php
+$this->crud->enableDetailsRow();
+// NOTE: you also need to do allow access to the right users:
+$this->crud->allowAccess('details_row');
+// NOTE: you also need to do overwrite the showDetailsRow($id) method in your EntityCrudController to show whatever you'd like in the details row OR overwrite the views/backpack/crud/details_row.blade.php
+$this->crud->setDetailsRowView('your-view');
+```
+
+- **disableDetailsRow()** - hide the + sign in the table view
+```php
+$this->crud->disableDetailsRow();
+```
+
+
+#### Export Buttons
+
+Please note it will only export the current _page_ of results. So in order to export all entries the user needs to make the current page show "All" entries from the top-left picker.
+
+- **enableExportButtons()** - Show export to PDF, CSV, XLS and Print buttons on the table view
+```php
+$this->crud->enableExportButtons();
+```
+
+
+#### Responsive Table
+
+- **disableResponsiveTable()** - stop the listEntries view from showing/hiding columns depending on viewport width
+```php
+$this->crud->disableResponsiveTable();
+```
+
+- **enableResponsiveTable()** - make the listEntries view show/hide columns depending on viewport width
+```php
+$this->crud->enableResponsiveTable();
+```
+
+
+#### Persistent Table
+
+- **enablePersistentTable()** - make the listEntries remember the filters, search and pagination for a user, even if he leaves the page, for 2 hours
+```php
+$this->crud->enablePersistentTable();
+```
+
+- **disablePersistentTable()** - stop the listEntries from remembering the filters, search and pagination for a user, even if he leaves the page
+```php
+$this->crud->disablePersistentTable();
+```
+
+
+#### Page Length
+
+- **setDefaultPageLength()** - change the number of items per page in the list view
+```php
+$this->crud->setDefaultPageLength(10);
+```
+
+- **setPageLengthMenu()** - change the entire page length menu in the list view
+```php
+$this->crud->setPageLengthMenu([100, 200, 300]);
+```
+
+
+#### Actions Column
+
+- **setActionsColumnPriority()** - make the actions column (in the table view) hide when not enough space is available, by giving it an unreasonable priority
+```php
+$this->crud->setActionsColumnPriority(10000);
+```
+
+
+#### Custom / Advanced Queries
+
+- **addClause()** - change what entries are shown in the table view; this allows _developers_ to forcibly change the query used by the table view, as opposed to filters, that allow _users_ to change the query with new inputs;
+```php
+$this->crud->addClause('active'); // apply local scope
+$this->crud->addClause('type', 'car'); // apply local dynamic scope
+$this->crud->addClause('where', 'name', '=', 'car');
+$this->crud->addClause('whereName', 'car');
+$this->crud->addClause('whereHas', 'posts', function($query) {
+ $query->activePosts();
+ });
+```
+
+- **groupBy()** - shorthand to add a **groupBy** clause to the query
+```php
+$this->crud->groupBy();
+```
+
+- **limit()** - shorthand to add a **limit** clause to the query
+```php
+$this->crud->limit();
+```
+
+- **orderBy()** - shorthand to add an **orderBy** clause to the query
+```php
+$this->crud->orderBy();
+```
+
+
+### Show
+
+Use [the same Columns API as for the ListEntries operation](#columns-api), but inside your ```show()``` method.
+
+
+### Create & Update Operations
+
+Manipulate what fields are shown in the create / update forms. Check out [CRUD > Operations > Create & Update > Fields](/docs/{{version}}/crud-fields) in the docs to see examples of ```$field_definition_array```.
+
+**Note:** The call is being performed for the current operation. So it's important to pay attention _where_ you're calling fields. Most likely, you'll want to do this inside ```setupCreateOperation()``` or ```setupUpdateOperation()```.
+
+- **addField()** - add one field
+```php
+$this->crud->addField($field_definition_array);
+$this->crud->addField('db_column_name'); // a lazy way to add fields: let the CRUD decide what field type it is and set it automatically, along with the field label
+```
+
+- **addFields()** - add multiple fields
+```php
+$this->crud->addFields($array_of_fields_definition_arrays);
+```
+
+- **modifyField()** - change the attributes of an existing field
+```php
+$this->crud->modifyField($name, $modifs_array);
+```
+
+- **removeField()** - remove a given field from the current operation
+```php
+$this->crud->removeField('name');
+```
+
+- **removeFields()** - remove multiple fields from the current operation
+```php
+$this->crud->removeFields($array_of_names);
+```
+
+- **removeAllFields()** - remove all registered fields
+```php
+$this->crud->removeAllFields();
+```
+- **Chained - beforeField()** - add a field _before_ a given field
+```php
+$this->crud->addField()->beforeField('name');
+```
+
+- **Chained - afterField()** - add a field _after_ a given field
+```php
+$this->crud->addField()->afterField('name');
+```
+
+- **setRequiredFields()** - check the FormRequests used in this EntityCrudController for required fields, and add an asterisk to them in the create or edit forms
+```php
+$this->crud->setRequiredFields(StoreRequest::class);
+```
+
+- **setValidation()** - makes sure validation and authorization in the FormRequest you've passed is being performed; also uses that file to figure out asterisk to show in the forms (calls ```setRequiredFields()``` above):
+```php
+$this->crud->setValidation(ArticleRequest::class);
+```
+
+
+### Reorder
+
+Show a reorder button in the table view, next to Add. Provides an interface to reorder & nest elements, provided the ```parent_id```, ```lft```, ```rgt```, ```depth``` columns are in the database, and ```$fillable``` on the model.
+
+```php
+$this->crud->set('reorder.label', 'name'); // which model attribute to use for labels
+$this->crud->set('reorder.max_level', 3); // maximum nesting depth; this example will prevent the user from creating trees deeper than 3 levels;
+```
+
+- **disableReorder()** - disable the Reorder functionality
+```php
+$this->crud->disableReorder();
+```
+
+- **isReorderEnabled()** - returns ```true```/```false``` if the Reorder operation is enabled or not
+```php
+$this->crud->isReorderEnabled();
+```
+
+
+### Revisions
+
+A.k.a. Audit Trail. Tracks all changes to an entry and provides an interface to revert to a previous state. In order to use this, you also need to ```use \Venturecraft\Revisionable\RevisionableTrait;```. Please check out the [Revision Operation](/docs/{{version}}/crud-operation-revisions) for more info.
+
+
+## All Operations
+
+### Access
+
+Prevent or allow users from accessing different CRUD operations.
+
+- **allowAccess()** - give users access to one or multiple operations
+```php
+$this->crud->allowAccess('list');
+$this->crud->allowAccess(['list', 'create', 'delete']);
+```
+
+- **denyAccess()** - prevent users from accessing one or multiple operations
+```php
+$this->crud->denyAccess('list');
+$this->crud->denyAccess(['list', 'create', 'delete']);
+```
+
+- **hasAccess()** - check if the current user has access to one or multiple operations
+```php
+$this->crud->hasAccess('something'); // returns true/false
+$this->crud->hasAccessOrFail('something'); // throws 403 error
+$this->crud->hasAccessToAll(['create', 'update']); // returns true/false
+$this->crud->hasAccessToAny(['create', 'update']); // returns true/false
+```
+
+### Eager Loading Relationships
+
+- **with()** - when the current entry is loaded (in any operation) also get its relationships, so that only one query is made to the database per entry
+```php
+$this->crud->with('relationship_name');
+```
+
+### Custom Views
+
+- **setShowView()**, **setEditView()**, **setCreateView()**, **setListView()**, **setReorderView()**, **setRevisionsView()**, **setRevisionsTimelineView()**, **setDetailsRowView()** - set the view for a certain CRUD operation or feature
+
+```php
+// use a custom view for a CRUD operation
+$this->crud->setShowView('path.to.your.view');
+$this->crud->setEditView('path.to.your.view');
+$this->crud->setCreateView('path.to.your.view');
+$this->crud->setListView('path.to.your.view');
+$this->crud->setReorderView('path.to.your.view');
+$this->crud->setRevisionsView('path.to.your.view');
+$this->crud->setRevisionsTimelineView('path.to.your.view');
+$this->crud->setDetailsRowView('path.to.your.view');
+
+// more generally, you can use the Settings API:
+$this->crud->set('create.view', 'path.to.your.view');
+
+// if you want to load something from the /resources/vendor/backpack/crud directory, you can do
+$this->crud->set('create.view', 'crud::yourfolder.yourview');
+// or
+$this->crud->set('create.view', 'resources.vendor.backpack.crud.yourfolder.yourview');
+```
+
+### Content Class
+
+- **setShowContentClass()**, **setEditContentClass()**, **setCreateContentClass()**, **setListContentClass()**, **setReorderContentClass()**, **setRevisionsContentClass()**, **setRevisionsTimelineContentClass()** - set the CSS class for an operation view, to make the main area bigger or smaller:
+
+```php
+// use a custom view for a CRUD operation
+$this->crud->setShowContentClass('col-md-8');
+$this->crud->setEditContentClass('col-md-8');
+$this->crud->setCreateContentClass('col-md-8');
+$this->crud->setListContentClass('col-md-8');
+$this->crud->setReorderContentClass('col-md-8');
+$this->crud->setRevisionsContentClass('col-md-8');
+$this->crud->setRevisionsTimelineContentClass('col-md-8');
+
+// more generally, you can use the Settings API:
+$this->crud->set('create.contentClass', 'col-md-12');
+```
+
+### Getters
+
+- **getEntry()** - get a certain entry of the current model type
+```php
+$this->crud->getEntry($entry_id);
+```
+- **getEntries()** - get all entries using the current CRUD query
+```php
+$this->crud->getEntries();
+```
+
+- **getFields()** - get all fields for a certain operation, or for both
+```php
+$this->crud->getFields('create/update/both');
+```
+
+- **getCurrentEntry()** - get the current entry, for operations that work on a single entry
+```php
+$this->crud->getCurrentEntry();
+// ex: in your update() method, after calling parent::updateCrud()
+```
+
+### Operations
+
+- **getOperation()** - get the name of the operation that is currently being performed
+```php
+$this->crud->getOperation();
+```
+
+- **setOperation()** - set the name of the operation that is currently being performed
+```php
+$this->crud->setOperation('ListEntries');
+```
+
+### Actions
+
+An action is the controller method that is currently being run.
+
+- **getActionMethod()** - returns the method on the controller that was called by the route; ex: ```create()```, ```update()```, ```edit()``` etc;
+```php
+$this->crud->getActionMethod();
+```
+
+- **actionIs()** - checks if the given controller method is the one called by the route
+```php
+$this->crud->actionIs('create');
+```
+
+### Title, Heading, Subheading
+
+Legend:
+- _operation_ - a collection of functions in a CrudController, that together allow the admin to perform something on the current model;
+- _action_ - a method (aka function) of an operation; it is the actual PHP function's name;
+
+- **getTitle()** - get the Title for the create action
+```php
+$this->crud->getTitle('create');
+```
+
+- **getHeading()** - get the Heading for the create action
+```php
+$this->crud->getHeading('create');
+```
+
+- **getSubheading()** - get the Subheading for the create action
+```php
+$this->crud->getSubheading('create');
+```
+
+- **setTitle()** - set the Title for the create action
+```php
+$this->crud->setTitle('some string', 'create');
+```
+
+- **setHeading()** - set the Heading for the create action
+```php
+$this->crud->setHeading('some string', 'create');
+```
+
+- **setSubheading()** - set the Subheading for the create action
+```php
+$this->crud->setSubheading('some string', 'create');
+```
+
+### CrudPanel Basic Info
+
+- **setModel()** - set the Eloquent object that should be used for all operations
+```php
+$this->crud->setModel("App\Models\Example");
+```
+
+- **setRoute()** - set the main route to this CRUD
+```php
+$this->crud->setRoute("admin/example");
+// OR $this->crud->setRouteName("admin.example");
+```
+
+- **setEntityNameStrings()** - set how the entity name should be shown to the user, in singular and in plural
+```php
+$this->crud->setEntityNameStrings("example", "examples");
+```
\ No newline at end of file
diff --git a/4.0/crud-basics.md b/4.0/crud-basics.md
new file mode 100644
index 00000000..4d3a32b1
--- /dev/null
+++ b/4.0/crud-basics.md
@@ -0,0 +1,46 @@
+# Basics
+
+---
+
+Backpack\CRUD provides a fast way to build administration panels - places where your administrators can Create, Read, Update, Delete entries for a specific Eloquent model. **One CRUD Panel provides functionality for one Eloquent Model.**
+
+
+## Requirements
+
+In order to create a CRUD Panel, you'll need:
+- **a table in the database** (and maybe connection tables for relationships);
+- **an Eloquent Model** that points to that db table;
+
+If you don't already have the models, don't worry, Backpack also includes a faster way to generate database migrations and models.
+
+
+## Architecture
+
+A Backpack CRUD Panel uses _the same elements_ you would have created for an administration panel, if you were doing it from scratch:
+- a **controller** - holds the logic for the all operations an admin can perform on that Eloquent model; will be generated in ```app/Http/Controllers/Admin```;
+- a **request** file - used to validate Create and Update forms; will be generated in ```app/Http/Requests```;
+- a resource **route** - points to the controller above; will be generated in ```routes/backpack/custom.php```;
+
+**The only difference** between building it from scratch and using Backpack\CRUD** is that:
+- your controller will be extending ```Backpack\CRUD\app\Http\Controllers\CrudController```**, which allow you to easily add traits that handle the most common operations: Create, Update, Delete, List, Show, Reorder, Revisions.
+- your model will ```use \Backpack\CRUD\CrudTrait```;
+
+This simple architecture (```ProductCrudController extends CrudController```) means:
+- **your CRUD Panel will not be a _black box_**; you can easily see the logic for each operation, by checking the methods on this controller, or the traits you'll be using;
+- **you can _easily_ overwrite what happens inside each operation**;
+- **you can _easily_ add custom operations**;
+
+For example:
+- want to change how a single ```Product``` is shown to the admin? just create a method called ```show()``` in your ```ProductCrudController```; simple OOP dictates that your method will be picked up, instead of the one in CrudController; same goes for ```create()```, ```store()```, etc - you have complete control;
+- want to create a new "Publish" operation on a ```Product```? your ```ProductCrudController``` is a great place for that logic; just create a custom ```publish()``` method and a route that points to it;
+
+
+## Files
+
+For a ```Tag``` entity, your CRUD Panel would consist of:
+- a controller (```app/Http/Controllers/Admin/TagCrudController.php```);
+- a request (```app/Http/Requests/TagCrudRequest.php```);
+- a route inside ```routes/backpack/custom.php```;
+- your existing model (```app/Models/Tag.php```);
+
+To further your understanding of how a CRUD Panel works, [read more about this example in the tutorial](/docs/{{version}}/crud-tutorial).
diff --git a/4.0/crud-buttons.md b/4.0/crud-buttons.md
new file mode 100644
index 00000000..c1fd3233
--- /dev/null
+++ b/4.0/crud-buttons.md
@@ -0,0 +1,202 @@
+# Buttons
+
+---
+
+
+## About
+
+Buttons are used inside the ListEdit operation, to allow the admin to trigger other operations. Some point to entirely new routes (```create```, ```update```, ```show```), others perform the operation on the current page using AJAX (```delete```).
+
+
+### Button Stacks
+
+The ShowList operation has 3 places where buttons can be placed:
+ - ```top``` (where the Add button is)
+ - ```line``` (where the Edit and Delete buttons are)
+ - ```bottom``` (after the table)
+
+When adding a button to the stack, you can choose whether to insert it at the ```beginning``` or ```end``` of the stack by specifying that as a last parameter.
+
+
+### Default Buttons
+
+Backpack adds a few buttons by default:
+- ```create``` to the ```top``` stack;
+- ```update``` and ```delete``` to the ```line``` stack;
+
+Default buttons are invisible if an operation has been disabled. For example, you can:
+- hide the "delete" button using ```$this->crud->denyAccess('delete')```;
+- show a "preview" button by using ```$this->crud->allowAccess('show')```;
+
+
+### Buttons API
+
+Here are a few things you can call in your EntityCrudController's ```setupListOperation()``` method, to manipulate buttons:
+
+```php
+// possible positions: 'beginning' and 'end'; defaults to 'beginning' for the 'line' stack, 'end' for the others;
+
+// add a button; possible types are: view, model_function
+$this->crud->addButton($stack, $name, $type, $content, $position);
+
+// add a button whose HTML is returned by a method in the CRUD model
+$this->crud->addButtonFromModelFunction($stack, $name, $model_function_name, $position);
+
+// add a button whose HTML is in a view placed at resources\views\vendor\backpack\crud\buttons
+$this->crud->addButtonFromView($stack, $name, $view, $position);
+
+// remove a button
+$this->crud->removeButton($name);
+
+// remove a button for a certain stack (top, line, bottom)
+$this->crud->removeButtonFromStack($name, $stack);
+```
+
+### Overwriting a Default Button
+
+Before showing any buttons, Backpack will check your ```resources\views\vendor\backpack\crud\buttons``` directory, to see if you've overwritten any default buttons. If it finds a blade file with the same name there as the default buttons, it will use your blade file, instead of the default.
+
+That means **you can overwrite an existing button simply by creating a blade file with the same name inside this directory**.
+
+
+### Creating a Custom Button
+
+To create a custom button:
+- create a new blade file in ```resources\views\vendor\backpack\crud\buttons```;
+- add that button using the ```addButton()``` syntax above, in the EntityCrudControllers you want, inside the ```setupListOperation()``` method;
+
+In this blade file, you can use:
+- ```$entry``` - the database entry you're showing (only inside the ```line``` stack);
+- ```$crud``` - the entire CrudPanel object;
+- ```$button``` - the button you're currently showing;
+
+
+## Examples
+
+
+### Adding a Custom Button with a Blade File
+
+Let's say we want to create a simple ```moderate.blade.php``` button. This button would just open a ```user/{id}/moderate/``` route, which would point to ```UserCrudController::moderate()```. The steps would be:
+
+- Create the ```resources\views\vendor\backpack\crud\buttons\moderate.blade.php``` file:
+```php
+@if ($crud->hasAccess('update'))
+ Moderate
+@endif
+```
+- Add the new route, next to ```UserCrudController```'s route (most likely inside ```routes/backpack/custom.php```):
+```php
+Route::get('user/{id}/moderate', 'UserCrudController@moderate');
+```
+
+- We can now add a ```moderate()``` method to our ```UserCrudController```, which would moderate the user, and redirect back.
+```php
+public function moderate()
+{
+ // show a form that does something
+}
+```
+
+- Now we can actually add this button to any of ```UserCrudController::setup()```:
+```php
+$this->crud->addButtonFromView('line', 'moderate', 'moderate', 'beginning');
+```
+
+
+### Adding a Custom Button without a Blade File
+
+Instead of creating a blade file for your button, you can use a function on your model to output the button's HTML.
+
+In your ```ArticleCrudController::setup()```:
+```php
+// add a button whose HTML is returned by a method in the CRUD model
+$this->crud->addButtonFromModelFunction('line', 'open_google', 'openGoogle', 'beginning');
+```
+
+In your ```Article``` model:
+
+```php
+public function openGoogle($crud = false)
+{
+ return ' Google it';
+}
+```
+
+
+
+### Adding a Custom Button with Javascript to the "top" stack
+
+Let's say we want to create an ```import.blade.php``` button. For simplicity, this button would just run an AJAX call which handles everything, and shows a status report to the user through notification bubbles.
+
+The "top" buttons are not bound to any certain entry, like buttons from the "list" stack. They can only do general things. And if they do general things, it's _generally_ recommended that you move their javascript to the bottom of the page. You can easily do that with ```@push('after_javascript')```, because the Backpack default layout has an ```after_javascript``` stack. This way, you can make sure your Javascript is moved at the bottom of the page, after all other Javascript has been loaded (jQuery, DataTables, etc). Check out the example below.
+
+The steps would be:
+
+- Create the ```resources\views\vendor\backpack\crud\buttons\import.blade.php``` file:
+
+```php
+@if ($crud->hasAccess('create'))
+
+ Import {{ $crud->entity_name }}
+
+@endif
+
+@push('after_scripts')
+
+@endpush
+```
+- Add the new route, next to ```UserCrudController```'s route (most likely inside ```routes/backpack/custom.php```):
+```php
+Route::get('user/import', 'UserCrudController@import');
+```
+
+- We can now add a ```import()``` method to our ```UserCrudController```, which would import the users.
+```php
+public function import()
+{
+ // whatever you decide to do
+}
+```
+
+- Now we can actually add this button to any of ```UserCrudController::setup()```:
+```php
+$this->crud->addButtonFromView('top', 'import', 'import', 'end');
+```
diff --git a/4.0/crud-cheat-sheet.md b/4.0/crud-cheat-sheet.md
new file mode 100644
index 00000000..f098cf4d
--- /dev/null
+++ b/4.0/crud-cheat-sheet.md
@@ -0,0 +1,319 @@
+# Crud API Cheat Sheet
+
+---
+
+Here are all the functions you will be using **inside your EntityCrudController's ```setup()``` method**, grouped by the operation you will most likely use them for.
+
+## Operations
+
+
+### ListEntries
+
+
+#### Columns
+
+Methods: addColumn(), addColumns(), modifyColumn(), removeColumn(), removeColumns(), setColumnDetails(), setColumnsDetails(), setColumns(), beforeColumn(), afterColumn(), makeFirstColumn()
+
+```php
+// Manipulate what columns are shown in the table view.
+$this->crud->addColumn($column_definition_array); // add a column, at the end of the stack
+$this->crud->addColumns([$column_definition_array, $another_column_definition_array]); // add multiple columns, at the end of the stack
+$this->crud->modifyColumn($name, $modifs_array);
+$this->crud->removeColumn('column_name'); // remove a column from the stack
+$this->crud->removeColumns(['column_name_1', 'column_name_2']); // remove an array of columns from the stack
+$this->crud->setColumnDetails('column_name', ['attribute' => 'value']);
+$this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
+
+$this->crud->setColumns(); // set the columns you want in the table view, either as array of column names, or multidimensional array with all columns detailed with their types
+
+// ------ REORDER COLUMNS
+$this->crud->addColumn()->beforeColumn('name'); // will show this before the given column
+$this->crud->addColumn()->afterColumn('name'); // will show this after the given column
+
+$this->crud->addColumn()->makeFirstColumn();
+ // will make this column the first one in the list
+ // you need to also specify priority 1 in your addColumn statement for details_row or responsive expand buttons to show
+```
+
+
+#### Buttons
+
+Methods: addButton(), addButtonFromModelFunction(), addButtonFromView(), removeButton(), removeButtonFromStack()
+
+```php
+// possible positions: 'beginning' and 'end'; defaults to 'beginning' for the 'line' stack, 'end' for the others;
+$this->crud->addButton($stack, $name, $type, $content, $position); // add a button; possible types are: view, model_function
+$this->crud->addButtonFromModelFunction($stack, $name, $model_function_name, $position); // add a button whose HTML is returned by a method in the CRUD model
+$this->crud->addButtonFromView($stack, $name, $view, $position); // add a button whose HTML is in a view placed at resources\views\vendor\backpack\crud\buttons
+$this->crud->removeButton($name);
+$this->crud->removeButtonFromStack($name, $stack);
+```
+
+
+#### Filters
+
+Methods: addFilter(), modifyFilter(), removeFilter(), removeAllFilters(), filters()
+
+```php
+// Manipulate what filters are shown in the table view.
+//
+// Note: check out CRUD > Features > Filters in the docs to see examples of $filter_definition_array
+$this->crud->addFilter($filter_definition_array, $values, $filter_logic);
+$this->crud->modifyFilter($name, $modifs_array);
+$this->crud->removeFilter($name);
+$this->crud->removeAllFilters();
+$this->crud->filters(); // gets all the filters
+```
+
+
+#### Details Row
+
+Methods: enableDetailsRow(), disableDetailsRow()
+
+```php
+// Shows a + sign next to each table row, so that the user can expand that row and reveal details. You are responsible for creating the view with those details.
+$this->crud->enableDetailsRow();
+// NOTE: you also need to do allow access to the right users: $this->crud->allowAccess('details_row');
+// NOTE: you also need to do overwrite the showDetailsRow($id) method in your EntityCrudController to show whatever you'd like in the details row OR overwrite the views/backpack/crud/details_row.blade.php
+
+$this->crud->disableDetailsRow();
+```
+
+
+#### Export Buttons
+
+Methods: enableExportButtons()
+
+```php
+// Show export to PDF, CSV, XLS and Print buttons on the table view. Please note it will only export the current _page_ of results. So in order to export all entries the user needs to make the current page show "All" entries from the top-left picker.
+$this->crud->enableExportButtons();
+```
+
+
+#### Responsive Table
+
+Methods: enableResponsiveTable(), disableResponsiveTable()
+
+```php
+$this->crud->disableResponsiveTable();
+$this->crud->enableResponsiveTable();
+```
+
+
+#### Persistent Table
+
+Methods: enablePersistenTable(), disablePersistenTable()
+
+```php
+$this->crud->disablePersistentTable();
+$this->crud->enablePersistentTable();
+```
+
+
+#### Page Length
+
+Methods: setDetaultPageLength(), setPageLengthMenu()
+
+```php
+$this->crud->setDefaultPageLength(10); // number of rows shown in list view
+$this->crud->setPageLengthMenu([100, 200, 300]); // page length menu to show in the list view
+```
+
+
+#### Actions Column
+
+Methods: setActionColumnPriority()
+
+```php
+// make the actions column (in the table view) hide when not enough space is available, by giving it an unreasonable priority
+$this->crud->setActionsColumnPriority(10000);
+```
+
+
+#### Custom / Advanced Queries
+
+Methods: addClause(), groupBy(), limit(), orderBy()
+
+```php
+// Change what entries are shown in the table view.
+// This changes all queries on the table view,
+// as opposed to filters, who only change it when that filter is applied.
+$this->crud->addClause('active'); // apply local scope
+$this->crud->addClause('type', 'car'); // apply local dynamic scope
+$this->crud->addClause('where', 'name', '=', 'car');
+$this->crud->addClause('whereName', 'car');
+$this->crud->addClause('whereHas', 'posts', function($query) {
+ $query->activePosts();
+ });
+$this->crud->groupBy();
+$this->crud->limit();
+
+$this->crud->orderBy();
+// please note it's generally a good idea to use crud->orderBy() inside "if (!$this->request->has('order')) {}"; that way, your custom order is applied ONLY IF the user hasn't forced another order (by clicking a column heading)
+```
+
+
+### Show
+
+Use the same Columns API as for the ListEntries operation, but inside your ```show()``` method.
+
+
+### Create & Update Operations
+
+Methods: addField(), addFields(), modifyField(), modifyFields(), removeField(), removeFields(), removeAllFields(), beforeField(), afterField()
+
+```php
+// ------
+// FIELDS
+// ------
+// Manipulate what fields are shown in the create / update forms.
+//
+// Note: check out CRUD > Features > Field Types in the docs to see examples of $field_definition_array
+
+$this->crud->addField($field_definition_array);
+$this->crud->addField('db_column_name'); // a lazy way to add fields: let the CRUD decide what field type it is and set it automatically, along with the field label
+$this->crud->addFields($array_of_fields_definition_arrays);
+$this->crud->modifyField($name, $modifs_array);
+$this->crud->removeField('name');
+$this->crud->removeFields($array_of_names);
+$this->crud->removeAllFields();
+
+// ------ REORDER FIELDS
+$this->crud->addField()->beforeField('name'); // will show this before the given field
+$this->crud->addField()->afterField('name'); // will show this after the given field
+```
+
+
+### Reorder
+
+Methods: enableReorder(), disableReorder(), isReorderEnabled()
+
+```php
+ protected function setupReorderOperation()
+ {
+ // model attribute to be shown on draggable items
+ $this->crud->set('reorder.label', 'name');
+ // maximum number of nesting allowed
+ $this->crud->set('reorder.max_level', 2);
+
+ // extras:
+ // $this->crud->disableReorder();
+ // $this->crud->isReorderEnabled();
+ }
+```
+
+
+### Revisions
+
+```php
+// -------------------------
+// REVISIONS aka Audit Trail
+// -------------------------
+// Tracks all changes to an entry and provides an interface to revert to a previous state.
+//
+// IMPORTANT: You also need to use \Venturecraft\Revisionable\RevisionableTrait;
+// Please check out: https://backpackforlaravel.com/docs/crud-operation-revisions
+$this->crud->allowAccess('revisions');
+```
+
+
+## All Operations
+
+Methods: allowAccess(), denyAccess(), hasAccess(), hasAccessOrFail(), hasAccessToAll(), hasAccessToAny(), setShowView(), setEditView(), setCreateView(), setListView(), setReorderView(), setRevisionsView, setRevisionsTimelineView(), setDetailsRowView(), getEntry(), getFields(), getColumns(), getCurrentEntry(), getTitle(), setTitle(), getHeading(), setHeading(), getSubheading(), setSubheading(),
+
+```php
+// ------
+// ACCESS
+// ------
+// Prevent or allow users from accessing different CRUD operations.
+
+$this->crud->allowAccess('list');
+$this->crud->allowAccess(['list', 'create', 'delete']);
+$this->crud->denyAccess('list');
+$this->crud->denyAccess(['list', 'create', 'delete']);
+
+$this->crud->hasAccess('add'); // returns true/false
+$this->crud->hasAccessOrFail('add'); // throws 403 error
+$this->crud->hasAccessToAll(['create', 'update']); // returns true/false
+$this->crud->hasAccessToAny(['create', 'update']); // returns true/false
+
+// -------------
+// EAGER LOADING
+// -------------
+
+// eager load a relationship
+$this->crud->with('relationship_name');
+
+// ------------
+// CUSTOM VIEWS
+// ------------
+
+// use a custom view for a CRUD operation
+$this->crud->setShowView('your-view');
+$this->crud->setEditView('your-view');
+$this->crud->setCreateView('your-view');
+$this->crud->setListView('your-view');
+$this->crud->setReorderView('your-view');
+$this->crud->setRevisionsView('your-view');
+$this->crud->setRevisionsTimelineView('your-view');
+$this->crud->setDetailsRowView('your-view');
+
+// -------------
+// CONTENT CLASS
+// -------------
+
+// use a custom CSS class for the content of a CRUD operation
+$this->crud->setShowContentClass('col-md-12');
+$this->crud->setEditContentClass('col-md-12');
+$this->crud->setCreateContentClass('col-md-12');
+$this->crud->setListContentClass('col-md-12');
+$this->crud->setReorderContentClass('col-md-12');
+$this->crud->setRevisionsContentClass('col-md-12');
+$this->crud->setRevisionsTimelineContentClass('col-md-12');
+
+// -------
+// GETTERS
+// -------
+
+$this->crud->getEntry($entry_id);
+$this->crud->getEntries();
+
+$this->crud->getFields('create/update/both');
+
+// in your update() method, after calling parent::updateCrud()
+$this->crud->getCurrentEntry();
+
+// -------
+// OPERATIONS
+// -------
+
+$this->crud->setOperation('list');
+$this->crud->getOperation();
+
+// -------
+// ACTIONS
+// -------
+
+$this->crud->getActionMethod(); // returns the method on the controller that was called by the route; ex: create(), update(), edit() etc;
+$this->crud->actionIs('create'); // checks if the controller method given is the one called by the route
+
+$this->crud->getTitle('create'); // get the Title for the create action
+$this->crud->getHeading('create'); // get the Heading for the create action
+$this->crud->getSubheading('create'); // get the Subheading for the create action
+
+$this->crud->setTitle('some string', 'create'); // set the Title for the create action
+$this->crud->setHeading('some string', 'create'); // set the Heading for the create action
+$this->crud->setSubheading('some string', 'create'); // set the Subheading for the create action
+
+// ---------------------------
+// CrudPanel Basic Information
+// ---------------------------
+$this->crud->setModel("App\Models\Example");
+$this->crud->setRoute("admin/example");
+// OR $this->crud->setRouteName("admin.example");
+$this->crud->setEntityNameStrings("example", "examples");
+
+// check the FormRequests used in that EntityCrudController for required fields, and add an asterisk to them in the create/edit form
+$this->crud->setRequiredFields(StoreRequest::class, 'create');
+$this->crud->setRequiredFields(UpdateRequest::class, 'edit');
+```
diff --git a/4.0/crud-columns.md b/4.0/crud-columns.md
new file mode 100644
index 00000000..ab7ab564
--- /dev/null
+++ b/4.0/crud-columns.md
@@ -0,0 +1,718 @@
+# Columns
+
+---
+
+
+## About
+
+A column shows the information of an Eloquent attribute, in a user-friendly format.
+
+It's used inside default operations to:
+- show a table cell in **ListEntries**;
+- show an attribute value in **Show**;
+
+A column consists of only one file - a blade file with the same name as the column type (ex: ```text.blade.php```). Backpack provides you with [default column types](#default-column-types) for the common use cases, but you can easily [change how a default field type works](#overwriting-default-column-types), or [create an entirely new field type](#creating-a-custom-column-type).
+
+
+### Mandatory Attributes
+
+When passing a column array, you need to specify at least these attributes:
+```php
+[
+ 'name' => 'options', // the db column name (attribute name)
+ 'label' => "Options", // the human-readable label for it
+ 'type' => 'text' // the kind of column to show
+],
+```
+
+
+### Optional Attributes
+
+- [```searchLogic```](#custom-search-logic)
+- [```orderLogic```](#custom-order-logic)
+- [```orderable```](#custom-order-logic)
+- [```visibleInTable```](#choose-where-columns-are-visible)
+- [```visibleInModal```](#choose-where-columns-are-visible)
+- [```visibleInExport```](#choose-where-columns-are-visible)
+- [```visibleInShow```](#choose-where-columns-are-visible)
+- [```priority```](#define-which-columns-to-hide-in-responsive-table)
+
+
+### Columns API
+
+Inside your ```setupListOperation()``` or ```setupShowOperation()``` method, there are a few calls you can make to configure or manipulate columns:
+
+```php
+// add a column, at the end of the stack
+$this->crud->addColumn($column_definition_array);
+
+// add multiple columns, at the end of the stack
+$this->crud->addColumns([$column_definition_array, $another_column_definition_array]);
+
+// remove a column from the stack
+$this->crud->removeColumn('column_name');
+
+// remove an array of columns from the stack
+$this->crud->removeColumns(['column_name_1', 'column_name_2']);
+
+// change the attributes of a column
+$this->crud->modifyColumn($name, $modifs_array);
+$this->crud->setColumnDetails('column_name', ['attribute' => 'value']);
+
+// change the attributes of multiple columns
+$this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
+
+// forget what columns have been previously defined, only use these columns
+$this->crud->setColumns([$column_definition_array, $another_column_definition_array]);
+```
+
+In addition, to manipulate the order columns are shown in, you can:
+
+```php
+// add this column before a given column
+$this->crud->addColumn('text')->beforeColumn('name');
+
+// add this column after a given column
+$this->crud->addColumn()->afterColumn('name');
+
+// make this column the first one in the list
+$this->crud->addColumn()->makeFirstColumn();
+```
+
+
+## Default Column Types
+
+
+### array
+
+Enumerate an array stored in the db column as JSON.
+```php
+[
+ 'name' => 'options', // The db column name
+ 'label' => "Options", // Table column heading
+ 'type' => 'array'
+],
+```
+
+
+### array_count
+
+Count the items in an array stored in the db column as JSON.
+
+```php
+[
+ 'name' => 'options', // The db column name
+ 'label' => "Options", // Table column heading
+ 'type' => 'array_count',
+ // 'suffix' => 'options', // if you want it to show "2 options" instead of "2 items"
+],
+```
+
+
+### boolean
+
+Show Yes/No (or custom text) instead of 1/0.
+
+```php
+[
+ 'name' => 'name',
+ 'label' => 'Status',
+ 'type' => 'boolean',
+ // optionally override the Yes/No texts
+ // 'options' => [0 => 'Active', 1 => 'Inactive']
+],
+```
+
+
+### check
+
+Show a favicon with a checked or unchecked box, depending on the given boolean.
+```php
+[
+ 'name' => 'featured', // The db column name
+ 'label' => "Featured", // Table column heading
+ 'type' => 'check'
+],
+```
+
+
+
+### checkbox
+
+Shows a checkbox (the form element), and inserts the js logic needed to select/deselect multiple entries. It is mostly used for [the Bulk Delete action](/docs/{{version}}/crud-operation-delete#delete-multiple-items-bulk-delete), and [custom bulk actions](/docs/{{version}}/crud-operations#creating-a-new-operation-with-a-bulk-action-no-interface).
+
+Shorthand:
+```php
+$this->crud->enableBulkActions();
+```
+(will also add an empty custom_html column)
+
+Verbose:
+```php
+$this->crud->addColumn([
+ 'type' => 'checkbox',
+ 'name' => 'bulk_actions',
+ 'label' => ' ',
+ 'priority' => 1,
+ 'searchLogic' => false,
+ 'orderable' => false,
+ 'visibleInModal' => false,
+])->makeFirstColumn();
+```
+
+
+### closure
+
+
+Show custom HTML based on a closure you specify in your EntityCrudController. Please note this column does not escape HTML before rendering. You need to do that yourself, if you consider it necessary.
+
+```php
+[
+ 'name' => 'created_at',
+ 'label' => 'Created At',
+ 'type' => 'closure',
+ 'function' => function($entry) {
+ return 'Created on '.$entry->created_at;
+ }
+],
+```
+
+
+### date
+
+
+The date column will show a localized date in the default date format (as specified in the ```config/backpack/base.php``` file), whether the attribute is casted as date in the model or not.
+
+Note that the ```format``` attribute uses ISO date formatting parameters and not PHP ```date()``` formatters. See for more information.
+
+```php
+[
+ 'name' => "name", // The db column name
+ 'label' => "Tag Name", // Table column heading
+ 'type' => "date",
+ // 'format' => 'l j F Y', // use something else than the base.default_date_format config value
+],
+```
+
+
+### datetime
+
+
+The date column will show a localized datetime in the default datetime format (as specified in the ```config/backpack/base.php``` file), whether the attribute is casted as datetime in the model or not.
+
+Note that the ```format``` attribute uses ISO date formatting parameters and not PHP ```date()``` formatters. See for more information.
+
+
+```php
+[
+ 'name' => "name", // The db column name
+ 'label' => "Tag Name", // Table column heading
+ 'type' => "datetime",
+ // 'format' => 'l j F Y H:i:s', // use something else than the base.default_datetime_format config value
+],
+```
+
+
+### email
+
+The email column will output the email address in the database (truncated to 254 characters if needed), with a ```mailto:``` link towards the full email. Its definition is:
+```php
+[
+ 'name' => 'email', // The db column name
+ 'label' => "Email Address", // Table column heading
+ 'type' => 'email',
+ // 'limit' => 500, // if you want to truncate the text to a different number of characters
+],
+```
+
+
+### image
+
+
+Show a thumbnail image.
+
+```php
+[
+ 'name' => 'profile_image', // The db column name
+ 'label' => "Profile image", // Table column heading
+ 'type' => 'image',
+ // 'prefix' => 'folder/subfolder/',
+ // image from a different disk (like s3 bucket)
+ // 'disk' => 'disk-name',
+ // optional width/height if 25px is not ok with you
+ // 'height' => '30px',
+ // 'width' => '30px',
+],
+```
+
+
+### markdown
+
+
+Convert a markdown string to HTML, using ```Illuminate\Mail\Markdown```. Since Markdown is usually used for long texts, this column is most helpful in the "Show" operation - not so much in the "ListEntries" operation, where only short snippets make sense.
+
+```php
+[
+ 'name' => 'text', // The db column name
+ 'label' => "Text", // Table column heading
+ 'type' => 'markdown',
+],
+```
+
+
+### model_function
+
+
+The model_function column will output a function on your main model. Its definition is:
+```php
+[
+ // run a function on the CRUD model and show its return value
+ 'name' => "url",
+ 'label' => "URL", // Table column heading
+ 'type' => "model_function",
+ 'function_name' => 'getSlugWithLink', // the method in your Model
+ // 'function_parameters' => [$one, $two], // pass one/more parameters to that method
+ // 'limit' => 100, // Limit the number of characters shown
+],
+```
+For this example, if your model would feature this method, it would return the link to that entity:
+```php
+public function getSlugWithLink() {
+ return ''.$this->slug.'';
+}
+```
+
+**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent JS and CSS from reaching your DB in the first place.
+
+
+### model_function_attribute
+
+
+If the function you're trying to use returns an object, not a string, you can use the model_function_attribute column, which will output the attribute on the function result. Its definition is:
+```php
+[
+ 'name' => "url",
+ 'label' => "URL", // Table column heading
+ 'type' => "model_function_attribute",
+ 'function_name' => 'getSlugWithLink', // the method in your Model
+ // 'function_parameters' => [$one, $two], // pass one/more parameters to that method
+ 'attribute' => 'route',
+ // 'limit' => 100, // Limit the number of characters shown
+],
+```
+
+**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent JS and CSS from reaching your DB in the first place.
+
+
+### multidimensional_array
+
+
+Enumerate the values in a multidimensional array, stored in the db as JSON.
+
+```php
+[
+ 'name' => 'options', // The db column name
+ 'label' => "Options", // Table column heading
+ 'type' => 'multidimensional_array',
+ 'visible_key' => 'name' // The key to the attribute you would like shown in the enumeration
+],
+```
+
+
+### number
+
+
+The text column will just output the number value of a db column (or model attribute). Its definition is:
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => "Tag Name", // Table column heading
+ 'type' => "number",
+ // 'prefix' => "$",
+ // 'suffix' => " EUR",
+ // 'decimals' => 2,
+ // 'dec_point' => ',',
+ // 'thousands_sep' => '.',
+ // decimals, dec_point and thousands_sep are used to format the number;
+ // for details on how they work check out PHP's number_format() method, they're passed directly to it;
+ // https://www.php.net/manual/en/function.number-format.php
+],
+```
+
+
+### phone
+
+The phone column will output the phone number from the database (truncated to 254 characters if needed), with a ```tel:``` link so that users on mobile can click them to call (or with Skype or similar browser extensions). Its definition is:
+```php
+[
+ 'name' => 'phone', // The db column name
+ 'label' => "Phone number", // Table column heading
+ 'type' => 'phone',
+ // 'limit' => 10, // if you want to truncate the phone number to a different number of characters
+],
+```
+
+
+### radio
+
+
+Show a pretty text instead of the database value, according to an associative array. Usually used as a column for the "radio" field type.
+
+```php
+[
+ 'name' => 'status',
+ 'label' => 'Status',
+ 'type' => 'radio',
+ 'options' => [
+ 0 => "Draft",
+ 1 => "Published"
+ ]
+],
+```
+
+This example will show:
+- "Draft" when the value stored in the db is 0;
+- "Published" when the value stored in the db is 1;
+
+
+### row_number
+
+
+Show the row number (index). The number depends strictly on the result set (x records per page, pagination, search, filters, etc). It does not get any information from the database. It is not searchable. It is only useful to show the current row number.
+
+```
+$this->crud->addColumn([
+ 'name' => 'row_number',
+ 'type' => 'row_number',
+ 'label' => '#',
+ 'orderable' => false,
+])->makeFirstColumn();
+```
+
+Notes:
+- you can have a different ```name```; just make sure your model doesn't have that attribute;
+- you can have a different label;
+- you can place the column as second / third / etc if you remove ```makeFirstColumn()```;
+- this column type allows the use of suffix/prefix just like the text column type;
+- if upon placement you notice it always shows ```false``` then please note there have been changes in the ```search()``` method - you need to add another parameter to your ```getEntriesAsJsonForDatatables()``` call;
+
+
+### text
+
+The text column will just output the text value of a db column (or model attribute). Its definition is:
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => "Tag Name", // Table column heading
+ // 'prefix' => "Name: ",
+ // 'suffix' => "(user)",
+ // 'limit' => 120, // character limit; default is 50;
+],
+```
+
+**Advanced use case:** The ```text``` column type can also show the attribute of a 1-1 relationship. If you have a relationship (like ```parent()```) set up in your Model, you can use relationship and attribute in the ```name```, using dot notation:
+```php
+[
+ 'name' => 'parent.title',
+ 'label' => 'Title',
+ 'type' => 'text'
+],
+```
+
+
+### select
+
+The select column will output its connected entity. Used for relationships like hasOne() and belongsTo(). Its name and definition is the same as for the select *field type*:
+```php
+[
+ // 1-n relationship
+ 'label' => "Parent", // Table column heading
+ 'type' => "select",
+ 'name' => 'parent_id', // the column that contains the ID of that connected entity;
+ 'entity' => 'parent', // the method that defines the relationship in your Model
+ 'attribute' => "name", // foreign key attribute that is shown to user
+ 'model' => "App\Models\Category", // foreign key model
+],
+```
+
+
+### select_from_array
+
+Show a particular text depending on the value of the attribute.
+
+```php
+[
+ // select_from_array
+ 'name' => 'status',
+ 'label' => "Status",
+ 'type' => 'select_from_array',
+ 'options' => ['draft' => 'Draft (invisible)', 'published' => 'Published (visible)'],
+],
+```
+
+
+### select_multiple
+
+The select_multiple column will output a comma separated list of its connected entities. Used for relationships like hasMany() and belongsToMany(). Its name and definition is the same as the select_multiple field:
+```php
+[
+ // n-n relationship (with pivot table)
+ 'label' => "Tags", // Table column heading
+ 'type' => "select_multiple",
+ 'name' => 'tags', // the method that defines the relationship in your Model
+ 'entity' => 'tags', // the method that defines the relationship in your Model
+ 'attribute' => "name", // foreign key attribute that is shown to user
+ 'model' => "App\Models\Tag", // foreign key model
+],
+```
+
+
+### table
+
+
+The ```table``` column will output a condensed table, when used on an attribute that stores a JSON array or object. It is meant to be used inside the show functionality (not list, though it also works there).
+
+Its definition is very similar to the [table *field type*](/docs/{{version}}/crud-fields#table).
+
+```php
+[
+ 'name' => 'features',
+ 'label' => 'Features',
+ 'type' => 'table',
+ 'columns' => [
+ 'name' => 'Name',
+ 'description' => 'Description',
+ 'price' => 'Price',
+ 'obs' => 'Observations'
+ ]
+],
+```
+
+
+### upload_multiple
+
+
+The ```table``` column will output a list of files and links, when used on an attribute that stores a JSON array of file paths. It is meant to be used inside the show functionality (not list, though it also works there), to preview files uploaded with the ```upload_multiple``` field type.
+
+Its definition is very similar to the [upload_multiple *field type*](/docs/{{version}}/crud-fields#upload_multiple).
+
+```php
+[
+ 'name' => 'photos',
+ 'label' => 'Photos',
+ 'type' => 'upload_multiple',
+ // 'disk' => 'public', // filesystem disk if you're using S3 or something custom
+],
+```
+
+
+### video
+
+
+Display a small screenshot for a Youtube or Vimeo video, stored in the database as JSON using the "video" field type.
+
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => "Tag Name", // Table column heading
+ 'type' => 'video',
+],
+```
+
+
+### view
+
+Display any custom column type you want. Usually used by Backpack package developers, to use views from within their packages, instead of having to publish the views.
+
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => "Tag Name", // Table column heading
+ 'type' => 'view',
+ 'view' => 'package::columns.column_type_name', // or path to blade file
+],
+```
+
+
+## Overwriting Default Column Types
+
+You can overwrite a column type by placing a file with the same name in your ```resources\views\vendor\backpack\crud\columns``` directory. When a file is there, Backpack will pick that one up, instead of the one in the package. You can do that from command line using ```php artisan backpack:publish crud/columns/column-file-name```
+
+Examples:
+- creating a ```resources\views\vendor\backpack\crud\columns\number.blade.php``` file would overwrite the ```number``` column functionality;
+- ```php artisan backpack:publish crud/columns/text``` will take the view from the package and copy it to the directory above, so you can edit it;
+
+>Keep in mind that when you're overwriting a default column type, you're forfeiting any future updates for that column. We can't push updates to a file that you're no longer using.
+
+
+## Creating a Custom Column Type
+
+Columns consist of only one file - a blade file with the same name as the column type (ex: ```text.blade.php```). You can create one by placing a new blad file inside ```resources\views\vendor\backpack\crud\columns```. Be careful to choose a distinctive name, otherwise you might be overwriting a default column type (see above).
+
+For example, you can create a ```markdown.blade.php```:
+```php
+{!! \Markdown::convertToHtml($entry->{$column['name']}) !!}
+```
+
+The most useful variables you'll have in this file here are:
+- ```$entry``` - the database entry you're showing (Eloquent object);
+- ```$crud``` - the entire CrudPanel object, with settings, options and variables;
+
+By default, custom columns are not searchable. In order to make your column searchable you need to [specify a custom ```searchLogic``` in your declaration](#custom-search-logic).
+
+
+
+## Advanced Columns Use
+
+
+### Custom Search Logic for Columns
+
+If your column points to something atypical (not a value that is stored as plain text in the database column, maybe a model function, or a JSON, or something else), you might find that the search doesn't work for that column. You can choose which columns are searchable, and what those columns actually search, by using the column's ```searchLogic``` attribute:
+
+```php
+// column with custom search logic
+$this->crud->addColumn([
+ 'name' => 'slug_or_title',
+ 'label' => 'Title',
+ 'searchLogic' => function ($query, $column, $searchTerm) {
+ $query->orWhere('title', 'like', '%'.$searchTerm.'%');
+ }
+]);
+
+
+// 1-n relationship column with custom search logic
+$this->crud->addColumn([
+ 'label' => "Cruise Ship",
+ 'type' => "select",
+ 'name' => 'cruise_ship_id',
+ 'entity' => 'cruise_ship',
+ 'attribute' => "cruise_ship_name_date", // combined name & date column
+ 'model' => "App\Models\CruiseShip",
+ 'searchLogic' => function ($query, $column, $searchTerm) {
+ $query->orWhereHas('cruise_ship', function ($q) use ($column, $searchTerm) {
+ $q->where('name', 'like', '%'.$searchTerm.'%')
+ ->orWhereDate('depart_at', '=', date($searchTerm));
+ });
+ }
+]);
+
+
+// column that doesn't need to be searchable
+$this->crud->addColumn([
+ 'name' => 'slug_or_title',
+ 'label' => 'Title',
+ 'searchLogic' => false
+]);
+
+// column whose search logic should behave like it were a 'text' column type
+$this->crud->addColumn([
+ 'name' => 'slug_or_title',
+ 'label' => 'Title',
+ 'searchLogic' => 'text'
+]);
+```
+
+
+### Custom Order Logic for Columns
+
+If your column points to something atypical (not a value that is stored as plain text in the database column, maybe a model function, or a JSON, or something else), you might find that the ordering doesn't work for that column. You can choose which columns are orderable, and how those columns actually get ordered, by using the column's ```orderLogic``` attribute.
+
+For example, to order Articles not by its Category ID (as default, but by the Category Name), you can do:
+
+```php
+$this->crud->addColumn([
+ // Select
+ 'label' => "Category",
+ 'type' => 'select',
+ 'name' => 'category_id', // the db column for the foreign key
+ 'entity' => 'category', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'orderable' => true,
+ 'orderLogic' => function ($query, $column, $columnDirection) {
+ return $query->leftJoin('categories', 'categories.id', '=', 'articles.select')
+ ->orderBy('categories.name', $columnDirection)->select('articles.*');
+ }
+]);
+```
+
+If you want a column to not be orderable at all, just pass ```'orderable' => false```
+
+
+### Choose Where Columns are Visible
+
+Starting with Backpack\CRUD 3.5.0, you can choose to show/hide columns in different contexts. You can pass ```true``` / ```false``` to the column attributes below, and Backpack will know to show the column or not, in different contexts:
+
+```php
+$this->crud->addColumn([
+ 'name' => 'description',
+ 'visibleInTable' => false, // no point, since it's a large text
+ 'visibleInModal' => false, // would make the modal too big
+ 'visibleInExport' => false, // not important enough
+ 'visibleInShow' => true, // sure, why not
+]);
+```
+
+This also allows you to do tricky things like:
+- add a column that's hidden from the table view, but WILL get exported;
+- adding a column that's hidden everywhere, but searchable (even with a custom ```searchLogic```);
+
+
+### Multiple Columns With the Same Name
+
+Starting with Backpack\CRUD 3.3 (Nov 2017), you can have multiple columns with the same name, by specifying a unique ```key``` property. So if you want to use the same column name twice, you can do that. Notice below we have the same name for both columns, but one of them has a ```key```. This additional key will be used as an array key, if provided.
+
+```php
+// column that shows the parent's first name
+$this->crud->addColumn([
+ 'label' => "Parent First Name", // Table column heading
+ 'type' => "select",
+ 'name' => 'parent_id', // the column that contains the ID of that connected entity;
+ 'entity' => 'parent', // the method that defines the relationship in your Model
+ 'attribute' => "first_name", // foreign key attribute that is shown to user
+ 'model' => "App\Models\User", // foreign key model
+]);
+
+// column that shows the parent's last name
+$this->crud->addColumn([
+ 'label' => "Parent Last Name", // Table column heading
+ 'type' => "select",
+ 'name' => 'parent_id', // the column that contains the ID of that connected entity;
+ 'key' => 'parent_last_name', // the column that contains the ID of that connected entity;
+ 'entity' => 'parent', // the method that defines the relationship in your Model
+ 'attribute' => "last_name", // foreign key attribute that is shown to user
+ 'model' => "App\Models\User", // foreign key model
+]);
+```
+
+
+### Define which columns to show or hide in the responsive table
+
+By default, DataTables-responsive will try his best to show:
+- **the first column** (since that usually is the most important for the user, plus it holds the modal button and the details_row button so it's crucial for usability);
+- **the last column** (the actions column, where the action buttons reside);
+
+When giving priorities, lower is better. So a column with priority 4 will be hidden BEFORE a column with priority 2. The first and last columns have a priority of 1. You can define a different priority for a column using the ```priority``` attribute. For example:
+
+```php
+$this->crud->addColumn([
+ 'name' => 'details',
+ 'type' => 'text',
+ 'label' => 'Details',
+ 'priority' => 2,
+]);
+$this->crud->addColumn([
+ 'name' => 'obs',
+ 'type' => 'text',
+ 'label' => 'Observations',
+ 'priority' => 3,
+]);
+```
+In the example above, depending on how much space it's got in the viewport, DataTables will first hide the ```obs``` column, then ```details```, then the last column, then the first column.
+
+You can make the last column be less important (and hide) by giving it an unreasonable priority:
+
+```php
+$this->crud->setActionsColumnPriority(10000);
+```
+
+>Note that responsive tables adopt special behavior if the table is not able to show all columns. This includes displaying a vertical ellipsis to the left of the row, and making the row clickable to reveal more detail. This behavior is automatic and is not manually controllable via a field property.
diff --git a/4.0/crud-fields.md b/4.0/crud-fields.md
new file mode 100644
index 00000000..d8dca2fb
--- /dev/null
+++ b/4.0/crud-fields.md
@@ -0,0 +1,1757 @@
+# Fields
+
+---
+
+
+## About
+
+Field types define how the admin can manipulate an entry's values. They're used by the Create and Update operations.
+
+Think of the field type as the type of input: ``````. But for most entities, you won't just need text inputs - you'll need datepickers, upload buttons, 1-n relationship, n-n relationships, textareas, etc.
+
+We have a lot of default field types, detailed below. If you don't find what you're looking for, you can [create a custom field type](/docs/{{version}}/crud-fields#creating-a-custom-field-type). Or if you just want to tweak a default field type a little bit, you can [overwrite default field types](/docs/{{version}}/crud-fields#overwriting-default-field-types).
+
+
+### Mandatory Field Attributes
+
+For each of them, you only need to define it properly in the Controller. All field types will need at least three things:
+- the ```name``` of the column in the database (ex: "title")
+- the human-readable ```label``` for the input (ex: "Title")
+- the ```type``` of the input (ex: "text")
+
+So at minimum, your field definition array should look like:
+```php
+[
+ 'name' => 'description',
+ 'type' => 'textarea',
+ 'label' => 'Article Description',
+],
+```
+
+
+### Optional Field Attributes
+
+There are a few optional attributes on all default field types, that you can use to easily achieve a few common customizations:
+
+```php
+[
+ 'prefix' => '',
+ 'suffix' => '',
+ 'default' => 'some value', // set a default value
+ 'hint' => 'Some hint text', // helpful text, shows up after the input
+ 'attributes' => [
+ 'placeholder' => 'Some text when empty',
+ 'class' => 'form-control some-class',
+ 'readonly'=>'readonly',
+ 'disabled'=>'disabled',
+ ], // change the HTML attributes of your input
+ 'wrapperAttributes' => [
+ 'class' => 'form-group col-md-12'
+ ], // change the HTML attributes for the field wrapper - mostly for resizing fields
+]
+```
+
+These will help you:
+
+- **prefix** - add a text or icon _before_ the actual input;
+- **suffix** - add a text or icon _after_ the actual input;
+- **default** - specify a default value for the input, on create;
+- **hint** - add descriptive text for this input;
+- **attributes** - change or add actual HTML attributes of the input (ex: readonly, disabled, class, placeholder, etc);
+- **wrapperAttributes** - change or add actual HTML attributes to the div that contains the input;
+
+
+### Fields API
+
+To manipulate fields, you can use the methods below. The action will be performed on the currently running operation. So make sure you run these methods inside ```setupCreateOperation()```, ```setupUpdateOperation()``` or in ```setup()``` inside operation blocks:
+
+```php
+// add a field to both Create and Update operation
+$this->crud->addField($field_definition_array);
+
+// add a field only to the Update operation
+$this->crud->addField($field_definition_array);
+
+// shorthand: add a text field to both Create and Update operations
+$this->crud->addField('db_column_name');
+
+// add multiple fields
+$this->crud->addFields([$field_definition_array_1, $field_definition_array_2]);
+
+// change the attributes of a field
+$this->crud->modifyField($name, $modifs_array);
+
+// remove a field from both operations
+$this->crud->removeField('name');
+
+// remove multiple fields from both operations
+$this->crud->removeFields($array_of_names);
+
+// remove all fields from all operations
+$this->crud->removeAllFields();
+
+// FIELD ORDER
+
+// add a field before a given field
+$this->crud->addField($field_definition_array)->beforeField('name');
+
+// add a field after a given field
+$this->crud->addField($field_definition_array)->afterField('name');
+```
+
+
+### Extra Fields Features
+
+
+#### Fake Fields (all stored as JSON in the database)
+
+In case you want to store insignificant information for an entry that doesn't need a database column, you can add any number of Fake Fields, and all their information will be stored inside one column in the db, as JSON. By default, an ```extras``` column is assumed on the database table, but you can change that.
+
+**Step 1.** Use the fake attribute on your field:
+```php
+[
+ 'name' => 'name', // JSON variable name
+ 'label' => "Tag Name", // human-readable label for the input
+
+ 'fake' => true, // show the field, but don't store it in the database column above
+ 'store_in' => 'extras' // [optional] the database column name where you want the fake fields to ACTUALLY be stored as a JSON array
+],
+```
+
+**Step 2.** On your model, make sure the db columns where you store the JSONs (by default only ```extras```):
+- are in your ```$fillable``` property;
+- are on a new ```$fakeColumns``` property (create it now);
+- are casted as array in ```$casts```;
+
+>If you need your fakes to also be translatable, remember to also place ```extras``` in your model's ```$translatable``` property.
+
+Example:
+```php
+[
+ 'name' => 'meta_title',
+ 'label' => "Meta Title",
+ 'fake' => true,
+ 'store_in' => 'metas' // [optional]
+],
+[
+ 'name' => 'meta_description',
+ 'label' => "Meta Description",
+ 'fake' => true,
+ 'store_in' => 'metas' // [optional]
+],
+[
+ 'name' => 'meta_keywords',
+ 'label' => "Meta Keywords",
+ 'fake' => true,
+ 'store_in' => 'metas' // [optional]
+],
+```
+
+In this example, these 3 fields will show up in the create & update forms, the CRUD will process as usual, but in the database these values won't be stored in the ```meta_title```, ```meta_description``` and ```meta_keywords``` columns. They will be stored in the ```metas``` column as a JSON array:
+
+```php
+{"meta_title":"title","meta_description":"desc","meta_keywords":"keywords"}
+```
+
+If the ```store_in``` attribute wasn't used, they would have been stored in the ```extras``` column.
+
+
+#### Split Fields into Tabs
+
+You can now split your create/edit inputs into multiple tabs.
+
+
+
+In order to use this feature, you just need to specify the tab name for each of your fields. Example:
+
+```php
+// select_from_array
+$this->crud->addField([
+ 'name' => 'select_from_array',
+ 'label' => "Select from array",
+ 'type' => 'select_from_array',
+ 'options' => ['one' => 'One', 'two' => 'Two', 'three' => 'Three'],
+ 'allows_null' => false,
+ 'allows_multiple' => true,
+ 'tab' => 'Tab name here',
+]);
+```
+
+If you forget to specify a tab name for a field, Backpack will place it above all tabs.
+
+
+
+## Default Field Types
+
+
+### address_algolia
+
+Use [Algolia Places autocomplete](https://community.algolia.com/places/) to help users type their address faster. With the ```store_as_json``` option, it will store the address, postcode, city, country, latitude and longitude in a JSON in the database. Without it, it will just store the address string.
+
+```php
+[ // Address
+ 'name' => 'address',
+ 'label' => 'Address',
+ 'type' => 'address_algolia',
+ // optional
+ 'store_as_json' => true
+],
+```
+
+> **Use attribute casting.** For information stored as JSON in the database, it's recommended that you use [attribute casting](https://mattstauffer.co/blog/laravel-5.0-eloquent-attribute-casting) to ```array``` or ```object```. That way, every time you get the info from the database you'd get it in a usable format.
+
+
+Input preview:
+
+
+
+
+### address_google
+
+Use [Google Places Search](https://developers.google.com/places/web-service/search) to help users type their address faster. With the ```store_as_json``` option, it will store the address, postcode, city, country, latitude and longitude in a JSON in the database. Without it, it will just store the complete address string.
+
+```php
+[ // Address
+ 'name' => 'address',
+ 'label' => 'Address',
+ 'type' => 'address_google',
+ // optional
+ 'store_as_json' => true
+],
+```
+
+Using Google Places API is dependent on using an API Key. Please [get an API key](https://console.cloud.google.com/apis/credentials) - you do have to configure billing, but you qualify for $200/mo free usage, which covers most use cases. Then copy-paste that key as your ```services.google_places.key``` value. So inside your ```config/services.php``` please add the items below:
+
+```php
+ 'google_places' => [
+ 'key' => 'the-key-you-got-from-google-places'
+ ],
+```
+
+> **Use attribute casting.** For information stored as JSON in the database, it's recommended that you use [attribute casting](https://mattstauffer.co/blog/laravel-5.0-eloquent-attribute-casting) to ```array``` or ```object```. That way, every time you get the info from the database you'd get it in a usable format. Also, it is heavily recommended that your database column can hold a large JSON - so use `text` rather than `string` in your migration (in MySQL this translates to `text` instead of `varchar`).
+
+Input preview:
+
+
+
+
+### browse
+
+If you've chosen to use [elFinder](http://elfinder.org/) upon Backpack installation, this button allows the admin to open [elFinder](http://elfinder.org/) and select a file from there.
+
+```php
+[ // Browse
+ 'name' => 'image',
+ 'label' => 'Image',
+ 'type' => 'browse'
+],
+```
+
+
+Input preview:
+
+
+
+Onclick preview:
+
+
+
+
+### browse_multiple
+
+Open elFinder and select multiple files from there.
+
+```php
+[ // Browse multiple
+ 'name' => 'files',
+ 'label' => 'Files',
+ 'type' => 'browse_multiple',
+ // 'multiple' => true, // enable/disable the multiple selection functionality
+ // 'sortable' => false, // enable/disable the reordering of chosen files with drag&drop
+ // 'mime_types' => null, // visible mime prefixes; ex. ['image'] or ['application/pdf']
+],
+```
+
+The field assumes you've cast your attribute as ```array``` on your model. That way, when you do ```$entry->files``` you get a nice array.
+
+Input preview:
+
+
+
+
+### base64_image
+
+Upload an image and store it in the database as Base64. Notes:
+- make sure the column type is LONGBLOB;
+- detailed [instructions and customizations here](https://github.com/Laravel-Backpack/CRUD/pull/56#issue-164712261);
+
+```php
+// base64_image
+$this->crud->addField([
+ 'label' => "Profile Image",
+ 'name' => "image",
+ 'filename' => "image_filename", // set to null if not needed
+ 'type' => 'base64_image',
+ 'aspect_ratio' => 1, // set to 0 to allow any aspect ratio
+ 'crop' => true, // set to true to allow cropping, false to disable
+ 'src' => NULL, // null to read straight from DB, otherwise set to model accessor function
+]);
+```
+
+Input preview:
+
+
+
+
+### checkbox
+
+Checkbox for true/false.
+
+```php
+[ // Checkbox
+ 'name' => 'active',
+ 'label' => 'Active',
+ 'type' => 'checkbox'
+],
+```
+
+Input preview:
+
+
+
+
+### checklist
+
+```php
+[
+ 'label' => 'Roles',
+ 'type' => 'checklist',
+ 'name' => 'roles',
+ 'entity' => 'roles',
+ 'attribute' => 'name',
+ 'model' => "Backpack\PermissionManager\app\Models\Role",
+ 'pivot' => true,
+]);
+```
+
+Input preview:
+
+
+
+
+### checklist_dependency
+
+```php
+
+// two interconnected entities
+'label' => 'User Role Permissions',
+'field_unique_name' => 'user_role_permission',
+'type' => 'checklist_dependency',
+'name' => ['roles', 'permissions'], // the methods that define the relationship in your Models
+'subfields' => [
+ 'primary' => [
+ 'label' => 'Roles',
+ 'name' => 'roles', // the method that defines the relationship in your Model
+ 'entity' => 'roles', // the method that defines the relationship in your Model
+ 'entity_secondary' => 'permissions', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'model' => "Backpack\PermissionManager\app\Models\Role", // foreign key model
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?]
+ 'number_columns' => 3, //can be 1,2,3,4,6
+ ],
+ 'secondary' => [
+ 'label' => 'Permission',
+ 'name' => 'permissions', // the method that defines the relationship in your Model
+ 'entity' => 'permissions', // the method that defines the relationship in your Model
+ 'entity_primary' => 'roles', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'model' => "Backpack\PermissionManager\app\Models\Permission", // foreign key model
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?]
+ 'number_columns' => 3, //can be 1,2,3,4,6
+ ],
+ ],
+],
+```
+
+Input preview:
+
+
+
+
+### ckeditor
+
+Show a wysiwyg CKEditor to the user.
+
+```php
+[ // CKEditor
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'ckeditor',
+ // optional:
+ 'extra_plugins' => ['oembed', 'widget']
+ 'options' => [
+ 'autoGrow_minHeight' => 200,
+ 'autoGrow_bottomSpace' => 50,
+ 'removePlugins' => 'resize,maximize',
+ ]
+],
+```
+
+Input preview:
+
+
+
+
+### color
+
+```php
+[ // Color
+ 'name' => 'background_color',
+ 'label' => 'Background Color',
+ 'type' => 'color',
+ 'default' => '#000000',
+],
+```
+
+Input preview:
+
+
+
+
+### color_picker
+
+Show a pretty colour picker using [Bootstrap Colorpicker](https://itsjavi.com/bootstrap-colorpicker/).
+
+```php
+[ // color_picker
+ 'label' => 'Background Color',
+ 'name' => 'background_color',
+ 'type' => 'color_picker',
+ 'default' => '#000000',
+ 'color_picker_options' => ['customClass' => 'custom-class']
+]
+```
+
+Input preview:
+
+
+
+
+### custom_html
+
+Allows you to insert custom HTML in the create/update forms. Usually used in forms with a lot of fields, to separate them using h1-h5, hr, etc, but can be used for any HTML.
+
+```php
+[ // CustomHTML
+ 'name' => 'separator',
+ 'type' => 'custom_html',
+ 'value' => ''
+],
+```
+
+
+### date
+
+```php
+[ // Date
+ 'name' => 'birthday',
+ 'label' => 'Birthday',
+ 'type' => 'date'
+],
+```
+
+Input preview:
+
+
+
+
+### date_picker
+
+Show a pretty [Bootstrap Datepicker](http://bootstrap-datepicker.readthedocs.io/en/latest/).
+
+```php
+[ // date_picker
+ 'name' => 'date',
+ 'type' => 'date_picker',
+ 'label' => 'Date',
+ // optional:
+ 'date_picker_options' => [
+ 'todayBtn' => 'linked',
+ 'format' => 'dd-mm-yyyy',
+ 'language' => 'fr'
+ ],
+],
+```
+
+Please note it is recommended that you use [attribute casting](https://laravel.com/docs/5.3/eloquent-mutators#attribute-casting) on your model (cast to date).
+
+
+Input preview:
+
+
+
+
+### date_range
+
+Starting with Backpack\CRUD 3.1.59
+
+Show a DateRangePicker and let the user choose a start date and end date.
+
+```php
+[ // date_range
+ 'name' => ['start_date', 'end_date'], // db columns for start_date & end_date
+ 'label' => 'Event Date Range',
+ 'type' => 'date_range',
+ // OPTIONALS
+ 'default' => ['2019-03-28 01:01', '2019-04-05 02:00'], // default values for start_date & end_date
+ 'date_range_options' => [
+ // options sent to daterangepicker.js
+ 'timePicker' => true,
+ 'locale' => ['format' => 'DD/MM/YYYY HH:mm']
+ ]
+],
+```
+
+Please note it is recommended that you use [attribute casting](https://laravel.com/docs/5.3/eloquent-mutators#attribute-casting) on your model (cast to date).
+
+Your end result will look like this:
+
+Input preview:
+
+
+
+
+### datetime
+
+```php
+[ // DateTime
+ 'name' => 'start',
+ 'label' => 'Event start',
+ 'type' => 'datetime'
+],
+```
+
+**Please note:** if you're using datetime [attribute casting](https://laravel.com/docs/5.3/eloquent-mutators#attribute-casting) on your model, you also need to place this mutator inside your model:
+```php
+ public function setDatetimeAttribute($value) {
+ $this->attributes['datetime'] = \Date::parse($value);
+ }
+```
+Otherwise the input's datetime-local format will cause some errors.
+
+Input preview:
+
+
+
+
+### datetime_picker
+
+Show a [Bootstrap Datetime Picker](https://eonasdan.github.io/bootstrap-datetimepicker/).
+
+```php
+[ // DateTime
+ 'name' => 'start',
+ 'label' => 'Event start',
+ 'type' => 'datetime_picker',
+ // optional:
+ 'datetime_picker_options' => [
+ 'format' => 'DD/MM/YYYY HH:mm',
+ 'language' => 'fr'
+ ],
+ 'allows_null' => true,
+ // 'default' => '2017-05-12 11:59:59',
+],
+```
+
+**Please note:** if you're using date [attribute casting](https://laravel.com/docs/5.3/eloquent-mutators#attribute-casting) on your model, you may also need to place this mutator inside your model:
+```php
+ public function setDatetimeAttribute($value) {
+ $this->attributes['datetime'] = \Date::parse($value);
+ }
+```
+Otherwise the input's datetime-local format will cause some errors. Remember to change "datetime" with the name of your attribute (column name).
+
+Input preview:
+
+
+
+
+### email
+
+```php
+[ // Email
+ 'name' => 'email',
+ 'label' => 'Email Address',
+ 'type' => 'email'
+],
+```
+
+Input preview:
+
+
+
+
+
+### enum
+
+Show a select with the values in the database for that ENUM field. Requires that the db column type is "enum". If the db column allows null, the " - " value will also show up in the select.
+
+```php
+[ // Enum
+ 'name' => 'status',
+ 'label' => 'Status',
+ 'type' => 'enum'
+],
+```
+
+PLEASE NOTE the enum field only works for MySQL databases.
+
+Input preview:
+
+
+
+
+### hidden
+
+Include an in the form.
+
+```php
+[ // Hidden
+ 'name' => 'status',
+ 'type' => 'hidden'
+],
+```
+
+
+### icon_picker
+
+Show an icon picker. Supported icon sets are fontawesome, glyphicon, ionicon, weathericon, mapicon, octicon, typicon, elusiveicon, materialdesign as per the jQuery plugin, [bootstrap-iconpicker](http://victor-valencia.github.io/bootstrap-iconpicker/).
+
+The stored value will be the class name (ex: fa-home).
+
+```php
+[ // icon_picker
+ 'label' => "Icon",
+ 'name' => 'icon',
+ 'type' => 'icon_picker',
+ 'iconset' => 'fontawesome' // options: fontawesome, glyphicon, ionicon, weathericon, mapicon, octicon, typicon, elusiveicon, materialdesign
+],
+```
+
+Your input will look like button, with a dropdown where the user can search or pick an icon:
+
+Input preview:
+
+
+
+
+### image
+
+Upload an image and store it on the disk.
+
+**Step 1.** Show the field.
+```php
+// image
+$this->crud->addField([
+ 'label' => "Profile Image",
+ 'name' => "image",
+ 'type' => 'image',
+ 'upload' => true,
+ 'crop' => true, // set to true to allow cropping, false to disable
+ 'aspect_ratio' => 1, // omit or set to 0 to allow any aspect ratio
+ // 'disk' => 's3_bucket', // in case you need to show images from a different disk
+ // 'prefix' => 'uploads/images/profile_pictures/' // in case your db value is only the file name (no path), you can use this to prepend your path to the image src (in HTML), before it's shown to the user;
+]);
+```
+
+**Step 2.** Set a mutator on your Model, so that the file can be stored. You can use this boilerplate code and modify it to match your use case:
+
+```php
+// ..
+
+use Illuminate\Support\Str;
+
+// ..
+
+Class Product extends Model
+{
+ // ..
+
+ public function setImageAttribute($value)
+ {
+ $attribute_name = "image";
+ $disk = config('backpack.base.root_disk_name'); // or use your own disk, defined in config/filesystems.php
+ $destination_path = "public/uploads/folder_1/folder_2"; // path relative to the disk above
+
+ // if the image was erased
+ if ($value==null) {
+ // delete the image from disk
+ \Storage::disk($disk)->delete($this->{$attribute_name});
+
+ // set null in the database column
+ $this->attributes[$attribute_name] = null;
+ }
+
+ // if a base64 was sent, store it in the db
+ if (starts_with($value, 'data:image'))
+ {
+ // 0. Make the image
+ $image = \Image::make($value)->encode('jpg', 90);
+
+ // 1. Generate a filename.
+ $filename = md5($value.time()).'.jpg';
+
+ // 2. Store the image on disk.
+ \Storage::disk($disk)->put($destination_path.'/'.$filename, $image->stream());
+
+ // 3. Delete the previous image, if there was one.
+ \Storage::disk($disk)->delete($this->{$attribute_name});
+
+ // 4. Save the public path to the database
+ // but first, remove "public/" from the path, since we're pointing to it from the root folder
+ // that way, what gets saved in the database is the user-accesible URL
+ $public_destination_path = Str::replaceFirst('public/', '', $destination_path);
+ $this->attributes[$attribute_name] = $public_destination_path.'/'.$filename;
+
+ }
+ }
+
+// ..
+```
+> **The uploaded images are not deleted for you.** If you delete an entry (using the CRUD or anywhere inside your app), the image file won't be deleted from the disk.
+> If you're NOT using soft deletes on that Model and want the image to be deleted at the same time the entry is, just specify that in your Model's ```deleting``` event:
+> ```php
+ public static function boot()
+ {
+ parent::boot();
+ static::deleting(function($obj) {
+ \Storage::disk('public_folder')->delete($obj->image);
+ });
+ }
+ ```
+
+**A note about aspect_ratio**
+The value for aspect ratio is a float that represents the ratio of the cropping rectangle height and width. By way of example,
+
+- Square = 1
+- Landscape = 2
+- Portrait = 0.5
+
+And you can, of course, use any value for more extreme rectangles.
+
+Input preview:
+
+
+
+
+
+### month
+
+```php
+[ // Month
+ 'name' => 'month',
+ 'label' => 'Month',
+ 'type' => 'month'
+],
+```
+
+Input preview:
+
+
+
+
+### number
+
+Shows an input type=number to the user, with optional prefix and suffix:
+
+```php
+[ // Number
+ 'name' => 'number',
+ 'label' => 'Number',
+ 'type' => 'number',
+ // optionals
+ // 'attributes' => ["step" => "any"], // allow decimals
+ // 'prefix' => "$",
+ // 'suffix' => ".00",
+],
+```
+
+Input preview:
+
+
+
+
+### page_or_link
+
+Select an existing page from PageManager or an internal or external link. It's used in the MenuManager package, but can be used in any other model just as well. Its definition looks like this:
+```php
+[ // PageOrLink
+ 'name' => 'type',
+ 'label' => "Type",
+ 'type' => 'page_or_link',
+ 'page_model' => '\Backpack\PageManager\app\Models\Page'
+],
+```
+
+Input preview:
+
+
+
+
+### password
+
+```php
+[ // Password
+ 'name' => 'password',
+ 'label' => 'Password',
+ 'type' => 'password'
+],
+```
+
+Input preview:
+
+
+
+
+Please note that this will NOT hash/encrypt the string before it stores it to the database. You need to hash the password manually. The most popular way to do that are:
+
+1. Using [a mutator on your Model](https://laravel.com/docs/7.x/eloquent-mutators#defining-a-mutator). For example:
+
+```php
+public function setPasswordAttribute($value) {
+ $this->attributes['password'] = Hash::make($value);
+}
+```
+
+2. By overwriting the Create/Update operation methods, inside the Controller. There's a working example [in our PermissionManager package](https://github.com/Laravel-Backpack/PermissionManager/blob/master/src/app/Http/Controllers/UserCrudController.php#L103-L124) but the gist of it is this:
+
+```php
+ use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation { store as traitStore; }
+
+ public function store()
+ {
+ $this->crud->request = $this->crud->validateRequest();
+
+ // Encrypt password if specified.
+ if ($request->input('password')) {
+ $request->request->set('password', Hash::make($request->input('password')));
+ } else {
+ $request->request->remove('password');
+ }
+
+ return $this->traitStore();
+ }
+```
+
+
+### radio
+
+Show radios according to an associative array you give the input and let the user pick from them. You can choose for the radio options to be displayed inline or one-per-line.
+
+```php
+[ // radio
+ 'name' => 'status', // the name of the db column
+ 'label' => 'Status', // the input label
+ 'type' => 'radio',
+ 'options' => [
+ // the key will be stored in the db, the value will be shown as label;
+ 0 => "Draft",
+ 1 => "Published"
+ ],
+ // optional
+ //'inline' => false, // show the radios all on the same line?
+],
+```
+
+Input preview:
+
+
+
+
+### range
+
+```php
+[ // Range
+ 'name' => 'range',
+ 'label' => 'Range',
+ 'type' => 'range'
+],
+```
+
+Input preview:
+
+
+
+
+### select (1-n relationship)
+
+Show a Select with the names of the connected entity and let the user select one of them.
+Your relationships should already be defined on your models as hasOne() or belongsTo().
+
+```php
+[ // Select
+ 'label' => "Category",
+ 'type' => 'select',
+ 'name' => 'category_id', // the db column for the foreign key
+ 'entity' => 'category', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+
+
+ // optional
+ 'model' => "App\Models\Category",
+ 'options' => (function ($query) {
+ return $query->orderBy('name', 'ASC')->where('depth', 1)->get();
+ }), // force the related options to be a custom query, instead of all(); you can use this to filter the results show in the select
+],
+```
+
+Input preview:
+
+
+
+
+
+### select_grouped
+
+Display a select where the options are grouped by a second entity (like Categories).
+
+```php
+[ // select_grouped
+ 'label' => 'Articles grouped by categories',
+ 'type' => 'select_grouped', //https://github.com/Laravel-Backpack/CRUD/issues/502
+ 'name' => 'article_id',
+ 'entity' => 'article',
+ 'attribute' => 'title',
+ 'group_by' => 'category', // the relationship to entity you want to use for grouping
+ 'group_by_attribute' => 'name', // the attribute on related model, that you want shown
+ 'group_by_relationship_back' => 'articles', // relationship from related model back to this model
+],
+```
+
+Input preview:
+
+
+
+
+### select2 (1-n relationship)
+
+Works just like the SELECT field, but prettier. Shows a Select2 with the names of the connected entity and let the user select one of them.
+Your relationships should already be defined on your models as hasOne() or belongsTo().
+
+```php
+[ // Select2
+ 'label' => "Category",
+ 'type' => 'select2',
+ 'name' => 'category_id', // the db column for the foreign key
+ 'entity' => 'category', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+
+ // optional
+ 'model' => "App\Models\Category", // foreign key model
+ 'default' => 2, // set the default value of the select2
+ 'options' => (function ($query) {
+ return $query->orderBy('name', 'ASC')->where('depth', 1)->get();
+ }), // force the related options to be a custom query, instead of all(); you can use this to filter the results show in the select
+],
+```
+
+Input preview:
+
+
+
+
+### select_multiple (n-n relationship)
+
+Show a Select with the names of the connected entity and let the user select any number of them.
+Your relationships should already be defined on your models as hasMany() or belongsToMany().
+
+```php
+[ // SelectMultiple = n-n relationship (with pivot table)
+ 'label' => "Tags",
+ 'type' => 'select_multiple',
+ 'name' => 'tags', // the method that defines the relationship in your Model
+ 'entity' => 'tags', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
+
+ // optional
+ 'model' => "App\Models\Tag", // foreign key model
+ 'options' => (function ($query) {
+ return $query->orderBy('name', 'ASC')->where('depth', 1)->get();
+ }), // force the related options to be a custom query, instead of all(); you can use this to filter the results show in the select
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### select2_multiple (n-n relationship)
+
+[Works just like the SELECT field, but prettier]
+
+Shows a Select2 with the names of the connected entity and let the user select any number of them.
+Your relationships should already be defined on your models as hasMany() or belongsToMany().
+
+```php
+[ // Select2Multiple = n-n relationship (with pivot table)
+ 'label' => "Tags",
+ 'type' => 'select2_multiple',
+ 'name' => 'tags', // the method that defines the relationship in your Model
+ 'entity' => 'tags', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
+ // 'select_all' => true, // show Select All and Clear buttons?
+
+ // optional
+ 'model' => "App\Models\Tag", // foreign key model
+ 'options' => (function ($query) {
+ return $query->orderBy('name', 'ASC')->where('depth', 1)->get();
+ }), // force the related options to be a custom query, instead of all(); you can use this to filter the results show in the select
+],
+```
+
+Input preview:
+
+
+
+
+### select2_nested
+
+Display a select2 with the values ordered hierarchically and indented, for an entity where you use Reorder. Please mind that the connected model needs:
+- a ```children()``` relationship pointing to itself;
+- the usual ```lft```, ```rgt```, ```depth``` attributes;
+
+```php
+[ // select2_nested
+ 'name' => 'category_id',
+ 'label' => "Category",
+ 'type' => 'select2_nested',
+ 'entity' => 'category', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+
+ // optional
+ 'model' => "App\Models\Category", // force foreign key model
+],
+```
+
+Input preview:
+
+
+
+
+
+### select2_grouped
+
+Display a select2 where the options are grouped by a second entity (like Categories).
+
+```php
+[ // select2_grouped
+ 'label' => 'Articles grouped by categories',
+ 'type' => 'select2_grouped', //https://github.com/Laravel-Backpack/CRUD/issues/502
+ 'name' => 'article_id',
+ 'entity' => 'article', // the method that defines the relationship in your Model
+ 'attribute' => 'title',
+ 'group_by' => 'category', // the relationship to entity you want to use for grouping
+ 'group_by_attribute' => 'name', // the attribute on related model, that you want shown
+ 'group_by_relationship_back' => 'articles', // relationship from related model back to this model
+],
+```
+
+Input preview:
+
+
+
+
+
+### select_and_order
+
+Display items on two columns and let the user drag&drop between them to choose which items are selected and which are not, and reorder the selected items with drag&drop.
+
+Its definition is exactly as ```select_from_array```, but the value will be stored as JSON in the database: ```["3","5","7","6"]```, so it needs the attribute to be cast to array on the Model:
+
+```php
+protected $casts = [
+ 'featured' => 'array'
+];
+```
+
+Definition:
+
+```php
+[ // select_and_order
+ 'name' => 'featured',
+ 'label' => "Featured",
+ 'type' => 'select_and_order',
+ 'options' => [
+ 1 => "Option 1",
+ 2 => "Option 2"
+ ]
+],
+```
+
+Also possible:
+
+```php
+[ // select_and_order
+ 'name' => 'featured',
+ 'label' => 'Featured',
+ 'type' => 'select_and_order',
+ 'options' => Product::get()->pluck('title','id')->toArray(),
+],
+```
+
+Input preview:
+
+
+
+
+
+### select_from_array
+
+Display a select with the values you want:
+
+```php
+[ // select_from_array
+ 'name' => 'template',
+ 'label' => "Template",
+ 'type' => 'select_from_array',
+ 'options' => ['one' => 'One', 'two' => 'Two'],
+ 'allows_null' => false,
+ 'default' => 'one',
+ // 'allows_multiple' => true, // OPTIONAL; needs you to cast this to array in your model;
+],
+```
+
+Input preview:
+
+
+
+
+### select2_from_array
+
+Display a select2 with the values you want:
+
+```php
+[ // select2_from_array
+ 'name' => 'template',
+ 'label' => "Template",
+ 'type' => 'select2_from_array',
+ 'options' => ['one' => 'One', 'two' => 'Two'],
+ 'allows_null' => false,
+ 'default' => 'one',
+ // 'allows_multiple' => true, // OPTIONAL; needs you to cast this to array in your model;
+],
+```
+
+Input preview:
+
+
+
+
+### select2_from_ajax
+
+Display a select2 that takes its values from an AJAX call.
+
+```
+[
+ // 1-n relationship
+ 'label' => "End", // Table column heading
+ 'type' => "select2_from_ajax",
+ 'name' => 'category_id', // the column that contains the ID of that connected entity
+ 'entity' => 'category', // the method that defines the relationship in your Model
+ 'attribute' => "name", // foreign key attribute that is shown to user
+ 'data_source' => url("http://github.com/api/category"), // url to controller search function (with /{id} should return model)
+
+ // OPTIONAL
+ // 'placeholder' => "Select a category", // placeholder for the select
+ // 'minimum_input_length' => 2, // minimum characters to type before querying results
+ // 'model' => "App\Models\Category", // foreign key model
+ // 'dependencies' => ['category'], // when a dependency changes, this select2 is reset to null
+ // 'method' => 'GET', // optional - HTTP method to use for the AJAX call (GET, POST)
+ // 'include_all_form_fields' => false, // optional - only send the current field through AJAX (for a smaller payload if you're not using multiple chained select2s)
+ ]
+```
+
+Of course, you also need to create a controller and routes for the data_source above. Here's an example:
+
+```
+Route::get('/api/category', 'Api\CategoryController@index');
+Route::get('/api/category/{id}', 'Api\CategoryController@show');
+```
+
+```
+input('q');
+ $page = $request->input('page');
+
+ if ($search_term)
+ {
+ $results = Category::where('name', 'LIKE', '%'.$search_term.'%')->paginate(10);
+ }
+ else
+ {
+ $results = Category::paginate(10);
+ }
+
+ return $results;
+ }
+
+ public function show($id)
+ {
+ return Category::find($id);
+ }
+}
+```
+
+Input preview:
+
+
+
+
+### select2_from_ajax_multiple
+
+Display a select2 that takes its values from an AJAX call. Same as [select2_from_ajax](#section-select2_from_ajax) above, but allows for multiple items to be selected. The only difference in the field definition is the "pivot" attribute.
+
+```
+[
+ // n-n relationship
+ 'label' => "Cities", // Table column heading
+ 'type' => "select2_from_ajax_multiple",
+ 'name' => 'cities', // a unique identifier (usually the method that defines the relationship in your Model)
+ 'entity' => 'cities', // the method that defines the relationship in your Model
+ 'attribute' => "name", // foreign key attribute that is shown to user
+ 'data_source' => url("http://github.com/api/cities"), // url to controller search function (with /{id} should return model)
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
+
+ // OPTIONAL
+ 'model' => "App\Models\City", // foreign key model
+ 'placeholder' => "Select a city", // placeholder for the select
+ 'minimum_input_length' => 2, // minimum characters to type before querying results
+ // 'include_all_form_fields' => false, // optional - only send the current field through AJAX (for a smaller payload if you're not using multiple chained select2s)
+ ]
+```
+
+Of course, you also need to create a controller and routes for the data_source above. Here's an example:
+
+```
+Route::get('/api/category', 'Api\CityController@index');
+Route::get('/api/category/{id}', 'Api\CityController@show');
+```
+
+```
+input('q');
+ $page = $request->input('page');
+
+ if ($search_term)
+ {
+ $results = City::where('name', 'LIKE', '%'.$search_term.'%')->paginate(10);
+ }
+ else
+ {
+ $results = City::paginate(10);
+ }
+
+ return $results;
+ }
+
+ public function show($id)
+ {
+ return City::find($id);
+ }
+}
+```
+
+Input preview:
+
+
+
+
+### simplemde
+
+Show a [SimpleMDE markdown editor](https://simplemde.com/) to the user.
+
+```php
+[ // SimpleMDE
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'simplemde',
+ // optional
+ // 'simplemdeAttributes' => [
+ // 'promptURLs' => true,
+ // 'status' => false,
+ // 'spellChecker' => false,
+ // 'forceSync' => true,
+ // ],
+ // 'simplemdeAttributesRaw' => $some_json
+],
+```
+
+Input preview:
+
+
+
+
+### summernote
+
+Show a [Summernote wysiwyg editor](http://summernote.org/) to the user.
+
+```php
+[ // Summernote
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'summernote',
+ // 'options' => [], // easily pass parameters to the summernote JS initialization
+],
+```
+
+Input preview:
+
+
+
+
+### table
+
+Show a table with multiple inputs per row and store the values as JSON in the database. The user can add more rows and reorder the rows as they please.
+
+```php
+[ // Table
+ 'name' => 'options',
+ 'label' => 'Options',
+ 'type' => 'table',
+ 'entity_singular' => 'option', // used on the "Add X" button
+ 'columns' => [
+ 'name' => 'Name',
+ 'desc' => 'Description',
+ 'price' => 'Price'
+ ],
+ 'max' => 5, // maximum rows allowed in the table
+ 'min' => 0, // minimum rows allowed in the table
+],
+```
+
+>It's highly recommended that you use [attribute casting](https://mattstauffer.co/blog/laravel-5.0-eloquent-attribute-casting) on your model when working with JSON stored in database columns, and cast your this attribute to either ```object``` or ```array```.
+
+Input preview:
+
+
+
+
+### text
+
+The basic field type, all it needs is the two mandatory parameters: name and label.
+
+```php
+[ // Text
+ 'name' => 'title',
+ 'label' => "Title",
+ 'type' => 'text',
+
+ // optional
+ //'prefix' => '',
+ //'suffix' => '',
+ //'default' => 'some value', // default value
+ //'hint' => 'Some hint text', // helpful text, show up after input
+ //'attributes' => [
+ //'placeholder' => 'Some text when empty',
+ //'class' => 'form-control some-class'
+ //], // extra HTML attributes and values your input might need
+ //'wrapperAttributes' => [
+ //'class' => 'form-group col-md-12'
+ //], // extra HTML attributes for the field wrapper - mostly for resizing fields
+ //'readonly'=>'readonly',
+],
+```
+
+You can use the optional 'prefix' and 'suffix' attributes to display something before and after the input, like icons, path prefix, etc:
+
+Input preview:
+
+
+
+
+### textarea
+
+Show a textarea to the user.
+
+```php
+[ // Textarea
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'textarea'
+],
+```
+
+Input preview:
+
+
+
+
+### time
+
+```php
+[ // Time
+ 'name' => 'start',
+ 'label' => 'Start time',
+ 'type' => 'time'
+],
+```
+
+
+### tinymce
+
+Show a wysiwyg (TinyMCE) to the user.
+
+```php
+[ // TinyMCE
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'tinymce',
+ // optional overwrite of the configuration array
+ // 'options' => [ 'selector' => 'textarea.tinymce', 'skin' => 'dick-light', 'plugins' => 'image,link,media,anchor' ],
+],
+```
+
+Input preview:
+
+
+
+
+### upload
+
+**Step 1.** Show a file input to the user:
+```php
+[ // Upload
+ 'name' => 'image',
+ 'label' => 'Image',
+ 'type' => 'upload',
+ 'upload' => true,
+ 'disk' => 'uploads', // if you store files in the /public folder, please omit this; if you store them in /storage or S3, please specify it;
+ // optional:
+ 'temporary' => 10 // if using a service, such as S3, that requires you to make temporary URLs this will make a URL that is valid for the number of minutes specified
+],
+```
+
+**Step 2.** In order to save/update/delete the file from disk&db, we need to create [a mutator](https://laravel.com/docs/5.3/eloquent-mutators#defining-a-mutator) on your model:
+```php
+public function setImageAttribute($value)
+ {
+ $attribute_name = "image";
+ $disk = "public";
+ $destination_path = "folder_1/subfolder_1";
+
+ $this->uploadFileToDisk($value, $attribute_name, $disk, $destination_path);
+
+ // return $this->attributes[{$attribute_name}]; // uncomment if this is a translatable field
+ }
+```
+
+**How it works:**
+
+The field sends the file, through a Request, to the Controller. The Controller then tries to create/update the Model. That's when the mutator on your model will run. That also means we can do any [file validation](https://laravel.com/docs/5.3/validation#rule-file) (```file```, ```image```, ```mimetypes```, ```mimes```) in the Request, before the file is stored on the disk.
+
+>NOTE: If this field is mandatory (required in validation) please use the [sometimes laravel validation rule](https://laravel.com/docs/5.8/validation#conditionally-adding-rules) together with **required** in your validation. (sometimes|required|file etc... )
+
+[The ```uploadFileToDisk()``` method](https://github.com/Laravel-Backpack/CRUD/blob/master/src/CrudTrait.php#L108-L129) will take care of everything for most use cases:
+
+```php
+/**
+ * Handle file upload and DB storage for a file:
+ * - on CREATE
+ * - stores the file at the destination path
+ * - generates a name
+ * - stores the full path in the DB;
+ * - on UPDATE
+ * - if the value is null, deletes the file and sets null in the DB
+ * - if the value is different, stores the different file and updates DB value
+ * /
+public function uploadFileToDisk($value, $attribute_name, $disk, $destination_path) {}
+```
+
+If you wish to have a different functionality, you can delete the method call from your mutator and do your own thing.
+
+>**The uploaded files are not deleted for you.** When you delete an entry (whether through CRUD or the application), the uploaded files will not be deleted.
+
+If you're NOT using soft deletes on that Model and want the file to be deleted at the same time the entry is, just specify that in your Model's ```deleting``` event:
+```php
+ public static function boot()
+ {
+ parent::boot();
+ static::deleting(function($obj) {
+ \Storage::disk('public_folder')->delete($obj->image);
+ });
+ }
+```
+
+Input preview:
+
+
+
+
+### upload_multiple
+
+Shows a multiple file input to the user and stores the values as a JSON array in the database.
+
+**Step 0.** Make sure the db column can hold the amount of text this field will have. For example, for MySQL, VARCHAR(255) might not be enough all the time (for 3+ files), so it's better to go with TEXT. Make sure you're using a big column type in your migration or db.
+
+**Step 1.** Show a multiple file input to the user:
+```php
+[ // Upload
+ 'name' => 'photos',
+ 'label' => 'Photos',
+ 'type' => 'upload_multiple',
+ 'upload' => true,
+ 'disk' => 'uploads', // if you store files in the /public folder, please omit this; if you store them in /storage or S3, please specify it;
+ // optional:
+ 'temporary' => 10 // if using a service, such as S3, that requires you to make temporary URLs this will make a URL that is valid for the number of minutes specified
+],
+```
+
+**Step 2.** In order to save/update/delete the files from disk&db, we need to create [a mutator](https://laravel.com/docs/5.3/eloquent-mutators#defining-a-mutator) on your model:
+```php
+public function setPhotosAttribute($value)
+ {
+ $attribute_name = "photos";
+ $disk = "public";
+ $destination_path = "folder_1/subfolder_1";
+
+ $this->uploadMultipleFilesToDisk($value, $attribute_name, $disk, $destination_path);
+ }
+```
+
+**Step 3.** Since the filenames are stored in the database as a JSON array, we're going to use [attribute casting](https://laravel.com/docs/5.3/eloquent-mutators#attribute-casting) on your model, so every time we get the filenames array from the database it's converted from a JSON array to a PHP array:
+```php
+ protected $casts = [
+ 'photos' => 'array'
+ ];
+```
+
+**How it works:**
+
+The field sends the files, through a Request, to the Controller. The Controller then tries to create/update the Model. That's when the mutator on your model will run. That also means we can do any [file validation](https://laravel.com/docs/5.3/validation#rule-file) (```file```, ```image```, ```mimetypes```, ```mimes```) in the Request, before the files are stored on the disk.
+
+[The ```uploadMultipleFilesToDisk()``` method](https://github.com/Laravel-Backpack/CRUD/blob/master/src/CrudTrait.php#L154-L189) will take care of everything for most use cases:
+
+```
+/**
+ * Handle multiple file upload and DB storage:
+ * - if files are sent
+ * - stores the files at the destination path
+ * - generates random names
+ * - stores the full path in the DB, as JSON array;
+ * - if a hidden input is sent to clear one or more files
+ * - deletes the file
+ * - removes that file from the DB.
+ * /
+public function uploadMultipleFilesToDisk($value, $attribute_name, $disk, $destination_path) {}
+```
+
+If you wish to have a different functionality, you can delete the method call from your mutator and do your own thing.
+
+>**The uploaded files are not deleted for you.** When you delete an entry (whether through CRUD or the application), the uploaded files will not be deleted.
+
+If you're NOT using soft deletes on that Model and want the files to be deleted at the same time the entry is, just specify that in your Model's ```deleting``` event:
+```php
+ public static function boot()
+ {
+ parent::boot();
+ static::deleting(function($obj) {
+ if (count((array)$obj->photos)) {
+ foreach ($obj->photos as $file_path) {
+ \Storage::disk('public_folder')->delete($file_path);
+ }
+ }
+ });
+ }
+```
+
+You might notice the field is using a ```clear_photos``` variable. Don't worry, you don't need it in your db table. That's just used to delete photos upon "update". If you use ```$fillable``` on your model, just don't include it. If you use ```$guarded``` on your model, place it in guarded.
+
+Input preview:
+
+
+
+
+### url
+
+```php
+[ // URL
+ 'name' => 'link',
+ 'label' => 'Link to video file',
+ 'type' => 'url'
+],
+```
+
+
+### video
+
+Allow the user to paste a YouTube/Vimeo link. That will get the video information with JavaScript and store it as a JSON in the database.
+
+Field definition:
+```php
+[ // URL
+ 'name' => 'video',
+ 'label' => 'Link to video file on YouTube or Vimeo',
+ 'type' => 'video',
+ 'youtube_api_key' => 'AIzaSycLRoVwovRmbIf_BH3X12IcTCudAErRlCE',
+],
+```
+
+An entry stored in the database will look like this:
+```
+$video = {
+ id: 234324,
+ title: 'my video title',
+ image: 'https://provider.com/image.jpg',
+ url: 'http://provider.com/video',
+ provider: 'youtube'
+}
+```
+
+So you should use [attribute casting](https://mattstauffer.co/blog/laravel-5.0-eloquent-attribute-casting) in your model, to cast the video as ```array``` or ```object```.
+
+Vimeo does not require an API key in order to query their DB, but YouTube does, even though their free quota is generous. You can get a free YouTube API Key inside [Google Developers Console](https://console.developers.google.com/) ([video tutorial here](https://www.youtube.com/watch?v=pP4zvduVAqo)).
+
+
+
+### view
+
+Load a custom view in the form.
+
+```php
+[ // view
+ 'name' => 'custom-ajax-button',
+ 'type' => 'view',
+ 'view' => 'partials/custom-ajax-button'
+],
+```
+
+**Note:** the same functionality can be achieved using a [custom field type](/docs/{{version}}/crud-fields#creating-a-custom-field-type), or using the [custom_html field type](/docs/{{version}}/crud-fields#custom-html) (if the content is really simple).
+
+
+### week
+
+```php
+[ // Week
+ 'name' => 'first_week',
+ 'label' => 'First week',
+ 'type' => 'week'
+],
+```
+
+Input preview:
+
+
+
+
+### wysiwyg
+
+Show a wysiwyg (CKEditor) to the user.
+
+```php
+[ // WYSIWYG Editor
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'wysiwyg'
+],
+```
+
+
+## Overwriting Default Field Types
+
+The actual field types are stored in the Backpack/CRUD package in ```/resources/views/fields```. If you need to change an existing field, you don't need to modify the package, you just need to add a blade file in your application in ```/resources/views/vendor/backpack/crud/fields```, with the same name. The package checks there first, and only if there's no file there, will it load it from the package.
+
+To quickly publish a field blade file in your project, you can use ```php artisan backpack:publish crud/fields/field_name```. For example, to publish the number field type, you'd type ```php artisan backpack:publish crud/fields/number```
+
+>Please keep in mind that if you're using _your_ file for a field type, you're not using the _package file_. So any updates we push to that file, you're not getting them. In most cases, it's recommended you create a custom field type for your use case, instead of overwriting default field types.
+
+
+## Creating a Custom Field Type
+
+If you need to extend the CRUD with a new field type, you create a new file in your application in ```/resources/views/vendor/backpack/crud/fields```. Use a name that's different from all default field types. That's it, you'll now be able to use it just like a default field type.
+
+Your field definition will be something like:
+
+```php
+[ // Custom Field
+ 'name' => 'address',
+ 'label' => 'Home address',
+ 'type' => 'address'
+ /// 'view_namespace' => 'yourpackage' // use a custom namespace of your package to load views within a custom view folder.
+],
+```
+
+And your blade file something like:
+```php
+
+
+
+
+@if ($crud->fieldTypeNotLoaded($field))
+ @php
+ $crud->markFieldTypeAsLoaded($field);
+ @endphp
+
+ {{-- FIELD EXTRA CSS --}}
+ {{-- push things in the after_styles section --}}
+ @push('crud_fields_styles')
+
+ @endpush
+
+
+ {{-- FIELD EXTRA JS --}}
+ {{-- push things in the after_scripts section --}}
+ @push('crud_fields_scripts')
+
+ @endpush
+@endif
+```
+
+Inside your custom field type, you can use these variables:
+- ```$crud``` - all the CRUD Panel settings, options and variables;
+- ```$entry``` - in the Update operation, the current entry being modified (the actual values);
+- ```$field``` - all attributes that have been passed for this field;
+
+If your field type uses JavaScript, we recommend you:
+- put a ```data-init-function="bpFieldInitMyCustomField"``` attribute on your input;
+- place your logic inside the scripts section mentioned above, inside ```function bpFieldInitMyCustomField(element) {}```; of course, you choose the name of the function but it has to match whatever you specified as data attribute on the input, and it has to be pretty unique; inside this method, you'll find that ```element``` is jQuery-wrapped object of the element where you specified ```data-init-function```; this should be enough for you to not have to use IDs, or any other tricks, to determine other elements inside the DOM - determine them in relation to the main element; if you want, you can choose to put the ```data-init-function``` attribute on a different element, like the wrapping div;
diff --git a/4.0/crud-filters.md b/4.0/crud-filters.md
new file mode 100644
index 00000000..a310950a
--- /dev/null
+++ b/4.0/crud-filters.md
@@ -0,0 +1,471 @@
+# Filters
+
+---
+
+
+## About
+
+Backpack CRUD allows you to show a filters bar right above the entries table. When selected or modified, they reload the DataTables results. The search will then search within the filtered elements.
+
+
+
+Just like with fields, columns or buttons, you can add existing filters or create a custom filter that fits to your particular needs. Everything's done inside your ```EntityCrudController::setupListOperation()```.
+
+
+### Filters API
+
+In order to manipulate filters, you can use:
+
+```php
+$this->crud->addFilter($options, $values, $filter_logic);
+
+$this->crud->removeFilter($name);
+$this->crud->removeAllFilters();
+
+$this->crud->filters(); // gets all the filters
+```
+
+
+### Adding a filter
+
+When adding a filter you need to specify the 3 parameters of the ```addFilter()``` method:
+- $options - an array of options (name, type, label are most important)
+- $values - filter values - can be an array or a closure
+- $filter_logic - what should happen if the filter is applied (usually add a clause to the query) - can be a closure, a string for a simple operation or false for a simple "where";
+
+Here's a simple example, with comments that explain what we're doing:
+```php
+// add a "simple" filter called Draft
+$this->crud->addFilter([
+ 'type' => 'simple',
+ 'name' => 'draft',
+ 'label'=> 'Draft'
+],
+false, // the simple filter has no values, just the "Draft" label specified above
+function() { // if the filter is active (the GET parameter "draft" exits)
+ $this->crud->addClause('where', 'draft', '1');
+ // we've added a clause to the CRUD so that only elements with draft=1 are shown in the table
+ // an alternative syntax to this would have been
+ // $this->crud->query = $this->crud->query->where('draft', '1');
+ // another alternative syntax, in case you had a scopeDraft() on your model:
+ // $this->crud->addClause('draft');
+});
+```
+> Notes about the filter logic closure
+> - the code will only be run on the controller's ```index()``` or ```search()``` methods;
+> - you can get the filter value by specifying a parameter to the function (ex: ```$value```);
+> - you have access to other request variables using ```$this->crud->request```;
+> - you also have read/write access to public properties using ```$this->crud```;
+> - when building complicated "OR" logic, make sure the first "where" in your closure is a "where" and only the subsequent are "orWhere"; Laravel 5.3+ no longer converts the first "orWhere" into a "where";
+
+
+## Filter types
+
+
+### Simple
+
+Only shows a label and can be toggled on/off. Useful for things like active/inactive and easily paired with [Eloquent Scopes](https://laravel.com/docs/5.3/eloquent#local-scopes). The "Draft" and "Has Video" filters in the screenshot above are simple filters.
+
+```php
+// simple filter
+$this->crud->addFilter([
+ 'type' => 'simple',
+ 'name' => 'active',
+ 'label'=> 'Active'
+],
+false,
+function() { // if the filter is active
+ // $this->crud->addClause('active'); // apply the "active" eloquent scope
+} );
+```
+
+
+### Text
+
+Shows a text input. Most useful for letting the user filter through information that's not shown as a column in the CRUD table - otherwise they could just use the DataTables search field.
+
+
+
+```php
+// simple filter
+$this->crud->addFilter([
+ 'type' => 'text',
+ 'name' => 'description',
+ 'label'=> 'Description'
+],
+false,
+function($value) { // if the filter is active
+ // $this->crud->addClause('where', 'description', 'LIKE', "%$value%");
+});
+```
+
+
+### Date
+
+Show a datepicker. The user can select one day.
+
+
+
+```php
+// date filter
+$this->crud->addFilter([
+ 'type' => 'date',
+ 'name' => 'date',
+ 'label' => 'Date'
+],
+ false,
+function ($value) { // if the filter is active, apply these constraints
+ // $this->crud->addClause('where', 'date', $value);
+});
+```
+
+
+### Date range
+
+Show a daterange picker. The user can select a start date and an end date.
+
+
+
+```php
+// daterange filter
+$this->crud->addFilter([
+ 'type' => 'date_range',
+ 'name' => 'from_to',
+ 'label' => 'Date range'
+],
+false,
+function ($value) { // if the filter is active, apply these constraints
+ // $dates = json_decode($value);
+ // $this->crud->addClause('where', 'date', '>=', $dates->from);
+ // $this->crud->addClause('where', 'date', '<=', $dates->to . ' 23:59:59');
+});
+```
+
+
+### Dropdown
+
+Shows a list of elements (that you provide) in a dropdown. The user can only select one of these elements.
+
+
+
+```php
+// dropdown filter
+$this->crud->addFilter([
+ 'name' => 'status',
+ 'type' => 'dropdown',
+ 'label'=> 'Status'
+], [
+ 1 => 'In stock',
+ 2 => 'In provider stock',
+ 3 => 'Available upon ordering',
+ 4 => 'Not available',
+], function($value) { // if the filter is active
+ // $this->crud->addClause('where', 'status', $value);
+});
+```
+
+
+### Select2
+
+Shows a select2 and allows the user to select one item from the list or search for an item. Useful when the values list is long (over 10 elements).
+
+
+
+```php
+// select2 filter
+$this->crud->addFilter([
+ 'name' => 'status',
+ 'type' => 'select2',
+ 'label' => 'Status'
+], function () {
+ return [
+ 1 => 'In stock',
+ 2 => 'In provider stock',
+ 3 => 'Available upon ordering',
+ 4 => 'Not available',
+ ];
+}, function ($value) { // if the filter is active
+ // $this->crud->addClause('where', 'status', $value);
+});
+```
+
+**Note:** If you want to pass all entries of a Laravel model to your filter, you can do it in the second parameter (the closure), with something like ```return \Backpack\NewsCRUD\app\Models\Category::all()->keyBy('id')->pluck('name', 'id')->toArray();```;
+
+
+### Select2_multiple
+
+Shows a select2 and allows the user to select one or more items from the list or search for an item. Useful when the values list is long (over 10 elements) and your user should be able to select multiple elements. You can decide yourself if the query for each element should use 'where' or 'orWhere', in the third parameter of the ```addFilter()``` method.
+
+
+
+```php
+// select2_multiple filter
+$this->crud->addFilter([
+ 'name' => 'status',
+ 'type' => 'select2_multiple',
+ 'label'=> 'Status'
+], function() {
+ return [
+ 1 => 'In stock',
+ 2 => 'In provider stock',
+ 3 => 'Available upon ordering',
+ 4 => 'Not available',
+ ];
+}, function($values) { // if the filter is active
+ // foreach (json_decode($values) as $key => $value) {
+ // $this->crud->addClause('where', 'published', $value);
+ // }
+});
+```
+
+
+### Select2_ajax
+
+Shows a select2 and allows the user to select one item from the list or search for an item. This list is fetched through an AJAX call by the select2. Useful when the values list is long (over 1000 elements).
+
+
+
+1. Add a route for the ajax search, right above your usual ```CRUD::resource()``` route. Example:
+
+```php
+Route::get('test/ajax-category-options', 'TestCrudController@categoryOptions');
+CRUD::resource('test', 'TestCrudController');
+```
+
+2. Add a method to your EntityCrudController that responds to a search term. The result should be an array with ```id => value```. Example for a 1-n relationship:
+
+```php
+public function categoryOptions(Request $request) {
+ $term = $request->input('term');
+ $options = App\Models\Category::where('name', 'like', '%'.$term.'%')->get()->pluck('name', 'id');
+ return $options;
+}
+```
+
+3. Add the select2_ajax filter and for the second parameter ("values") specify the exact route.
+
+```php
+// select2_ajax filter
+$this->crud->addFilter([
+ 'name' => 'category_id',
+ 'type' => 'select2_ajax',
+ 'label'=> 'Category',
+ 'placeholder' => 'Pick a category'
+],
+url('http://github.com/admin/test/ajax-category-options'), // the ajax route
+function($value) { // if the filter is active
+ // $this->crud->addClause('where', 'category_id', $value);
+});
+```
+
+
+### Range
+
+Shows two number inputs, for min and max.
+
+
+
+```php
+$this->crud->addFilter([
+ 'name' => 'number',
+ 'type' => 'range',
+ 'label'=> 'Range',
+ 'label_from' => 'min value',
+ 'label_to' => 'max value'
+],
+false,
+function($value) { // if the filter is active
+ $range = json_decode($value);
+ if ($range->from) {
+ $this->crud->addClause('where', 'number', '>=', (float) $range->from);
+ }
+ if ($range->to) {
+ $this->crud->addClause('where', 'number', '<=', (float) $range->to);
+ }
+});
+```
+
+### View
+
+Display any custom column filter you want. Usually used by Backpack package developers, to use views from within their packages, instead of having to publish them.
+
+```php
+// custom filter view
+$this->crud->addFilter([
+ 'name' => 'category_id',
+ 'type' => 'view',
+ 'view' => 'package::columns.column_type_name', // or path to blade file
+ 'label'=> 'Category',
+ 'placeholder' => 'Pick a category',
+],
+false,
+function($value) { // if the filter is active
+ // $this->crud->addClause('where', 'category_id', $value);
+});
+```
+
+
+## Creating custom filters
+
+Creating a new filter type is as easy as using the template below and placing a new view in your ```resources/views/vendor/backpack/crud/filters``` folder. You can then call this new filter by its view's name (ex: ```custom_select.blade.php``` will mean your filter type is called ```custom_select```).
+
+The filters bar is actually a [bootstrap navbar](http://getbootstrap.com/components/#navbar) at its core, but slimmer. So adding a new filter will be just like adding a menu item (for the HTML). Start from the ```text``` filter below and build your functionality.
+
+Inside this file, you'll have:
+- ```$filter``` object - includes everything you've defined on the current field;
+- ```$crud``` - the CrudPanel object;
+
+```php
+{{-- Text Backpack CRUD filter --}}
+
+
+
+{{-- ########################################### --}}
+{{-- Extra CSS and JS for this particular filter --}}
+
+
+{{-- FILTERS EXTRA JS --}}
+{{-- push things in the after_scripts section --}}
+
+@push('crud_list_scripts')
+
+
+@endpush
+{{-- End of Extra CSS and JS --}}
+{{-- ########################################## --}}
+```
+
+
+## Examples
+
+Use a dropdown to filter by the values of a MySQL ENUM column:
+
+```php
+// select2 filter
+$this->crud->addFilter([
+ 'name' => 'published',
+ 'type' => 'select2',
+ 'label'=> 'Published'
+], function() {
+ return \App\Models\Test::getEnumValuesAsAssociativeArray('published');
+}, function($value) { // if the filter is active
+ $this->crud->addClause('where', 'published', $value);
+});
+```
+
+Use a select2 to filter by a 1-n relationship:
+```php
+// select2 filter
+$this->crud->addFilter([
+ 'name' => 'category_id',
+ 'type' => 'select2',
+ 'label'=> 'Category'
+], function() {
+ return \App\Models\Category::all()->pluck('name', 'id')->toArray();
+}, function($value) { // if the filter is active
+ $this->crud->addClause('where', 'category_id', $value);
+});
+```
+
+Use a select2_multiple to filter Products by an n-n relationship:
+```php
+// select2_multiple filter
+$this->crud->addFilter([
+ 'name' => 'tags',
+ 'type' => 'select2_multiple',
+ 'label'=> 'Tags'
+], function() { // the options that show up in the select2
+ return Product::all()->pluck('name', 'id')->toArray();
+}, function($values) { // if the filter is active
+ foreach (json_decode($values) as $key => $value) {
+ $this->crud->query = $this->crud->query->whereHas('tags', function ($query) use ($value) {
+ $query->where('tag_id', $value);
+ });
+ }
+});
+```
+
+Use a simple filter to add a scope if the filter is active:
+```php
+// add a "simple" filter called Published
+$this->crud->addFilter([
+ 'type' => 'simple',
+ 'name' => 'published',
+ 'label'=> 'Published'
+],
+false,
+function() { // if the filter is active (the GET parameter "published" exits)
+ $this->crud->addClause('published');
+});
+```
+
+Use a simple filter to show the softDeleted items (trashed):
+```php
+$this->crud->addFilter([
+ 'type' => 'simple',
+ 'name' => 'trashed',
+ 'label'=> 'Trashed'
+],
+false,
+function($values) { // if the filter is active
+ $this->crud->query = $this->crud->query->onlyTrashed();
+});
+```
diff --git a/4.0/crud-how-to.md b/4.0/crud-how-to.md
new file mode 100644
index 00000000..2298b49f
--- /dev/null
+++ b/4.0/crud-how-to.md
@@ -0,0 +1,358 @@
+# How To for Backpack\CRUD
+
+---
+
+In addition the usual CRUD functionality, Backpack also allows you to do a few more complicated things:
+
+
+## Customize Views for each CRUD Panel
+
+Backpack loads its views through a double-fallback mechanism:
+- by default, it will load the views in the vendor folder (the package views);
+- if you've included views with the exact same name in your ```resources/views/vendor/backpack/crud``` folder, it will pick up those instead; you can use this method to overwrite a blade file for all CRUDs;
+- alternatively, if you only want to change a blade file for one CRUD, you can use the methods below in your ```setup()``` method, to change a particular view:
+```php
+$this->crud->setShowView('your-view');
+$this->crud->setEditView('your-view');
+$this->crud->setCreateView('your-view');
+$this->crud->setListView('your-view');
+$this->crud->setReorderView('your-view');
+$this->crud->setRevisionsView('your-view');
+$this->crud->setRevisionsTimelineView('your-view');
+$this->crud->setDetailsRowView('your-view');
+```
+
+
+## Customize CSS and JS for Default CRUD Operations
+
+Each default Backpack operation has its own CSS and JS file, in:
+- ```public/vendor/backpack/crud/css```
+- ```public/vendor/backpack/crud/js```
+
+If you don't find one there, you can create one, and Backpack will pick it up in that operation's view (ex: ```create.css``` or ```list.js```).
+
+
+## Add Extra CRUD Routes
+
+Starting with Backpack\CRUD 4.0, routes are defined inside the Controller, in methods that look like ```setupOperationNameRoutes()```; you can use this naming convention to setup extra routes, for your custom operations:
+
+```php
+protected function setupModerateRoutes($segment, $routeName, $controller) {
+ Route::get($segment.'/{id}/moderate', [
+ 'as' => $routeName.'.moderate',
+ 'uses' => $controller.'@moderate',
+ 'operation' => 'moderate',
+ ]);
+
+ Route::post($segment.'/{id}/moderate', [
+ 'as' => $routeName.'.saveModeration',
+ 'uses' => $controller.'@saveModeration',
+ 'operation' => 'moderate',
+ ]);
+}
+```
+
+If you want the route to point to a different controller, you can add the route in ```routes/backpack/custom.php``` instead.
+
+
+## Publish a column / field / filter / button and modify it
+
+All Backpack packages allow you to easily overwrite and customize the views. If you want Backpack to pick up _your_ file, instead of the one in the package, you can do that by just placing a file with the same name in your views. So if you want to overwrite the select2 field (```vendor/backpack/crud/src/resources/views/fields/select2.blade.php```) to change some functionality, you need to create ```resources/views/vendor/backpack/crud/fields/select2.blade.php```. You can do that manually, or use this command:
+```shell
+php artisan backpack:publish crud/fields/select2
+```
+This will look for the blade file and copy it inside the folder, so you can edit it.
+
+>**Please note:** Once you place a file with the same name inside your project, Backpack will pick that one up instead of the one in the package. That means that even though the file in the package is updated, you won't be getting those updates, since you're not using that file. Blade modifications are almost never breaking changes, but it's a good thing to receive updates with zero effort. Even small ones. So please overwrite the files as little as possible. Best to create your own custom fields/column/filters/buttons, whenever you can.
+
+
+## Filter the options in a select field
+
+This also applies to: select2, select2_multiple, select2_from_ajax, select2_from_ajax_multiple.
+
+There are 3 possible solutions:
+1. If there will be few options (dozens), the easiest way would be to use ```select_from_array``` or ```select2_from_array``` instead. Since you tell it what the options are, you can do any filtering you want there.
+2. If there are a lot of options (100+), best to use ```select2_from_ajax``` instead. You'll be able to filter the results any way you want in the controller method (the one that responds with the results to the AJAX call).
+3. If you can't use ```select2_from_array``` for ```select2_from_ajax```, you can create another model and add a global scope to it. For example, say you only want to show the users that belong to the user's company. You can create ```App\Models\CompanyUser``` and use that in your ```select2``` field instead of ```App\Models\User```:
+
+```php
+company_id) {
+ $companyId = Auth::user()->company->id;
+
+ static::addGlobalScope('company_id', function (Builder $builder) use ($companyId) {
+ $builder->where('company_id', $companyId);
+ });
+ }
+ }
+}
+```
+
+
+## Use the same column name multiple times in a CRUD
+
+If you try to add multiple columns with the same ```name```, by default Backpack will only show the last one. That's because ```name``` is also used as a key in the ```$column``` array. So when you ```addColumn()``` with the same name twice, it just overwrites the previous one.
+
+In order to insert two columns with the same name, use the ```key``` attribute on the second column (or both columns). If this attribute is present for a column, Backpack will use ```key``` instead of ```name```. Example:
+
+```diff
+ $this->crud->addColumn([
+ 'label' => "Location",
+ 'type' => 'select',
+ 'name' => 'location_id',
+ 'entity' => 'location',
+ 'attribute' => 'title',
+ 'model' => "App\Models\Location"
+ ]);
+
+ $this->crud->addColumn([
+ 'label' => "Location Type",
+ 'type' => 'radio_location_type',
+ 'options' => [
+ 1 => "Country",
+ 2 => "Region"
+ ],
+ 'name' => 'location_id',
++ 'key' => 'location_type',
+ 'entity' => 'location',
+ 'attribute' => 'type',
+ 'model' => "App\Models\Location"
+ ]);
+```
+
+
+## Use the Media Library (File Manager)
+
+If you've chosen to install [elFinder](http://elfinder.org/) when installing Backpack, you already have a media manager. And it's integrated into:
+- TinyMCE (as "tinymce" fieldtype)
+- CKEditor (as "ckeditor" fieldtype)
+- CRUD "browse" fieldtype
+- standalone, at the *your-project/admin/elfinder* route;
+
+For the integration, barryvdh's [laravel-elfinder](https://github.com/barryvdh/laravel-elfinder) package is used.
+
+
+
+
+## Manually install Backpack
+
+If the automatic installation doesn't work for you and you need to manually install CRUD, here are all the commands it is running:
+
+1) In your terminal:
+
+``` bash
+composer require backpack/crud
+```
+
+2) If you'd also like a file manager, run:
+```bash
+composer require barryvdh/laravel-elfinder
+mkdir -p public/uploads
+php artisan elfinder:publish
+php artisan vendor:publish --provider="Backpack\CRUD\BackpackServiceProvider" --tag="elfinder"
+php artisan backpack:base:add-sidebar-content '
'
+```
+
+3) Actually install Backpack:
+```bash
+php artisan vendor:publish --provider="Backpack\CRUD\BackpackServiceProvider" --tag="minimum"
+php artisan vendor:publish --provider="Prologue\Alerts\AlertsServiceProvider"
+php artisan migrate
+php artisan backpack:publish-user-model
+php artisan backpack:publish-middleware
+```
+
+
+## Load fields from a different folder
+
+If you're developing a package, you might need Backpack to pick up fields from your package folder, instead of having to publish them upon installation.
+
+Fields, Columns and Filters all have a ```view_namespace``` parameter you can use. Type your folder there, and Backpack will check that folder first, then where the views are published, then Backpack's package folder. Example:
+
+```php
+$this->crud->addFilter([ // add a "simple" filter called Draft
+ 'type' => 'complex',
+ 'name' => 'checkbox',
+ 'label' => 'Checked',
+ 'view_namespace' => 'custom_filters'
+],
+false, // the simple filter has no values, just the "Draft" label specified above
+function () { // if the filter is active (the GET parameter "draft" exits)
+ $this->crud->addClause('where', 'checkbox', '1');
+});
+```
+This will make Backpack look for the ```resources/views/custom_filters/complex.blade.php```, and pick that up before anything else.
+
+
+## Add a select2 field that depends on another field
+
+The ```select2_from_ajax``` and ```select2_from_ajax_multiple``` fields allow you to filter the results of a select2, depending on what has already been selected in a form. Say you have to select2 fields. When the AJAX call is made to the second field, all other variables in the page also get passed - that means you can filter the results of the second select2.
+
+Say you want to show two selects:
+- the first one shows Categories
+- the second one shows Articles, but only from the category above
+
+1. In you CrudController you would do:
+
+```php
+$this->crud->addField([ // SELECT2
+ 'label' => 'Category',
+ 'type' => 'select',
+ 'name' => 'category',
+ 'entity' => 'category',
+ 'attribute' => 'name',
+]);
+
+$this->crud->addField([ // select2_from_ajax: 1-n relationship
+ 'label' => "Article", // Table column heading
+ 'type' => 'select2_from_ajax_multiple',
+ 'name' => 'articles', // the column that contains the ID of that connected entity;
+ 'entity' => 'article', // the method that defines the relationship in your Model
+ 'attribute' => 'title', // foreign key attribute that is shown to user
+ 'data_source' => url('http://github.com/api/article'), // url to controller search function (with /{id} should return model)
+ 'placeholder' => 'Select an article', // placeholder for the select
+ 'minimum_input_length' => 0, // minimum characters to type before querying results
+ 'dependencies' => ['category'], // when a dependency changes, this select2 is reset to null
+ // 'method' => 'GET', // optional - HTTP method to use for the AJAX call (GET, POST)
+]);
+```
+
+**DIFFERENT HERE**: ```minimum_input_length``` and ```dependencies```.
+
+2. That second select points to routes that need to be registered:
+
+```php
+Route::get('api/article', 'App\Http\Controllers\Api\ArticleController@index');
+Route::get('api/article/{id}', 'App\Http\Controllers\Api\ArticleController@show');
+```
+
+**DIFFERENT HERE**: Nothing.
+
+3. Then that controller would look something like this:
+
+```php
+input('q');
+ $form = collect($request->input('form'))->pluck('value', 'name');
+
+ $options = Article::query();
+
+ // if no category has been selected, show no options
+ if (! $form['category']) {
+ return [];
+ }
+
+ // if a category has been selected, only show articles in that category
+ if ($form['category']) {
+ $options = $options->where('category_id', $form['category']);
+ }
+
+ if ($search_term) {
+ $results = $options->where('title', 'LIKE', '%'.$search_term.'%')->paginate(10);
+ } else {
+ $results = $options->paginate(10);
+ }
+
+ return $options->paginate(10);
+ }
+
+ public function show($id)
+ {
+ return Article::find($id);
+ }
+}
+```
+
+**DIFFERENT HERE**: We use ```$form``` to determine what other variables have been selected in the form, and modify the result accordingly.
+
+
+
+## Change the content class for an operation
+
+If you want to make the contents of an operation take more / less space from the window, you can do that:
+
+(A) for all CRUDs by specifying the custom content class in your ```config/backpack/crud.php```:
+
+```php
+ // Here you may override the css-classes for the content section of the create view globally
+ // To override per view use $this->crud->setCreateContentClass('class-string')
+ 'create_content_class' => 'col-md-8 col-md-offset-2',
+
+ // Here you may override the css-classes for the content section of the edit view globally
+ // To override per view use $this->crud->setEditContentClass('class-string')
+ 'edit_content_class' => 'col-md-8 col-md-offset-2',
+
+ // Here you may override the css-classes for the content section of the revisions timeline view globally
+ // To override per view use $this->crud->setRevisionsTimelineContentClass('class-string')
+ 'revisions_timeline_content_class' => 'col-md-10 col-md-offset-1',
+
+ // Here you may override the css-class for the content section of the list view globally
+ // To override per view use $this->crud->setListContentClass('class-string')
+ 'list_content_class' => 'col-md-12',
+
+ // Here you may override the css-classes for the content section of the show view globally
+ // To override per view use $this->crud->setShowContentClass('class-string')
+ 'show_content_class' => 'col-md-8 col-md-offset-2',
+
+ // Here you may override the css-classes for the content section of the reorder view globally
+ // To override per view use $this->crud->setReorderContentClass('class-string')
+ 'reorder_content_class' => 'col-md-8 col-md-offset-2',
+```
+
+(B) for a single CRUD, by using:
+
+```php
+$this->crud->setCreateContentClass('col-md-8 col-md-offset-2');
+$this->crud->setUpdateContentClass('col-md-8 col-md-offset-2');
+$this->crud->setListContentClass('col-md-8 col-md-offset-2');
+$this->crud->setShowContentClass('col-md-8 col-md-offset-2');
+$this->crud->setReorderContentClass('col-md-8 col-md-offset-2');
+$this->crud->setRevisionsTimelineContentClass('col-md-8 col-md-offset-2');
+```
+
+
+
+## Overwrite a Method on the CrudPanel Object
+
+Starting with Backpack v4, you can use a custom CrudPanel object instead of the one in the package. In your custom CrudPanel object, you can overwrite any method you want, but please note that this means that you're overwriting core components, and will be making it more difficult to upgrade to newer versions of Backpack.
+
+You can do this in any of your service providers (ex: ```app/Providers/AppServiceProvider.php```) to load your class instead of the one in the package:
+
+```php
+$this->app->extend('crud', function () {
+ return new \App\MyExtendedCrudPanel;
+});
+```
+
+Details and implementation [here](https://github.com/Laravel-Backpack/CRUD/pull/1990).
diff --git a/4.0/crud-operation-clone.md b/4.0/crud-operation-clone.md
new file mode 100644
index 00000000..856389ce
--- /dev/null
+++ b/4.0/crud-operation-clone.md
@@ -0,0 +1,116 @@
+# Clone
+
+--
+
+
+## About
+
+This CRUD operation allows your admins to duplicate one or more entries from the database.
+
+>**IMPORTANT:** The clone operation does NOT duplicate related entries. So n-n relationships will be unaffected. However, this also means that n-n relationships are ignored. So when you clone an entry, the new entry:
+>- will NOT have the same 1-1 relationships
+>- will have the same 1-n relationships
+>- will NOT have the same n-1 relationships
+>- will NOT have the same n-n relationships
+>
+>This might be somewhat counterintuitive for end users - though it should make perfect sense for us developers. This is why the Clone operation is NOT enabled by default.
+
+
+## Clone a Single Item
+
+
+### How it Works
+
+Using AJAX, a POST request is performed towards ```/entity-name/{id}/clone```, which points to the ```clone()``` method in your EntityCrudController.
+
+
+### How to Use
+
+To enable it, you need to ```use \Backpack\CRUD\app\Http\Controllers\Operations\CloneOperation;``` on your EntityCrudController. For example:
+
+```php
+crud->setModel(\App\Models\Product::class);
+ $this->crud->setRoute(backpack_url('http://github.com/product'));
+ $this->crud->setEntityNameStrings('product', 'products');
+ }
+}
+```
+
+This will make the Clone button appear in the table view, and will allow access to the controller method if manually accessed.
+
+
+### How to Overwrite
+
+In case you need to change how this operation works, overwrite the ```clone()``` trait method in your EntityCrudController; make sure you give the method in the trait a different name, so that there are no conflicts:
+
+```php
+use \Backpack\CRUD\app\Http\Controllers\Operations\CloneOperation { clone as traitClone; }
+
+public function clone($id)
+{
+ $this->crud->hasAccessOrFail('clone');
+ $this->crud->setOperation('clone');
+
+ // whatever you want
+
+ // if you still want to call the old clone method
+ $this->traitClone($id);
+}
+```
+
+You can also overwrite the clone button by creating a file with the same name inside your ```resources/views/vendor/backpack/crud/buttons/```. You can easily publish the clone button there to make changes using:
+
+```zsh
+php artisan backpack:publish crud/buttons/clone
+```
+
+
+## Clone Multiple Items (Bulk Clone)
+
+In addition to the button for each entry, you can show checkboxes next to each element, and allow your admin to clone multiple entries at once.
+
+
+
+### How it Works
+
+Using AJAX, a POST request is performed towards ```/entity-name/bulk-clone```, which points to the ```bulkClone()``` method in your EntityCrudController.
+
+
+### How to Use
+
+To enable it, you need to ```use \Backpack\CRUD\app\Http\Controllers\Operations\BulkCloneOperation;``` on your EntityCrudController.
+
+
+### How to Overwrite
+
+In case you need to change how this operation works, just create a ```bulkClone()``` method in your EntityCrudController:
+
+```php
+use \Backpack\CRUD\app\Http\Controllers\Operations\BulkCloneOperation { bulkClone as traitBulkClone; }
+
+public function bulkClone($id)
+{
+ // your custom code here
+ //
+ // then you can call the old bulk clone if you want
+ $this->traitBulkClone($id);
+}
+```
+
+You can also overwrite the bulk clone button by creating a file with the same name inside your ```resources/views/vendor/backpack/crud/buttons/```. You can easily publish the clone button there to make changes using:
+
+```zsh
+php artisan backpack:publish crud/buttons/bulk_clone
+```
diff --git a/4.0/crud-operation-create.md b/4.0/crud-operation-create.md
new file mode 100644
index 00000000..5506248c
--- /dev/null
+++ b/4.0/crud-operation-create.md
@@ -0,0 +1,120 @@
+# Create
+
+---
+
+
+## About
+
+This operation allows your admins to add new entries to a database table.
+
+
+
+
+## Requirements
+
+All editable attributes should be ```$fillable``` on your Model.
+
+
+## How to Use
+
+To use the Create operation, you must:
+
+**Step 0. Use the operation trait on your EntityCrudController**. This should be as simple as this:
+
+```php
+crud->setValidation(StoreRequest::class);
+ // $this->crud->addField($field_definition_array);
+ }
+}
+```
+
+**Step 1. Specify what field types** you'd like to show for each editable attribute, in your EntityCrudController's ```setupCreateOperation()``` method. You can do that using the [Fields API](/docs/{{version}}/crud-fields#fields-api). In short you can:
+
+```php
+protected function setupCreateOperation()
+{
+ $this->crud->addField($field_definition_array);
+}
+```
+
+**Step 2. Specify validation rules, in your the EntityCrudRequest file**. Then make sure that file is used for validation, by telling the CRUD to validate that request file in ```setupCreateOperation()```:
+```php
+$this->crud->setValidation(StoreRequest::class);
+```
+
+For more on how to manipulate fields, please read the [Fields documentation page](/docs/{{version}}/crud-fields). For more on validation rules, check out [Laravel's validation docs](https://laravel.com/docs/master/validation#available-validation-rules).
+
+
+## How It Works
+
+CrudController is a RESTful controller, so the ```Create``` operation uses two routes:
+- GET to ```/entity-name/create``` - points to ```create()``` which shows the Add New Entry form (```create.blade.php```);
+- POST to ```/entity-name``` - points to ```store()``` which does the actual storing operation;
+
+The ```create()``` method will show all the fields you've defined for this operation using the [Fields API](/docs/{{version}}/crud-fields#fields-api), then upon Save the ```store()``` method will first check the validation from the FormRequest you've specified, then create the entry using the Eloquent model. Only attributes that are specified as fields, and are ```$fillable``` on the model will actually be stored in the database.
+
+
+## Callbacks
+
+Developers coming from GroceryCRUD or other CRUD systems will be looking for callbacks to run before_insert, before_update, after_insert, after_update. **There are no callbacks in Backpack**. The store code is inside a trait, so you can easily overwrite it:
+
+```php
+crud->request->request->add(['author_id'=> backpack_user()->id]);
+ // $this->crud->addField(['type' => 'hidden', 'name' => 'author_id']);
+ // $this->crud->request->request->remove('password_confirmation');
+ // $this->crud->removeField('password_confirmation');
+ $response = $this->traitStore();
+ // do something after save
+ return $response;
+ }
+}
+```
+
+>But before you do that, ask yourself - **_is this something that should be done when an entry is added/updated/deleted from the application, too_**? Not just the admin panel? If so, a better place for it would be the Model. Remember your Model is a pure Eloquent Model, so the cleanest way might be to use [Eloquent Event Observers](https://laravel.com/docs/5.5/eloquent#events) or [accessors and mutators](https://laravel.com/docs/master/eloquent-mutators#accessors-and-mutators).
+
+
+## Translatable models and multi-language CRUDs
+
+For UX purposes, when creating multi-language entries, the Create form will only allow the admin to add an entry in one language, the default one. The admin can then edit that entry in all available languages, to translate it. Check out [this same section in the Update operation](/docs/{{version}}/crud-operation-update#translatable-models) for how to enable multi-language functionality.
+
+
+## Separate Validation Rules for Create and Update
+
+**Differences between the Create and Update validations?** If your Update operation requires a different validation than the Create operation, just:
+- create a separate request file for each operation;
+- instruct your EntityCrudController to use separate files, in the "use" section;
+
+For example, we could create ```UpdateTagRequest.php``` and ```CreateTagRequest.php```, with different validations, then in TagCrudController just do:
+```diff
+- use App\Http\Requests\TagRequest as StoreRequest;
++ use App\Http\Requests\CreateTagRequest as StoreRequest;
+- use App\Http\Requests\TagRequest as UpdateRequest;
++ use App\Http\Requests\UpdateTagRequest as UpdateRequest;
+```
diff --git a/4.0/crud-operation-delete.md b/4.0/crud-operation-delete.md
new file mode 100644
index 00000000..16577983
--- /dev/null
+++ b/4.0/crud-operation-delete.md
@@ -0,0 +1,96 @@
+# Delete
+
+--
+
+
+## About
+
+This CRUD operation allows your admins to remove one or more entries from the table.
+
+>In case your entity has SoftDeletes, it will perform a soft delete. The admin will _not_ know that his entry has been hard or soft deleted, since it will no longer show up in the ListEntries view.
+
+
+## Delete a Single Item
+
+
+### How it Works
+
+Using AJAX, a DELETE request is performed towards ```/entity-name/{id}```, which points to the ```destroy()``` method in your EntityCrudController.
+
+
+### How to Use
+
+To enable it, you need to ```use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;``` on your EntityCrudController. For example:
+
+```php
+
+### How to Overwrite
+
+In case you need to change how this operation works, just create a ```destroy()``` method in your EntityCrudController:
+
+```php
+use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation { destroy as traitDestroy; }
+
+public function destroy($id)
+{
+ $this->crud->hasAccessOrFail('delete');
+
+ return $this->crud->delete($id);
+}
+```
+
+You can also overwrite the delete button by creating a file with the same name inside your ```resources/views/vendor/backpack/crud/buttons/```. You can easily publish the delete button there to make changes using:
+
+```zsh
+php artisan backpack:publish crud/buttons/delete
+```
+
+
+## Delete Multiple Items (Bulk Delete)
+
+In addition to the button for each entry, you can show checkboxes next to each element, and allow your admin to delete multiple entries at once.
+
+
+
+### How it Works
+
+Using AJAX, a DELETE request is performed towards ```/entity-name/bulk-delete```, which points to the ```bulkDelete()``` method in your EntityCrudController.
+
+
+### How to Use
+
+You need to ```use \Backpack\CRUD\app\Http\Controllers\Operations\BulkDeleteOperation;``` on your EntityCrudController.
+
+
+### How to Overwrite
+
+In case you need to change how this operation works, just create a ```bulkDelete()``` method in your EntityCrudController:
+
+```php
+use \Backpack\CRUD\app\Http\Controllers\Operations\BulkDeleteOperation { bulkDelete as traitBulkDelete; }
+
+public function bulkDelete($id)
+{
+ // your custom code here
+}
+```
+
+You can also overwrite the bulk delete button by creating a file with the same name inside your ```resources/views/vendor/backpack/crud/buttons/```. You can easily publish the delete button there to make changes using:
+
+```zsh
+php artisan backpack:publish crud/buttons/bulk_delete
+```
diff --git a/4.0/crud-operation-list-entries.md b/4.0/crud-operation-list-entries.md
new file mode 100644
index 00000000..993ce593
--- /dev/null
+++ b/4.0/crud-operation-list-entries.md
@@ -0,0 +1,229 @@
+# List
+
+---
+
+
+## About
+
+This operation shows a table with all database entries. It's the first page the admin lands on (for an entity), and it's usually the gateway to all other operations, because it holds all the buttons.
+
+A simple List view might look like this:
+
+
+
+But a complex implementation of the ListEntries operation, using Columns, Filters, custom Buttons, custom Operations, responsive table, Details Row, Export Buttons will still look pretty good:
+
+
+
+You can easily customize [columns](#columns), [buttons](#buttons), [filters](#filters), [enable/disable additional features we've built](#other-features), or [overwrite the view and build your own features](#how-to-overwrite).
+
+
+## How It Works
+
+The main route leads to ```EntityCrudController::index()```, which shows the table view (```list.blade.php```. Inside that table view, we're using AJAX to fetch the entries and place them inside DataTables. That AJAX points to the same controller, ```EntityCrudController::search()```.
+
+Actions:
+- ```index()```
+- ```search()```
+
+For views, it uses:
+- ```list.blade.php```
+- ```columns/```
+- ```buttons/```
+
+
+## How to Use
+
+Use the operation trait on your controller:
+```php
+crud->addColumn();
+ }
+}
+```
+
+Configuration for this operation should be done inside your ```setupListOperation()``` method. **For a minimum setup, you only need to define the columns you need to show in the table.**
+
+
+### Columns
+
+The List operation uses "columns" to determine how to show the attributes of an entry to the user. All column types must have their ```name```, ```label``` and ```type``` specified, but some could require some additional attributes.
+
+```php
+$this->crud->addColumn([
+ 'name' => 'name', // The db column name
+ 'label' => "Tag Name", // Table column heading
+ 'type' => 'Text'
+]);
+```
+
+Backpack has 22+ [column types](/docs/{{version}}/crud-columns) you can use. Plus, you can easily [create your own type of column](/docs/{{version}}/crud-columns##creating-a-custom-column-type). **Check out the [Columns](/docs/{{version}}/crud-columns##creating-a-custom-column-type) documentation page** for a detailed look at column types, API and usage.
+
+
+### Buttons
+
+Buttons are used to trigger other operations. Some point to entirely new routes (```create```, ```update```, ```show```), others perform the operation on the current page using AJAX (```delete```).
+
+The ShowList operation has 3 places where buttons can be placed:
+ - ```top``` (where the Add button is)
+ - ```line``` (where the Edit and Delete buttons are)
+ - ```bottom``` (after the table)
+
+Backpack adds a few buttons by default:
+- ```create``` to the ```top``` stack;
+- ```update``` and ```delete``` to the ```line``` stack;
+
+To learn more about buttons, **check out the [Buttons](/docs/{{version}}/crud-buttons) documentation page**.
+
+
+### Filters
+
+Filters show up right before the actual table, and provide a way for the admin to filter the results in the ListEntries table. To learn more about filters, **check out the [Filters](/docs/{{version}}/crud-filters) documentation page**.
+
+
+### Other Features
+
+
+#### Details Row
+
+The details row functionality allows you to present more information in the table view of a CRUD. When enabled, a "+" button will show up next to every row, which on click will expand a "details row" below it, showing additional information.
+
+
+
+On click, an AJAX request is sent to the ```entity/{id}/details``` route, which calls the ```showDetailsRow()``` method on your EntityCrudController. Everything returned by that method is then shown in the details row. You'll want to overwrite that method to show anything you'd like in the details row.
+
+To use, inside your ```EntityCrudController```:
+1. Enable the functionality: ```$this->crud->enableDetailsRow();```
+2. Overwrite the ```showDetailsRow($id)``` method;
+
+Alternative for the 2nd step: overwrite ```views/backpack/crud/details_row.blade.php``` which is called by the default ```showDetailsRow($id)``` functionality.
+
+
+#### Export Buttons
+
+Exporting the DataTable to PDF, CSV, XLS is as easy as typing ```$this->crud->enableExportButtons();``` in your constructor.
+
+
+
+**Please note that when clicked, the button will export**
+- **the _currently visible_ table columns** (except columns marked as ```visibleInExport => false```);
+- **the columns that are forced to export** (with ```visibleInExport => true``` or ```exportOnlyField => true```);
+
+**In the UI, the admin can use the "Visibility" button, and the "Items per page" dropdown to manipulate what is visible in the table - and consequently what will be exported.**
+
+**Export Buttons Rules**
+
+Available customization:
+```
+'visibleInExport' => true/false
+'visibleInTable' => true/false
+'exportOnlyField' => true
+```
+
+By default, the field will start visible in the table. Users can hide it toggling visibility. Will be exported if visible in the table.
+
+If you force `visibleInExport => true` you are saying that independent of field visibility in table it will **always** be exported.
+
+Contrary is `visibleInExport => false`, even if visible in table, field will not be exported as per developer instructions.
+
+Setting `visibleInTable => true` will force the field to stay in the table no matter what. User can't hide it. (By default all fields visible in the table will be exported. If you don't want to export this field use with combination with `visibleInExport => false`)
+
+Using `'visibleInTable' => false` will make the field start hidden in the table. But users can toggle it's visibility.
+
+If you want a field that is not on table, user can't show it, but will **ALWAYS** be exported use the `exportOnlyField => true`. If used will ignore any other custom visibility you defined.
+
+
+#### Custom Query
+
+By default, all entries are shown in the ListEntries table, before filtering. If you want to restrict the entries to a subset, you can use the methods below in your EntityCrudController's ```setupListOperation()``` method:
+
+```php
+// Change what entries are shown in the table view.
+// This changes all queries on the table view,
+// as opposed to filters, who only change it when that filter is applied.
+$this->crud->addClause('active'); // apply a local scope
+$this->crud->addClause('type', 'car'); // apply local dynamic scope
+$this->crud->addClause('where', 'name', '=', 'car');
+$this->crud->addClause('whereName', 'car');
+$this->crud->addClause('whereHas', 'posts', function($query) {
+ $query->activePosts();
+ });
+$this->crud->groupBy();
+$this->crud->limit();
+
+$this->crud->orderBy();
+// please note it's generally a good idea to use crud->orderBy() inside "if (!$this->request->has('order')) {}"; that way, your custom order is applied ONLY IF the user hasn't forced another order (by clicking a column heading)
+```
+
+
+#### Responsive Table
+
+If your CRUD table has more columns than can fit inside the viewport (on mobile / tablet or smaller desktop screens), unimportant columns will start hiding and an expansion icon (three dots) will appear to the left of each row. We call this behaviour "_responsive table_", and consider this to be the best UX. By behaviour we consider the 1st column the most important, then 2nd, then 3rd, etc; the "actions" column is considered as important as the 1st column. You can of course [change the importance of columns](/docs/{{version}}/crud-columns#define-which-columns-to-hide-in-responsive-table).
+
+If you do not like this, you can **toggle off the responsive behaviour for all CRUD tables** by changing this config value in your ```config/backpack/crud.php``` to ```false```:
+```php
+ // enable the datatables-responsive plugin, which hides columns if they don't fit?
+ // if not, a horizontal scrollbar will be shown instead
+ 'responsive_table' => true
+```
+
+To turn off the responsive table behaviour for _just one CRUD panel_, you can use ```$this->crud->disableResponsiveTable()``` in your ```setupListOperation()``` method.
+
+
+#### Persistent Table
+
+By default, ListEntries will NOT remember your filtering, search and pagination when you leave the page. If you want ListEntries to do that, you can enable a ListEntries feature we call ```persistent_table```.
+
+**This will take the user back to the _filtered table_ after adding an item, previewing an item, creating an item or just browsing around**, preserving the table just like he/she left it - with the same filtering, pagination and search applied. It does so by saving the pagination, search and filtering for an arbitrary amount of time (by default: forever).
+
+To use ```persistent_table``` you can:
+- enable it for all CRUDs with the config option ```'persistent_table' => true``` in your ```config/backpack/crud.php```;
+- enable it inside a particular crud controller with ```$this->crud->enablePersistentTable();```
+- disable it inside a particular crud controller with ```$this->crud->disablePersistentTable();```
+
+> You can configure the persistent table duration in ``` config/backpack/crud.php ``` under `operations > list > persistentTableDuration`. False is forever. Set any amount of time you want in minutes. Note: you can configure it's expiring time on a per-crud basis using `$this->crud->setOperationSetting('persistentTableDuration', 120); in your setupListOperation()` for 2 hours persistency. The default is `false` which means forever.
+
+
+## How to Overwrite
+
+The main route leads to ```EntityCrudController::index()```, which loads ```list.blade.php```. Inside that table view, we're using AJAX to fetch the entries and place them inside a DataTables. The AJAX points to the same controller, ```EntityCrudController::search()```.
+
+
+### The View
+
+You can change how the ```list.blade.php``` file looks and works, by just placing a file with the same name in your ```resources/views/vendor/backpack/crud/list.blade.php```. To quickly do that, run:
+
+```zsh
+php artisan backpack:publish crud/list
+```
+
+Keep in mind that by publishing this file, you won't be getting any updates we'll be pushing to it.
+
+
+### The Operation Logic
+
+Getting and showing the information is done inside the ```index()``` method. Take a look at the ```CrudController::index()``` method (your EntityCrudController is extending this CrudController) to see how it works.
+
+To overwrite it, just create an ```index()``` method in your ```EntityCrudController```.
+
+
+### The Search Logic
+
+An AJAX call is made to the ```search()``` method:
+- when entries are shown in the table;
+- when entries are filtered in the table;
+- when search is performed on the table;
+- when pagination is performed on the table;
+
+You can of course overwrite this ```search()``` method by just creating one with the same name in your ```EntityCrudController```. In addition, you can overwrite what a specific column is searching through (and how), by [using the searchLogic attribute](/docs/{{version}}/crud-columns#custom-search-logic) on columns.
diff --git a/4.0/crud-operation-reorder.md b/4.0/crud-operation-reorder.md
new file mode 100644
index 00000000..b821e30c
--- /dev/null
+++ b/4.0/crud-operation-reorder.md
@@ -0,0 +1,82 @@
+# Reorder
+
+---
+
+
+## About
+
+This operation allows your admins to reoder & nest entries.
+
+
+
+
+## Requirements
+
+Your model should have the following integer fields, with a default value of 0: ```parent_id```, ```lft```, ```rgt```, ```depth```.
+
+Additionnaly, the `parent_id` field has to be nullable.
+
+
+## How to Use
+
+In order to enable this operation in your CrudController, you need to use the ```ReorderOperation``` trait, and have a ```setupReorderOperation()``` method that defines the ```label``` and ```max_level``` of allowed depth.
+
+```php
+crud->set('reorder.label', 'name');
+ // define how deep the admin is allowed to nest the items
+ // for infinite levels, set it to 0
+ $this->crud->set('reorder.max_level', 2);
+ }
+}
+```
+
+This will:
+- allow access to the Reorder operation;
+- make a "Reorder" button appear next to "Add entry" in the List view, if the List operation is enabled;
+- enable the routes needed by the Reorder operation;
+
+Where:
+- ```attribute_name``` should be the attribute you want shown on the draggable elements (ex: ```name```);
+- ```ALLOWED_DEPTH``` should be an integer, how many levels deep would you allow your admin to go when nesting; for infinit levels, you should set it to ```0```;
+
+
+## How It Works
+
+The ```/reorder``` route points to a ```reorder()``` method in your ```EntityCrudController```.
+
+
+
+## How to Overwrite
+
+In case you need to change how this operation works, take a look at the ```ReorderOperation.php``` trait to understand how it works. You can easily overwrite the ```reorder()``` or the ```saveReorder()``` methods:
+
+```php
+use \Backpack\CRUD\app\Http\Controllers\Operations\ReorderOperation { reorder as traitReorder; }
+
+public function reorder()
+{
+ // your custom code here
+
+ // call the method in the trait
+ $this->traitReorder();
+}
+```
+
+You can also overwrite the reorder button by creating a file with the same name inside your ```resources/views/vendor/backpack/crud/buttons/```. You can easily publish the reorder button there to make changes using:
+
+```zsh
+php artisan backpack:publish crud/buttons/reorder
+```
\ No newline at end of file
diff --git a/4.0/crud-operation-revisions.md b/4.0/crud-operation-revisions.md
new file mode 100644
index 00000000..38f8f5d4
--- /dev/null
+++ b/4.0/crud-operation-revisions.md
@@ -0,0 +1,65 @@
+# Revisions
+
+---
+
+
+## About
+
+Revisions allows your admins to store, see and undo changes to entries on an Eloquent model.
+
+The operation provides you with a simple interface to work with [venturecraft/revisionable](https://github.com/VentureCraft/revisionable#implementation), which is a great package that stores all changes in a separate table. It can work as an audit trail, a backup system and an accountability system for the admins.
+
+When enabled, ```Revisions``` will show another button in the table view, between _Edit_ and _Delete_. On click, that button opens another page which will allow an admin to see all changes and who made them:
+
+
+
+
+
+
+## How to Use
+
+In order to enable this operation for a CrudController, you need to:
+
+1. Create the revisions table:
+
+```bash
+cp vendor/venturecraft/revisionable/src/migrations/2013_04_09_062329_create_revisions_table.php database/migrations/ && php artisan migrate
+```
+
+2. Use [venturecraft/revisionable](https://github.com/VentureCraft/revisionable#implementation) on your model, and an ```identifiableName()``` method that returns an attribute on the model that the admin can use to distiguish between entries (ex: name, title, etc). If you are using another bootable trait be sure to override the boot method in your model.
+
+```php
+namespace MyApp\Models;
+
+class Article extends Eloquent {
+ use \Backpack\CRUD\CrudTrait, \Venturecraft\Revisionable\RevisionableTrait;
+
+ public function identifiableName()
+ {
+ return $this->name;
+ }
+
+ // If you are using another bootable trait
+ // be sure to override the boot method in your model
+ public static function boot()
+ {
+ parent::boot();
+ }
+}
+```
+
+3. In your CrudController, add the Revisions trait:
+
+```php
+
+## About
+
+This CRUD operation allows your admins to preview an entry. When enabled, it will add a "Preview" button in the ListEntries view, that points to a show page:
+
+
+
+In case your entity is translatable, it will show a multi-language dropdown, just like Edit.
+
+
+## How it Works
+
+The ```/entity-name/{id}/show``` route points to the ```show()``` method in your EntityCrudController. Inside this method, it uses ```setFromDb()``` to try to magically figure out all attributes you would like shown for this Model, and shows them using [Column types](/docs/{{version}}/crud-columns) inside ```show.blade.php```.
+
+
+## How to Use
+
+To enable this operation, you need to use the ```ShowOperation``` trait on your CrudController:
+
+```php
+crud->set('show.setFromDb', false);
+
+ // example logic
+ $this->crud->addColumn([
+ 'name' => 'table',
+ 'label' => 'Table',
+ 'type' => 'table',
+ 'columns' => [
+ 'name' => 'Name',
+ 'desc' => 'Description',
+ 'price' => 'Price',
+ ]
+ ]);
+ $this->crud->addColumn([
+ 'name' => 'fake_table',
+ 'label' => 'Fake Table',
+ 'type' => 'table',
+ 'columns' => [
+ 'name' => 'Name',
+ 'desc' => 'Description',
+ 'price' => 'Price',
+ ],
+ ]);
+ $this->crud->addColumn('text');
+ // $this->crud->removeColumn('date');
+ // $this->crud->removeColumn('extras');
+ }
+```
+
+
+## How to Overwrite
+
+In case you need to modify the show logic in a meaningful way, you can create a ```show()``` method in your EntityCrudController. The route will then point to your method, instead of the one in the trait. For example:
+
+```php
+use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation { show as traitShow; }
+
+public function show($id)
+{
+ // custom logic before
+ $content = $this->traitShow($id);
+ // cutom logic after
+ return $content;
+}
+```
diff --git a/4.0/crud-operation-update.md b/4.0/crud-operation-update.md
new file mode 100644
index 00000000..327fee5c
--- /dev/null
+++ b/4.0/crud-operation-update.md
@@ -0,0 +1,216 @@
+# Update
+
+---
+
+
+## About
+
+This operation allows your admins to edit entries from the database.
+
+
+
+
+## Requirements
+
+All editable attributes should be ```$fillable``` on your Model.
+
+
+## How to Use
+
+**Step 0. Use the operation trait on your controller**:
+
+```php
+crud->setValidation(StoreRequest::class);
+ // $this->crud->addField()
+ // or just do everything you've done for the Create Operation
+ // $this->crud->setupCreateOperation();
+ }
+}
+```
+
+This will:
+- allow access to this operation;
+- make an Edit button appear in the ```line``` stack, next to each entry, in the List operation view;
+
+To use the Update operation, you must:
+
+**Step 1. Specify what field types** you'd like to show for each attribute, in your controller's ```setupUpdateOperation()``` method. You can do that using the [Fields API](/docs/{{version}}/crud-fields#fields-api). In short you can:
+
+```php
+// add a field only to the Update operation
+$this->crud->addField($field_definition_array);
+// add a field to both the Update and Update operations
+$this->crud->addField($field_definition_array);
+```
+
+**Step 2. Specify which FormRequest file to use for validation and authorization**, inside your ```setupUpdateOperation()``` method. You can pass the same FormRequest as you did for the Create operation if there are no differences. If you need separate validation for Create and Update [look here](#separate-validation).
+```php
+$this->crud->setValidation(StoreRequest::class);
+```
+
+For more on how to manipulate fields, please read the [Fields documentation page](/docs/{{version}}/crud-fields). For more on validation rules, check out [Laravel's validation docs](https://laravel.com/docs/master/validation#available-validation-rules).
+
+
+## How It Works
+
+CrudController is a RESTful controller, so the ```Update``` operation uses two routes:
+- GET to ```/entity-name/{id}/edit``` - points to ```edit()``` which shows the Edit form (```edit.blade.php```);
+- POST to ```/entity-name/{id}/edit``` - points to ```store()``` which uses Eloquent to update the entry in the database;
+
+The ```edit()``` method will show all the fields you've defined for this operation using the [Fields API](/docs/{{version}}/crud-fields#fields-api), then upon Save the ```update()``` method will first check the validation from the typehinted FormRequest, then create the entry using the Eloquent model. Only attributes that have a field type added and are ```$fillable``` on the model will actually be updated in the database.
+
+
+## Callbacks
+
+Developers coming from GroceryCRUD or other CRUD systems will be looking for callbacks to run before_insert, before_update, after_insert, after_update. **There are no callbacks in Backpack**. The store code is inside a trait, so you can easily overwrite it:
+
+```php
+crud->request->request->add(['author_id'=> backpack_user()->id]);
+ // $this->crud->addField(['type' => 'hidden', 'name' => 'author_id']);
+ // $this->crud->request->request->remove('password_confirmation');
+ // $this->crud->removeField('password_confirmation');
+ $response = $this->traitUpdate();
+ // do something after save
+ return $response;
+ }
+}
+```
+
+>But before you do that, ask yourself - **_is this something that should be done when an entry is added/updated/deleted from the application, too_**? Not just the admin admin? If so, a better place for it would be the Model. Remember your Model is a pure Eloquent Model, so the cleanest way might be to use [Eloquent Event Observers](https://laravel.com/docs/5.5/eloquent#events) or [accessors and mutators](https://laravel.com/docs/master/eloquent-mutators#accessors-and-mutators).
+
+
+## Translatable models and multi-language CRUDs
+
+
+
+For localized apps, you can let your admins edit multi-lingual entries. Translations are stored using [spatie/laravel-translatable](https://github.com/spatie/laravel-translatable).
+
+In order to make one of your Models translatable (localization), you need to:
+0. Be running MySQL 5.7+ (or a PostgreSQL with JSON column support);
+1. [Install spatie/laravel-translatable](https://github.com/spatie/laravel-translatable#installation);
+2. In your database, make all translatable columns either JSON or TEXT.
+3. Use Backpack's ```HasTranslations``` trait on your model (instead of using spatie's ```HasTranslations```) and define what fields are translatable, inside the ```$translatable``` property. For example:
+
+```php
+ You DO NOT need to cast translatable string columns as array/json/object in the Eloquent model. From Eloquent's perspective they're strings. So:
+> - you _should NOT_ cast ```name```; it's a string in Eloquent, even though it's stored as JSON in the db by SpatieTranslatable;
+> - you _should_ cast ```extras``` to ```array```, if each translation stores an array of some sort;
+
+Change the languages available to translate to/from, in your crud config file (```config/backpack/crud.php```). By default there are quite a few enabled (English, French, German, Italian, Romanian).
+
+Additionally, if you have slugs, you'll need to use backpack's classes instead of the ones provided by cviebrock/eloquent-sluggable:
+
+```php
+ [
+ 'source' => 'slug_or_name',
+ ],
+ ];
+ }
+}
+```
+
+
+## Separate Validation Rules for Create and Update
+
+**Differences between the Create and Update validations?** If your Update operation requires a different validation than the Create operation, just:
+- create a separate request file for each operation;
+- instruct your EntityCrudController to use separate files, in the "use" section;
+
+For example, we could create ```UpdateTagRequest.php``` and ```CreateTagRequest.php```, with different validations, then in TagCrudController just do:
+```diff
+- use App\Http\Requests\TagRequest as StoreRequest;
++ use App\Http\Requests\CreateTagRequest as StoreRequest;
+- use App\Http\Requests\TagRequest as UpdateRequest;
++ use App\Http\Requests\UpdateTagRequest as UpdateRequest;
+```
diff --git a/4.0/crud-operations.md b/4.0/crud-operations.md
new file mode 100644
index 00000000..0f8d93a3
--- /dev/null
+++ b/4.0/crud-operations.md
@@ -0,0 +1,964 @@
+# Operations
+
+---
+
+When creating a CRUD Panel, your ```EntityCrudController``` (where Entity = your model name) is extending ```CrudController```. **By default, no operations are enabled.** No routes are registered.
+
+To use an operation, you need to use the operation trait on your controller. For example, to enable the List operation:
+
+```php
+Routes()```; this gets called in your ```routes/backpack/custom.php``` by the ```Route::crud('product', 'ProductCrudController``` macro, which determines which routes to register for that CrudController;
+- default setup inside a ```setupDefaults()``` method, that gets called automatically by CrudController when you use that operation on a controller;
+- methods that return views, or perform certain operations;
+
+Of course, you can easily [add custom operations](/#creating-a-custom-operation).
+
+
+## Standard Operations
+
+No operations are enabled by default.
+
+But Backpack does provide the logic for the most common operations admins perform on Eloquent model. You just need to use it (and maybe configure it) in your controller.
+
+Operations provided by Backpack:
+- [List](/docs/{{version}}/crud-operation-list-entries) - allows the admin to see all entries for an Eloquent model, with pagination, search, filters;
+- [Create](/docs/{{version}}/crud-operation-create) - allows the admin to add a new entry;
+- [Update](/docs/{{version}}/crud-operation-update) - allows the admin to edit an existing entry;
+- [Show](/docs/{{version}}/crud-operation-show) - allows the admin to preview an entry;
+- [Delete](/docs/{{version}}/crud-operation-delete) - allows the admin to remove and entry;
+- [BulkDelete](/docs/{{version}}/crud-operation-delete) - allows the admin to remove multiple entries in one go;
+- [Clone](/docs/{{version}}/crud-operation-clone) - allows the admin to make a copy of a database entry;
+- [BulkClone](/docs/{{version}}/crud-operation-clone) - allows the admin to make a copy of multiple database entries in one go;
+- [Reorder](/docs/{{version}}/crud-operation-reorder) - allows the admin to reorder & nest all entries of a model, in a hierarchy tree;
+- [Revisions](/docs/{{version}}/crud-operation-revisions) - shows an audit log of all changes to an entry, and allows the admin to undo modifications;
+
+
+
+### Operation Actions
+
+Each Operation is actually _a trait_, which can be used on CrudControllers. This trait can contain one or more methods (or functions). Since Laravel calls each Controller method an _action_, that means each _Operation_ can have one or many _actions_. For example, we have the ```create``` operation and two actions: ```create()``` and ```store()```.
+
+```php
+trait CreateOperation
+{
+ public function create()
+ {
+ // ...
+ }
+
+ public function store()
+ {
+ // ...
+ }
+}
+```
+
+An action can do something with AJAX and return true/false, it can return a view, or whatever else you can do inside a controller method. Notice that it's a ```public``` method - which is a Laravel requirement, in order to point a route to it.
+
+You can check which action is currently being performed using the [standard Laravel Route API](https://laravel.com/api/5.7/Illuminate/Routing/Route.html):
+
+- ```\Route::getCurrentRoute()->getAction()``` or ```$this->request->route()->getAction()```:
+```
+array:7 [▼
+ "middleware" => array:2 [▼
+ 0 => "web"
+ 1 => "admin"
+ ]
+ "as" => "crud.monster.index"
+ "uses" => "App\Http\Controllers\Admin\MonsterCrudController@index"
+ "controller" => "App\Http\Controllers\Admin\MonsterCrudController@index"
+ "namespace" => "App\Http\Controllers\Admin"
+ "prefix" => "admin"
+ "where" => []
+]
+```
+- ```\Route::getCurrentRoute()->getActionName()``` or ```$this->request->route()->getActionName()```:
+```
+App\Http\Controllers\Admin\MonsterCrudController@index
+```
+- ```\Route::getCurrentRoute()->getActionMethod()``` or ```$this->request->route()->getActionMethod()```:
+```
+index
+```
+
+You can also use the shortcuts on the CrudPanel object:
+```php
+$this->crud->getActionMethod(); // returns the method on the controller that was called by the route; ex: create(), update(), edit() etc;
+$this->crud->actionIs('create'); // checks if the controller method given is the one called by the route
+```
+
+
+### Titles, Headings and Subheadings
+
+For standard CRUD operations, each _action_ that shows an interface uses some texts to show the user what page, operation or action he is currently performing:
+- **Title** - page title, shown in the browser's title bar;
+- **Heading** - biggest heading on page;
+- **Subheading** - short description of the current page, sits beside the heading;
+
+
+
+You can get and set the above using:
+```php
+// Getters
+$this->crud->getTitle('create'); // get the Title for the create action
+$this->crud->getHeading('create'); // get the Heading for the create action
+$this->crud->getSubheading('create'); // get the Subheading for the create action
+
+// Setters
+$this->crud->setTitle('some string', 'create'); // set the Title for the create action
+$this->crud->setHeading('some string', 'create'); // set the Heading for the create action
+$this->crud->setSubheading('some string', 'create'); // set the Subheading for the create action
+```
+
+These methods are usually useful inside actions, not in ```setup()```. Since action methods are called _after_ ```setup()```, any call to these getters and setters in ```setup()``` would get overwritten by the call in the action.
+
+
+### Handling Access to Operations
+
+Admins are allowed to do an operation or not using a very simple system: ```$crud->settings['operation_name']['access']``` will either be ```true``` or ```false```. When you enable a stock Backpack operation by doing ```use SomeOperation;``` on your controller, all operations will run ```$this->crud->allowAccess('operation_name');```, which will toggle that variable to ```true```.
+
+You can easily add or remove elements to this access array in your ```setup()``` method, or your custom methods, using:
+```php
+$this->crud->allowAccess('operation_name');
+$this->crud->allowAccess(['list', 'update', 'delete']);
+$this->crud->denyAccess('operation');
+$this->crud->denyAccess(['update', 'create', 'delete']);
+
+$this->crud->hasAccess('operation_name'); // returns true/false
+$this->crud->hasAccessOrFail('create'); // throws 403 error
+$this->crud->hasAccessToAll(['create', 'update']); // returns true/false
+$this->crud->hasAccessToAny(['create', 'update']); // returns true/false
+```
+
+
+### Operation Routes
+
+Starting with Backpack 4.0, routes can be defined in the CrudController. Your ```routes/backpack/custom.php``` file will have calls like ```Route::crud('product', 'ProductCrudController');```. This ```Route::crud()``` is a macro that will go to that controller and run all the methods that look like ```setupXxxRoutes()```. That means each operation can have its own method to define the routes it needs. And they do - if you check out the code of any operation, you'll see every one of them has a ```setupOperationNameRoutes()``` method.
+
+If you want to add a new route to your controller, there are two ways to do it:
+1. Add a route in your ```routes/backpack/custom.php```;
+2. Add a method following the ```setupXxxRoutes()``` convention to your controller;
+
+Inside a ```setupOperationNameRoutes()```, you'll notice that's also where we define the operation name:
+
+```php
+ protected function setupShowRoutes($segment, $routeName, $controller)
+ {
+ Route::get($segment.'/{id}/show', [
+ 'as' => $routeName.'.show',
+ 'uses' => $controller.'@show',
+ 'operation' => 'show',
+ ]);
+ }
+```
+
+
+### Getting an Operation Name
+
+Once an operation name has been set using that route, you can do ```$crud->getOperation()``` inside your views and do things according to this.
+
+
+
+## Creating a Custom Operation
+
+
+## Command-line Tool
+
+If you've installed ```backpack/generators```, you can do ```php artisan backpack:crud-operation {OperationName}``` to generate an empty operation trait, that you can edit and use on your CrudControllers. For example:
+
+```bash
+php artisan backpack:crud-operation Comment
+```
+
+Will generate ```app/Http/Controllers/Admin/Operations/CommentOperation``` with the following contents:
+
+```php
+ $routeName.'.comment',
+ 'uses' => $controller.'@comment',
+ 'operation' => 'comment',
+ ]);
+ }
+
+ /**
+ * Add the default settings, buttons, etc that this operation needs.
+ */
+ protected function setupCommentDefaults()
+ {
+ $this->crud->allowAccess('comment');
+
+ $this->crud->operation('comment', function () {
+ $this->crud->loadDefaultOperationSettingsFromConfig();
+ });
+
+ $this->crud->operation('list', function () {
+ // $this->crud->addButton('top', 'comment', 'view', 'crud::buttons.comment');
+ // $this->crud->addButton('line', 'comment', 'view', 'crud::buttons.comment');
+ });
+ }
+
+ /**
+ * Show the view for performing the operation.
+ *
+ * @return Response
+ */
+ public function comment()
+ {
+ $this->crud->hasAccessOrFail('comment');
+
+ // prepare the fields you need to show
+ $this->data['crud'] = $this->crud;
+ $this->data['title'] = $this->crud->getTitle() ?? 'comment '.$this->crud->entity_name;
+
+ // load the view
+ return view("crud::operations.comment", $this->data);
+ }
+}
+```
+
+You'll notice the generated operation has:
+- a GET route (inside ```setupCommentRoutes()```);
+- a method that sets the defaults for this operation (```setupCommentDefaults()```);
+- a method to perform the operation, or show an interface (```comment()```);
+
+You can customize these to fit the operation you have in mind, then ```use \App\Http\Controllers\Admin\Operations\CommentOperation;``` inside the CrudControllers where you want the operation.
+
+
+## Contents of a Custom Operation
+
+Thanks to [Backpack's simple architecture](/docs/{{version}}/crud-basics#architecture), each CRUD panel uses a controller and a route, that are placed inside your project. That means you hold the keys to how this controller works.
+
+To add an operation to an ```EntityCrudController```, you can:
+- decide on your operation name; for example... "publish";
+- create a method that loads the routes inside your controller:
+```php
+ protected function setupPublishRoutes($segment, $routeName, $controller)
+ {
+ Route::get($segment.'/{id}/publish', [
+ 'as' => $routeName.'.publish',
+ 'uses' => $controller.'@publish',
+ 'operation' => 'publish',
+ ]);
+ }
+```
+- create a method that performs the operation you want:
+```php
+ public function publish($id)
+ {
+ // do something
+ // return something
+ }
+```
+- [add a new button for this operation to the List view](/docs/{{version}}/crud-buttons#creating-a-custom-button), or enable access to it, inside a ```setupPublishDefaults()``` method:
+```php
+ protected function setupPublishDefaults()
+ {
+ $this->crud->allowAccess('publish');
+
+ $this->crud->operation('list', function () {
+ $this->crud->addButton('line', 'publish', 'view', 'buttons.publish', 'beginning');
+ });
+ }
+```
+
+Take a look at the examples below for a better picture and code examples.
+
+If you intend to reuse this operation across multiple controllers, you can group all the methods above in a trait, say ```PublishOperation.php``` and then just use that trait on the controllers where you need the operation:
+
+```php
+ $routeName.'.publish',
+ 'uses' => $controller.'@publish',
+ 'operation' => 'publish',
+ ]);
+ }
+
+ protected function setupPublishDefaults()
+ {
+ $this->crud->allowAccess('publish');
+
+ $this->crud->operation('list', function () {
+ $this->crud->addButton('line', 'publish', 'view', 'buttons.publish', 'beginning');
+ });
+ }
+
+ public function publish($id)
+ {
+ // do something
+ // return something
+ }
+}
+```
+
+In the example above, you could just do ```use \App\Http\Controllers\Admin\CustomOperations\PublishOperation;``` on any EntityCrudController, and your operation will be added - complete with routes, buttons, access, actions, everything.
+
+
+### Access to Custom Operations
+
+Since you're creating a new operation, in terms of restricting access you can:
+1. allow access to this new operation depending on access to a default operation (usually if the admin can ```update```, he's ok to perform custom operations);
+2. customize access to this particular operation, by just using a different key than the default ones; for example, you can allow access by using ```$this->crud->allowAccess('publish')``` in your ```setup()``` method, then check for access to that operation using ```$this->crud->hasAccess('publish')```;
+
+
+### Adding Settings to the CrudPanel object
+
+#### Using the Settings API
+
+Anything an operation does to configure itself, or process information, should be stored inside ```$this->crud->settings``` . It's an associative array, and you can add/change things using the Settings API:
+
+```php
+// for the operation that is currently being performed
+$this->crud->setOperationSetting('show_title', true);
+$this->crud->getOperationSetting('show_title');
+$this->crud->hasOperationSetting('show_title');
+
+// for a particular operation, pass the operation name as a last parameter
+$this->crud->setOperationSetting('show_title', true, 'create');
+$this->crud->getOperationSetting('show_title', 'create');
+$this->crud->hasOperationSetting('show_title', 'create');
+
+// alternatively, you could use the direct methods with no fallback to the current operation
+$this->crud->set('create.show_title', false);
+$this->crud->get('create.show_title');
+$this->crud->has('create.show_title');
+```
+
+#### Using the crud config file
+
+Additionally, operations can load default settings from the config file. You'll notice the ```config/backpack/crud.php``` file contains an array of operations, each with various settings. Those settings there are loaded by the operation as defaults, to allow users to change one setting in the config, and have that default changed across ALL of their CRUDs. If you take a look at the List operation you'll notice this:
+
+```php
+ /**
+ * Add the default settings, buttons, etc that this operation needs.
+ */
+ protected function setupListDefaults()
+ {
+ $this->crud->allowAccess('list');
+
+ $this->crud->operation('list', function () {
+ $this->crud->loadDefaultOperationSettingsFromConfig();
+ });
+ }
+```
+
+You can do the same in custom operations. Because this call happens in setupListDefaults(), inside an operation closure, the settings will only be added when that operation is being performed.
+
+
+
+### Adding Methods to the CrudPanel Object
+
+You can add static methods to this ```$this->crud``` (which is a CrudPanel object) object with ```$this->crud->macro()```, because the object is [macroable](https://unnikked.ga/understanding-the-laravel-macroable-trait-dab051f09172). So you can do:
+
+```php
+class MonsterCrudController extends CrudController
+{
+ public function setup()
+ {
+ $this->crud->macro('doStuff', function($something) {
+ echo '
'; var_dump($something); echo '
';
+ dd($this);
+ });
+ $this->crud->macro('getColumnsInTheFormatIWant', function() {
+ $columns = $this->columns();
+ // ... do something to $columns;
+ return $columns;
+ });
+
+ // bla-bla-bla the actual setup code
+ }
+ public function sendEmail()
+ {
+ // ...
+ $this->crud->doStuff();
+ dd($this->crud->getColumnsInTheFormatIWant());
+ // ...
+ }
+ public function markPending()
+ {
+ // ...
+ $this->crud->doStuff();
+ dd($this->crud->getColumnsInTheFormatIWant());
+ // ...
+ }
+}
+```
+
+So if you define a custom operation that needs some static methods added to the ```CrudPanel``` object, you can add them. The best place to register your macros in a custom operation would probably be inside your ```setupXxxDefaults()``` method, inside an operation closure. That way, the static methods you add are only added when that operation is being performed. For example:
+
+```php
+protected function setupPrintDefaults()
+{
+ $this->crud->allowAccess('print');
+
+ $this->crud->operation('print', function() {
+ $this->crud->macro('getColumnsInTheFormatIWant', function() {
+ $columns = $this->columns();
+ // ... do something to $columns;
+ return $columns;
+ });
+ });
+}
+```
+
+With the example above, you'll be able to use ```$this->crud->getColumnsInTheFormatIWant()``` inside your operation actions.
+
+
+### Using a feature from another operation
+
+Anything an operation does to configure itself, or process information, is stored on the ```$this->crud->settings``` property. Operation features (ex: fields, columns, buttons, filters, etc) are created in such a way that all they do is add an entry in settings, for an operation, and manipulate it. That means there is nothing stopping you from using a feature from one operation in a different operation.
+
+If you create a Print operation, and want to use the ```columns``` feature that List and Show use, you can just go ahead and do ```$this->crud->addColumn()``` calls inside your operation. You'll notice the columns are stored inside ```$this->crud->settings['print.columns']```, so they're completely different from the ones in the List or Show operation. You'll need to actually do something with the columns you added, inside your operation methods or views - of course.
+
+
+
+### Examples
+
+
+#### Creating a New Operation With No Interface
+
+Let's say we have a ```UserCrudController``` and we want to create a simple ```Clone``` operation, which would create another entry with the same info. So very similar to ```Delete```. What we need to do is:
+
+1. Create a route for this operation - as we've learned above we can do that in a ```setupXxxRoutes()``` method:
+
+```php
+ protected function setupPublishRoutes($segment, $routeName, $controller)
+ {
+ Route::get($segment.'/{id}/clone', [
+ 'as' => $routeName.'.clone',
+ 'uses' => $controller.'@clone',
+ 'operation' => 'clone',
+ ]);
+ }
+```
+
+2. Add the method inside ```UserCrudController```:
+
+```php
+public function clone($id)
+{
+ $this->crud->hasAccessOrFail('create');
+ $this->crud->setOperation('Clone');
+
+ $clonedEntry = $this->crud->model->findOrFail($id)->replicate();
+
+ return (string) $clonedEntry->push();
+}
+```
+
+3. Create a button for this method. Since our operation is similar to "Delete", lets start from that one and customize what we need. The button should clone the entry using an AJAX call. No need to load another page for an operation this simple. We'll create a ```resources\views\vendor\backpack\crud\buttons\clone.blade.php``` file:
+
+```php
+@if ($crud->hasAccess('create'))
+ Clone
+@endif
+
+{{-- Button Javascript --}}
+{{-- - used right away in AJAX operations (ex: List) --}}
+{{-- - pushed to the end of the page, after jQuery is loaded, for non-AJAX operations (ex: Show) --}}
+@push('after_scripts') @if ($crud->request->ajax()) @endpush @endif
+
+@if (!$crud->request->ajax()) @endpush @endif
+```
+
+4. We can now actually add this button to our ```UserCrudController::setupCloneOperation()``` method, or our ```setupCloneDefaults()``` method:
+
+```php
+protected setupCloneDefaults() {
+ $this->crud->allowAccess('clone');
+
+ $this->crud->operation(['list', 'show'], function () {
+ $this->crud->addButtonFromView('line', 'clone', 'clone', 'beginning');
+ });
+}
+```
+
+>Of course, **if you plan to re-use this operation on another EntityCrudController**, it's a good idea to isolate the method inside a trait, then use that trait on each EntityCrudController where you want the operation to work.
+
+
+#### Creating a New Operation With An Interface
+
+Let's say we have a ```UserCrudController``` and we want to create a simple ```Moderate``` operation, where we show a form where the admin can add his observations and what not. In this respect, it should be similar to ```Update``` - the button should lead to a separate form, then that form will probably have a Save button. So when creating the methods, we should look at ```CrudController::edit()``` and ```CrudController::updateCrud()``` for working examples.
+
+What we need to do is:
+
+1. Create routes for this operation - we can do that using the ```setupOperationNameRoutes()``` convention inside a ```UserCrudController```:
+
+```php
+ protected function setupModerateRoutes($segment, $routeName, $controller)
+ {
+ Route::get($segment.'/{id}/moderate', [
+ 'as' => $routeName.'.getModerate',
+ 'uses' => $controller.'@getModerateForm',
+ 'operation' => 'moderate',
+ ]);
+ Route::post($segment.'/{id}/moderate', [
+ 'as' => $routeName.'.postModerate',
+ 'uses' => $controller.'@postModerateForm',
+ 'operation' => 'moderate',
+ ]);
+ }
+```
+
+2. Add the methods inside ```UserCrudController```:
+
+```php
+public function getModerateForm($id)
+{
+ $this->crud->hasAccessOrFail('update');
+ $this->crud->setOperation('Moderate');
+
+ // get the info for that entry
+ $this->data['entry'] = $this->crud->getEntry($id);
+ $this->data['crud'] = $this->crud;
+ $this->data['title'] = 'Moderate '.$this->crud->entity_name;
+
+ return view('vendor.backpack.crud.moderate', $this->data);
+}
+
+public function postModerateForm(Request $request = null)
+{
+ $this->crud->hasAccessOrFail('update');
+
+ // TODO: do whatever logic you need here
+ // ...
+ // You can use
+ // - $this->crud
+ // - $this->crud->getEntry($id)
+ // - $request
+ // ...
+
+ // show a success message
+ \Alert::success('Moderation saved for this entry.')->flash();
+
+ return \Redirect::to($this->crud->route);
+}
+```
+
+3. Create the ```/resources/views/vendor/backpack/crud/moderate.php``` blade file, which shows the moderate form and what not. Best to start from the ```edit.blade.php``` file and customize:
+
+```html
+@extends(backpack_view('layouts.top_left'))
+
+@php
+ $defaultBreadcrumbs = [
+ trans('backpack::crud.admin') => backpack_url('http://github.com/dashboard'),
+ $crud->entity_name_plural => url(http://github.com/$crud-%3Eroute),
+ 'Moderate' => false,
+ ];
+
+ // if breadcrumbs aren't defined in the CrudController, use the default breadcrumbs
+ $breadcrumbs = $breadcrumbs ?? $defaultBreadcrumbs;
+@endphp
+
+@section('header')
+
+
+@endsection
+
+```
+
+4. Create a button for this operation. Since our operation is similar to "Update", lets start from that one and customize what we need. The button should just take the admin to the route that shows the Moderate form. Nothing fancy. We'll create a ```resources\views\vendor\backpack\crud\buttons\moderate.blade.php``` file:
+
+```php
+@if ($crud->hasAccess('moderate'))
+ Moderate
+@endif
+```
+
+4. We can now actually add this button to our ```UserCrudController::setup()```, to register that button inside the List operation:
+
+```php
+$this->crud->operation('list', function() {
+ $this->crud->addButtonFromView('line', 'moderate', 'moderate', 'beginning');
+});
+```
+
+Or better yet, we can do this inside a ```setupModerateDefaults()``` method, which gets called automatically by CrudController when the ```moderate``` operation is being performed (thanks to the operation name set on the routes):
+
+```php
+protected function setupModerateDefaults()
+{
+ $this->crud->allowAccess('moderate');
+
+ $this->crud->operation('list', function() {
+ $this->crud->addButtonFromView('line', 'moderate', 'moderate', 'beginning');
+ });
+}
+```
+
+>Of course, **if you plan to re-use this operation on another EntityCrudController**, it's a good idea to isolate the method inside a trait, then use that trait on each EntityCrudController where you want the operation to be enabled.
+
+```php
+ $routeName.'.getModerate',
+ 'uses' => $controller.'@getModerateForm',
+ 'operation' => 'moderate',
+ ]);
+ Route::post($segment.'/{id}/moderate', [
+ 'as' => $routeName.'.postModerate',
+ 'uses' => $controller.'@postModerateForm',
+ 'operation' => 'moderate',
+ ]);
+ }
+
+ protected function setupmoderateDefaults()
+ {
+ $this->crud->allowAccess('moderate');
+
+ $this->crud->operation('list', function() {
+ $this->crud->addButtonFromView('line', 'moderate', 'moderate', 'beginning');
+ });
+ }
+
+ public function getModerateForm($id)
+ {
+ $this->crud->hasAccessOrFail('update');
+ $this->crud->setOperation('Moderate');
+
+ // get the info for that entry
+ $this->data['entry'] = $this->crud->getEntry($id);
+ $this->data['crud'] = $this->crud;
+ $this->data['title'] = 'Moderate '.$this->crud->entity_name;
+
+ return view('vendor.backpack.crud.moderate', $this->data);
+ }
+
+ public function postModerateForm(Request $request = null)
+ {
+ $this->crud->hasAccessOrFail('update');
+
+ // TODO: do whatever logic you need here
+ // ...
+ // You can use
+ // - $this->crud
+ // - $this->crud->getEntry($id)
+ // - $request
+ // ...
+
+ // show a success message
+ \Alert::success('Moderation saved for this entry.')->flash();
+
+ return \Redirect::to($this->crud->route);
+ }
+}
+```
+
+
+#### Creating a New Operation With a Bulk Action (No Interface)
+
+Say we want to create a ```BulkClone``` operation, with a button which clones multiple entries at the same time. So very similar to our ```BulkDelete```. What we need to do is:
+
+1. Create a new button:
+
+```html
+@if ($crud->hasAccess('bulkClone') && $crud->get('list.bulkActions'))
+ Clone
+@endif
+
+@push('after_scripts')
+
+@endpush
+```
+
+2. Create a method in your EntityCrudController (or in a trait, if you want to re-use it for multiple CRUDs):
+
+```php
+ public function bulkClone()
+ {
+ $this->crud->hasAccessOrFail('create');
+
+ $entries = $this->request->input('entries');
+ $clonedEntries = [];
+
+ foreach ($entries as $key => $id) {
+ if ($entry = $this->crud->model->find($id)) {
+ $clonedEntries[] = $entry->replicate()->push();
+ }
+ }
+
+ return $clonedEntries;
+ }
+```
+
+3. Add a route to point to this new method:
+
+```php
+protected function setupBulkCloneRoutes($segment, $routeName, $controller)
+{
+ Route::post($segment.'/bulk-clone', [
+ 'as' => $routeName.'.bulkClone',
+ 'uses' => $controller.'@bulkClone',
+ 'operation' => 'bulkClone',
+ ]);
+}
+```
+
+4. Setup the default features we need for the operation to work:
+```php
+protected function setupBulkCloneDefaults()
+{
+ $this->crud->allowAccess('bulkClone');
+
+ $this->crud->operation('list', function () {
+ $this->crud->enableBulkActions();
+ $this->crud->addButton('bottom', 'bulk_clone', 'view', 'bulk_clone', 'beginning');
+ });
+}
+```
+
+
+Now there's a Clone button on our List bottom stack, that works as expected for multiple entries.
+
+The button makes one call for all entries, and only triggers one notification. If you would rather make a call for each entry, you can use something like below:
+
+```html
+@if ($crud->hasAccess('create') && $crud->bulk_actions)
+ Clone
+@endif
+
+@push('after_scripts')
+
+@endpush
+```
diff --git a/4.0/crud-tutorial.md b/4.0/crud-tutorial.md
new file mode 100644
index 00000000..464c4f91
--- /dev/null
+++ b/4.0/crud-tutorial.md
@@ -0,0 +1,375 @@
+# CRUD Tutorial
+
+---
+
+What's the simplest entity you can think of? It will probably be something like ```Tag```, which only holds an ```id``` and a ```name```. Let's create this new entity in the database, the model for it, then create a CRUD Panel to let admins manage entries for this entity.
+
+We assume:
+- you've [installed Backpack](/docs/{{version}}/installation);
+- you don't already have a ```Tag``` model in your project;
+
+
+## Generate Files
+
+Since we don't have an Eloquent model for it already, we're going to use [Jeffrey Way's Generators](https://github.com/laracasts/Laravel-5-Generators-Extended) package, which you've most likely installed along with Backpack, to generate the migration.
+
+```zsh
+# STEP 0. create migration
+php artisan make:migration:schema create_tags_table --model=0 --schema="name:string:unique"
+php artisan migrate
+```
+
+Now that we have the ```tags``` table in the database, let's generate the actual files we'll be using:
+
+```zsh
+php artisan backpack:crud tag #use singular, not plural
+```
+
+The code above will have generated:
+- a migration (```database/migrations/yyyy_mm_dd_xyz_create_tags_table.php```);
+- a database table (```tags``` with just two columns: ```id``` and ```name```);
+- a model (```app/Models/Tag.php```);
+- a controller (```app/Http/Controllers/Admin/TagCrudController.php```);
+- a request (```app/Http/Requests/TagCrudRequest.php```);
+- a resource route, as a line inside ```routes/backpack/custom.php```;
+- a new item in the sidebar menu, in ```resources/views/vendor/backpack/base/inc/sidebar_content.blade.php```;
+
+**Next up:** we'll need to go through the generated files, and customize for our needs.
+
+
+## Customize Generated Files
+
+We'll skip the migration and database table, since there's nothing there specific to Backpack, nothing to customize, and we've already run the migration.
+
+
+### The Model
+
+Let's take a look at the generated model:
+
+```php
+
+### The Controller
+
+Let's take a look at ```app/Http/Controllers/Admin/TagCrudController.php```. It should look something like this:
+
+```php
+crud->setModel("App\Models\Tag");
+ $this->crud->setRoute("admin/tag");
+ $this->crud->setEntityNameStrings('tag', 'tags');
+ }
+
+ protected function setupListOperation()
+ {
+ // TODO: remove setFromDb() and manually define Columns, maybe Filters
+ $this->crud->setFromDb();
+ }
+
+ protected function setupCreateOperation()
+ {
+ $this->crud->setValidation(TagRequest::class);
+
+ // TODO: remove setFromDb() and manually define Fields
+ $this->crud->setFromDb();
+ }
+
+ protected function setupUpdateOperation()
+ {
+ $this->setupCreateOperation();
+ }
+}
+```
+
+#### The Basics
+
+What we should notice inside this TagCrudController is that:
+- ```TagCrudController extends CrudController```;
+- ```TagCrudController``` has a ```setup()``` method, where can plug in the basics of our CRUD panel; everything we write here is applied on ALL operations;
+- All operations are enabled by using that operation's trait on the controller;
+- Each operation is set up inside a ```setupXxxOperation()``` method;
+
+As we can tell from the comments in our ```setupXxxOperation()``` methods, in most cases we _shouldn't_ use ```$this->crud->setFromDb()```, which automagically figures out which columns and fields to show. That's because for real models, in real projects, it would _never_ be able to 100% figure out which field types to use. Real projects are very custom - that's a fact. In real projects, models are complicated, use a bunch of field types and you'll want to customize things. Instead of using ```setFromDb()``` then gradually changing what you don't like, **we heavily recommend you manually define all fields and columns you need**.
+
+That being said, since our ```Tag``` model is so simple, we _can_ leave it like this - it will work perfectly, since we only need a ```text``` field and a ```text``` column. But let's not do that. Let's define our fields and columns manually, like big boys & girls.
+
+#### Option 1. SetupXxxOperation Methods
+
+We can either define each operations inside its ```setupXxxOperation()``` method:
+
+```php
+ protected function setupListOperation()
+ {
+ $this->crud->addColumn(['name' => 'name', 'type' => 'text', 'label' => 'Name']);
+ }
+
+ protected function setupCreateOperation()
+ {
+ $this->crud->setValidation(TagRequest::class);
+ $this->crud->addField(['name' => 'name', 'type' => 'text', 'label' => 'Name']);
+ }
+
+ protected function setupUpdateOperation()
+ {
+ $this->setupCreateOperation(); // since this calls the methods above, no need to do anything here
+ }
+```
+
+This will:
+- disable the ```setFromDb()``` functionality (since we deleted that line);
+- add a simple ```text``` column for our ```name``` attribute for the List operation (the table view);
+- add a simple ```text``` field for our ```name``` attribute to the Create and Update forms;
+
+It's the exact same thing ```setFromDb()``` would have figured out, but done manually. This way, if we want to add [other columns](/docs/{{version}}/crud-columns)) or [other fields](/docs/{{version}}/crud-fields), we can easily do that. If we want to change the label of the ```name``` field from ```Name``` to ```Tag name```, we just make that small change. The benefits of _not_ using ```setFromDb()``` will be more obvious once you use Backpack on real models, we promise.
+
+#### Option 2. Operation Closures
+
+An alternative to defining operation inside ```setupXxxOperation()``` methods is to do it inside the ```setup()``` method. However, as we've mentioned before, everything you run in your ```setup()``` method is run for ALL operations. So you can easily end up bloating your operation with unnecessary operations. If you don't like having a method to configure each operation, and would like to define everything in ```setup()```, you should do so inside an ```operation()``` closure. Whatever's inside that closure will only be run for that operation. For example, everything we've done above would look like this if done inside operation closures:
+
+```php
+ public function setup()
+ {
+ $this->crud->setModel('App\Models\Tag');
+ $this->crud->setRoute(config('backpack.base.route_prefix') . '/tag');
+ $this->crud->setEntityNameStrings('tag', 'tags');
+
+ $this->crud->operation('list', function() {
+ $this->crud->addColumn(['name' => 'name', 'type' => 'text', 'label' => 'Name']);
+ });
+
+ $this->crud->operation(['create', 'update'], function() {
+ $this->crud->addValidation(TagCrudRequest::class);
+ $this->crud->addField(['name' => 'name', 'type' => 'text', 'label' => 'Name']);
+ });
+ }
+
+
+}
+```
+
+#### Other Calls
+
+Here, inside your ```setup()``` or ```setupXxxOperation``` methods, you can also do a lot of other things, like adding buttons, adding filters, customizing your query, etc. For a full list of the things you can do inside ```setup()``` check out our [cheat sheet](/docs/{{version}}/crud-cheat-sheet).
+
+Next, let's continue to another generated file.
+
+
+### The Request
+
+Backpack will also generate a [standard FormRequest file](https://laravel.com/docs/master/validation#form-request-validation), that you can use for validation of the Create and Update forms. There is nothing Backpack-specific in here, but let's take a look at the generated ```app/Http/Requests/TagRequest.php``` file:
+
+```php
+check();
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules()
+ {
+ return [
+ // 'name' => 'required|min:5|max:255'
+ ];
+ }
+
+ /**
+ * Get the validation attributes that apply to the request.
+ *
+ * @return array
+ */
+ public function attributes()
+ {
+ return [
+ //
+ ];
+ }
+
+ /**
+ * Get the validation messages that apply to the request.
+ *
+ * @return array
+ */
+ public function messages()
+ {
+ return [
+ //
+ ];
+ }
+}
+
+```
+
+This file is a 100% pure FormRequest file - all Laravel, nothing particular to Backpack. In generated FormRequest files, no validation rules are imposed by default. But we do want ```name``` to be ```required``` and ```unique```, so let's do that, using the [standard Laravel validation rules](https://laravel.com/docs/master/validation#available-validation-rules):
+
+```diff
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules()
+ {
+ return [
+- // 'name' => 'required|min:5|max:255'
++ 'name' => 'required|min:5|max:255|unique:tags,name'
+ ];
+ }
+```
+
+> If your validation needs to be different between the Create and Update operations, [you can easily do that too](/docs/{{version}}/crud-operation-create#separate-requests-for-create-and-update), by specifying different FormRequest files for each operation.
+
+
+### The Route
+
+We have already generated our CRUD route, and we don't need to do anything about it, but let's check our ```routes/backpack/custom.php```. It should look like this:
+
+```php
+ config('backpack.base.route_prefix', 'admin'),
+ 'middleware' => ['web', config('backpack.base.middleware_key', 'admin')],
+ 'namespace' => 'App\Http\Controllers\Admin',
+], function () { // custom admin routes
+ // CRUD resources and other admin routes
+ Route::crud('tag', 'TagCrudController');
+}); // this should be the absolute last line of this file
+```
+
+Here, we can see that our routes have been placed:
+- under a prefix that we can change in ```config/backpack/base.php```;
+- under a middleware we can change in ```config/backpack/base.php```;
+- inside the ```App\Http\Controllers\Admin``` namespace, because that's where our custom CrudControllers will be generated;
+
+**It's generally a good idea to have the all admin routes in this separate file.** If you edit this file in the future, make sure you leave the last line intact, so that other routes can be automatically generated inside this file. And of course, add your routes inside this route group, so that:
+- you have a single prefix for your admin routes (ex: ```admin/tag```, ```admin/product```, ```admin/dashboard```);
+- all your admin panel functionality is protected by the same middleware;
+- all your admin panel controllers live in one place (```App\Http\Controllers\Admin```);
+
+
+### The Menu Item
+
+We've previously generated a menu item in the ```views/vendor/backpack/base/inc/sidebar_content.php``` file. You'll see this file is pure HTML. This will allow you to customize the menu as much as you want. The "active" state of the menu is done with JavaScript, based on the ```href``` attribute.
+
+This is the bit that has been generated for you:
+
+```php
+
+```
+
+You can of course change anything here, if you want.
+
+
+## The result
+
+You are now ready to go to ```your-app-name.domain/admin/tag``` and see your fully functional admin panel for ```Tags```.
+
+**Congratulations, you should now have a good understanding of how Backpack\CRUD works!** This is a very very basic example, but the process will be identical for Models with 50+ attributes, complicated logic, etc.
diff --git a/4.0/demo.md b/4.0/demo.md
new file mode 100644
index 00000000..5aca183c
--- /dev/null
+++ b/4.0/demo.md
@@ -0,0 +1,66 @@
+# Demo
+
+---
+
+We've put together a working Laravel app (backend-only), that you can install on your machine. This should make it easier to:
+- see how it looks & feels;
+- see how it works;
+- change stuff in code, to see how easy it is to customize Backpack;
+
+In this [Demo repository](https://github.com/laravel-backpack/demo), we've:
+- installed Laravel 6;
+- installed Backpack\CRUD on top;
+- created a few demo models (Monsters, Icons, Products) and admin panels for them, using dozens of field types, column types, filters, etc - to show off most of Backpack's default features;
+- installed a few Backpack extensions: PermissionManager, PageManager, LogManager, BackupManager, Settings, MenuCRUD, NewsCRUD;
+
+
+>**Don't use this demo to start your real projects.** Please use [the recommended installation procedure](/docs/{{version}}/installation). You don't want all the bogus entities we've created. You don't want all the packages we've used. And you _definitely_ don't want the default admin user. Start from scratch.
+
+
+## Demo Preview
+
+If you just want to take a look at the Backpack interface and click around, you don't need to install the Demo. **Take a look at [demo.backpackforlaravel.com](https://demo.backpackforlaravel.com/admin) - we've installed for you.** The online demo is wiped and reinstalled every hour, on the hour.
+
+
+## Demo Installation
+
+1) In your ```Projects``` or ```www``` directory, wherever you host your apps:
+
+```zsh
+git clone https://github.com/Laravel-Backpack/demo.git backpack-demo
+```
+
+2) Set your database information in your ```.env``` file (use ```.env.example``` as an example);
+
+3) Install all the requirements:
+``` zsh
+cd backpack-demo
+composer install
+```
+
+4) Populate the database and stuff:
+```zsh
+php artisan key:generate
+php artisan migrate
+php artisan db:seed --class="Backpack\Settings\database\seeds\SettingsTableSeeder"
+php artisan db:seed
+```
+
+
+## Demo Usage
+
+Once everything's installed, and your database has been set up:
+
+- Your admin panel is available at http://localhost/backpack-demo/admin
+- Login with email ```admin@example.com```, password ```admin```
+- You can register a different account, to check out the process and see your gravatar inside the admin panel.
+- By default, registration is open only in your local environment. Check out ```config/backpack/base.php``` to change this and other preferences.
+- Check out the Monsters admin panel - it features over 40 field types.
+- The magic of Backpack is not in its standard functionality, but in how easy it is to code your own, or customize every little bit of it. Our recommendation:
+ - Go through the [CRUD Tutorial](/docs/{{version}}/crud-tutorial) to understand it;
+ - Create a new CRUD panel for an entity, using the faster procedure outlined at the end of that page; say... ```car```;
+
+
+>**vhost configurations**
+>
+>Depending on your vhost configuration you might need to access the application via a different url, for example if you're using ```artisan serve``` you can access it on http://127.0.0.1:8000/admin - if you're using Laravel Valet, then it may look like http://backpack-demo.test/admin - you will need to access the url which matches your systems configuration. If you do not understand how to configure your virtual hosts, we suggest [watching Laracasts Episode #1](https://laracasts.com/series/laravel-from-scratch/episodes/1) to quickly get started.
diff --git a/4.0/getting-started-advanced-features.md b/4.0/getting-started-advanced-features.md
new file mode 100644
index 00000000..cd1fedbd
--- /dev/null
+++ b/4.0/getting-started-advanced-features.md
@@ -0,0 +1,43 @@
+# 3. Advanced Features
+
+---
+
+**Duration:** 5 min
+
+Here are some other cool things Backpack makes easy for you. We recommend going through them one by one, just browsing. You might not need the feature _right now_, but when _you do_, you'll know how to find it.
+
+---
+
+
+## Other Operations
+- [Show](/docs/{{version}}/crud-operation-show) Operation - you can let your admins preview an entry
+- [Reorder](/docs/{{version}}/crud-operation-reorder) Operation - you can reorder and nesting entries (hierarchy tree)
+- [Revisions](/docs/{{version}}/crud-operation-revisions) Operation - you can keep a record of all modifications to an entry, and let your admin revert changes
+- [Clone](/docs/{{version}}/crud-operation-clone) Operation - you can make a copy of an entry;
+- [BulkDelete](/docs/{{version}}/crud-operation-delete) Operation - you can delete multiple items in one go;
+- [BulkClone](/docs/{{version}}/crud-operation-clone) Operation - you can clone multiple items in one go;
+
+---
+
+
+## Other Features
+- **Create & Update**
+ - [Manage files on disk](/docs/{{version}}/crud-how-to#use-the-media-library-file-manager) (media library)
+ - [Fake fields](/docs/{{version}}/crud-fields#fake-fields-all-stored-as-json-in-the-database)
+ - Translatable models and [multi-language CRUDs](/docs/{{version}}/crud-operation-update#translatable-models)
+ - [Tabs in create/update forms](/docs/{{version}}/crud-fields#split-fields-into-tabs)
+
+--
+
+- **ListEntries**
+ - you can add a "+" button next to each entry, to allow the admin to easily preview some quick information that was too big to fit inside a columns - we call it [details row](/docs/{{version}}/crud-operation-list-entries#details-row)
+ - export all visible items in the table by adding [export buttons](/docs/{{version}}/crud-operation-list-entries#export-buttons)
+ - [custom search logic](/docs/{{version}}/crud-columns#custom-search-logic) for the columns in the list view
+
+
+Additionally, here are a few more ways you can customize your CRUDs:
+- [Custom Views for each CRUD](/docs/{{version}}/crud-how-to#customize-views-for-each-crud-panel)
+- [Custom Content Class for each CRUD](/docs/{{version}}/crud-how-to#resize-the-content-wrapper-for-an-operation)
+- [Custom CSS or JS](/docs/{{version}}/crud-how-to#customize-css-and-js-for-default-crud-operations) for each CRUD Operation
+
+**That's it for today!** Told you we're done with long lessons :-) Hopefully some of the above have peaked your interest and you've clicked to see what Backpack can do. In the [next lesson](/docs/{{version}}/getting-started-license-and-support) we'll go through a few other Backpack packages that cover some recurring use cases.
diff --git a/4.0/getting-started-basics.md b/4.0/getting-started-basics.md
new file mode 100644
index 00000000..9afabc44
--- /dev/null
+++ b/4.0/getting-started-basics.md
@@ -0,0 +1,140 @@
+# 1. Basics
+
+---
+
+**Duration:** 5 minutes
+
+> **Are you already comfortable with Laravel?** In order to understand this series and make use of Backpack, you'll need to have a decent understanding of the Laravel framework. If you don't, please go ahead and [watch this excellent intro series on Laracasts](https://laracasts.com/series/laravel-from-scratch-2018) and accommodate yourself with Laravel first.
+
+
+
+## What is Backpack?
+A software that helps Laravel professionals build administration panels - secure areas where administrators login and create, read, update and delete application information. It is *not* a CMS, it is more a framework that lets you *build your own* CMS. You can install it in your existing project or in a totally new project.
+
+It's designed to be flexible enough to allow you to **build admin panels for everything from simple presentation websites to CRMs, ERPs, eCommerce, eLearning, etc**. We can vouch for that, because we have built all that stuff using Backpack already.
+
+
+## What's a CRUD?
+
+A **CRUD** is what we call a section of your admin panel that lets the admin _Create, Read, Update or Delete_ entries of a certain entity (or Model). So you can have a CRUD for Products, a CRUD for Articles, a CRUD for Categories, or whatever else you might want to create, read, update or delete.
+
+For the purpose of this series, we'll show examples on the ```Tag``` entity. This is what a Tag CRUD could look like:
+
+
+
+But Backpack is prepared for feature-packed CRUDs - since it's a good tool for very complex projects too. Here's what a CRUD that uses all of Backpack's features could look like:
+
+
+
+Mind that you will _almost never_ use all of Backpack's features in one CRUD. But if you do... it still looks good, and it'll be intuitive to use.
+
+
+## Main Features
+
+
+### Front-End Design
+
+Backpack installs the [CoreUI](https://coreui.io) HTML theme, and our own design on top - [Backstrap](https://backstrap.net). It uses Bootstrap 4, and has many HTML blocks ready for you to use. When you're building a custom page in your admin panel, it's easy to just copy-paste the HTML from our [Backstrap demo](https://backstrap.net), or from the [CoreUI documentation](https://coreui.io/docs/getting-started/introduction/), and it look good, without you having to design anything.
+
+It also installs Noty for triggering JS notification bubbles, and SweetAlerts. So you can easily use these across your admin panel. You can [trigger notification bubbles in PHP](/docs/{{version}}/base-about#triggering-notification-bubbles-in-php) or [trigger notification bubbles in JavaScript](/docs/{{version}}/base-about#triggering-notification-bubbles-in-javascript).
+
+
+
+### Authentication
+
+Backpack comes with a basic authentication system that's separate from Laravel's. This way, you can have different login screens for users & admins, if you need. If not, you can choose to use only one authentication - either Laravel's, or Backpack's.
+
+
+
+After you [install Backpack](/docs/{{version}}/installation) (don't do it now), you'll be able to log into your admin panel at ```http://yourapp/admin```. You can change the URL prefix from ```admin``` to something else in your ```config/backpack/base.php``` file, along with a bunch of other configuration options. [Click here](https://github.com/Laravel-Backpack/CRUD/blob/master/src/config/backpack/base.php) to browse the configuration file and see what it can do for you.
+
+
+
+### CRUDs
+
+This is where it gets interesting. As soon as you [install Backpack](/docs/{{version}}/installation) in your project, you can create **CRUDs** for your admins to easily manipulate DB information. Let's browse through a simple example, of creating a CRUD administration panel for a Tag entity:
+
+```zsh
+# STEP 1. create migration
+php artisan make:migration:schema create_tags_table --model=0 --schema="name:string:unique,slug:string:unique"
+php artisan migrate
+
+# STEP 2. create crud
+php artisan backpack:crud tag #use singular, not plural
+```
+
+This will create a simple CRUD panel, which you should now be able to see in the Sidebar.
+
+For a simple entry like this, the generated CRUD panel will even work "as is", no need for customizations. But don't expect this for more complex entities. They will usually have particularities and need customization. That's where Backpack shines - modifying anything in the CRUD Panel is easy and intuitive, once you understand how it works.
+
+The code above would generate:
+- a **migration** file
+- a **model** (```app\Models\Tag.php```)
+- a **request** file, for form validation (```app\Http\Requests\TagCrudRequest.php```)
+- a **controller** file, where you can customize how the CrudPanel looks and feels (```app\Http\Controllers\Admin\TagCrudController.php```)
+- a **route**, as a line inside ```routes/backpack/custom.php```
+
+It will also add:
+- a route inside ```routes/backpack/custom.php```, pointing to that controller;
+- a sidebar item inside ```resources/views/vendor/backpack/base/inc/sidebar_content.blade.php```;
+
+You might have noticed that **no views** are generated. That's because in most cases you _don't need_ custom views with Backpack. All your custom code is in the controller, model or request, so the default views are loaded, from the package. If you do, however, need to customize a view, it is [ridiculously easy](/docs/{{version}}/crud-how-to#customize-views-for-each-crud-panel).
+
+Also, we won't be covering the **migration**, **model** and **request** files here, as they are in no way custom. The only thing you need to make sure is that the Model is properly configured (db table, relationships, ```$fillable``` or ```$guarded``` properties, etc) and that it uses our ```CrudTrait```. What we _will_ be covering is ```TagCrudController``` - which is where most of your logic will reside. Here's a copy of a simple one you might use to achieve the above:
+
+```php
+crud->setModel("App\Models\Tag");
+ $this->crud->setRoute("admin/tag");
+ $this->crud->setEntityNameStrings('tag', 'tags');
+ }
+
+ public function setupListOperation()
+ {
+ $this->crud->setColumns(['name', 'slug']);
+ }
+
+ public function setupCreateOperation()
+ {
+ $this->crud->setValidation(TagCrudRequest::class);
+
+ $this->crud->addField([
+ 'name' => 'name',
+ 'type' => 'text',
+ 'label' => "Tag name"
+ ]);
+ $this->crud->addField([
+ 'name' => 'slug',
+ 'type' => 'text',
+ 'label' => "URL Segment (slug)"
+ ]);
+ }
+
+ public function setupUpdateOperation()
+ {
+ $this->setupCreateOperation();
+ }
+}
+```
+
+You should notice:
+- It uses basic inheritance (```TagCrudController extends CrudController```); so if you want to modify a behaviour (save, update, reorder, etc), you can easily do that by overwriting the corresponding method in your ```TagCrudController```;
+- All operations are enabled by using that operation's trait on the controller;
+- The ```setup()``` method defines the basics of the CRUD panel;
+- Each operation is set up inside a ```setupXxxOperation()``` method;
+
+**That's all for today! **If you want to learn more, go ahead and [read the next lesson](/docs/{{version}}/getting-started-crud-operations) of this series.
diff --git a/4.0/getting-started-crud-operations.md b/4.0/getting-started-crud-operations.md
new file mode 100644
index 00000000..fe8f5c05
--- /dev/null
+++ b/4.0/getting-started-crud-operations.md
@@ -0,0 +1,248 @@
+# 2. CRUD Operations
+
+---
+
+**Duration:** 10 minutes
+
+Let's bring back the example in our first lesson. The Tags CRUD:
+
+
+
+With its ```TagCrudController```:
+
+```php
+crud->setModel("App\Models\Tag");
+ $this->crud->setRoute("admin/tag");
+ $this->crud->setEntityNameStrings('tag', 'tags');
+ }
+
+ public function setupListOperation()
+ {
+ $this->crud->setColumns(['name', 'slug']);
+ }
+
+ public function setupCreateOperation()
+ {
+ $this->crud->setValidation(TagCrudRequest::class);
+
+ $this->crud->addField([
+ 'name' => 'name',
+ 'type' => 'text',
+ 'label' => "Tag name"
+ ]);
+ $this->crud->addField([
+ 'name' => 'slug',
+ 'type' => 'text',
+ 'label' => "URL Segment (slug)"
+ ]);
+ }
+
+ public function setupUpdateOperation()
+ {
+ $this->setupCreateOperation();
+ }
+}
+```
+
+In the example above, we've enabled the most common operations:
+- **Create** - using a create form (aka "*add form*")
+- **List** - using AJAX DataTables (aka "*list view*", aka "*table view*")
+- **Update** - using an update form (aka "*edit form*")
+- **Delete** - using a *button* in the *list view*
+- **Show** - using a *button* in the *list view*
+
+These are the basic operations an admin can execute on an Eloquent model, thanks to Backpack. We do have additional operations (Reorder, Revisions, Clone, BulkDelete, BulkClone), and you can easily _create a custom operation_, but let's not get ahead of ourselves. Baby steps. **Let's go through the most important features of the operations you'll be using _all the time_: ListEntries, Create and Update**.
+
+
+## Create & Update Operations
+
+
+
+
+### Fields
+
+Inside your Controller's ```setupCreateOperation()``` or ```setupUpdateOperation()``` method, you'll be able to define what fields you want the admin to see, when creating/updating entries. In the example above, we only have two fields, both using the ```text``` field type. So that's what's shown to the admin. When the admin presses _Save_, assuming your model has those two attributes as ```$fillable```, Backpack will save the entry and take you back to the ListEntries view. Keep in mind we're using a _pure_ Eloquent model. So of course, inside the model you could use accessors, mutators, events, etc.
+
+
+But a lot of times, you won't just need text inputs. You'll need datepickers, upload buttons, 1-n relationship, n-n relationships, textareas, etc. For each field, you only need to define it properly in the Controller. Here are the most used methods to manipulate fields:
+
+```php
+$this->crud->addField($field_definition_array);
+$this->crud->addFields([$field_definition_array_1, $field_definition_array_2]);
+$this->crud->removeField('name');
+$this->crud->removeFields(['name_1', 'name_2']);
+
+// pro tip:
+// a quick way to add simple fields: let the CRUD decide what field type it is
+$this->crud->addField('db_column_name');
+```
+
+A typical *field definition array* will need at least three things:
+- ```name``` - the attribute (column in the database), which will also become the name of the input;
+- ```type``` - the kind of field we'd like to use (text, number, select2, etc);
+- ```label``` - the human-readable label for the input (will be generated from ```name``` if not given);
+
+
+You can use [one of the 44+ field types we've provided](/docs/{{version}}/crud-fields#default-field-types), or easily [create a custom field type](/docs/{{version}}/crud-fields#creating-a-custom-field-type) if you have some super-specific need that we haven't covered yet, or even [overwrite how a field type works](#overwriting-default-field-types). Take a few minutes and [browse the 44+ field types](/docs/{{version}}/crud-fields#default-field-types), to understand how the definition array differs from one to another and how many use cases you have already covered.
+
+Let's take another example, slightly more complicated than the ```text``` fields we used above. Something you'll encounter all the time is relationship fields. So let's say the ```Tag``` model has an **n-n relationship** with an Article model:
+
+```php
+ public function articles()
+ {
+ return $this->belongsToMany('App\Models\Article', 'article_tag');
+ }
+```
+
+We could use the code below to add a ```select2_multiple``` field to the Tag update forms:
+
+```php
+$this->crud->addField([
+ 'type' => 'select2_multiple',
+ 'name' => 'articles', // the relationship name in your Model
+ 'entity' => 'articles', // the relationship name in your Model
+ 'attribute' => 'title', // attribute on Article that is shown to admin
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
+]);
+```
+
+**Notes:**
+- If we call this inside ```setupUpdateOperation()``` it will only be added on that operation;
+- Because we haven't specified a ```label```, Backpack will take the "_articles_" name and turn it into a label: "_Articles_";
+
+If we had an Articles CRUD, and the reverse relationship defined on the ```Article``` model too, we could also add a ```select2_multiple``` field in the Article CRUD, to allow the admin to choose which tags apply to each article. This actually makes more sense than the above :-)
+
+```php
+$this->crud->addField([
+ 'label' => "Tags",
+ 'type' => 'select2_multiple',
+ 'name' => 'tags', // the method that defines the relationship in your Model
+ 'entity' => 'tags', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
+]);
+```
+
+> When generating a CrudController, you might be using the ```$this->crud->setFromDb();``` method by default, which tries to figure out what fields you might need in your create/update forms and what columns in your list view, but - as you'd expect - it only works for the simple field types. You can:
+>
+> (1) choose to keep using ```setFromDb()``` and add/remove/change additional fields
+>
+> or
+>
+> (2) delete ```setFromDb()``` and manually define each field and column;
+>
+> **Our recommendation**, for anything but the simplest CRUDs, **is to manually define each field** - much easier to understand and customize, for your future self and any other developer that comes after you.
+
+
+### Callbacks
+
+Developers coming from GroceryCRUD on CodeIgniter or other CRUD systems will be looking for callbacks to run ```before_insert```, ```before_update```, ```after_insert```, ```after_update```. **There are no callbacks in Backpack**. The ```store()``` and ```update()``` code is inside a trait, so you can easily overwrite that method, and call it inside your new method. For example, here's how we can do things before/after an item is saved in the Create operation:
+
+```php
+traitStore();
+ // do something after save
+ return $response;
+ }
+}
+```
+
+>But before you do that, ask yourself - **_is this something that should be done when an entry is added/updated/deleted from the application, too_**? Not just the admin panel? If so, a better place for it would be the Model. Remember your Model is a pure Eloquent Model, so the cleanest way might be to use [Eloquent Event Observers](https://laravel.com/docs/6.0/eloquent#events) or [accessors and mutators](https://laravel.com/docs/master/eloquent-mutators#accessors-and-mutators).
+
+
+## List Operation
+
+List shows the admin a table with all entries. On the front-end, the information is pulled using AJAX calls, and shown using DataTables. It's the most feature-packed operation in Backpack, but right now we're just going through the most important features you need to know about: columns, filters and buttons.
+
+You should configure the List operation inside the ```setupListOperation()``` method.
+
+
+### Columns
+
+Columns help you specify *which* attributes are shown in the table and *in which order*. **Their syntax is super-similar to fields**:
+
+```php
+$this->crud->addColumn($column_definition_array); // add a single column, at the end of the table
+$this->crud->addColumns([$column_definition_array_1, $column_definition_array_2]); // add multiple columns, at the end of the table
+$this->crud->removeColumn('column_name'); // remove a column from the table
+$this->crud->removeColumns(['column_name_1', 'column_name_2']); // remove an array of columns from the table
+$this->crud->setColumnDetails('column_name', ['attribute' => 'value']);
+$this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
+
+$this->crud->setColumns([$column_definition_array_1, $column_definition_array_2]); // make these the only columns in the table
+```
+
+You can use one of the [14+ column types](/docs/{{version}}/crud-columns#default-column-types) to show information to the user in the table, or easily [create a custom column type](/docs/{{version}}/crud-columns#creating-a-custom-column-type), if you have a super-specific need. Here's an example of using the methods above:
+
+```php
+$this->crud->addColumn([
+ 'name' => 'published_at',
+ 'type' => 'date',
+ 'label' => 'Publish_date',
+]);
+
+// PRO TIP: to quickly add a text column, just pass the name string instead of an array
+$this->crud->addColumn('text'); // adds a text column, at the end of the stack
+```
+
+
+### Filters
+
+
+
+Filters provide an easy way for the admin to well… _filter_ the ListEntries table. The syntax is very similar to Fields and Columns and you can use one of the [existing 8 filter types](/docs/{{version}}/crud-filters) or easily [create a custom filter](/docs/{{version}}/crud-filters#creating-custom-filters).
+
+```php
+$this->crud->addFilter($options, $values, $filter_logic);
+$this->crud->removeFilter($name);
+$this->crud->removeAllFilters();
+```
+
+For more on this, check out the [filters documentation page](/docs/{{version}}/crud-filters), when you need them.
+
+
+### Buttons
+
+
+
+If you want to add a custom button to an entry, you can do that. If you want to remove a button, you can also do that. Look for the [buttons documentation](/docs/{{version}}/crud-buttons) when you need it.
+
+```php
+// positions: 'beginning' and 'end'
+// stacks: 'line', 'top', 'bottom'
+// types: view, model_function
+$this->crud->addButton($stack, $name, $type, $content, $position);
+$this->crud->removeButton($name);
+$this->crud->removeButtonFromStack($name, $stack);
+```
+
+**That's it for today!** Thanks for sticking with us this long. This has been the most important and longest lesson. You can go ahead and [install Backpack](/docs/{{version}}/installation) now, as you've already gone through the most important features. Or [read the next lesson](/docs/{{version}}/getting-started-advanced-features), about advanced features.
\ No newline at end of file
diff --git a/4.0/getting-started-license-and-support.md b/4.0/getting-started-license-and-support.md
new file mode 100644
index 00000000..ba628e86
--- /dev/null
+++ b/4.0/getting-started-license-and-support.md
@@ -0,0 +1,43 @@
+# 4. Add-ons, License & Support
+
+---
+
+**Duration:** 3 minutes
+
+
+## Add-ons
+
+In addition to our core packages (Base and CRUD), we have quite a few packages you can install or download, that treat common use cases. Some have been developed by our core team, some by our wonderful community. For example, we have plug&play interfaces to manage [site-wide settings](https://github.com/Laravel-Backpack/Settings), [the default Laravel users table](https://github.com/eduardoarandah/UserManager), [users, groups & permissions](https://github.com/Laravel-Backpack/PermissionManager), [content for custom pages, using page templates](https://github.com/Laravel-Backpack/PageManager), [news articles, categories and tags](https://github.com/Laravel-Backpack/NewsCRUD), etc.
+
+Take a look at:
+- [all official add-ons](/docs/{{version}}/add-ons-official)
+- [all community add-ons](/docs/{{version}}/add-ons-community)
+
+
+## License
+
+Backpack is **free for non-commercial use**, but needs a license code in order to prevent "_unlicensed use_" notification bubbles and interruption of service. You can get a license code for your project:
+- ```free```, if you're using it for non-commercial purposes; [apply here](https://backpackforlaravel.com/pricing);
+- ```free```, if you've contributed to Backpack on Github; [apply here](https://backpackforlaravel.com/pricing);
+- ```€69 EUR/project```, if you're making money using it for a project; [buy here](https://backpackforlaravel.com/pricing);
+- ```€399 EUR for unlimited projects```, if you use Backpack a lot; [buy here](https://backpackforlaravel.com/pricing);
+
+**Freelancers** or companies **who make money using Backpack** - for themselves, their employers or their clients, **should [purchase a commercial license here](https://backpackforlaravel.com/pricing)**.
+
+
+>**You don't need a license code on LOCALHOST.** If you're just trying Backpack on your own machine, you don't need a license code. You only need a license code when you take your application to production.
+
+
+## Support
+
+With thousands of developers using Backpack, a lot of them non-commercial, and such a small price, **we can't offer official support for the packages**. We've been doing this since 2016, we actively maintain the packages, we try to squash any bugs ASAP and add new features all the time, but we unfortunately can't spend time on back-and-forth on implementation issues in your project. But. We do have good documentation and have been blessed with a **great community**, where people help each other out. If Backpack becomes your tool of preference, I highly recommend you join our gang. Help others get started, create cool stuff, or even influence the direction of Backpack:
+
+- **[StackOverflow tag](https://stackoverflow.com/questions/tagged/backpack-for-laravel) for support requests** (If you need help creating something using Backpack, post your question on StackOverflow using the ```backpack-for-laravel``` tag. We've been blessed with a great community that is happy to help. Who doesn't like getting StackOverflow points?)
+- **[Gitter Chatroom](https://gitter.im/BackpackForLaravel/Lobby) for quick questions** (If you have an urgent matter that won't take much time to answer, use our 24/7 Gitter chatroom. Be considerate, everyone's probably working on their own project right now.)
+- **[Github Issues](https://github.com/laravel-backpack/) for bugs** (Found a bug? Great! Please search for it on Github first - someone might have already found it. If not, open an issue, we're happy to learn about it and make Backpack better. )
+
+Thank you for sticking up with us for so long. This is the last Backpack lesson we can give you. **Now you have absolutely no excuse not to start your first Backpack project :-)** Here are a few links for if you still don't think you're ready:
+
+- [Go through the demo](/docs/{{version}}/demo) and play around
+- Read this [CRUD Tutorial](/docs/{{version}}/crud-tutorial)
+- Take a look at the [CrudController API Cheat Sheet](/docs/{{version}}/crud-cheat-sheet)
diff --git a/4.0/index.md b/4.0/index.md
new file mode 100644
index 00000000..e692fe22
--- /dev/null
+++ b/4.0/index.md
@@ -0,0 +1,46 @@
+#### About
+
+- [Getting Started](/docs/{{version}}/introduction)
+ - [1. Basics](/docs/{{version}}/getting-started-basics)
+ - [2. CRUD Operations](/docs/{{version}}/getting-started-crud-operations)
+ - [3. Advanced Features](/docs/{{version}}/getting-started-advanced-features)
+ - [4. Add-ons, License & Support](/docs/{{version}}/getting-started-license-and-support)
+- [Demo](/docs/{{version}}/demo)
+- [Installation](/docs/{{version}}/installation)
+- [Release Notes](/docs/{{version}}/release-notes)
+- [Upgrade Guide](/docs/{{version}}/upgrade-guide)
+
+#### Admin UI
+
+- [About](/docs/{{version}}/base-about)
+- [Widgets](/docs/{{version}}/base-widgets)
+- [Breadcrumbs](/docs/{{version}}/base-breadcrumbs)
+- [How To](/docs/{{version}}/base-how-to)
+
+#### CRUD Pages
+
+- [Basics](/docs/{{version}}/crud-basics)
+- [Tutorial](/docs/{{version}}/crud-tutorial)
+- [API](/docs/{{version}}/crud-api)
+- [Cheat Sheet](/docs/{{version}}/crud-cheat-sheet)
+- [Operations](/docs/{{version}}/crud-operations)
+ + [List](/docs/{{version}}/crud-operation-list-entries)
+ + [Columns](/docs/{{version}}/crud-columns)
+ + [Buttons](/docs/{{version}}/crud-buttons)
+ + [Filters](/docs/{{version}}/crud-filters)
+ + [Create](/docs/{{version}}/crud-operation-create) & [Update](/docs/{{version}}/crud-operation-update)
+ + [Fields](/docs/{{version}}/crud-fields)
+ + [Delete](/docs/{{version}}/crud-operation-delete)
+ + [Clone](/docs/{{version}}/crud-operation-clone)
+ + [Show](/docs/{{version}}/crud-operation-show)
+ + [Columns](/docs/{{version}}/crud-columns)
+ + [Reorder](/docs/{{version}}/crud-operation-reorder)
+ + [Revisions](/docs/{{version}}/crud-operation-revisions)
+- [How To](/docs/{{version}}/crud-how-to)
+
+
+#### Add-ons
+
+- [Official Add-ons](/docs/{{version}}/add-ons-official)
+- [Community Add-ons](/docs/{{version}}/add-ons-community)
+- [How to Create an Add-on](/docs/{{version}}/add-ons-tutorial)
diff --git a/4.0/install-optionals.md b/4.0/install-optionals.md
new file mode 100644
index 00000000..16d4c8c0
--- /dev/null
+++ b/4.0/install-optionals.md
@@ -0,0 +1,150 @@
+# Install Optional Packages
+
+---
+
+Each Backpack package has its own installation instructions in its readme file. We duplicate them here for easy access.
+
+Everything else is optional. Your project might use them or it might not. Only do each of the following steps if you need the functionality that package provides.
+
+
+## BackupManager
+
+[>> See screenshots and installation](https://github.com/Laravel-Backpack/BackupManager)
+
+1) In your terminal
+
+``` bash
+# Install the package
+composer require backpack/backupmanager
+
+# Publish the config file and lang files:
+php artisan vendor:publish --provider="Backpack\BackupManager\BackupManagerServiceProvider"
+
+# [optional] Add a sidebar_content item for it
+php artisan backpack:add-sidebar-content "
"
+```
+
+2) Add a new "disk" to config/filesystems.php:
+
+```php
+ // used for Backpack/BackupManager
+ 'backups' => [
+ 'driver' => 'local',
+ 'root' => storage_path('backups'), // that's where your backups are stored by default: storage/backups
+ ],
+```
+This is where you choose a different driver if you want your backups to be stored somewhere else (S3, Dropbox, Google Drive, Box, etc).
+
+3) [optional] Modify your backup options in config/backup.php
+
+4) [optional] Instruct Laravel to run the backups automatically in your console kernel:
+
+```php
+// app/Console/Kernel.php
+
+protected function schedule(Schedule $schedule)
+{
+ $schedule->command('backup:clean')->daily()->at('04:00');
+ $schedule->command('backup:run')->daily()->at('05:00');
+}
+```
+
+5) [optional] If you need to change the path to the mysql_dump command, you can do that in your config/database.php file. For MAMP on Mac OS, add these to your mysql connection:
+```
+ 'dump' => [
+ 'dump_binary_path' => '/Applications/MAMP/Library/bin/', // only the path, so without `mysqldump` or `pg_dump`
+ 'use_single_transaction',
+ 'timeout' => 60 * 5, // 5 minute timeout
+ ]
+```
+
+
+## LogManager
+
+[>> See screenshots and installation](https://github.com/Laravel-Backpack/logmanager)
+
+
+1) Install via composer:
+
+``` bash
+composer require backpack/logmanager
+```
+
+2) Add a "storage" filesystem disk in config/filesystems.php:
+
+```
+// used for Backpack/LogManager
+'storage' => [
+ 'driver' => 'local',
+ 'root' => storage_path(),
+ ],
+```
+
+3) Configure Laravel to create a new log file for every day, in your .ENV file, if it's not already. Otherwise there will only be one file at all times.
+
+```
+ APP_LOG=daily
+```
+
+or directly in your config/app.php file:
+```
+ 'log' => env('APP_LOG', 'daily'),
+```
+
+4) [optional] Add a menu item for it in resources/views/vendor/backpack/base/inc/sidebar_content.blade.php or menu.blade.php:
+
+```bash
+php artisan backpack:add-sidebar-content "
"
+```
+
+## Settings
+
+An interface for the administrator to easily change application settings. Uses Laravel Backpack.
+
+[>> See screenshots and installation](https://github.com/Laravel-Backpack/settings)
+
+Installation:
+
+``` bash
+# install the package
+composer require backpack/settings
+
+# run the migration
+php artisan vendor:publish --provider="Backpack\Settings\SettingsServiceProvider"
+php artisan migrate
+
+# [optional] add a menu item for it to the sidebar_content file
+php artisan backpack:add-sidebar-content "
"
+
+# [optional] insert some example dummy data to the database
+php artisan db:seed --class="Backpack\Settings\database\seeds\SettingsTableSeeder"
+```
+
+
+## PageManager
+
+An admin panel where you, as a developer, can define templates with different fields, and the admin can choose between those templates to create/edit pages with content.
+
+[>> See screenshots and installation](https://github.com/Laravel-Backpack/pagemanager)
+
+
+## PermissionManager
+
+An admin panel for user authentication on Laravel 5, using Backpack\CRUD. Add, edit, delete users, roles and permission.
+
+[>> Installation](https://github.com/Laravel-Backpack/PermissionManager#install)
+[>> Github](https://github.com/Laravel-Backpack/PermissionManager)
+
+
+## MenuCrud
+
+An admin panel for menu items on Laravel 5, using Backpack\CRUD. Add, edit, reorder, nest, rename menu items and link them to Backpack\PageManager pages, external link or custom internal link.
+
+[>> Github](https://github.com/Laravel-Backpack/MenuCRUD)
+
+
+## NewsCrud
+
+Since NewsCRUD does not provide any extra functionality other than Backpack\CRUD, it is not a package. It's just a tutorial to show you how this can be achieved. In the future, CRUD examples like this one will be easily installed from the command line, from a central repository. Until then, you will need to manually create the files.
+
+[>> Github](https://github.com/Laravel-Backpack/NewsCRUD)
diff --git a/4.0/installation.md b/4.0/installation.md
new file mode 100644
index 00000000..c67c93b4
--- /dev/null
+++ b/4.0/installation.md
@@ -0,0 +1,74 @@
+# Installation
+
+---
+
+
+## Requirements
+
+If you can run Laravel 5.8, Laravel 6 or Laravel 7, you can install Backpack. Backpack does _not_ have additional requirements. For the following process, we assume:
+
+- you have a [working installation of Laravel](https://laravel.com/docs/7.x#installation) (an existing project is fine, you don't need a *fresh* Laravel install);
+
+- you have put your database and email credentials in your .ENV file;
+
+- you can run the ```composer``` command from any directory (you have ```composer``` registered as a global command); if you need to run ```php composer.phar``` or reference another directory, please remember to adapt the commands below to your configuration;
+
+
+## Installation
+
+
+### Install Core Packages
+
+0) Open your project folder in your terminal:
+
+```bash
+cd your-laravel-project-name
+```
+
+1) In your project's main directory, install CRUD using composer:
+
+``` bash
+composer require backpack/crud:"4.0.*"
+
+# you might also want to install these tools that help during development
+composer require backpack/generators --dev
+composer require laracasts/generators --dev
+```
+
+2) Now run the installation commands for Backpack:
+
+``` bash
+php artisan backpack:install
+```
+
+Note: If you'd also like to enable the [file manager functionality](https://backpackforlaravel.com/uploads/home_slider/4.png), reply "yes" when the installer asks you. By default it lets users manage the ```public/uploads``` directory, but you can change that in the ```elfinder.php``` config file. Most of the times it is _not_ recommended to give your admins power over file structure - not even their uploads alone. So ```elfinder``` does not come installed by default.
+
+3) [Optional] You should now:
+- Change configuration values in ```config/backpack/base.php``` to make the admin panel your own. Backpack is white label, so you can change everything: menu color, project name, developer name etc.
+- If your User model has been moved (it is not ```App\User.php```, please go change ```App\Models\BackpackUser.php``` and make sure it extends the correct user model;
+- If you have separate admin panels for Users and Administrators, and already have a way to differentiate between the two, please change ```app/Http/Middleware/CheckIfAdmin.php```, particularly ```checkIfUserIsAdmin($user)```, to make sure all users who get log into the admin panel have a right to do that;
+- If your application has only one login screen (for the admins), that means you're not going to use the auth controllers that Laravel provided by default. You're only going to use Backpack's auth controllers. You can keep the Laravel ones in your project, of course. But some people like to delete them to not get confused later on:
+
+``` bash
+# OPTIONAL! Please read the notice above.
+rm -rf app/Http/Controllers/Auth #deletes laravel's demo auth controllers
+```
+
+That's it. If you already know how to use Backpack, next up you'll probably want to [create CRUD Panels](/docs/{{version}}/crud-tutorial#generate-files).
+
+> If it's your first time installing Backpack, it is **highly recommended** that you go through our [Getting Started series](/docs/{{version}}/getting-started-basics), to understand how Backpack works. That's why we created it - to help you learn how to use this admin panel framework. In ~23 minutes we'll teach you 80% of what you can do, and how.
+
+
+
+### Install Add-ons
+
+In case you want to add extra functionality that's already been built, check out [the installation steps for the add-ons we've developed](/docs/{{version}}/install-optionals).
+
+
+## Frequently Asked Questions
+
+- **Error: The process X exceeded the timeout of 60 seconds.** It might mean Github or Packagist is unavailable at the moment. This usually doesn't last for more than a few minutes, so you can run ```php artisan backpack:install --timeout=600``` to increase the timeout to 10 minutes. If this doesn't work either, take a look behind the scenes with ```php artisan backpack:install --timeout=600 --debug```, and refer to [this thread](https://github.com/Laravel-Backpack/Base/issues/217).
+
+- **Error: SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long**. Your MySQL version might be a bit old. Please [apply this quick fix](https://laravel-news.com/laravel-5-4-key-too-long-error), then run ```php artisan migrate:fresh```.
+
+- **Any other installation error?** If you can't install Backpack\\Base because of a different error, you can [try the manual installation process](/docs/{{version}}/base-how-to#manually-install-base), which you can tweak to your needs.
diff --git a/4.0/introduction.md b/4.0/introduction.md
new file mode 100644
index 00000000..b55de1a5
--- /dev/null
+++ b/4.0/introduction.md
@@ -0,0 +1,76 @@
+# Getting Started
+
+---
+
+Backpack is a collection of Laravel packages that help you **build custom administration panels**, for anything from presentation websites to complex web applications. You can install them on top of existing Laravel installations _or_ fresh projects.
+
+In a nutshell:
+
+- Backpack will provide you with a _visual interface_ for the admin panel (the HTML, the CSS, the JS); it pulls in the excellent [CoreUI](https://coreui.io/) theme, with our own design called [Backstrap](https://backstrap.net), adds authentication functionality & bubble notifications; when you decide to build a custom feature for your admin panel, you already have the HTML blocks for the UI, and it will look good;
+- Backpack will help you build _sections where your admins can manipulate entries for Eloquent models_; we call them _CRUD Panels_ after the most basic operations: Create/Read/Update/Delete; after [understanding Backpack](/docs/{{version}}/getting-started-basics), you'll be able to create a CRUD panel for each entity in about 10 minutes / model:
+
+```bash
+# STEP 0. create migration (in case you're starting from scratch)
+php artisan make:migration:schema create_tags_table --model=0 --schema="name:string:unique"
+php artisan migrate
+
+# STEP 1. create a model, a request and a controller for the admin panel
+php artisan backpack:crud tag #use singular, not plural
+
+# STEP 2. add a route for this admin panel to routes/backpack/custom.php
+php artisan backpack:add-custom-route "Route::crud('tag', 'TagCrudController');"
+
+# STEP 3. go through the generated files, customize according to your needs
+```
+
+
+## Need to Know
+
+
+### Requirements
+
+ - Laravel 7, Laravel 6 or Laravel 5.8
+ - PHP 7.2.5+
+ - MySQL (recommended) / PostgreSQL / SQLite / SQL Server
+
+
+### Screenshots
+
+Take a look at [our homepage](https://backpackforlaravel.com/).
+
+
+### Demo
+
+You can easily [install our demo Laravel project with Backpack installed](/docs/{{version}}/demo) and play around.
+
+
+### Security
+
+Backpack has never had a critical vulnerability/hack. But there _have_ been important security updates for dependencies (including Laravel). Please [login with Github](/auth/github) or [subscribe to our monthly newsletter](https://backpackforlaravel.com/newsletter), so we can reach you in case anything bad happens. No spam, no marketing emails, we promise. We only send one email per month max, when we introduce major Backpack updates.
+
+
+### Maintenance
+
+Backpack 4.0 is the current version, and is being actively maintained by Backpack's creator, [Cristian Tabacitu](https://tabacitu.ro), with the help of a wonderful community of Backpack veterans. [See all contributors](https://github.com/Laravel-Backpack/CRUD/graphs/contributors).
+
+
+### License
+
+Backpack is under a license we call "_You make money, I make money_" (YummY). Backpack's source is public, and you can use it for free for non-commercial purposes (testing, non-profits, personal use, etc), but if you make money using it, you need to purchase a commercial license. Please see [the pricing section](https://backpackforlaravel.com/pricing) for more details. In production, you need a license code for both commercial and non-commercial use, to prevent nagging notification bubbles. **On localhost, you don't need a license code.**
+
+
+### Add-ons
+
+In addition to our core CRUD package, there are a few extra that treat common use cases. Some have been developed by our core team, some by our wonderful community. You can just install interfaces to manage [site-wide settings](https://github.com/Laravel-Backpack/Settings), [the default Laravel users table](https://github.com/eduardoarandah/UserManager), [users, groups & permissions](https://github.com/Laravel-Backpack/PermissionManager), [content for custom pages, using page templates](https://github.com/Laravel-Backpack/PageManager), [news articles, categories and tags](https://github.com/Laravel-Backpack/NewsCRUD), etc.
+
+For more, please see:
+- [all official add-ons](/docs/{{version}}/add-ons-official)
+- [all community add-ons](/docs/{{version}}/add-ons-community)
+
+
+## How to Start
+
+We heavily recommend you spend a little time to understand Backpack, and only afterwards install and use it. Currently your options are:
+- **[Text Tutorial](/docs/{{version}}/getting-started-basics)** - 23 minutes
+- **[Email Tutorial](https://backpackforlaravel.com/getting-started-emails)** - 1 email per day, for 5 days, 5 minutes each
+- **Video Tutorial** - working on it
diff --git a/4.0/release-notes.md b/4.0/release-notes.md
new file mode 100644
index 00000000..aa590b60
--- /dev/null
+++ b/4.0/release-notes.md
@@ -0,0 +1,89 @@
+# Release Notes
+
+---
+
+**Launch date:** September 24th, 2019
+
+Here are the main differences between [Backpack 3.6](https://backpackforlaravel.com/docs/3.6) and Backpack 4.0.
+
+
+# Added
+- using Bootstrap 4 instead of Bootstrap 3;
+- new design; we're now using a custom design we made, called [Backstrap](https://backstrap.net), based on [CoreUI](http://coreui.io); (_get it? Backpack... Bootstrap... Backstrap? Pff..._)
+- no CSS and JS assets are loaded from CDNs; everything's inside the Backpack/CRUD package, installed through NPM, and gets published into your ```public``` folder upon installation; you don't need to use NPM yourself to install or update assets - the Backpack maintainers do that for you;
+- offline & intranet support - thanks to our move away from CDNs, Backpack now works without an internet connection;
+- ability to easily add Vue.JS, React, or any other JS file inside all your admin panel pages, by modifying an array in ```config/backpack/base.php```;
+- ability to easily remove the bundled JS and CSS and use CDNs if you want to;
+- ability to toggle breadcrumbs on/off, in the ```config/backpack/base.php``` config file;
+- ability to choose a different theme for Backpack views, in ```config/backpack/base.php```;
+- SweetAlerts - instead of showing the default browser alert(), Backpack now uses much prettier SweetAlert pop-ups;
+- API to [change breadcrumb links from controllers or from views](/docs/{{version}}/base-how-to#use-breadcrumbs);
+- [Widgets](/docs/{{version}}/base-widgets) - easily add stats, pie charts, line charts and other quick stats to a dashboard or CRUD (or any part of your admin panel);
+- support for Right-to-Left (RTL) languages; just change ```html_direction``` to ```rtl``` inside ```config/backpack/base.php```;
+
+
+# Removed
+- AdminLTE design; we're now using Bootstrap 4 + [CoreUI](http://coreui.io), with a custom design we made, called [Backstrap](https://backstrap.net); (_get it? Backpack... Bootstrap... Backstrap?_)
+- Pnotify was removed in favour of Noty to show notificatio bubbles;
+- loading multiple files for CSS and JS, on every page; now Backpack's default is to load one CSS bundle file, and one JS bundle file; CSS and JS for field types is still loaded separately, when needed, of course - you wouldn't want all CSS & JS loaded for all 40+ field types, on every page load;
+- ```backpack/generators``` and ```laracasts/generators``` are no longer installed automatically; however, the official installation process does instruct you to install them;
+- Backpack/Base; All the functionality in Backpack\Base has now been included in the Backpack\CRUD repository; However, we've kept the separate config files (```config/backpack/base.php``` and ```config/backpack/crud.php```) and views are still in the two folders you're used to, ```resources/views/vendor/backpack/base``` and ```resources/views/vendor/backpack/crud```; We've done this so it's easier for you to upgrade, but we _will_ merge the config files and views in the next Backpack 5.0 or 6.0;
+
+
+# Licensing
+
+
+## New Buyers
+
+All licenses you can purchase now on BackpackForLaravel.com are valid for _both_ v3 and v4. We've bumped the prices a bit, they're now:
+- 0 EUR for non-commercial projects (unlimited developers, one project);
+- 69 EUR for a single commercial project (unlimited developers, one project);
+- 399 EUR for unlimited commercial projects (unlimited developers, unlimited projects);
+
+Check out our [pricing page](https://backpackforlaravel.com/pricing) for more details,
+
+
+## Backpack v3 Buyers
+
+You can still use Backpack v3.6 for your projects. There's nothing wrong with it, if you don't want the new features in v4. But please know - v3 will only receive _security_ updates in the future: no bug fixes, no new features. We've provided upgrades and new features for Backpack v3 for _more than 3 years_. We hope this means you've already gotten a great bang for your buck out of your Backpack v3 license.
+
+### Single License
+
+Depending on _when_ you've purchased your Backpack v3 Project license, you'll qualify for a discount for upgrading your project to v4:
+- bought in 2016 - 10 EUR discount (aprox 14%);
+- bought in 2017 - 15 EUR discount (aprox 21%);
+- bought in 2018 - 20 EUR discount (aprox 28%);
+- bought in January-June 2019 - 25 EUR discount (aprox 36%);
+- bought in July-August 2019 - 39 EUR discount (aprox 56%);
+- bought in September 2019 - 49 EUR discount (aprox 71%);
+
+If you're an EU resident/company, VAT may be added to your invoice.
+
+There's only one catch: **To receive the discount, you have to purchase the upgrade before October 27th 2019**. You can purchase the upgrade in your Backpack account - you'll notice a new button has shown up next to your v3 license "_Upgrade for xxx EUR_". That button will disappear on October 28th 2019, 00:01 GMT. You will not be able to purchase with a discount after that.
+
+
+### Unlimited License
+
+Depending on _when_ you've purchased your Backpack v3 Unlimited license, you'll qualify for a discount for upgrading all your projects to v4 _and_ creating new projects with Backpack v4:
+- bought in 2016 - 20 EUR discount (aprox 5%);
+- bought in 2017 - 40 EUR discount (aprox 10%);
+- bought in 2018 - 80 EUR discount (aprox 20%);
+- bought in January-June 2019 - 120 EUR discount (aprox 30%);
+- bought in July-August 2019 - 200 EUR discount (aprox 51%);
+- bought in September 2019 - 299 EUR discount (aprox 75%);
+
+If you're an EU resident/company, VAT may be added to your invoice.
+
+There's only one catch: **To receive the discount, you have to purchase the upgrade before October 27th 2019**. You can purchase the upgrade in your Backpack account - you'll notice a new button has shown up next to your v3 license "_Upgrade for xxx EUR_". That button will disappear on October 28th 2019, 00:01 GMT. You will not be able to purchase with a discount after that.
+
+If you've bought the Unlimited License very recently, and haven't launched any projects using Backpack v3, we don't want you to feel cheated. We can make a special discount for you - we'll discount the entire v3 Unlimited cost from your v4 Unlimited License. You'd only pay the price difference from v3 to v4 (100 EUR), and you'd be licensed to use both v3 and v4 in production. [Contact us](https://backpackforlaravel.com/contact).
+
+
+
+# Versioning
+
+When installing Backpack, require its minor version (currently ```4.0.*```). Backpack follows the same versioning system as Laravel 5.x - minor versions include minor breaking changes. This allows us to push new features without charging our users again. For us, this is what ```major.minor.patch``` means:
+
+- ```major``` - **PAID upgrade; MAJOR breaking changes;** historically every 2-3 years; upgrading may take even 2-3 hours; includes major new features, major changes in how the whole system works, and complete rewrites; it allows us to _considerably_ improve the product, and add features that were previously impossible;
+- ```minor``` - **FREE upgrade; MINOR breaking changes**; historically every 6-12 months; upgrading takes less than 30 minutes; it allows us to add big new features, for free;
+- ```patch``` - **FREE upgrade; NO breaking changes**; historically every week; upgrading can be done automatically with composer; includes bug fixes and non-breaking new features;
diff --git a/4.0/upgrade-guide.md b/4.0/upgrade-guide.md
new file mode 100644
index 00000000..4dc5cd01
--- /dev/null
+++ b/4.0/upgrade-guide.md
@@ -0,0 +1,517 @@
+# Upgrade Guide
+
+---
+
+This will guide you through upgrading from Backpack 3.6 to 4.0.
+
+
+> **Backpack v4 is a paid upgrade.** You can upgrade your project and run it just fine on localhost - no license key needed for that. But in production you'll need a different license code for v4. For details please see this version's [release notes](/docs/{{version}}/release-notes#licensing).
+
+
+
+## Requirements
+
+Please make sure your project respects the requirements below, before you start the upgrade process. You can check with ```php artisan backpack:base:version```:
+
+- Backpack\CRUD 3.6.x installed; if not, please follow the minor upgrade guides below to get to 3.6;
+- Laravel 5.8 / Laravel 6.0 installed
+- PHP 7.2+
+- 30-60 minutes for most projects
+
+**If you're running Backpack/CRUD version 3.3, 3.4 or 3.5, please follow the minor upgrade guide first, to get to 3.6**. Only _afterwards_ can you upgrade from 3.6 to 4.0. Guides:
+- [upgrade from 3.5 to 3.6](https://backpackforlaravel.com/docs/3.6/upgrade-guide);
+- [upgrade from 3.4 to 3.5](https://backpackforlaravel.com/docs/3.5/upgrade-guide);
+- [upgrade from 3.3 to 3.4](https://backpackforlaravel.com/docs/3.4/upgrade-guide);
+
+
+## Upgrade Steps
+
+
+### Composer
+
+**Step 0.**
+
+Update your ```composer.json``` file to require:
+- ```"backpack/crud": "^4.0.0"```
+- ```"laravel/framework": "5.8.*|^6.0"```
+- ```"backpack/generators": "^2.0"``` (in require-dev)
+
+Then run ```composer update```.
+
+[OPTIONAL] If you have a lot of Backpack add-ons installed (and their dependencies), here are their latest versions, you can copy-paste the versions of the packages you're using:
+```
+ "backpack/crud": "^4.0.0",
+ "backpack/logmanager": "^3.0.0",
+ "backpack/settings": "^3.0.0",
+ "backpack/pagemanager": "^2.0.0",
+ "backpack/menucrud": "^2.0.0",
+ "backpack/newscrud": "^3.0.0",
+ "backpack/permissionmanager": "^5.0",
+ "backpack/backupmanager": "^2.0.0",
+ "backpack/generators": "^2.0",
+ "spatie/laravel-translatable": "^4.0",
+ "barryvdh/laravel-elfinder": "^0.4.2",
+ "spatie/laravel-backup": "^6.1"
+```
+
+**Note:** If you're using ```webfactor/laravel-generators```, please remove it for now. It does not support Backpack v4 yet.
+
+
+### Models
+
+**Step 1.** We've moved the model traits and notifications, so please do a search-and-replace in your ```app``` or ```Models``` folder:
+- replace ```Backpack\CRUD\CrudTrait``` with ```Backpack\CRUD\app\Models\Traits\CrudTrait```
+- replace ```Backpack\Base\app\Models\Traits\InheritsRelationsFromParentModel``` with ```Backpack\CRUD\app\Models\Traits\InheritsRelationsFromParentModel```
+- replace ```Backpack\Base\app\Notifications\ResetPasswordNotification``` with ```Backpack\CRUD\app\Notifications\ResetPasswordNotification```
+- replace ```Backpack\CRUD\ModelTraits\SpatieTranslatable``` with ```Backpack\CRUD\app\Models\Traits\SpatieTranslatable```
+
+
+### Routes
+
+**Step 2.0** Change all you CRUD routes as shown below (most developers hold their CRUD routes inside ```routes/backpack/custom.php```):
+```diff
+Route::group([
+ 'prefix' => config('backpack.base.route_prefix', 'admin'),
+ 'middleware' => ['web', config('backpack.base.middleware_key', 'admin')],
+ 'namespace' => 'App\Http\Controllers\Admin',
+], function () {
+- CRUD::resource('menu-item', 'MenuItemCrudController');
++ Route::crud( 'menu-item', 'MenuItemCrudController');
+});
+```
+
+Best to search-and-replace in your entire ```routes``` folder:
+- replace ```CRUD::resource``` with ```Route::crud```
+
+**Step 2.1** Backpack no longer provides a `->with()` function for adding extra routes on your controllers. If you've used ```->with()``` on your CRUD routes, please either:
+- (A) move your routes outside the with() closure, as normal routes, in your ```custom.php```;
+- (B) move your routes to the controller, inside a ```setupXxxRoutes()``` method; any method on the controller that looks like that will automatically be called when loading the routes; take a look at [any operation](https://github.com/Laravel-Backpack/CRUD/tree/master/src/app/Http/Controllers/Operations) to see an example;
+
+See the latest docs for more details [Add Extra CRUD Routes](https://backpackforlaravel.com/docs/4.0/crud-how-to#add-extra-crud-routes)
+
+**Step 2.2**
+If you refer to CRUD routes by name - we've dropped the "crud" prefix. You'll need to update any references in your code. So `crud.model-name.index` is now `model-name.index`. This Regex search should help you find any calls to `route()` which use the `crud.` prefix: `/route\s*\(\s*['"]crud./`
+
+
+### CrudControllers
+
+The steps below should apply for each of your CrudControllers. For each Step, go through every one of your CrudControllers (usually stored in ```app\Http\Controllers\Admin```:
+
+**Step 3.** Make sure the method where you set up your CrudPanel is called ```setup()```, not ```__construct()```. Especially if you've generated your CRUDs using versions of Backpack v3 from 2016-2017. In most cases you can just rename ```__construct()``` to ```setup()```, since ```setup()``` is called inside ```CrudController::__construct()``` anyway.
+
+**Step 4.** In v4, CrudController comes with ZERO operations loaded by default (instead of create, read, update, delete). You need to use a few operation traits in each of you EntityCrudControllers, to enable the previously-default operations:
+
+```php
+
+ use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
+ use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
+ use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
+ use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
+
+```
+
+Make sure they're used INSIDE you EntityCrudController, not just OUTSIDE it:
+
+```diff
+
+class SettingCrudController extends CrudController
+{
++ use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
++ use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
++ use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
++ use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
+
+ public function setup()
+ {
+ // ...
+```
+
+This is a great time to think about which default operations you're NOT using with each CrudController. If you're actually not using an operation, just commend or delete the ```use``` statement for that operation. This will also prevent the routes for that operation from being registered, so your ```php artisan route:list``` will be cleaner.
+
+**Step 5.** You might also be using other, non-default operations, in your CrudControllers. If so, you need to do the same for them (use the operation trait on the EntityCrudController where you'd like to use that operation). Here are all the operations Backpack v4 provides, use them on your EntityCrudControllers as you see fit:
+
+```php
+ // previously default operations (in Backpack v3)
+ use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
+ use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
+ use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
+ use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
+
+ // previously optional operations (in Backpack v3)
+ use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
+ use \Backpack\CRUD\app\Http\Controllers\Operations\ReorderOperation;
+ use \Backpack\CRUD\app\Http\Controllers\Operations\RevisionsOperation;
+ use \Backpack\CRUD\app\Http\Controllers\Operations\CloneOperation;
+ use \Backpack\CRUD\app\Http\Controllers\Operations\BulkCloneOperation;
+ use \Backpack\CRUD\app\Http\Controllers\Operations\BulkDeleteOperation;
+
+```
+
+**Step 6.** If in any of your EntityCrudControllers, you're using ```parent::``` to call a method from Backpack's CrudController, it will not work anymore. Since the methods are now applied using a trait, not by extending a CrudController. You will now have to rename the trait's method in the Use statement in order to call it from your custom method, for example:
+
+```
+class MyCrudController extends CrudController
+{
+ use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation {
+ edit as parentEdit;
+ }
+
+ public function edit($id)
+ {
+ // customizations go here
+ // then we call the parent
+ return $this->parentEdit($id);
+ }
+
+```
+
+**(6.1)** If your ```store()``` and ```update()``` methods don't have any custom logic apart than calling the parent method, you can delete them. We no longer need the Request type-hinted. So if they look like this, you can delete them:
+```php
+ public function store(StoreRequest $request)
+ {
+ // your additional operations before save here
+ $redirect_location = parent::storeCrud($request);
+ // your additional operations after save here
+ // use $this->data['entry'] or $this->crud->entry
+ return $redirect_location;
+ }
+
+ public function update(UpdateRequest $request)
+ {
+ // your additional operations before save here
+ $redirect_location = parent::updateCrud($request);
+ // your additional operations after save here
+ // use $this->data['entry'] or $this->crud->entry
+ return $redirect_location;
+ }
+```
+
+**IMPORTANT!!!** For the validation to still take place, using the same FormRequest, you need to instruct that operation to do so. In v4 you can setup an individual operation in methods that look like this: ```setupXxxOperation()```. So in this case, if you've deleted the previous ```store()``` and ```update()``` methods, it's now:
+
+```php
+ protected function setupCreateOperation()
+ {
+ $this->crud->setValidation(StoreRequest::class);
+ }
+
+ protected function setupUpdateOperation()
+ {
+ $this->crud->setValidation(UpdateRequest::class);
+ }
+```
+
+**(6.2)** If you have custom logic inside your ```store()``` and ```update()``` methods, note that we've changed the parent method names:
+- from ```updateCrud()``` to ```update()```
+- from ```storeCrud()``` to ```store()```
+
+Follow step 6.1 with this in mind. The end result should be something like this:
+
+```php
+ use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation { store as traitStore; }
+ use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation { update as traitUpdate; }
+
+ public function store(StoreRequest $request)
+ {
+ // do something before validation, before save, before everything; for example:
+
+ // $this->crud->request->request->add(['author_id'=> backpack_user()->id]);
+ // $this->crud->addField(['type' => 'hidden', 'name' => 'author_id']);
+ // $this->crud->request->request->remove('password_confirmation');
+ // $this->crud->removeField('password_confirmation');
+
+ $redirect_location = $this->traitStore();
+
+ // do something after save
+
+ return $redirect_location;
+ }
+
+ public function update(UpdateRequest $request)
+ {
+ // ..
+ $redirect_location = $this->traitUpdate($request);
+ // ..
+ return $redirect_location;
+ }
+
+```
+
+
+**(6.3)** To be able to call the same method, but from the trait (not the parent), please rename the method from the trait, and call that name instead:
+
+```diff
+use Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
+
+class MonsterCrudController extends CrudController
+{
+- use ShowOperation;
++ use ShowOperation {
++ show as traitShow;
++ }
+
+ public function show()
+ {
+ // do sth custom here
+- return parent::show();
++ return $this->traitShow();
+ }
+```
+
+Notice it's now ```$this->```, not ```parent::```. You do NOT need to do this for every method in your EntityCrudController that you've overwritten completely. Only for the methods that have a ```parent::smth()``` call inside them.
+
+
+**Step 7.** The ```store()``` and ```update()``` methods previously stored all inputs the form, _except for_ special inputs (like ```_token```, ```_method```, ```current_tab``` etc.). This process has now been changed: they now store _only_ the inputs defined by the fields.
+
+**(7.1)** If you've used the ```checklist_dependency``` field type, its definition has changed - it should now have an array for name, instead of a string:
+
+```diff
+$this->crud->addField([
+ 'label' => 'Roles and Permissions',
+ 'field_unique_name' => 'user_role_permission',
+ 'type' => 'checklist_dependency',
+- 'name' => 'roles_and_permissions',
++ 'name' => ['roles', 'permissions'],
+ 'subfields' => [...]
+]);
+```
+
+**(7.2)** If you've used the ```date_range``` field type, it's definition has changed. Its ```start_name``` and ```end_name``` have been merged into ```name``` (an array), and its ```default_start``` and ```default_end``` have been merged into ```default``` (an array) too:
+
+```diff
+$this->crud->addField([
+- 'name' => 'date_range', // a unique name for this field
+- 'start_name' => 'start_date', // the db column that holds the start_date
+- 'end_name' => 'end_date', // the db column that holds the end_date
++ 'name' => ['start_date', 'end_date'] // the db column that holds the start_date and end_date
+ 'label' => 'Event Date Range',
+ 'type' => 'date_range',
+ // OPTIONALS
+- 'start_default' => '2019-10-05 09:00', // default value for start_date
+- 'end_default' => '2019-10-10 10:00', // default value for end_date
++ 'default' => ['2019-10-05 09:00', '2019-10-10 10:00'], // default value for start_date and end_date
+ 'date_range_options' => [ // options sent to daterangepicker.js
+ 'timePicker' => true,
+ 'locale' => ['format' => 'DD/MM/YYYY HH:mm']
+ ],
+]);
+```
+
+**(7.3)** If you have custom field types, where the `````` differs from ```$field['name']```, you need to modify your field type so that it uses ```$field['name']``` as its name.
+
+**(7.4)** If you have custom field types, where there are other inputs that you want stored in the database in addition to ```$field['name']```, you can use ```$field['name']``` as an array. Make sure you pass an array when you call addField(), then use that array in the blade file. Take a look at how the ```date_range``` field does it, you can do the same.
+
+**Step 8.** In Backpack v4, you can no longer specify which form to add a field to, as a second parameter to ```addField()```. Doing ```$this->crud->addField('smth', 'create');``` inside ```setup()``` won't add it to Create, it will add it to whatever operation is currently being performed. Which sometimes is the Update operation. The way to define which fields show up in Create and which in Update has become the same as ANY feature, for ANY operation - you place the calls inside the closure/method for that operation.
+
+It is recommended you split all the feature calls (fields, columns, filters, buttons) in your ```setup()``` method by operation, to avoid conflicts between operations that use the same features. We've provided two methods. Take a look at both, and decide which one you like better:
+
+**Option 8.A. Operation Closures**. Move your calls to an operation closure, and that code will be run ONLY when that operation is being performed.
+
+```php
+public function setup()
+{
+ //..
+
+ // run calls for this one operation
+ $this->crud->operation('list', function() {
+ // your addColumn, addFilter, addButton calls here, for the List operation
+ });
+
+ // run calls for one of these operations
+ $this->crud->operation(['create', 'update'], function() {
+ // your addField, etc for the Create and Update operations
+ });
+
+ // ..
+}
+```
+
+**Option 8.B. setupXxxOperation methods**. Move your calls to a method that follows the ```setupXxxOperation()``` naming convention, where ```Xxx``` is the operation name, and that code will only be run when operation ```Xxx``` is being performed.
+
+```php
+public function setupListOperation()
+{
+ // calls to addColumn, addFilter, addButton, etc
+}
+
+public function setupCreateOperation()
+{
+ // calls to addField
+}
+
+public function setupUpdateOperation()
+{
+ // calls to addField
+ // $this->setupCreateOperation(); // if it's the same as Create
+}
+
+public function setupShowOperation()
+{
+ // calls to addColumn
+ // $this->setupListOperation(); // if you want it to have the same columns as List
+}
+```
+
+_Note: You can keep your calls inside ```setup()``` too, but they will be applied for ALL operations, like in Backpack v3. In most cases, if you haven't had a conflict in v3, you won't have a conflict in v4. But we recommended you take the time now, and split up your ```setup()```. It will also make your admin panels faster._
+
+**Step 9.** Optional. We've added a ```CRUD``` facade, so that you can do ```CRUD::smth() instead of ```$this->crud->smth()```. You can replace all your ```$this->crud->smth()``` calls to ```CRUD::smth()```, if you like it better that way, if you import the facade at the top of your EntityCrudController:
+- (A) ```use CRUD;``` or
+- (B) ```use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;```
+
+**Step 10.** Some operations that were previously non-default (Revisions, Reorder, Clone, BulkClone, BulkDelete) can now set themselves up automatically, if you use the trait on your EntityCrudController. If you're using one of these operations on your EntityCrudController, consider taking a look at the changes, and removing the useless code from your controllers.
+
+**(10.1) RevisionsOperation**. To enable the operation, you have to ```use use \Backpack\CRUD\app\Http\Controllers\Operations\RevisionsOperation;``` on your EntityCrudController. If you've done so, you can delete calls to ```$this->crud->allowAccess('revisions')``` from your ```setup()```. This is performed automatically by the operation now.
+
+**(10.2) ReorderOperation**. To enable the operation, you have to ```use use \Backpack\CRUD\app\Http\Controllers\Operations\ReorderOperation;``` on your EntityCrudController. If you've done so, you can delete calls to ```$this->crud->allowAccess('reorder')``` from your ```setup()```. This is performed automatically by the operation now. The same goes with ```$this->crud->enableReorder()``` - you can delete that, it's performed by the operation. In fact, all you need to configure the operation now is:
+```php
+ protected function setupReorderOperation()
+ {
+ $this->crud->set('reorder.label', 'name'); // the attribute on the Model which will be shown on draggable elements
+ $this->crud->set('reorder.max_level', 2); // how deep do you want to allow the nesting
+ }
+```
+
+**(10.3) CloneOperation**. To enable the operation, you have to ```use use \Backpack\CRUD\app\Http\Controllers\Operations\CloneOperation;``` on your EntityCrudController. If you've done so, you can delete the calls to ```$this->crud->allowAccess('clone')``` from your ```setup()```. It's performed by default by the operation.
+
+**(10.4) BulkCloneOperation**. Previously to enable the BulkClone operation you needed to do this in your ```setup()```:
+```php
+$this->crud->enableBulkActions();
+$this->crud->allowAccess('clone');
+$this->crud->addButton('bottom', 'bulk_clone', 'view', 'crud::buttons.bulk_clone', 'beginning');
+```
+You can delete that now, if you've added ```use use \Backpack\CRUD\app\Http\Controllers\Operations\BulkCloneOperation;``` on your EntityCrudController - it's being performed by default by the operation.
+
+**(10.5) BulkDeleteOperation**. Previously to enable the BulkDelete operation you needed to do this in your ```setup()```:
+```php
+$this->crud->enableBulkActions();
+$this->crud->addBulkDeleteButton();
+```
+You can delete that now, if you've added ```use use \Backpack\CRUD\app\Http\Controllers\Operations\BulkDeleteOperation;``` on your EntityCrudController - it's being performed by default by the operation.
+
+
+**Step 11.** Only affects advanced usage. If you've used _properties_ to interact with operation features on ```$this->crud```, instead of getters & setters, most likely that property no longer exists. So if you've used the undocumented ```$this->crud->columns```, ```$this->crud->create_fields```, ```$this->crud->update_fields```, ```$this->crud->buttons```, ```$this->crud->access``` properties or anything like that, instead of using the methods that were documented, this step is for you.
+
+All CrudPanel properties that were there only to support a feature for a CRUD Operation have been removed. Instead, all those things are stored in one array, ```$this->crud->settings```, and we've provided an API to easily work with that array. [Read this detailed explanation](https://github.com/Laravel-Backpack/CRUD/pull/1997#issuecomment-536255543) if you're interested in this huge change. An easier way to migrate your usage of properties would be to see how it now works inside that operation trait, and use the new Settings API to interact with operation features, just like the operation does.
+
+Using CrudPanel properties instead of getters & setters was undocumented, but possible. So most people will not be affected by this. But if you have used CrudPanel properties directly, use the new Settings API instead of direct properties. Your old code will not work under v4.
+
+**Step 12.** [OPTIONAL] If you want your calls to be shorter, you can now do ```CRUD::smth()``` instead of ```$this->crud->smth()```. For this to work, make sure your CrudController uses our new Facade. So it would be:
+
+```php
+
+// ..
+use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
+// ..
+
+public function CategoryCrudController {
+ // ..
+ public function setup()
+ {
+ CRUD::setModel("App\Models\Category");
+ CRUD::setRoute(config('backpack.base.route_prefix', 'admin').'/category');
+ CRUD::setEntityNameStrings('category', 'categories');
+ }
+}
+```
+
+instead of
+
+```php
+ public function setup()
+ {
+ $this->crud->setModel("App\Models\Category");
+ $this->crud->setRoute(config('backpack.base.route_prefix', 'admin').'/category');
+ $this->crud->setEntityNameStrings('category', 'categories');
+ }
+```
+
+This is completely optional - whatever you prefer.
+
+
+
+### Views
+
+Most views have suffered big changes, since we've moved from Bootstrap 3 to Bootstrap 4, and from AdminLTE to CoreUI. If you've overwritten many Backpack views, the upgrade process will be more difficult for you: you have to start from our new views and make the changes again.
+
+**Step 13.** Check your ```resources/views/vendor/backpack``` folder for any views. If you find anything there beside ```base/inc/sidebar_content.blade.php```, you'll need to take a look at that file in our package - it most likely has changed, and you may need to make changes to your file too. We recommend you use a diff tool - should save some time. [Kaleidoscope](https://www.kaleidoscopeapp.com) is our preferred diff tool, on Mac OS. [WinMerge](https://winmerge.org) is a good option for Windows.
+
+If you've overwritten a lot of blade files, you may hate us for this, we know :-) But keep in mind that we've moved from Bootstrap 3 to Bootstrap 4. And from AdminLTE to CoreUI. We tried to keep the changes to a minimum. But this major change was _impossible_ to do without changing a lot of blade files.
+
+**Step 14.** Fix you sidebar menu. In your ```resources/views/vendor/backpack/base/inc/sidebar_content.blade.php```, apply the new classes to your sidebar elements (notice ```nav-item```, ```nav-link``` and ```nav-icon```):
+
+```html
+
+
+```
+
+**Step 15.** Publish the new CSS&JS, for Backpack v4: ```php artisan vendor:publish --provider="Backpack\CRUD\BackpackServiceProvider" --tag=minimum```
+
+**Step 16.** Delete the old CSS & JS, for Backpack v3:
+```bash
+# delete the AdminLTE css and js
+rm -rf public/vendor/adminlte
+
+# MANUAL: if you've added any custom css & js for Backpack/CRUD or Backpack/Base, move them:
+# - from vendor/backpack/base to packages/backpack/base
+# - from vendor/backpack/crud to packages/backpack/crud
+
+# delete the CSS and JS for Backpack v3
+rm -rf public/vendor/backpack
+
+# if the public/vendor directory is empty now, delete it
+rmdir public/vendor
+```
+
+**Step 17.** If you have custom buttons in your ```resources/views/vendor/backpack/crud/buttons```, or added through a model function, consider using the ```btn btn-sm btn-link``` classes on the anchor, so that they match the rest of the buttons.
+
+
+**Step 18.** If you've installed and used the File Manager (elFinder), please:
+```php
+# delete its published views
+rm -rf resources/views/vendor/elfinder
+
+# re-publish them
+php artisan backpack:install
+```
+
+
+### Config
+
+** Step 19. ```config/backpack/crud.php```**
+
+Most variables have been renamed and reordered - they're now sorted by operation name. Please manually insert take [the contents of the new file](https://github.com/Laravel-Backpack/CRUD/blob/v4/src/config/backpack/crud.php). Change the values to match your old config file. [Diff here](https://github.com/Laravel-Backpack/CRUD/pull/2064/files#diff-d548ca942f541d9c99eaf64f83e92bf9).
+
+
+** Step 20. ```config/backpack/base.php```**
+
+Follow the same process as with the config file above, making sure your file will have [the new content](https://github.com/Laravel-Backpack/CRUD/blob/v4/src/config/backpack/base.php). There have been NO changes in the following sections:
+- Registration
+- Routing
+- Authentication
+- File System
+- License Code
+
+
+
+### Cache
+
+**Step 21.** Clear your app's cache:
+```bash
+php artisan config:clear
+php artisan cache:clear
+php artisan view:clear
+```
+
+---
+
+**You're done! Good job.** Thank you for taking the time to upgrade. Keep in mind that Backpack v4 is not a free upgrade. A different license code is required. More details inside this version's [release notes](/docs/{{version}}/release-notes#licensing).
diff --git a/4.1/add-ons-community.md b/4.1/add-ons-community.md
new file mode 100644
index 00000000..c0cde2e2
--- /dev/null
+++ b/4.1/add-ons-community.md
@@ -0,0 +1,19 @@
+# Community Add-ons
+
+---
+
+We've been blessed with a wonderful, supportive community, where developers help each other out. Some of them have even created add-ons, so that we can all reuse functionality across our projects:
+
+| Name | Description | License |
+| ------------- |:-------------:| --------:|
+| [BackpackBlog](https://github.com/AbbyJanke/BackpackBlog) | blog front-end and back-end | - |
+| [BackpackMeta](https://github.com/AbbyJanke/BackpackMeta) | helps create meta options for extending core functions | - |
+| [LogViewer](https://github.com/eduardoarandah/backpacklogviewer) | advanced logging interface - brings the ArcaneDev/LogViewer package to Backpack admin panels | [MIT](https://github.com/eduardoarandah/backpacklogviewer/blob/master/LICENSE.md) |
+| [UserManager](https://github.com/eduardoarandah/UserManager) | manage the default Laravel users table (no permissions, no groups) | [MIT](https://github.com/eduardoarandah/UserManager/blob/master/LICENSE) |
+| [laravel-backpack-redirection-manager](https://github.com/novius/laravel-backpack-redirection-manager) | manage missing page redirections | [AGPL-3](https://github.com/eduardoarandah/backpacklogviewer/blob/master/LICENSE.md) |
+| [laravel-backpack-translation-manager](https://github.com/novius/laravel-backpack-translation-manager) | manage translations stored in the database | - |
+| [estarter-ecommerce-for-laravel](https://github.com/updivision/estarter-ecommerce-for-laravel) | complete e-commerce back-end (products, categories, clients, orders) | [YUMMY](https://github.com/updivision/estarter-ecommerce-for-laravel/blob/master/LICENSE.md) |
+| [laravel-generators](https://github.com/webfactor/laravel-generators) | CLI to generate migrations, factories, seeders, CRUDs, lang files, route files | [MIT](https://github.com/webfactor/laravel-generators/blob/master/LICENSE.md) |
+| [laravel-backpack-gallery-crud](https://gitlab.com/seandowney/laravel-backpack-gallery-crud) | manage photo galleries | [MIT](https://gitlab.com/seandowney/laravel-backpack-gallery-crud/blob/master/LICENSE.md) |
+| [signature-field-for-backpack](https://github.com/iMokhles/signature-field-for-backpack) | field type that lets admins draw their signature | [MIT](https://github.com/iMokhles/signature-field-for-backpack/blob/master/license.md) |
+| [DynamicFieldHintsForBackpack](https://github.com/DoDSoftware/DynamicFieldHintsForBackpack) | automatically add db comments as field hints | [MIT](https://github.com/DoDSoftware/DynamicFieldHintsForBackpack/blob/master/license.md) |
diff --git a/4.1/add-ons-custom-operation.md b/4.1/add-ons-custom-operation.md
new file mode 100644
index 00000000..1edf1910
--- /dev/null
+++ b/4.1/add-ons-custom-operation.md
@@ -0,0 +1,197 @@
+# Create an Add-On for a Custom Operation
+
+-----
+
+This tutorial will help you package a custom operation into a Composer package, so that you (or other people) can use it in multiple Laravel projects. If you haven't already, please [create your custom operation](/docs/{{version}}/crud-operations#creating-a-custom-operation) first, and make sure it's working well, before you move it to a package. It's just easier that way.
+
+
+
+## Part A. Create The Package
+
+
+
+### Step 1. Generate the package folder
+
+Install this excellent package that will create the boilerplate code for you:
+```sh
+composer require jeroen-g/laravel-packager --dev
+```
+
+Ask the package to generate the boilerplate code for your new package:
+
+```sh
+php artisan packager:new MyName SomeCustomOperation --i
+```
+
+Keep in mind:
+- the ```MyName``` should be your Github handle (or organisation), in studly case (```CompanyName```);
+- the ```SomeCustomOperation``` should be the package name you want, in studly case (```ModerateOperation```);
+- the ```website``` should be a valid URL, so include the protocol too: ```http://example.com```;
+- the ```description``` should be pretty short;
+- the ```license``` is just the license name, if it's a common one (ex: ```MIT```, ```GPLv2```);
+
+This will create a ```/packages/MyName/SomeCustomOperation``` folder in your root directory, which will hold all the code for your package. It has pulled a basic package template, that we need to customize.
+
+It will also modify your project's ```composer.json``` file to point to this new folder.
+
+
+### Step 2. Define dependencies
+
+Inside your ```/packages/MyName/SomeCustomOperation/composer.json``` file, make sure you require the version of Backpack your package will support. If unsure, copy-paste the requirement from your project's ```composer.json``` file.
+
+```diff
+ "require": {
++ "backpack/crud": "^4.0.0"
+- "illuminate/support": "~5|~6"
+ },
+```
+
+Note:
+- you can also remove the ```illuminate/support``` requirement in most cases - if Backpack is installed, so is that;
+- feel free to add any other requirements your package might have;
+
+Notice that this ```composer.json``` will also:
+- define your package namespace (in ```autoload/psr-4```);
+- set up Laravel package autoloading (in ```extra/laravel/providers```);
+
+
+### Step 3. Instruct your Laravel Project to use your package
+
+```sh
+composer require myname/somecustomoperation
+```
+
+Congratulations! Now you have a basic package, installed in ```packages/MyName/SomeCustomOperation```, that is loaded in your current Laravel project. Note that:
+- The command above added a requirement to your **project's ```composer.json``` file**, to require the package; Because previously Packager has pointed to the packages folder, it will pick it up from there, instead of the Internet;
+- Then your **package's ```composer.json```** file will point to the ```ServiceProvider``` inside your package's ```src``` folder;
+- The ServiceProvider is the class that ties your package to Laravel's inner workings.
+
+> If you want to test that your package is being loaded, you can do a ```dd('got here')``` inside your package's ```ServiceProvider::boot``` method. If you refresh the page, you should see that ```dd()``` statement executed.
+
+
+
+### Step 4. Move the files needed for the operation
+
+You can choose whatever folder structure you want for your package. But within Backpack add-ons, we follow the convention that the package folder should look as much as possible like a Laravel project folder. That way, when someone looks at the addon's source code, they instantly understand where everything is.
+
+**Operation Trait**
+
+Notice a file has already been created, with the operation name, inside your package's ```src``` folder. You can **move your operation trait code** from ```app/Http/Controllers/Admin/Operations``` to this ```src/SomeCustomOperation``` file, but make sure:
+- you use the proper namespace (```MyName\SomeCustomOperation```);
+- you define it as a Trait, not a Class;
+
+**Views**
+
+If your operation has a user interface, consider moving all the views this operation needs inside your package folder, inside a ```resources/views``` folder.
+
+Then in your package's ServiceProvider, make sure inside ```boot()``` that you load the views:
+```php
+ $this->loadViewsFrom(__DIR__.'/../resources/views', 'somecustomoperation');
+```
+
+**Config**
+
+For most custom Operations, there's really no need to define your own config file. You can just instruct people to use the ```config/backpack/crud.php``` file, and define stuff inside ```operations```, inside an array with your operation's name. If this works for you, then:
+- delete the ```config``` folder entirely;
+- inside your ServiceProvider's ```register()``` method, delete the line with ```mergeConfigFrom()```;
+- inside your ServiceProvider's ```bootForConsole()``` method, delete the line that publishes the config file;
+- inside your ServiceProvider's ```bootFromConsole()``` method, include:
+```bash
+ $this->publishes([
+ __DIR__.'/../resources/views' => base_path('resources/views/vendor/backpack'),
+ ], 'somecustomoperation.views');
+```
+
+That way, developers define config values for your custom operation the same way they define them for a default Backpack operation.
+
+**Translations**
+
+If your Operation has an inteface, it most likely also needs a translation file, so that strings are translatable. To add a translation file:
+- inside your ServiceProvider's ```boot()``` method, include:
+```bash
+$this->loadTranslationsFrom(__DIR__.'/../resources/lang', 'backpack');
+```
+- inside your ServiceProvider's ```bootFromConsole()``` method, include:
+```bash
+ $this->publishes([
+ __DIR__.'/../resources/lang' => resource_path('lang/vendor/backpack'),
+ ], 'somecustomoperation');
+```
+- create the ```resources/lang/en``` folder;
+- create a PHP file with a shorter representative name inside that folder, for example ```somecustom.php```, with the translation lines there;
+- you'll be able to use ```trans('somecustomoperation::somecustom.line_key')``` throughout your operation's controller/views;
+
+
+
+### Step 5. Delete the package files you don't need
+
+- in most cases you won't need a Facade for the operation, so you can delete the ```src/Facades``` folder; if you do that, also remove the alias to that Facade, at the bottom of your package's ```composer.json``` file;
+- in most cases you won't need the ```register()```, ```provides()``` methods in your ServiceProvider; it's best to remove them;
+
+
+
+### Step 6. Customize Markdown Files
+
+Inside your package folder, go through all markdown files and make them your own. At the very least, go through:
+- LICENSE.md - use the [MIT license](https://opensource.org/licenses/MIT) if unsure;
+- README.md - write a clear description and instructions for how to use your operation; if you include clear documentation and screenshots, more people will use your package, guaranteed;
+
+
+
+### Step 7. Make your first git commit
+
+Inside your package folder, run:
+```bash
+cd packages/myname/somecustomoperation
+git init
+git add .
+git commit -m "first commit"
+```
+
+
+
+## Part B. Put The Package Online
+
+
+
+### Put it on Github
+
+First, [create a new Github Repository](https://github.com/new) for it. Remember to use the same name you defined in your package's ```composer.json```. If in doubt, double-check.
+
+Second, add that new Github Repo as a remote, and push your code to your new Github repo.
+
+```bash
+git remote add origin git@github.com:yourusername/yourrepository.git
+git push -u origin master
+git tag -a 1.0.0 -m 'First version'
+git push --tags
+```
+
+The tags are the way you will version your package, so it's important you do it.
+
+
+### Put it on Packagist
+
+In order for people to be able to install your package using composer, your package needs to be registered with Packagist, Composer's free package registry.
+
+On [Packagist.org](https://packagist.org/), submit a new package. Enter your package's GitHub URL and click Check. If any errors occur, follow the onscreen instructions. When you're done, you're taken to your package's packagist page.
+
+**Congrats, you have a working package online**, you can now install it using Composer.
+
+Note: On the package page, you might get a notice like this: _This package is not auto-updated. Please set up the [GitHub Service Hook](https://packagist.org/profile/) for Packagist so that it gets updated whenever you push!_ Let's take care of that. Click that link, get your API token and go to your package's GitHub page, in Settings / Webhooks & Services / Add a new service. Search for Packagist. Enter your username and the token and hit Submit. Your error in Packagist should disappear in 5–10 minutes.
+
+
+### Feedback and Promotion
+
+Congratulations on your new Backpack addon!
+
+To get feedback, ask people to try it on:
+- [our subredddit](https://www.reddit.com/r/BackpackForLaravel/)
+- [our Gitter chatroom](https://gitter.im/BackpackForLaravel/Lobby)
+
+Make sure you write something nice, so people are interested to click.
+
+After you've got some feedback, and a few users have installed your package and everything seems fine, time to promote it big time:
+- post it to [laravel-news.com/links](https://laravel-news.com/links)
+- show it off in the [Laracasts forum](https://laracasts.com/discuss)
+- ask people to try it in [laravel.io](https://laravel.io/forum)
diff --git a/4.1/add-ons-how-to-create-a-backpack-addon.md b/4.1/add-ons-how-to-create-a-backpack-addon.md
new file mode 100644
index 00000000..194b6ed9
--- /dev/null
+++ b/4.1/add-ons-how-to-create-a-backpack-addon.md
@@ -0,0 +1,216 @@
+# How to Create an Add-on
+
+---
+
+
+### Intro
+
+There's nothing special about add-ons. They are simple Composer packages.
+
+But for consistency, we recommend you follow our simple folder structure. Our rule of thumb: **organize your ```src``` folder like it were a Laravel application**. We do this because it's easier for users to understand how the package works, and it makes it easy to copy-paste the code inside their apps and modify, for complicated use cases. That way, add-ons can be kept super-simple, with everybody adding functionality _in their own apps_. Example folder structure:
+- [src]
+ - [app]
+ - [Http]
+ - [Models]
+ - [Requests]
+ - [database]
+ - [migrations]
+ - [seeds]
+ - [routes]
+ - YourPackageNameServiceProvider.php
+- [tests]
+- composer.json
+- CHANGELOG.md
+- LICENSE.md
+- README.md
+
+Requirements:
+- a working installation of the [Backpack demo](https://github.com/laravel-backpack/demo)
+- 1-2 hours
+
+
+## Step 1. Create a package
+
+### Install Backpack Demo
+
+We're going to use [the Backpack demo project](https://github.com/laravel-backpack/demo) to create a new package. Follow the instructions in [the Installation chapter](https://github.com/laravel-backpack/demo#install).
+
+Any Laravel & Backpack app would work. But since you're going to require packages that you only need during package development, and make various changes to app files, we recommended you _create_ the package using a Backpack demo. After the package is online (with zero functionality), you will _install_ it in a real application, and _modify_ it right there, in the ```vendor``` folder. You will then delete this Backpack demo project.
+
+
+### Install CLI tool
+
+We're going to use [Jeroen-G/laravel-packager](https://github.com/Jeroen-G/laravel-packager) to generate a new package. Follow the instructions in the Installation chapter.
+
+### Generate Package Files
+
+Next up, decide what your vendor name will be. This is NOT the package name, it's the name all your packages will reside under. For example, Laravel uses "laravel". Backpack for Laravel uses "backpack". Jeffrey Way uses "way". If unsure, use your github username for the vendor name. That's what people usually do, if they don't run a company / brand.
+
+Then decide what your package name will be. Ex: ```newscrud```, ```usermanager```, etc.
+
+Then run:
+```
+php artisan packager:new myvendor mypackage
+```
+
+This will create a ```/packages/``` folder in your root directory, where your package will be stored, so you can build it. It will also pull [a very basic package template](https://github.com/thephpleague/skeleton), created by thephpleague. Everything you have right now is in ```packages/myvendor/mypackage``` - check it out.
+
+### Customize Generated Files
+
+Now let's customise it and add some boilerplate code, everything that most Laravel Packages will need. Replace everything you need in ```composer.json```, ```CHANGELOG.md```, ```CONTRIBUTING.md```, ```LICENSE.md```, ```README.md```. Make it yours.
+
+If you want to use Laravel package auto-discovery (and why wouldn't you), make sure to include the Laravel providers section in your ```composer.json```'s ```extra``` section, like so:
+```
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ },
+ "laravel": {
+ "providers": [
+ "Backpack\\NewsCRUD\\NewsCRUDServiceProvider"
+ ]
+ }
+ }
+```
+
+In ```/src/``` you'll find your service provider. That's where your package's logic is, but it's empty. Use this Service Provider template and replace ```League``` with your ```myvendor``` and ```Skeleton``` with your ```mypackage```. Your package will probably need some Controllers, routes and config files.
+
+### Create The Files Your Package Needs
+
+Here are a few commands that could help you do that:
+
+```bash
+# make sure everything is inside your src folder
+cd src/
+
+# to create a controller
+echo "app/Http/Controllers/ControllerName.php
+
+# to create a request file
+echo "app/Http/Requests/EntityRequest.php
+
+# to create a route file
+echo "routes/mypackage.php
+
+# to create a config file
+echo "config/mypackage.php
+
+# to create a views folder
+mkdir resources/views/
+```
+
+You use the routes, config and controller files just like you use the ones in your application. Nothing changes there. But remember that all classes should have the package's namespace:
+
+```php
+namespace MyVendor\MyPackage\Http\Controllers;
+```
+
+### Make Sure Your Laravel App Loads The Package
+
+Add your service provider to your app's ```/config/app.php```
+
+If not, add it:
+```
+"MyVendor\MyPackage\MyPackageServiceProvider",
+```
+
+Check that you autoload your package in composer.json:
+```
+"autoload" : {
+ "psr-4": {
+ "Domain\\PackageName\\": "packages/Domain/PackageName/src"
+ }
+},
+```
+
+Let's recreate the autoload
+```
+cd ../../../..
+composer dump-autoload
+```
+
+If you have a config file to publish, do:
+```
+php artisan vendor:publish
+```
+
+Now test it. Start by doing a ```dd('testing)``` in your service provider's ```boot()``` method. If your package is working fine, I recommend you put it online first, even before it does _anything useful_. You'll get the setup out of the way, and be able to focus on code. Plus, you'll be able to install it in a _real_ Backpack application, and edit it from the ```vendor/myvendor/mypackage``` folder (and push to your git remote).
+
+---
+
+
+## Step 2. Put it on GitHub
+
+```
+cd packages/domain/packagename/
+git init
+git add .
+git commit -m "first commit"
+```
+
+Create [a new GitHub repository](https://github.com/new).
+
+```
+git remote add origin git@github.com:yourusername/yourrepository.git
+git push -u origin master
+git tag -a 1.0.0 -m 'First version'
+git push --tags
+```
+
+Tags are the way you will version your package, so it's important you do it. People will only be able to get updates if you tag them.
+
+---
+
+
+## Step 3. Put it on Packagist
+
+On [Packagist.org](https://packagist.org), submit a new package. Enter your package's GitHub URL and click Check. If any errors occur, follow the onscreen instructions.
+
+When you're done, you'll be taken to your packagist page, where you'll probably get a notice like this:
+
+>This package is not auto-updated. Please set up the [GitHub Service Hook](https://packagist.org/profile/) for Packagist so that it gets updated whenever you push!
+
+Let's take care of that. Click that link, get your API token and go to your package's GitHub page, in ```Settings / Webhooks & Services / Add a new service```. Search for Packagist. Enter your username and the token and hit Submit. Your error in Packagist should disappear in 5–10 minutes.
+
+Congrats! You now have a working package online. You can now require it with composer.
+
+
+---
+
+
+## Step 4. Install in a Real Project
+
+We've instructed you to create the package in a disposable backpack-demo install. If you've done so, you can now install your package **in your _real_ project**:
+
+```bash
+composer require myvendor/mypackage --prefer-source
+```
+
+Using the ```prefer-source``` flag will actually _clone the git repo_ inside your ```vendor/myvendor/mypackage``` directory. So you can do:
+
+```bash
+cd /vendor/myvendor/mypackage
+git checkout master
+```
+
+Then after each change you want to publish, you would mark that change in your ```CHANGELOG.md``` file and do:
+```bash
+git pull origin master
+git add .
+git commit -am "fixes #14189 - some problem or feature with an id"
+git tag 1.0.3
+git push origin master --tags
+```
+
+---
+
+**That's it. Go build your package!** If you end up with something you like, please share it with the community in the [Gitter Chatroom](https://gitter.im/BackpackForLaravel/Lobby), and add it to [the Community Add-Ons page](/docs/{{version}}/add-ons-community), so other people know about it (_login, then click Edit in the top-right corner of the page_).
+
+You can now delete the Backpack project, and the database you've created for it (if any).
+
+For extra reading credits, these are the resources we've used to create this guide:
+- https://laravel.com/docs/packages
+- https://laracasts.com/discuss/channels/tips/developing-your-packages-in-laravel-5
+- https://github.com/jaiwalker/setup-laravel5-package
+- https://github.com/Jeroen-G/laravel-packager
+- https://laracasts.com/lessons/package-development-101
diff --git a/4.1/add-ons-official.md b/4.1/add-ons-official.md
new file mode 100644
index 00000000..25a1f911
--- /dev/null
+++ b/4.1/add-ons-official.md
@@ -0,0 +1,20 @@
+# Official Add-ons
+
+In addition to our core packages (Base and CRUD), we've developed a few packages you can install or download, that treat common use cases.
+
+Premium add-ons (paid separately, on top of your [Backpack license](https://backpackforlaravel.com/pricing)):
+- [Backpack DevTools](https://backpackforlaravel.com/products/devtools) - a GUI to easily generate Migrations, Models, Seeders, Factories and CRUDs, right from your browser window; a power user's dream come true!
+- [Backpack Figma Template](https://backpackforlaravel.com/products/figma-template) - quickly create designs and mockups, using Backpack's design, screens and components; empower your designers to design admin panels that are easy-to-code;
+
+
+Free add-ons:
+ - [PermissionManager](https://github.com/Laravel-Backpack/PermissionManager) - interface to manage users & permissions, using [spatie/laravel-permission](https://github.com/spatie/laravel-permission); ```free```
+ - [Settings](https://github.com/Laravel-Backpack/Settings) - interface to edit site-wide settings; ```free```
+ - [PageManager](https://github.com/Laravel-Backpack/PageManager) - interface to manage content for custom pages, using page templates; ```free```
+ - [MenuCRUD](https://github.com/Laravel-Backpack/MenuCRUD) - interface to create/update/reorder menu items; ```free```
+ - [NewsCRUD](https://github.com/Laravel-Backpack/NewsCRUD) - interface to manage news articles, categories and tags; ```free```
+ - [LogManager](https://github.com/Laravel-Backpack/LogManager) - interface to preview Laravel log files; ```free```
+ - [BackupManager](https://github.com/Laravel-Backpack/BackupManager) - interface to backup your files & db using [spatie/laravel-backup](https://github.com/spatie/laravel-backup); ```free```
+
+
+>**The free add-ons only provide basic functionality.** What will be enough for _most_ projects. They do not intend to be a complete solution for all use cases. If you need to customize a package for your specific use case, you can easily do that, by copy-pasting their code in your project and modifying it. Every official package has been created with this in mind, has a very simple architecture, uses Backpack best practices. Find the "extend" section in each of their docs for more about this.
diff --git a/4.1/add-ons-tutorial-using-the-addon-skeleton.md b/4.1/add-ons-tutorial-using-the-addon-skeleton.md
new file mode 100644
index 00000000..1fa90683
--- /dev/null
+++ b/4.1/add-ons-tutorial-using-the-addon-skeleton.md
@@ -0,0 +1,302 @@
+# Create an Add-On using our Addon Skeleton
+
+-----
+
+This tutorial will help you package a Backpack operation or entire CRUD into a Composer package, so that you can use it in multiple Laravel projects. And if you open-source it, others can do the same.
+
+
+
+## Part A. Build the Functionality in Your Project
+
+Make sure you have working code in your project. Code everything the package will need, the same way you normally do. Before even _thinking_ about turning it into a package, you should have working code. This is easier because:
+- you don't have to do anything new while working on functionality
+- you don't have to think about package namespaces
+- you don't have to think about what to make configurable or translatable
+- you can test the functionality alone (without the package wiring and stuff)
+
+**(optional) Hot tip:** Don't commit the code to your package yet. Or, if you've already done a commit (and it's the last commit), run `git reset HEAD^` to undo the commit (but keep the changes). This is _not necessary_ but we find it super-helpful. If you changes are inside your project, but uncommitted, you can easily see the files that have changed using `git status`, hence... the files that contain the functionality you should move to the package. It's like a progress screen - everything here should disappear - that's how you know you're done.
+
+**(optional) Bonus points:** You can use a Git client (like [Git Fork](https://git-fork.com/)) instead of `git status`, because that'll also show the atomic changes you've made to route files, sidebar etc... not only the file names:
+
+
+
+As you move things to your new package, they'll disappear from here. You know you're done when you only have the changes the users of your package need to make, to use it. Normally that's just a change to the `composer.json` and (maybe) a configuration file.
+
+
+
+## Part B. Create The Package
+
+
+
+### Step 1. Generate the package folder
+
+Let's install this excellent package that will make everything a lot faster:
+```sh
+composer require jeroen-g/laravel-packager --dev
+```
+
+Let's create our package. Instead of using their skeleton, we're going to use the Backpack [addon-skeleton](https://github.com/Laravel-Backpack/addon-skeleton):
+
+```sh
+php artisan packager:new --i --skeleton="https://github.com/Laravel-Backpack/addon-skeleton/archive/master.zip"
+```
+
+It will then ask you some basic information about the package. Keep in mind:
+- the ```vendor-name``` should probably be your Github handle (or organisation), in kebab-case (ex: `company-name`); it will be used for folder names, but also for Github and Packagist links;
+- the ```package-name``` should be in `kebab-case` too (ex: ```moderate-operation```);
+- the `skeleton`, if you haven't copied the entire command above, should probably be the one we provide: `https://github.com/Laravel-Backpack/addon-skeleton/archive/master.zip`, which has everything you need to quickly create a Backpack add-on, including an innovative `AddonServiceProvider` that "_just works_";
+- the ```website``` should be a valid URL, so include the protocol too: ```http://example.com```;
+- the ```description``` should be pretty short; you can change it later in `composer.json`;
+- the ```license``` is just the license name, if it's a common one (ex: ```MIT```, ```GPLv2```); our skeleton assumes you want `MIT` but you can easily change it;
+
+Ok great. The command has:
+- created a ```/packages/vendor-name/package-name``` folder in your root directory;
+- modified your project's ```composer.json``` file to load the files in this new folder;
+
+This new folder should hold all your package files. You're off to a great start, because you're using our package skeleton (aka template), so it's already a _working package_. And it's already got a good file structure.
+
+Let's take a look at the generated files inside ```/packages/vendor-name/package-name```:
+
+
+
+
+You'll notice that it looks _exactly_ like a Laravel project, with a few exceptions:
+- PHP classes live in `src` instead of `app`;
+- inside that `src` folder you also have an `AddonServiceProvider`; so let's take a moment to explain why it's there, and what it does:
+ - normally a package needs a ServiceProvider to tell Laravel "load the views from here", "load the migrations from here", "load configs from here", things like that; because a Composer package can also be a general PHP package (non-Laravel), normally you have to code a ServiceProvider for your package, that tells Laravel how to use your package - you have to write all that wiring logic;
+ - but thanks to `AddonServiceProvicer`, you don't have to do any of that; it's all done _automatically_ if the files are in the right directories, just like Laravel does itself, in your project's folders;
+ - the only thing you should worry about is placing your route files in `routes`, your migrations in `database/migrations` etc. and the `AddonServiceProvider` will understand and tell Laravel to load them; easy-peasy;
+
+Excited by how easy it'll be to make it work? Excellent, let's do it.
+
+> If you want to test that your package is being loaded, you can do a ```dd('got here')``` inside your package's ```AddonServiceProvider::boot``` method. If you refresh the page, you should see that ```dd()``` statement executed.
+
+
+### Step 1. Initialize a git repo and make your first package commit
+
+Let's save what we have so far - the generated files:
+```bash
+# go to the package folder (of course - use your names here)
+cd packages/vendor-name/package-name
+
+# create a new git repo
+git init
+
+# (optional, but recommended)
+# by default the skeleton includes folders for most of the stuff you need
+# so that it's easier to just drag&drop files there; but you really
+# shouldn't have folders that you don't use in your package;
+# so an optional but recommended step here would be to
+# delete all .gitkeep files, so that you leave the
+# empty folders empty; that way, you can still
+# drag&drop stuff into them, but Git will
+# ignore the empty folders
+find . -name ".gitkeep" -print # shows all .gitkeep files, to double-check
+find . -name ".gitkeep" -exec rm -rf {} \; # deletes all .gitkeep files
+
+# commit the initially generated files
+git add .
+git commit -am "generated package code using laravel-packager and the backpack addon-skeleton"
+```
+
+Excellent. Now we have _two_ git repos, that we can use as a progress indicator:
+- the _project_ repo, where the files are uncommitted;
+- the _package_ repo, where we'll be moving the functionality;
+
+If you've used a git client you can even place them side-by-side, and see the progress as you move files from the project (left) to the package (right). But you don't _have to_ do that, it's just a nice visual indicator if it's your first package:
+
+
+
+
+### Step 2. Define any extra dependencies
+
+Your ```/packages/vendor-name/package-name/composer.json``` file already requires the latest version of Backpack (thanks to the addon skeleton). If your package needs any third-party packages apart from Backpack and Laravel, make sure to add them to the `require` section. Normally this just means cutting&pasting the line from your project's `composer.json` to your package's `composer.json`.
+
+
+
+### Step 3. Move the functionality from your project to your package
+
+Time to move files from your _project_ to your _package_. You can use whatever you want for that - drag&drop, the command line, your IDE or editor, whatever you want.
+
+
+
+
+As you do that, your `git status` or git client should show fewer and fewer files in your _project_, and more and more files in your _package_.
+
+Below we'll take each project directory, one by one, and explain where its files should go. But this should all pretty intuitive:
+
+#### Files inside your project's ```app``` directory
+
+Move from the subdirectory there to the same subdirectory inside your package's `src`; that means:
+ - controllers go inside `src/Http/Controllers`;
+ - requests go inside `src/Http/Requests`;
+ - models go inside `src/Models`;
+ - commands go inside `src/Commands`;
+ - etc.
+
+IMPORTANT: Since you're moving PHP classes, **after moving them you must also change their namespaces**. Your class is no longer `App\Http\Controllers\Admin\ExampleCrudController` but `VendorName\PackageName\Http\Controllers\ExampleCrudController`.
+
+I'd love to tell you you can it using a search&replace, but... no. In this case search&replace is not worth it, because it might also replace other stuff you don't want replaced. So it's best to just go ahead:
+- open all the files you've moved;
+- manually replace stuff like `App\Http` with `VendorName\PackageName\Http`;
+
+#### Files inside your project's `config` directory
+
+If you _won't_ be using config files, just delete the entire `config` package directory.
+
+If you _will_ be using config files, to let the users of your package publish it and change how stuff works that way, it's super-simple to use:
+- you already have a file generated in `/packages/vendor-name/package-name/config/package-name.php`;
+- cut&paste any config values you want over here; if you add for example `config_key`, it'll be available in your classes using `config('vendor-name.package-name.config_key')`;
+
+If you don't have any configs right now, but will want to add later, that's ok too. Do it later.
+
+#### Files inside your project's `database` directory
+
+You have the same directory in your package, just move them there.
+
+That means:
+- `database/migrations`
+- `database/seeds` or `database/seeders`
+- `database/factories`
+
+
+#### Files inside your project's `resources\views` directory
+
+You have the same directory in your package, just move them there. Views moved in your package folder will be automatically available in the `vendor-name.package-name` namespace, so you can load them using `view('vendor-name.package-name::path.to.file')`.
+
+For views that need to be changed by the user upon installation, and cannot be moved to the package (for example, menu items inside `sidebar_content.blade.php`), add the changes the user needs to do inside your package's `readme.md` file, under Installation.
+
+#### Files inside your project's `resources\lang` directory
+
+If your package won't support translations yet, just skip this.
+
+If it will, notice you already have a lang file created for English, in your package - `/packages/vendor-name/package-name/resources/lang/en/package-name.php`. Populate that file with the language lines you need, by cutting&pasting from your project. They'll be available as `lang('vendor-name.package-name::package-name.line_key')` so you need to also find&replace your old keys with the new ones.
+
+#### Files inside your project's `routes` directory
+
+If your package only adds a view (ex: a field, a column, a filter, a widget) then it probably wont't need a route, you can just delete the entire `routes` directory in your package.
+
+If you package _does_ need routes (like when it provides an entire CRUD), you'll find there's already a file in your `/packages/vendor-name/package-name/route/package-name.php`, waiting for your routes, with a few helpful comments. Just cut&paste the routes from your project inside that file.
+
+#### Helper functions inside your project's `bootstrap\helpers.php` file
+
+If you've added any functions there that you need inside the package, you'll notice there's already a `/packages/vendor-name/package-name/bootstrap/helpers.php` file waiting for you. Cut&paste them there.
+
+If your package does not any extra need helper functions, just delete the entire `bootstrap` directory in the package.
+
+
+### Step 4. Test that the package works
+
+That's pretty much it. You've created your package! 🥳 All the files your package need are inside your package, and the only remaining changes in your project (as reflected by `git status`) should be the minimal changes that users need to do to install your package.
+
+Go ahead and test it in the browser. Make sure the functionality that was working inside your _project_ is still working now that it's inside a _package_. You might have forgotten something - we all do sometimes.
+
+
+### Step 5. Delete the package files you don't need
+
+Now that you know your package is working, go through the package folder and delete whatever your package isn't actually using: empty directories, empty files, placeholder files. Clean it up a little bit.
+
+
+
+### Step 6. Customize Markdown Files
+
+Inside your package folder, go through all markdown files and make them your own. At the very least, open the `README.md` file and spend a little time on it, give it some love:
+- write a clear description;
+- add a screenshot if appropriate;
+- write clear installation instructions (step-by-step) for how to use your package;
+- answer any questions users might have about what the package does;
+- link to whatever dependencies or resources your add-on uses, so that they check out their docs instead of bugging you about it;
+
+If you plan to make this package public, take the `README.md` seriously, because it's a HUGE factor in how popular your package can become. If you include clear documentation and screenshots, more people will use your package - guaranteed.
+
+
+
+## Part C. Put The Package Online
+
+
+First, [create a new Github Repository](https://github.com/new) for it. Remember to use the same name you defined in your package's ```composer.json```. If in doubt, double-check.
+
+Second, add that new Github Repo as a remote, and push your code to your new Github repo.
+
+```bash
+# save your working files to Git
+git add .
+git commit -am "working code for v1.0.0"
+
+# add the remote to Github
+git remote add origin git@github.com:yourusername/yourrepository.git
+git branch -M main
+git push -u origin main
+git tag -a 1.0.0 -m 'First version'
+git push --tags
+```
+
+The tags are the way you will version your package, so it's important you do it.
+
+
+
+## Part D. Make the package public (on Packagist)
+
+In order for people to be able to install your package using Composer, your package needs to be registered with [Packagist.org](https://packagist.org/), Composer's free package registry.
+
+On [Packagist.org](https://packagist.org/), submit a new package. Enter your package's GitHub URL and click Check. If any errors occur, follow the onscreen instructions. When you're done, you're taken to your package's packagist page.
+
+**Congrats, you have a working package online**, you can now install it using Composer.
+
+Note: On the package page, you might get a notice like this: _This package is not auto-updated. Please set up the [GitHub Service Hook](https://packagist.org/profile/) for Packagist so that it gets updated whenever you push!_ Let's take care of that. Click that link, get your API token and go to your package's GitHub page, in Settings / Webhooks & Services / Add a new service. Search for Packagist. Enter your username and the token and hit Submit. Your error in Packagist should disappear in 5–10 minutes.
+
+
+
+## Part E. Install the repo from Github
+
+If you look close to your project's `composer.json` file, you'll notice your project is loading the package from `packages/vendor-name/package-name`. Which is fine, it's worked fine until now. But it's now time to install the package like your users will, and have it in `vendor/vendor-name/package-name`. That way:
+- you test that your users are able to install the package;
+- you don't commit anything extra inside your project;
+- you can _easily_ make changes to your package, from whatever project you're using it in;
+
+To do that, go ahead and do this to uninstall your package from your project:
+```bash
+cd ../../.. # so that you're inside your project, not package
+
+# discard the changes in your composer files
+# and delete the files from packages/vendor-name/package-name
+php artisan packager:remove vendor-name package-name
+```
+
+And now install it exactly the same as your users will:
+- if it's closed-source, add the Github repo to your `composer.json` then move on to the next step; do NOT do this if your package is open-source:
+
+```json
+ "repositories": {
+ "vendor-name/package-name": {
+ "type": "vcs",
+ "url": "https://github.com/vendor-name/package-name"
+ }
+ }
+```
+
+- both for closed-source and open-source (on Packagist), install it using Composer's `--prefer-source` flag, so that it pulls the actual Github repo:
+
+```bash
+composer require vendor-name/package-name --prefer-source
+```
+
+That's it. It should be working fine now, but from the `vendor/vendor-name/package-name` directory. You can `cd vendor/vendor-name/package-name` and you'll see that you can `git checkout master`, make changes, tag releases, push to github, everything.
+
+
+
+### Feedback and Promotion
+
+Congratulations on your new Backpack addon!
+
+To get feedback, ask people to try it on:
+- [our addons repo](https://github.com/laravel-backpack/addons)
+- [our subredddit](https://www.reddit.com/r/BackpackForLaravel/)
+- [our Gitter chatroom](https://gitter.im/BackpackForLaravel/Lobby)
+
+Make sure you write something nice, so people are interested to click.
+
+After you've got some feedback, and a few users have installed your package and everything seems fine, time to promote it big time:
+- post it to [laravel-news.com/links](https://laravel-news.com/links)
+- show it off in the [Laracasts forum](https://laracasts.com/discuss)
+- ask people to try it in [laravel.io](https://laravel.io/forum)
diff --git a/4.1/add-ons-tutorial.md b/4.1/add-ons-tutorial.md
new file mode 100644
index 00000000..527103e9
--- /dev/null
+++ b/4.1/add-ons-tutorial.md
@@ -0,0 +1,232 @@
+# How to Create a Backpack Add-on
+
+---
+
+
+### Intro
+
+So you've created a custom field, column, filter, or an entire CRUD. Great! If you want to re-use it across projects, or you think _other people_ would like to use it too, there's a good way to do that.
+
+The process below will involve creating a new package on Github, Composer & Packagist - which is a little challenging to wrap your head around, the first time you do it. But if you were able to create a custom field, you will be able to do that too. And in doing this, you'll learn the basics of creating and maintaining a PHP package. That's something that not all PHP developers can do, so it's pretty cool, I think.
+
+> If you already know how to create & maintain a PHP package, this tutorial might be too easy for you. Try to skim it, because we give useful tips. But you can also just go to [:DigitallyHappy/toggle-field-for-backpack](https://github.com/DigitallyHappy/toggle-field-for-backpack), clone the repo and make the changes you see fit.
+
+Requirements:
+- a working installation of Laravel & Backpack 4 (alternative: you can install the [Backpack demo](https://github.com/laravel-backpack/demo));
+- a Github account (free or paid);
+- 15-30 minutes;
+
+
+
+## Step 0. Scope and Constants
+
+**Decide what your package is going to do.** Try to keep the package as small as possible. If you're trying to share multiple fields/columns/etc, we recommend you create a different package for each field type. This will make it:
+- easier for you to communicate what the package does;
+- easier for you to maintain a field type (or abandon it);
+- more likely for people to install & use your package;
+
+In the tutorial below, we'll assume you're trying to share one custom field - ```dummy.blade.php```. But the process will be the same no matter what you're building, starting from the skeletons packages below.
+
+Once you know what you're building, there are a few constants which you need to decide upon. Names that once you've chosen, it will be _possible_, but _very difficult_ to change:
+
+**Package Name.** Try to find a name that is as explicit as possible. So that users, just by reading the name, will pretty much understand what the package does. Also, try to include "_for Backpack_" - that way it will stand out to developers who use Backpack (your target audience).
+- Good Examples: ```json-editor-field-for-backpack```, ```user-column-for-backpack```, ```users-crud-for-backpack```;
+- Bad Examples: ```custom-field``` (too general), ```cbf``` (too cryptic), ```aurora``` (this is not the place to be creative :smile: );
+Since in this example we're trying to build a package for the new ```dummy``` field type, we'll choose ```dummy-field-for-backpack``` as the package name.
+
+**Vendor Name.** You noticed how every time you install a composer package, it's ```composer install something/package-name```? Well that's what that "something" is - the _vendor name_. It's usually the name of the company or person behind the project. The easiest to remember would be your github username, or your company's github username. But, if you're not happy with those, you _can_ choose a different vendor name - basically a brand name, under which you build packages. This could be the place to be creative :smile:, if you don't have a company name already. In the example below we'll use ```company-name```.
+
+**Class Namespace.** When people reference your package's classes, this is what they see first. It's a good practice to use VendorName/PackageName as the namespace for your package. But notice it's no longer kebab-case (using dashes - ```my-company/dummy-field-for-backpack```), it is PascalCase (```MyCompany/DummyFieldForBackpack```).
+
+
+
+## Step 1. Clone the skeleton package
+
+To get your package online ASAP, we've prepared a few "skeleton" packages, that you can fork and modify:
+- [:DigitallyHappy/toggle-field-for-backpack](https://github.com/DigitallyHappy/toggle-field-for-backpack) - field add-on example;
+- TODO - column add-on example;
+- TODO - filter add-on example;
+- TODO - button add-on example;
+- TODO - CRUD add-on example;
+- TODO - multiple CRUD add-on example;
+- TODO - CRUD with dependencies add-on example;
+
+Pick the skeleton package that's as similar as possible to what you want to build. On its Github page, under if you click the green **Clone or Download** button, you'll get the path to that repo. In your project, let's clone that repo:
+```bash
+# git clone {REPO URL} packages/{VENDOR NAME}/{PACKAGE NAME}
+git clone git@github.com:DigitallyHappy/toggle-field-for-backpack.git packages/my-company/dummy-field-for-backpack
+```
+
+
+## Step 2. Make it your own
+
+Take a look at the files you've copied - it's a very simple package. In you package's root folder we have:
+- ```README.md``` - your package's "home page" on Github; this should hold all the information needed to use your package;
+- ```composer.json``` - configuration file that tells Composer (the PHP package installer) more about your package;
+- ```CHANGELOG.md``` - where you should write every time you make changes to the field;
+- ```LICENSE.md``` - so that people know how they're allowed to use your package (MIT is the default);
+
+Take a look at all of them and modify to fit your needs. It should be faster to modify by hand, and pretty intuitive. But, if it's the first time you create a PHP package, you can use the process below, to make sure you don't mess up anything, since making a casing mistake somewhere (```my-vendor``` instead of ```MyVendor```) could take you very long to debug:
+- **namespace** - find ```DigitallyHappy\ToggleFieldForBackpack``` and replace with your _VendorName\PackageName_ (ex: ```MyCompany\DummyFieldForBackpack```);
+- **escaped namespace** - find ```DigitallyHappy\\ToggleFieldForBackpack``` and replace with your _VendorName\\PackageName_ (ex: ```MyCompany\\DummyFieldForBackpack```);
+- **vendor and package name** - find ```digitallyhappy/toggle-field-for-backpack``` and replace with your _vendor-name/package-name_ (ex: ```my-company/dummy-field-for-backpack```);
+- **package name** - find ```toggle-field-for-backpack``` and replace with your _package-name_ (ex: ```dummy-field-for-backpack```);
+- **vendor name** - find ```digitallyhappy``` and replace with your _vendor-name_ (ex: ```my-company```);
+- **author name** - find ```Cristian Tabacitu``` and replace with your name (ex: ```John Doe```);
+- **author email** - find ```hello@tabacitu.ro``` and replace with your email (ex: ```john@example.com```);
+- **author website** - find ```https://tabacitu.ro``` and replace with your website or Github page (ex: ```http://example.com```);
+- open ```changelog.md``` and keep only the 1.0.0 version; put today's date;
+- open ```composer.json``` and change the description of your package;
+- open ```readme.md``` and change the text to better describe _your_ package; don't worry about the screenshot, we'll change that one in a future step;
+
+In ```/src/``` you'll find your service provider, which does one thing: it loads the views in your ```src/resources/views``` under the ```dummy-field-for-backpack``` view namespace. So that anybody who installs your package can use a view that your package includes, by referencing ```dummy-field-for-backpack::path.to.view```.
+
+Also in ```/src/``` you'll notice ```src/resources/views/fields/toggle.blade.php```. This is the example field, which you can rename and use to start coding you field. Or if you already have your field ready, you can just delete this file, and copy-paste the finished blade file from your project
+
+
+## Step 3. Put it on GitHub
+
+```
+# make sure you replace the below with your actual vendor name and package name
+cd packages/my-company/dummy-field-for-backpack/
+git add .
+git commit -m "turned the skeleton package into dummy-field package"
+```
+
+Create [a new GitHub repository](https://github.com/new). Then get the Git URL the same way you did for the Toggle package, from the green "Clone or Download" button. With that Git URL:
+
+```
+# remove the old origin (pointing to the toggle package)
+git remote rm origin
+
+# add a remote pointing to YOUR github repo
+git remote add origin git@github.com:yourusername/yourrepository.git
+
+# refresh the new origin remote everywhere
+git config master.remote origin
+git config master.merge refs/heads/master
+
+# push your code to your github repo
+git push -u origin master
+
+# tag your release as 1.0.0
+git tag -a 1.0.0 -m 'First version'
+
+# push your tags to the Repo - this is very important to Packagist;
+git push --tags
+```
+
+You might not have used git tags until now. Tags are the way you will version your package, so it's important you do it. For every new version, you need to:
+- write your changes inside the ```changelog.md``` file, so people can easily see what's new;
+- tag your release with the proper tag, so that Packagist will know you've pushed a new version;
+
+---
+
+
+## Step 4. Put it on Packagist
+
+On [Packagist.org](http://packagist.org), create an account if you don't have one already, then click "Submit package" in the top-right corner. Enter your package's GitHub URL and click Check. If any errors occur, follow the onscreen instructions.
+
+When you're done, you'll be taken to your packagist page, where you'll probably get a notice like this:
+
+>This package is not auto-updated. Please set up the [GitHub Service Hook](https://packagist.org/profile/) for Packagist so that it gets updated whenever you push!
+
+Let's take care of that. Click [that link](https://packagist.org/profile/), click "Show API Token", copy it and go to _your package's GitHub page_, in ```Settings / Webhooks & Services / Add a new service```. Search for Packagist. Enter your username and the token and hit Submit. Your error in Packagist should disappear in 5–10 minutes.
+
+Congrats! You now have a working package online. You can now require it with composer.
+
+
+---
+
+
+## Step 5. Install it
+
+Since your package is now online, you can now install it using composer.
+
+```bash
+# go to the root of you Laravel app
+cd ../../..
+
+# delete the folder from packages
+rm -r packages
+
+composer require my-company/dummy-field-for-backpack --prefer-source
+```
+
+Notice we've installed it using the ```prefer-source``` flag. This will actually _clone the git repo_ inside your ```vendor/myvendor/mypackage``` directory. So you can do:
+
+```bash
+cd /vendor/my-company/dummy-field-for-backpack
+git checkout master
+```
+
+**That's it. Your package is online and installable!** You have most of the knowledge needed to build and maintain a PHP package.
+
+
+
+## Step 6. Double-check, then triple-check
+
+### Are you sure it's working?
+After your package is online and ready to use, double-check that it's working well. Then triple-check.
+
+### Your README is your home page
+Afterwards go to your README file again, and make sure it's the best it can be. Remember, your README file is the first thing people see when they find your package. If it's not appealing, they won't use it. If it doesn't do a good job of explaining how to use it, they won't use it. Take this seriously. This is where A LOT of packages go wrong - the authors do not spend the right amount of time on their README page.
+
+IMPORTANT. Make sure your README has a nice screenshot of the functionality you're offering. The easier it is for a developer to see the benefit of using your package, the more likely it is for them to install it. There's a trick in uploading images to Github, then using them in your README file. Go to your package's Github page, and add an issue. In that issue's body, drag&drop the screenshot image. Github will upload it, and give it an URL. Copy-paste that URL, submit the issue (you can also already close the issue), then use that image URL inside your README file. Boom! Free image hosting.
+
+By now you should have made some changes to your files, inside your ```vendor/my-company/dummy-field-for-backpack``` directory.
+
+After each change you want to publish, you should:
+1. Write about that change in your ```CHANGELOG.md``` file. Increment the version sticking to SEMVER.
+
+2. Commit and push your changes, remembering to also create a new tag with the version.
+```bash
+git pull origin master
+git add .
+git commit -am "fixes #14189 - some problem or feature with an id from Github"
+git tag 1.0.1
+git push origin master --tags
+```
+
+
+## Step 7. Feedback and Promotion
+
+Congratulations on your new Backpack addon!
+
+To get feedback, ask people to try it on:
+- [our subredddit](https://www.reddit.com/r/BackpackForLaravel/)
+- [our Gitter chatroom](https://gitter.im/BackpackForLaravel/Lobby)
+
+Make sure you write something nice, so people are interested to click.
+
+After you've got some feedback, and a few users have installed your package and everything seems fine, time to promote it big time:
+- post it to [laravel-news.com/links](https://laravel-news.com/links)
+- show it off in the [Laracasts forum](https://laracasts.com/discuss)
+- ask people to try it in [laravel.io](https://laravel.io/forum)
+
+
+## Extra Credits
+
+If you're building a bigger package, with one CRUD or more, we recommend you follow the simple folder structure we use across all Backpack packages. Our rule of thumb: **organize your ```src``` folder like it were a Laravel application**. We do this because it's easier for developers to understand how the package works, and it makes it easy to copy-paste the code inside their apps and modify, for complicated use cases. That way, add-ons can be kept super-simple, with everybody adding functionality _in their own apps_. Example folder structure:
+- [src]
+ - [app]
+ - [Http]
+ - [Models]
+ - [Requests]
+ - [database]
+ - [migrations]
+ - [seeds]
+ - [routes]
+ - AddonServiceProvider.php
+- [tests]
+- composer.json
+- CHANGELOG.md
+- LICENSE.md
+- README.md
+
+For extra reading credits, these are the resources we've used to create this guide:
+- https://laravel.com/docs/packages
+- https://laracasts.com/discuss/channels/tips/developing-your-packages-in-laravel-5
+- https://github.com/jaiwalker/setup-laravel5-package
+- https://github.com/Jeroen-G/laravel-packager
+- https://laracasts.com/lessons/package-development-101
diff --git a/4.1/base-about.md b/4.1/base-about.md
new file mode 100644
index 00000000..f3a0b99c
--- /dev/null
+++ b/4.1/base-about.md
@@ -0,0 +1,219 @@
+# About Backpack's User Interface
+
+---
+
+Backpack helps you build admin panels faster by:
+- installing our custom HTML theme, [Backstrap](https://backstrap.net), based on Bootstrap 4 and [CoreUI](https://coreui.io);
+- installing [sweetalert](https://sweetalert.js.org/) for triggering pretty Confirm modals;
+- installing [noty](https://ned.im/noty/#/) to show notification bubbles upon error/success/warning/info - triggered from Javascript;
+- installing [prologue/alerts](https://github.com/prologuephp/alerts) for triggering notification bubbles from PHP (both on the same page and using flashdata);
+- providing a separate authentication system for your admins;
+- providing pretty error pages for most common errors;
+- providing a horizontal menu and a side menu you can customize;
+- providing a place for your admin to to change his email/name/password;
+- providing a few helpers you can use throughout your admin panel;
+
+For the simplest projects, you will never need to know how it works, never need to customize anything but the ```config/backpack/base.php``` file. But here's how everything works, below.
+
+
+## Layout & Design
+
+
+### General
+
+Backpack pulls in our custom HTML template, [Backstrap](https://www.npmjs.com/package/@digitallyhappy/backstrap), and adds our own CSS file on top, for a few cosmetic improvements. We've chosen to base Backstrap on [CoreUI](https://coreui.io), because it provides design blocks for all common features of an administration panel. When you decide to build custom pages for your Admin Panel, you can just use Backstrap's HTML blocks - no designer needed. You can see all the HTML components Backstrap provides on [backstrap.net](https://backstrap.net), and copy-paste HTML from there, or use [CoreUI](https://coreui.io)'s documentation for details.
+
+
+### New Files in Your App
+
+After installation, you'll notice Backpack has added a few files:
+
+**1) View to ```resources/views/vendor/backpack/base/inc/sidebar_content.blade.php```**
+
+This file is used to show the contents of the menu to the left (sidebar). It's been published there so that you can easily modify its contents, by editing its HTML.
+
+**2) Middleware to ```app/Http/Middleware/CheckIfAdmin.php```**
+
+This middleware is used to test if users have access to admin panel pages. You can (and should customize it) if you have both users and admins in your app.
+
+**3) Route file to ```routes/backpack/custom.php```**
+
+This route file is for convenience and convention. We recommend you place all your admin panel routes here.
+
+
+
+### Published Views
+
+After installation, you'll notice Backpack has added a new blade file in ```resources/views/vendor/backpack/base/```:
+ - ```inc/sidebar_content.blade.php```;
+
+That file is used to show the contents of the menu to the left (sidebar). It's been published there so that you can easily modify its contents, by editing its HTML or adding dynamic content through [widgets](/docs/{{version}}/base-widgets).
+
+
+### Unpublished Views
+
+You can change any blade file to your own needs. Determine what file you'd need to modify if you were to edit directly in the project's vendor folder, then go to ```resources/views/vendor/backpack/base``` and create a file with the exact same name. Backpack\Base will use this new file, instead of the one in the package.
+
+For example:
+- if you want to add an item to the top menu, you could just create a file called ```resources/views/vendor/backpack/base/inc/topbar_left_content.blade.php```; Backpack will now use this file's contents, instead of ```vendor/backpack/base/src/resources/views/inc/topbar_left_content.php```;
+- if you want to change the contents of the dashboard page, you can just create a file called `resources/views/vendor/backpack/base/dashboard.blade.php` and Backpack will use that one, instead of the one in the package;
+
+You can create blade views from scratch, or you can use our command to publish the view from the package and edit it to your liking:
+```
+php artisan backpack:publish base/dashboard
+```
+
+Then inside the blade files, you can use either plain-old HTML or add dynamic content through [Backpack widgets](/docs/{{version}}/base-widgets).
+
+
+### Folder Structure
+
+If you'll take a look inside any Backpack package, you'll notice the ```src``` directory is organised like a standard Laravel app. This is intentional. It should help you easily understand how the package works, and how you can overwrite/customize its functionality.
+
+- ```app```
+ - ```Console```
+ - ```Commands```
+ - ```Http```
+ - ```Controllers```
+ - ```Middleware```
+ - ```Requests```
+ - ```Notifications```
+- ```config```
+- ```resources```
+ - ```lang```
+ - ```views```
+- ```routes```
+
+
+## Authentication
+
+When installed, Backpack provides a way for admins to login, recover password and register (don't worry, register is only enabled on ```localhost```). It does so with its own authentication controllers, models and middleware. If you have regular end-users (not admins), you can keep the _user_ authentication completely separate from _admin_ authentication. You can change which model, middleware classes Backpack uses, inside the ```config/backpack/base.php``` config file.
+
+> **Backpack uses Laravel's default ```App\User``` model**. This assumes you weren't already using this model, or the ```users``` table, for anything else. Or that you plan to use it for both users & admins. Otherwise, please read below.
+
+
+### Using a Different User Model
+
+If you want to use a different User model than ```App\User``` or you've changed its location, please, you can tell Backpack to use _a different_ model in ```config/backpack/base.php``` instead of the ```App\User``` model that Laravel apps usually have. Look for ```user_model_fqn```.
+
+
+
+### Having Both Regular Users and Admins
+
+If you already use the ```users``` table to store end-users (not admins), you will need a way to differentiate admins from regular users. Backpack does not force one method on you. Here are two methods we recommend, below:
+- (A) adding an ```is_admin``` column to your ```users``` table, then changing the ```app/Http/Middleware/CheckIfAdmin::checkIfUserIsAdmin()``` method to test that attribute exists, and is true;
+- (B) using the [PermissionManager](https://github.com/Laravel-Backpack/PermissionManager) extension - this will also add groups and permissions; Then tell Backpack to use _your new permission middleware_ to check if a logged in user is an admin, inside ```config/backpack/base.php```;
+
+
+### Routes
+
+By default, all administration panel routes will be behind an ```/admin/``` prefix, and under an ```CheckIfAdmin``` middleware. You can change that inside ```config/backpack/base.php```.
+
+Inside your _admin controllers or views_, please:
+- use ```backpack_auth()``` instead of ```auth()```;
+- use ```backpack_user()``` instead of ```auth()->user```;
+- use ```backpack_url()``` instead of ```url()```;
+
+This will make sure you're using the model, prefix & middleware that you've defined in ```config/backpack/base.php```. In case you decide to make changes there later, you won't need to change anything else. There are also [other backpack helpers you can use](#helpers).
+
+
+## Admin Account
+
+When logged in, the admin can click his/her name to go to his "account" page. There, they will be able to do a few basic operations: change name, email or password.
+
+
+### Change Name and Email
+
+Changing name and email is done inside ```Backpack\Base\app\Http\Controllers\Auth\MyAccountController```, using the ```getAccountInfoForm()``` and ```postAccountInfoForm()``` methods. If you want to change how this works, we recommend you create a ```routes/backpack/base.php``` file, copy-paste all Backpack\Base routes there and change whatever routes you need, to point to _your own controller_, where you can do whatever you want.
+
+If you only want to add a few new inputs, you can do that by creating a file in ```resources/views/vendor/backpack/base/my_account.blade.php``` that uses code from the same file in the Backpack package, but adds the inputs you need. Remember to also make these fields ```$fillable``` in your User model.
+
+
+### Change Password
+
+Password changing is done inside ```Backpack\Base\app\Http\Controllers\Auth\MyAccountController```. If you want to change how this works, we recommend you create a ```routes/backpack/base.php``` file, copy-paste all Backpack\Base routes there and change whatever you need. You can then point the route to your own controller, where you can do whatever you want.
+
+
+
+## Helpers
+
+You can use these helpers anywhere in your app (models, views, controllers, requests, etc), except the config files, since the config files are loaded _before_ the helpers.
+
+- **```backpack_url(http://github.com/$path)```** - Use this helper instead of ```url()``` to generate paths with the admin prefix prepended.
+- **```backpack_auth()```** - Returns the Auth facade, using the current Backpack guard. Basically a shorthand for ```\Auth::guard(backpack_guard_name())```. Use this instead of ```auth()``` inside your admin panel pages.
+- **```backpack_middleware()```** - Returns the key for the admin middleware. Default is ```admin```.
+- ```backpack_authentication_column()``` - Returns the username column. The Laravel and Backpack default is ```email```.
+- ```backpack_users_have_email()``` - Tests that the ```email``` column exists on the users table and returns true/false.
+- ```backpack_avatar($user)``` - Receives a user object and returns a path to an avatar image, according to the preferences in the config file (gravatar, placeholder or custom).
+- ```backpack_guard_name()``` - Returns the guard used for Backpack authentication.
+- ```backpack_user()``` - Returns the current Backpack user, if logged in. Basically a shorthand for ```\Auth::guard(backpack_guard_name())->user()```. Use this instead of ```auth()->user()``` inside your admin pages.
+
+
+## Error Pages
+
+When installing Backpack, a few error views are published into ```resources/views/errors```, if you don't already have other files there. This is because Laravel does not provide error pages for all HTTP error codes. Having these files in your project will make sure that, if a user gets an HTTP error, at least it will look decent. Error pages are provided for the following error codes: ```400```, ```401```, ```403```, ```404```, ```405```, ```408```, ```429```, ```500```, ```503```.
+
+
+
+## Custom Pages
+
+To create a new page for your admin panel, you can follow the same process you would if you created a normal Laravel page (a Route, View and maybe a Controller). Just make sure that:
+- the route file is under the `admin` middleware;
+- the view extends one of our layout files (so that you get the design and the topbar+sidebar layout;
+
+### Add a custom page to your admin panel (dynamic page)
+
+```php
+
+# Step 1. Create a route for it (we recommend you place it in your `routes/backpack/custom.php` for simplicity)
+
+Route::get('example-page', 'PageController@example');
+
+# Step 2. Create the controller (we recommend you place it in your `app/Http/Controllers/Admin`)
+
+Example page
+@endsection
+```
+
+### Add a custom page to your admin panel (static page)
+
+Alternatively, if you are not getting any information from the database, and are just creating a quick static page, here's a quicker way:
+
+
+```php
+
+# Step 1. Create a route for it (we recommend you place it in your `routes/backpack/custom.php` for simplicity)
+
+Route::get('example-page', function () { return view('admin.example_page'); });
+
+# Step 2. Create that view (we recommend you place it in your `resources/views/admin`:
+
+@extends(backpack_view('blank'))
+
+@section('content')
+
Example page
+@endsection
+
+```
+
diff --git a/4.1/base-alerts.md b/4.1/base-alerts.md
new file mode 100644
index 00000000..6bfe0be2
--- /dev/null
+++ b/4.1/base-alerts.md
@@ -0,0 +1,63 @@
+# Alerts
+
+---
+
+
+## About
+
+When building custom functionality, you'll probably need to give feedback to the admin for something that happened in the background. You can easily do that in Backpack by triggering alerts (aka notification bubbles, aka notifications). You can do that both from Javascript and from PHP - and they will look exactly the same. In fact, Backpack operations use this same API. By using Alerts in your custom pages too, you make sure your alerts look the same across your admin panel - and your UI will be consistent.
+
+
+
+### Triggering Alerts in PHP
+
+We use [prologue/alerts](https://github.com/prologuephp/alerts#adding-alerts-through-alert-levels) to trigger notifications. Check out its documentation for the entire syntax.
+
+Most of the time, all you need to do is trigger a notification of a certain type, or trigger a notification using flash data, so that it shows after a redirect:
+
+```php
+public function foo()
+{
+ \Alert::add('info', 'This is a blue bubble.');
+ \Alert::add('warning', 'This is a yellow/orange bubble.');
+ \Alert::add('error', 'This is a red bubble.');
+ \Alert::add('success', 'Got it This is HTML in a green bubble.');
+ \Alert::add('primary', 'This is a dark blue bubble.');
+ \Alert::add('secondary', 'This is a grey bubble.');
+ \Alert::add('light', 'This is a light grey bubble.');
+ \Alert::add('dark', 'This is a black bubble.');
+
+ // the layout will make sure to show your notifications
+ return view('some_view');
+}
+
+public function bar()
+{
+ \Alert::add('success', 'You have successfully logged in')->flash();
+
+ // please note the above flash() method; this will store your notification in a session variable, so that you can redirect to another page, but the notification will still be shown (on the page you redirect to)
+ return Redirect::to('some-url');
+}
+```
+
+
+### Triggering Alerts in JavaScript
+
+We use [Noty](https://ned.im/noty/#/) to show notifications from JavaScript, on the same page. Check out its docs for detailed use. Most of the time you'll only need to do:
+
+```php
+new Noty({
+ type: "success",
+ text: 'Some notification text',
+}).show();
+
+// available types:
+// - success
+// - info
+// - warning/notice
+// - error/danger
+// - primary
+// - secondary
+// - dark
+// - light
+```
\ No newline at end of file
diff --git a/4.1/base-breadcrumbs.md b/4.1/base-breadcrumbs.md
new file mode 100644
index 00000000..a3a7d5ad
--- /dev/null
+++ b/4.1/base-breadcrumbs.md
@@ -0,0 +1,89 @@
+# Breadcrumbs
+
+---
+
+
+## About
+
+Breadcrumbs show a path to the current page in the top-right corner of the screen, and can be a useful part of the UI for deeply nested admin panels.
+
+Breadcrumbs are loaded in the default layout _before_ the ```header``` section.
+
+
+## Enable / Disable Breadcrumbs
+
+You can hide or show breadcrumbs on ALL of your admin panel pages by changing a boolean variable in your ```config/backpack/base.php```:
+
+```php
+ // Show / hide breadcrumbs on admin panel pages.
+ 'breadcrumbs' => true,
+```
+
+
+## How Breadcrumbs Work
+
+The ```inc.breadcrumbs``` view will show all breadcrumbs from the ```$breadcrumbs``` variable, if it's present on the page. The ```$breadcrumbs``` variable should be a simple associative array ```[ $label1 => $link1, $label2 => $link2 ]```. Examples:
+
+```php
+ $breadcrumbs = [
+ trans('backpack::crud.admin') => backpack_url('http://github.com/dashboard'),
+ trans('backpack::base.dashboard') => false,
+ ];
+
+ $breadcrumbs = [
+ trans('backpack::crud.admin') => backpack_url('http://github.com/dashboard'),
+ trans('backpack::base.dashboard') => false,
+ ];
+
+ $breadcrumbs = [
+ 'Admin' => route('dashboard'),
+ 'Dashboard' => false,
+ ];
+```
+
+Notice the last item should NOT have a link, it should be ```false```.
+
+
+## How to Define Breadcrumbs
+
+
+### Define Breadcrumbs Inside the Controller
+
+Make sure a ```$breadcrumbs``` variable is present inside your views:
+```php
+ /**
+ * Show the admin dashboard.
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function dashboard()
+ {
+ $this->data['title'] = trans('backpack::base.dashboard'); // set the page title
+ $this->data['breadcrumbs'] = [
+ trans('backpack::crud.admin') => backpack_url('http://github.com/dashboard'),
+ trans('backpack::base.dashboard') => false,
+ ];
+
+ return view('backpack::dashboard', $this->data);
+ }
+```
+
+
+### Define Breadcrumbs Inside the View
+
+Make sure a ```$breadcrumbs``` variable is present:
+
+```php
+@extends('backpack::layout')
+
+@php
+ $breadcrumbs = [
+ 'Admin' => backpack_url('http://github.com/dashboard'),
+ 'Dashboard' => false,
+ ];
+@endphp
+
+@section('content')
+ some other content here
+@endsection
+```
\ No newline at end of file
diff --git a/4.1/base-how-to.md b/4.1/base-how-to.md
new file mode 100644
index 00000000..fbaa0cb5
--- /dev/null
+++ b/4.1/base-how-to.md
@@ -0,0 +1,540 @@
+# FAQs for the admin UI
+
+---
+
+
+
+## Look and feel
+
+
+### Customize the menu or sidebar
+
+During installation, Backpack publishes a few files in you ```resources/views/vendor/backpack/base/inc``` folder. In there, you'll also find:
+- ```sidebar_content.php```
+- ```topbar_left_content.php```
+- ```topbar_right_content.php```
+
+Change those files as you please.
+
+
+### Customize the dashboard
+
+The dashboard is shown from ```Backpack\Base\app\Http\Controller\AdminController.php::dashboard()```. If you take a look at that method, you'll see that the only thing it does is to set a title, breadcrumbs, and return a view: ```backpack::dashboard```.
+
+In order to place something else inside that view, like [widgets](/docs/{{version}}/base-widgets), simply publish that view in your project, and Backpack will pick it up, instead of the one in the package. Create a ```resources/views/vendor/backpack/base/dashboard.blade.php``` file:
+
+```html
+@extends(backpack_view('blank'))
+
+@php
+ $widgets['before_content'][] = [
+ 'type' => 'jumbotron',
+ 'heading' => trans('backpack::base.welcome'),
+ 'content' => trans('backpack::base.use_sidebar'),
+ 'button_link' => backpack_url('http://github.com/logout'),
+ 'button_text' => trans('backpack::base.logout'),
+ ];
+@endphp
+
+@section('content')
+
Your custom HTML can live here
+@endsection
+```
+
+To use information from the database, you can:
+- [use view composers](https://laravel.com/docs/5.7/views#view-composers) to push variables inside this view, when it's loaded;
+- load all your dashboard information using AJAX calls, if you're loading charts, reports, etc, and the DB queries might take a long time;
+- use the full namespace for your models, like ```\App\Models\Product::count()```;
+
+Take a look at the [widgets](/docs/{{version}}/base-widgets) we have - you can easily use those in your dashboard. You can also add whatever HTML you want inside the content block - check the [Backstrap HTML Template](https://backstrap.net/widgets.html) for design components you can copy-paste to speed up your custom HTML.
+
+
+### Customizing the design of the menu / sidebar / footer
+
+In ```config/backpack/base.php``` you'll notice there are variables where you can change exactly what CSS classes are placed on the HTML elements that represent the header, body, sidebar and footer:
+
+```php
+ // Horizontal navbar classes. Helps make the admin panel look similar to your project's design.
+ 'header_class' => 'app-header bg-light border-0 navbar',
+ // Try adding bg-dark, bg-primary, bg-secondary, bg-danger, bg-warning, bg-success, bg-info, bg-blue, bg-light-blue, bg-indigo, bg-purple, bg-pink, bg-red, bg-orange, bg-yellow, bg-green, bg-teal, bg-cyan
+ // You might need to add "navbar-dark" too if the background color is a dark one.
+ // Add header-fixed if you want the header menu to be sticky
+
+ // Body element classes.
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ // Try sidebar-hidden, sidebar-fixed, sidebar-compact, sidebar-lg-show
+
+
+ // Sidebar element classes.
+ 'sidebar_class' => 'sidebar sidebar-pills bg-light',
+ // Remove "sidebar-transparent" for standard sidebar look
+ // Try "sidebar-light" or "sidebar-dark" for dark/light links
+ // You can also add a background class like bg-dark, bg-primary, bg-secondary, bg-danger, bg-warning, bg-success, bg-info, bg-blue, bg-light-blue, bg-indigo, bg-purple, bg-pink, bg-red, bg-orange, bg-yellow, bg-green, bg-teal, bg-cyan
+
+ // Footer element classes.
+ 'footer_class' => 'app-footer',
+```
+
+Our default design might not be pleasant for your, or you might need to make the UI integrate better into your project. We totally understand. You can use the classes above to make it look considerably different.
+
+You'll find a few examples below - but you should use which classes you want to get the result you need.
+
+
+#### Backstrap
+
+Transparent top menu, transparent sidebar, transparent footer. This is the default. This is what _we_ think is best for most users, from our 8+ years of experience building admin panels. Prioritising _content_ over _menus_.
+
+
+
+```php
+ 'header_class' => 'app-header bg-light border-0 navbar',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar sidebar-pills bg-light',
+ 'footer_class' => 'app-footer',
+```
+
+
+#### Inspired by CoreUI
+
+White top menu, dark sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar',
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+#### Inspired by Github
+
+Black top menu, white sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header bg-dark navbar',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar bg-white sidebar-pills',
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+#### Blue Top Menu
+
+Blue top menu, dark sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar navbar-color bg-primary border-0',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar', // add "bg-white sidebar-pills" for light sidebar
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+
+#### Construction / Warning
+
+Yellow top menu, dark sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar navbar-light bg-warning',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar', // add "bg-white sidebar-pills" for light sidebar
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+#### Red Top Menu
+
+Red top menu, dark sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar navbar-color bg-error border-0',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar', // add "bg-white sidebar-pills" for light sidebar
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+#### Pink Top Menu
+
+Pink top menu, transparent sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar navbar-color bg-error border-0',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar sidebar-pills bg-light',
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+
+#### Green Top Menu
+
+Green top menu, white sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar navbar-color bg-green border-0',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar sidebar-pills bg-white',
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+### Create a new theme / child theme
+
+You can create a theme with your own HTML. Create a folder with all the views you want to overwrite, then change ```view_namespace``` inside your ```config/backpack/base.php``` to point to that folder. All views will be loaded from _that_ folder if they exist, then from ```resources/views/vendor/backpack/base```, then from the Base package.
+
+You can use child themes to:
+- create packages for your Backpack admin panels to look different (and re-use across projects)
+- use a different CSS framework (ex: Tailwind, Bulma)
+
+
+
+### Add custom Javascript to all admin panel pages
+
+In ```config/backpack/base.php``` you'll notice this config option:
+
+```php
+ // JS files that are loaded in all pages, using Laravel's asset() helper
+ 'scripts' => [
+ // Backstrap includes jQuery, Bootstrap, CoreUI, PNotify, Popper
+ 'packages/backpack/base/js/bundle.js?v='.\PackageVersions\Versions::getVersion('backpack/base'),
+
+ // examples (everything inside the bundle, loaded from CDN)
+ // 'https://code.jquery.com/jquery-3.4.1.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js',
+ // 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js',
+ // 'https://unpkg.com/@coreui/coreui/dist/js/coreui.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/pace/1.0.2/pace.min.js',
+ // 'https://unpkg.com/sweetalert/dist/sweetalert.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/noty/3.1.4/noty.min.js'
+
+ // examples (VueJS or React)
+ // 'https://unpkg.com/vue@2.4.4/dist/vue.min.js',
+ // 'https://unpkg.com/react@16/umd/react.production.min.js',
+ // 'https://unpkg.com/react-dom@16/umd/react-dom.production.min.js',
+ ],
+```
+
+You can add files to this array, and they'll be loaded in all admin panels pages.
+
+
+### Add custom CSS to all admin panel pages
+
+In ```config/backpack/base.php``` you'll notice this config option:
+
+```php
+ // CSS files that are loaded in all pages, using Laravel's asset() helper
+ 'styles' => [
+ 'packages/@digitallyhappy/backstrap/css/style.min.css',
+
+ // Examples (the fonts above, loaded from CDN instead)
+ // 'https://maxcdn.icons8.com/fonts/line-awesome/1.1/css/line-awesome-font-awesome.min.css',
+ // 'https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic',
+ ],
+```
+
+You can add files to this array, and they'll be loaded in all admin panels pages.
+
+
+### Customize the look and feel of the admin panel (using CSS)
+
+If you want to change the look and feel of the admin panel, you can create a custom CSS file wherever you want. We recommend you do it inside ```public/packages/myname/mycustomthemename/css/style.css``` folder so that it's easier to turn into a theme, if you decide later to share or re-use your CSS in other projects.
+
+In ```config/backpack/base.php``` add your file to this config option:
+
+```php
+ // CSS files that are loaded in all pages, using Laravel's asset() helper
+ 'styles' => [
+ 'packages/@digitallyhappy/backstrap/css/style.min.css',
+ // ...
+ 'packages/myname/mycustomthemename/css/style.css',
+ ],
+```
+
+This config option allows you to add CSS files that add style _on top_ of Backstrap, to make it look different. You can create a CSS file anywhere inside your ```public``` folder, and add it here.
+
+
+### How to add VueJS to all Backpack pages
+
+You can add any script you want inside all Backpack's pages by just adding it in your ```config/backpack/base.php``` file:
+
+```php
+
+ // JS files that are loaded in all pages, using Laravel's asset() helper
+ 'scripts' => [
+ // Backstrap includes jQuery, Bootstrap, CoreUI, PNotify, Popper
+ 'packages/backpack/base/js/bundle.js',
+
+ // examples (everything inside the bundle, loaded from CDN)
+ // 'https://code.jquery.com/jquery-3.4.1.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js',
+ // 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js',
+ // 'https://unpkg.com/@coreui/coreui/dist/js/coreui.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/pace/1.0.2/pace.min.js',
+ // 'https://unpkg.com/sweetalert/dist/sweetalert.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/noty/3.1.4/noty.min.js'
+
+ // examples (VueJS or React)
+ // 'https://unpkg.com/vue@2.4.4/dist/vue.min.js',
+ // 'https://unpkg.com/react@16/umd/react.production.min.js',
+ // 'https://unpkg.com/react-dom@16/umd/react-dom.production.min.js',
+ ],
+```
+
+You should be able to load Vue.JS by just uncommenting that one line. Or providing a link to a locally stored VueJS file.
+
+
+
+### Customize the translated strings (aka overwrite the language files)
+
+Backpack uses Laravel translations across the admin panel, to easily translate strings (ex: `{{ trans('backpack::base.already_have_an_account') }}`). If you don't like a translation, you're welcome to submit a PR to correct it for all users of your language. If you only want to correct it inside your app, or need to add a new translation string, you can *create a new file in your `resources/lang/vendor/backpack/en/base.php`* (similarly, `crud.php` or any other file). Any language strings that are inside your app, in the right folder, will be preferred over the ones in the package.
+
+Alternatively, if you need to customize A LOT of strings, you can use:
+```bash
+php artisan vendor:publish --provider="Backpack\CRUD\BackpackServiceProvider" --tag="lang"
+```
+which will publish ALL lang files, for ALL languages, inside `resources/lang/vendor/backpack`. But it's highly unlikely you need to modify all of them. In case you do publish all languages, please delete the ones you didn't change. That way, you only keep what's custom in your custom files, and it'll be easier to upgrade those files in the future.
+
+
+
+### Use the HTML & CSS for the front-end (Backstrap for front-facing website)
+
+If you like how Backpack looks and feels you can use the same interface to power your front-end, simply by making sure your blade view extend Backpack's layout file, instead of a layout file you'd create. Make sure your blade views extend `backpack_view('blank')` or create a layout file similar to our `layouts/top_left.blade.php` that better fits your needs. Then use it across your app:
+
+```php
+@extends(backpack_view('blank'))
+
+
Something
+```
+
+It's a good idea to go through our main layout file - [`layouts/top_left.blade.php`](https://github.com/Laravel-Backpack/CRUD/blob/master/src/resources/views/base/layouts/top_left.blade.php) - to understand how it works and how you can use it to your advantage. Most notably, you can:
+- use our `before_styles` and `after_styles` sections to easily _include_ CSS there - `@section('after_styles')`;
+- use our `before_styles` and `after_styles` stacks to easily _push_ CSS there - `@push('after_styles')`;
+- use our `before_scripts` and `after_scripts` sections to easily _include_ JS there - `@section('after_scripts')`;
+- use our `before_scripts` and `after_scripts` stacks to easily _push_ JS there - `@push('after_scripts')`;
+
+
+
+
+## Authentication
+
+
+### Customizing the Auth controllers
+
+In ```config/backpack/base.php``` you'll find these configuration options:
+
+```php
+ // Set this to false if you would like to use your own AuthController and PasswordController
+ // (you then need to setup your auth routes manually in your routes.php file)
+ 'setup_auth_routes' => true,
+```
+
+You can change both ```setup_auth_routes``` to ```false```. This means Backpack\Base won't register the Auth routes any more, so you'll have to manually register them in your route file, to point to the Auth controllers you want. If you're going to use the Auth controllers that Laravel generates, these are the routes you can use:
+```php
+Route::group(['middleware' => 'web', 'prefix' => config('backpack.base.route_prefix')], function () {
+ Route::auth();
+ Route::get('logout', 'Auth\LoginController@logout');
+});
+```
+
+
+### Customize the routes
+
+#### Custom routes - option 1
+
+You can place a new routes file in your ```app/routes/backpack/base.php```. If a file is present there, no default Backpack\Base routes will be loaded, only what's present in that file. You can use the routes file ```vendor/backpack/base/src/resources/views/base.php``` as an example, and customize whatever you want.
+
+#### Custom routes - option 2
+
+In ```config/backpack/base.php``` you'll find these configuration options:
+
+```php
+
+ /*
+ |--------------------------------------------------------------------------
+ | Routing
+ |--------------------------------------------------------------------------
+ */
+
+ // The prefix used in all base routes (the 'admin' in admin/dashboard)
+ 'route_prefix' => 'admin',
+
+ // Set this to false if you would like to use your own AuthController and PasswordController
+ // (you then need to setup your auth routes manually in your routes.php file)
+ 'setup_auth_routes' => true,
+
+ // Set this to false if you would like to skip adding the dashboard routes
+ // (you then need to overwrite the login route on your AuthController)
+ 'setup_dashboard_routes' => true,
+```
+
+In order to completely customize the auth routes, you can change both ```setup_auth_routes``` and ```setup_dashboard_routes``` to ```false```. This means Backpack\Base won't register any routes any more, so you'll have to manually register them in your route file. Here's what you can use to get started:
+```php
+Route::group(['middleware' => 'web', 'prefix' => config('backpack.base.route_prefix', 'namespace' => 'Backpack\Base\app\Http\Controllers')], function () {
+ Route::auth();
+ Route::get('logout', 'Auth\LoginController@logout');
+ Route::get('dashboard', 'AdminController@dashboard');
+ Route::get('/', 'AdminController@redirect');
+});
+```
+
+
+### Use separate login/register forms for users and admins
+
+This is a default in Backpack v4.
+
+Backpack's authentication uses a completely separate authentication driver, provider, guard and password broker. They're all named ```backpack```, and registered in the vendor folder, invisible to you.
+
+If you need a separate login for user, just go ahead and create it. [Add the Laravel authentication, like instructed in the Laravel documentation](https://laravel.com/docs/5.7/authentication#authentication-quickstart): ```php artisan make:auth```. You'll then have:
+- the user login at ```/login``` -> using the AuthenticationController Laravel provides
+- the admin login at ```/admin/login``` -> using the AuthenticationControllers Backpack provides
+
+The user login will be using Laravel's default authentication driver, provider, guard and password broker, from ```config/auth.php```.
+
+Backpack's authentication driver, provider, guard and password broker can easily be overwritten by creating a driver/provider/guard/broker with the ```backpack``` name inside your ```config/auth.php```. If one named ```backpack``` exists there, Backpack will use that instead.
+
+
+### Overwrite Backpack authentication driver, provider, guard or password broker
+
+Backpack's authentication uses a completely separate authentication driver, provider, guard and password broker. Backpack adds them to what's defined in ```config/auth.php``` on runtime, and they're all named ```backpack```.
+
+To change a setting in how Backpack's driver/provider/guard or password broker works, create a driver/provider/guard/broker with the ```backpack``` name inside your ```config/auth.php```. If one named ```backpack``` exists there, Backpack will use that instead.
+
+
+### Use separate sessions for admin&user authentication
+
+This is a default in Backpack v4.
+
+
+### Login with username instead of email
+
+1. Create a ```username``` column in your users table and add it in ```$fillable``` on your ```User``` model. Best to do this with a migration.
+2. Remove the UNIQUE and NOT NULL constraints from ```email``` on your table. Best to do this with a migration. Alternatively, delete your ```email``` column and remove it from ```$fillable``` on your ```User``` model. If you already have a CRUD for users, you might also need to delete it from the Request, and from your UserCrudController.
+3. Change your ```config/backpack/base.php``` config options:
+```php
+ // Username column for authentication
+ // The Backpack default is the same as the Laravel default (email)
+ // If you need to switch to username, you also need to create that column in your db
+ 'authentication_column' => 'username',
+ 'authentication_column_name' => 'Username',
+```
+That's it. This will:
+- use ```username``` for login;
+- use ```username``` for registration;
+- use ```username``` in My Account, when a user wants to change his info;
+- completely disable the password recovery (if you've deleted the ```email``` db column);
+
+
+
+### Use your own User model instead of App\User
+
+By default, authentication and everything else inside Backpack is done using the ```App\User``` model. If you change the location of ```App\User```, or want to use a different User model for whatever other reason, you can do so by changing ```user_model_fqn``` in ```config/backpack/base.php``` to your new class.
+
+
+
+### Use your own profile image (avatar)
+
+By default, Backpack will use Gravatar to show the profile image for the currently logged in backpack user. In order to change this, you can use the option in ```config/backpack/base.php```:
+```php
+// What kind of avatar will you like to show to the user?
+// Default: gravatar (automatically use the gravatar for his email)
+//
+// Other options:
+// - placehold (generic image with his first letter)
+// - example_method_name (specify the method on the User model that returns the URL)
+'avatar_type' => 'gravatar',
+```
+
+Please note that this does not allow the user to change his profile image.
+
+
+
+### Add one or more fields to the Register form
+
+To add a new field to the Registration page, you should:
+
+**Step 1.** Overwrite the registration route, so it leads to _your_ controller, instead of the one in the package. We recommend you add it your ```routes/backpack/custom.php```, BEFORE the route group where you define your CRUDs:
+
+```php
+Route::get('admin/register', 'App\Http\Controllers\Admin\Auth\RegisterController')->name('backpack.auth.register');
+```
+
+**Step 2.** Create the new RegisterController somewhere in your project, that extends the RegisterController in the package, and overwrites the validation & user creation methods. For example:
+
+```php
+getTable();
+ $email_validation = backpack_authentication_column() == 'email' ? 'email|' : '';
+
+ return Validator::make($data, [
+ 'name' => 'required|max:255',
+ backpack_authentication_column() => 'required|'.$email_validation.'max:255|unique:'.$users_table,
+ 'password' => 'required|min:6|confirmed',
+ ]);
+ }
+
+ /**
+ * Create a new user instance after a valid registration.
+ *
+ * @param array $data
+ *
+ * @return User
+ */
+ protected function create(array $data)
+ {
+ $user_model_fqn = config('backpack.base.user_model_fqn');
+ $user = new $user_model_fqn();
+
+ return $user->create([
+ 'name' => $data['name'],
+ backpack_authentication_column() => $data[backpack_authentication_column()],
+ 'password' => bcrypt($data['password']),
+ ]);
+ }
+}
+```
+Add whatever validation rules & inputs you want, in addition to name and password.
+
+**Step 3.** Add the actual inputs to your HTML. You can easily overwrite the register view by adding this method to the same RegisterController:
+
+```php
+ public function showRegistrationForm()
+ {
+
+ return backpack_view('auth.register');
+ }
+```
+This will make the registration process pick up a view you can create, in ```resources/views/vendor/backpack/base/auth/register.blade.php```. You can copy-paste the original view, and modify as you please. Including adding your own custom inputs.
+
diff --git a/4.1/base-widgets.md b/4.1/base-widgets.md
new file mode 100644
index 00000000..eab8068a
--- /dev/null
+++ b/4.1/base-widgets.md
@@ -0,0 +1,570 @@
+# Widgets
+
+---
+
+
+## About
+
+Widgets (aka cards, aka charts, aka graphs) provide a simple way to insert blade files into admin panel pages. You can use them to insert cards, charts, notices or custom content into pages.
+
+
+
+### Requirements
+
+In order to use the ```Widget``` class, you should make sure your main views (for new admin panel pages) extend the ```backpack::blank``` or ```backpack_view('blank')``` blade template. This template includes two sections where you can push widgets:
+- ```before_content```
+- ```after_content```
+
+
+
+### How to Use
+
+You can easily push widgets to these sections, by using the autoloaded ```Widget``` class. You can think of the ```Widget``` class as a global container for widgets, for the current page being rendered. That means you can call the ```Widget``` container inside a ```Controller```, inside a ```view```, or inside a service provider you create - wherever you want.
+
+```php
+use Backpack\CRUD\app\Library\Widget;
+
+Widget::add($widget_definition_array)->to('before_content');
+
+// alternatively, use a fluent syntax to define each widget attribute
+Widget::add()
+ ->to('before_content')
+ ->type('card')
+ ->content(null);
+```
+
+
+
+### Mandatory Attributes
+
+When passing a widget array, you need to specify at least these attributes:
+```php
+[
+ 'type' => 'card' // the kind of widget to show
+ 'content' => null // the content of that widget (some are string, some are array)
+],
+```
+
+
+### Optional Attributes
+
+Most widget types also have these attributes present, which you can use to tweak how the widget looks inside the page:
+```php
+'wrapper' => [
+ 'class' => 'col-sm-6 col-md-4', // customize the class on the parent element (wrapper)
+ 'style' => 'border-radius: 10px;',
+]
+```
+
+
+### Widgets API
+
+To manipulate widgets, you can use the methods below. The action will be performed on the page being constructed for the current request. And the ```Widget``` class is a global container, so you can add widgets to it both from the Controller, and from the view.
+
+```php
+// to add a widget to a different section than the default 'before_content' section:
+Widget::add($widget_definition_array)->to('after_content');
+Widget::add($widget_definition_array)->section('after_content');
+Widget::add($widget_definition_array)->group('after_content');
+
+// to create a widget, WITHOUT adding it to a section
+Widget::make($widget_definition_array);
+
+// to define the contents of a widget, pass the definition array to the make()/add() methods
+Widget::add($widget_definition_array);
+Widget::make($widget_definition_array);
+// alternatively, define each widget attribute one by one, using a fluent syntax
+Widget::add()
+ ->to('after_content')
+ ->type('card')
+ ->content('something');
+
+// to reference a widget later on, give it a unique 'name'
+Widget::add($widget_definition_array)->name('my_widget');
+
+// you can then easily modify it
+Widget::name('my_widget')->content('some other content'); // change the 'content' attribute
+Widget::name('my_widget')->forget('attribute_name'); // unset a widget attribute
+Widget::name('my_widget')->makeFirst(); // make a widget the first one in its section
+Widget::name('my_widget')->makeLast(); // to make a widget the last one in its section
+Widget::name('my_widget')->remove(); // remove the widget from its section
+```
+
+
+
+
+## Default Widget Types
+
+
+### Alert
+
+Shows a notification bubble, with the heading and text you specify:
+
+```php
+[
+ 'type' => 'alert',
+ 'class' => 'alert alert-danger mb-2',
+ 'heading' => 'Important information!',
+ 'content' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Corrupti nulla quas distinctio veritatis provident mollitia error fuga quis repellat, modi minima corporis similique, quaerat minus rerum dolorem asperiores, odit magnam.',
+ 'close_button' => true, // show close button or not
+]
+```
+
+For different colors, you can use the following classes: ```alert-success```, ```alert-warning```, ```alert-info```, ```alert-danger``` ```alert-primary```, ```alert-secondary```, ```alert-light```, ```alert-dark```.
+
+Widget Preview:
+
+
+
+
+
+
+### Card
+
+Shows a Bootstrap card, with the heading and body you specify. You can customize the class name to get cards of different color, size, etc.
+
+```php
+[
+ 'type' => 'card',
+ // 'wrapper' => ['class' => 'col-sm-6 col-md-4'], // optional
+ // 'class' => 'card bg-dark text-white', // optional
+ 'content' => [
+ 'header' => 'Some card title', // optional
+ 'body' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non mi nec orci euismod venenatis. Integer quis sapien et diam facilisis facilisis ultricies quis justo. Phasellus sem turpis, ornare quis aliquet ut, volutpat et lectus. Aliquam a egestas elit. Nulla posuere, sem et porttitor mollis, massa nibh sagittis nibh, id porttitor nibh turpis sed arcu.',
+ ]
+]
+```
+
+For different background colors, you can use the following classes: ```bg-success```, ```bg-warning```, ```bg-info```, ```bg-danger``` ```bg-primary```, ```bg-secondary```, ```bg-light```, ```bg-dark```.
+
+Other useful helper classes: ```text-center```, ```text-white```.
+
+Widget Preview:
+
+
+
+
+
+
+### Chart
+
+Shows a pie chart / line chart / bar chart inside a Bootstrap card, with the heading and body you specify.
+
+
+
+To create and use a new widget chart, you need to:
+
+**Step 1.** Install laravel-charts, that offers a single PHP syntax for 6 different charting libraries:
+```
+composer require consoletvs/charts:"6.*"
+```
+
+**Step 2.** Create a new ChartController:
+
+```
+php artisan backpack:chart WeeklyUsers
+
+```
+
+This will create:
+- a new ChartController inside ```app\Http\Controllers\Admin\Charts\WeeklyUsersChartController```
+- a route towards that ChartController in your ```routes/backpack/custom.php```
+
+**Step 3.** Add the widget that points to that ChartController you just created:
+```php
+Widget::add([
+ 'type' => 'chart',
+ 'controller' => \App\Http\Controllers\Admin\Charts\WeeklyUsersChartController::class,
+
+ // OPTIONALS
+
+ // 'class' => 'card mb-2',
+ // 'wrapper' => ['class'=> 'col-md-6'] ,
+ // 'content' => [
+ // 'header' => 'New Users',
+ // 'body' => 'This chart should make it obvious how many new users have signed up in the past 7 days.
',
+ // ],
+]);
+```
+
+**Step 4.** Configure the ChartController you just created:
+- ```public function setup()``` (MANDATORY)
+ - initialize and configure ```$this->chart```, using the methods detailed in the [laravel-charts documentation](https://charts.erik.cat/getting_started.html);
+ - you _can_ define your dataset here, if you want your DB queries to be called upon page load;
+- ```public function data()``` (OPTIONAL, but recommended)
+ - use ```$this->chart->dataset()``` to configure what the chart should contain;
+ - if it's defined, the chart will loads its contents using AJAX;
+
+Optionally:
+- you can _easily_ switch the JavaScript library used, by changing the use statement at the top of this file:
+
+```diff
+-use ConsoleTVs\Charts\Classes\Chartjs\Chart;
++use ConsoleTVs\Charts\Classes\Echarts\Chart;
++use ConsoleTVs\Charts\Classes\Fusioncharts\Chart;
++use ConsoleTVs\Charts\Classes\Highcharts\Chart;
++use ConsoleTVs\Charts\Classes\C3\Chart;
++use ConsoleTVs\Charts\Classes\Frappe\Chart;
+```
+- you can change the path to the JS library; if you don't want it loaded from a CDN, you can define ```$library``` or ```getLibraryFilePath()``` on your ChartController:
+
+```php
+protected $library = 'http://path/to/file';
+
+// or
+
+public function getLibraryFilePath()
+{
+ return asset('path/to/your/js/file');
+
+ // or
+
+ return [
+ asset('path/to/first/js/file'),
+ asset('path/to/second/js/file'),
+ ];
+}
+```
+
+
+
+**That's it!** Refresh the page to see your new chart widget. Below, you'll find a few examples of how the ChartController can end up looking.
+
+
+
+**Example 1:** ChartController that loads results using AJAX:
+```php
+chart = new Chart();
+
+ // MANDATORY. Set the labels for the dataset points
+ $labels = [];
+ for ($days_backwards = 30; $days_backwards >= 0; $days_backwards--) {
+ if ($days_backwards == 1) {
+ }
+ $labels[] = $days_backwards.' days ago';
+ }
+ $this->chart->labels($labels);
+
+ // RECOMMENDED.
+ // Set URL that the ChartJS library should call, to get its data using AJAX.
+ $this->chart->load(backpack_url('http://github.com/charts/new-entries'));
+
+ // OPTIONAL.
+ $this->chart->minimalist(false);
+ $this->chart->displayLegend(true);
+ }
+
+ /**
+ * Respond to AJAX calls with all the chart data points.
+ *
+ * @return json
+ */
+ public function data()
+ {
+ for ($days_backwards = 30; $days_backwards >= 0; $days_backwards--) {
+ // Could also be an array_push if using an array rather than a collection.
+ $users[] = User::whereDate('created_at', today()
+ ->subDays($days_backwards))
+ ->count();
+ $articles[] = Article::whereDate('created_at', today()
+ ->subDays($days_backwards))
+ ->count();
+ $categories[] = Category::whereDate('created_at', today()
+ ->subDays($days_backwards))
+ ->count();
+ $tags[] = Tag::whereDate('created_at', today()
+ ->subDays($days_backwards))
+ ->count();
+ }
+
+ $this->chart->dataset('Users', 'line', $users)
+ ->color('rgb(77, 189, 116)')
+ ->backgroundColor('rgba(77, 189, 116, 0.4)');
+
+ $this->chart->dataset('Articles', 'line', $articles)
+ ->color('rgb(96, 92, 168)')
+ ->backgroundColor('rgba(96, 92, 168, 0.4)');
+
+ $this->chart->dataset('Categories', 'line', $categories)
+ ->color('rgb(255, 193, 7)')
+ ->backgroundColor('rgba(255, 193, 7, 0.4)');
+
+ $this->chart->dataset('Tags', 'line', $tags)
+ ->color('rgba(70, 127, 208, 1)')
+ ->backgroundColor('rgba(70, 127, 208, 0.4)');
+ }
+}
+
+```
+
+**Example 2.** Pie chart with both labels and dataset defined in the ```setup()``` method (no AJAX):
+
+```php
+chart = new Chart();
+
+ $this->chart->dataset('Red', 'pie', [10, 20, 80, 30])
+ ->backgroundColor([
+ 'rgb(70, 127, 208)',
+ 'rgb(77, 189, 116)',
+ 'rgb(96, 92, 168)',
+ 'rgb(255, 193, 7)',
+ ]);
+
+ // OPTIONAL
+ $this->chart->displayAxes(false);
+ $this->chart->displayLegend(true);
+
+ // MANDATORY. Set the labels for the dataset points
+ $this->chart->labels(['HTML', 'CSS', 'PHP', 'JS']);
+ }
+}
+
+```
+
+
+
+
+
+### Div
+
+Allows you to include multiple widgets in the div attributes of your choice. For example, you can include multiple widgets in a `````` with the code below:
+
+```php
+[
+ 'type' => 'div',
+ 'class' => 'row',
+ 'content' => [ // widgets
+ [ 'type' => 'card', 'content' => ['body' => 'One'] ],
+ [ 'type' => 'card', 'content' => ['body' => 'Two'] ],
+ [ 'type' => 'card', 'content' => ['body' => 'Three'] ],
+ ]
+]
+```
+
+Anything you specify on this widget, other than ```type``` and ```content```, has to be a string, and will be considered an attribute of the "div" element.
+
+
+
+
+### Jumbotron
+
+Shows a Bootstrap jumbotron component, with the heading and body you specify.
+
+```php
+[
+ 'type' => 'jumbotron',
+ 'heading' => 'Welcome!',
+ 'content' => 'Use the sidebar to the left to create, edit or delete content.',
+ 'button_link' => backpack_url('http://github.com/logout'),
+ 'button_text' => 'Logout',
+]
+```
+
+Widget Preview:
+
+
+
+
+
+
+### Progress
+
+Shows a colorful card to signify the progress towards a goal. You can customize the class name to get cards of different color, size, etc.
+
+```php
+[
+ 'type' => 'progress',
+ 'class' => 'card text-white bg-primary mb-2',
+ 'value' => '11.456',
+ 'description' => 'Registered users.',
+ 'progress' => 57, // integer
+ 'hint' => '8544 more until next milestone.',
+]
+```
+
+For different background colors, you can use the following classes: ```bg-success```, ```bg-warning```, ```bg-info```, ```bg-danger``` ```bg-primary```, ```bg-secondary```, ```bg-light```, ```bg-dark```.
+
+Other useful helper classes: ```text-center```, ```text-white```.
+
+Widget Preview:
+
+
+
+
+
+
+### Progress White
+
+Shows a white card to signify the progress towards a goal. You can customize the class name to get progress bars of different color.
+
+```php
+[
+ 'type' => 'progress_white',
+ 'class' => 'card mb-2',
+ 'value' => '11.456',
+ 'description' => 'Registered users.',
+ 'progress' => 57, // integer
+ 'progressClass' => 'progress-bar bg-primary',
+ 'hint' => '8544 more until next milestone.',
+]
+```
+
+For different progress bar colors, you can use the following classes: ```bg-success```, ```bg-warning```, ```bg-info```, ```bg-danger``` ```bg-primary```, ```bg-secondary```, ```bg-light```, ```bg-dark```.
+
+Widget Preview:
+
+
+
+
+
+
+### View
+
+Loads a blade view from a location you specify. Any attributes you give it will be available in the ```$widget``` variable inside that view.
+
+```php
+[
+ 'type' => 'view',
+ 'view' => 'path.to.custom.view',
+ 'someAttr' => 'some value',
+]
+```
+
+It helps load blade files that are not specifically created to be widgets, that live in a different path than ```resources/views/vendor/backpack/base/widgets```, as if they were widgets.
+
+
+
+
+## Overwriting Default Widget Types
+
+You can overwrite a widget type by placing a file with the same name in your ```resources\views\vendor\backpack\base\widgets``` directory. When a file is there, Backpack will pick that one up, instead of the one in the package. You can do that from command line using ```php artisan backpack:publish base/widgets/widget-name```
+
+Examples:
+- creating a ```resources\views\vendor\backpack\base\widgets\card.blade.php``` file would overwrite the ```card``` widget functionality;
+- ```php artisan backpack:publish base/widgets/card``` will take the view from the package and copy it to the directory above, so you can edit it;
+
+>Keep in mind that when you're overwriting a default widget type, you're forfeiting any future updates for that widget. We can't push updates to a file that you're no longer using.
+
+
+## Creating a Custom Widget Type
+
+Widgets consist of only one file - a blade file with the same name as the widget type (ex: ```card.blade.php```). You can create one by placing a new blade file inside ```resources\views\vendor\backpack\base\widgets```. Be careful to choose a distinctive name, otherwise you might be overwriting a default widget type (see above).
+
+For example, you can create a ```well.blade.php```:
+```php
+@includeWhen(!empty($widget['wrapper']), 'backpack::widgets.inc.wrapper_start')
+
+ {!! $widget['content'] !!}
+
+@includeWhen(!empty($widget['wrapper']), 'backpack::widgets.inc.wrapper_end')
+```
+
+You can then use the ```well``` widget in a Controller or View:
+```php
+@extends(backpack_view('blank'))
+
+@php
+ Widget::add([
+ 'type' => 'well',
+ 'wrapper' => ['class' => 'col-sm-12'],
+ 'content' => 'This text will be in a div with the class "well".',
+ ]);
+@endphp
+
+@section('content')
+@endsection
+```
+
+To use information from the database, you can:
+- use the full namespace for your models, like ```\App\Models\Product::count()```;
+- load all your dashboard information using AJAX calls, if you're loading charts, reports, etc, and the DB queries might take a long time;
+- [use view composers](https://laravel.com/docs/5.7/views#view-composers) to push variables inside this view when it's loaded, Like. ```View::composer('backpack::widgets.well, 'App\Http\View\Composers\WellComposer');```
+
+Inside the widget blade files, you include custom CSS and JS, by pushing to the stacks in the layout:
+```php
+@includeWhen(!empty($widget['wrapper']), 'backpack::widgets.inc.wrapper_start')
+
+ {!! $widget['content'] !!}
+
+@includeWhen(!empty($widget['wrapper']), 'backpack::widgets.inc.wrapper_end')
+
+@push('after_styles')
+
+
+@endpush
+
+
+@push('after_scripts')
+
+
+@endpush
+```
+
+
+
+## Using a Widget Type from a Package
+
+You can choose the view namespace when loading a widget:
+
+```php
+
+// using the fluent syntax, use the 'from' alias
+Widget::add($widget_definition_array)->from('package::widgets');
+
+// using the widget definition array, specify its 'viewNamespace'
+Widget::add([
+ 'type' => 'card',
+ 'viewNamespace' => 'package::widgets',
+ 'wrapper' => ['class' => 'col-sm-6 col-md-4'],
+ 'class' => 'card text-white bg-primary text-center',
+ 'content' => [
+ // 'header' => 'Another card title',
+ 'body' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non mi nec orci euismod venenatis. Integer quis sapien et diam facilisis facilisis ultricies quis justo. Phasellus sem turpis, ornare quis aliquet ut, volutpat et lectus. Aliquam a egestas elit.',
+ ],
+]);
+
+```
+
+Similarly, if you want to create widgets somewhere else than in ```resources/views/vendor/backpack/base/widgets```, you can pass that directory as the namespace of your widget. For example, ```resources/views/admin/widgets``` would have ```admin.widgets``` as the namespace.
diff --git a/4.1/crud-api.md b/4.1/crud-api.md
new file mode 100644
index 00000000..04857b66
--- /dev/null
+++ b/4.1/crud-api.md
@@ -0,0 +1,530 @@
+# CRUD API
+
+---
+
+Here are all the features you will be using **inside your EntityCrudController**, grouped by the operation you will most likely use them for.
+
+## Operations
+
+- **operation()** - allows you to add a set of instructions inside ```setup()```, that only gets called when a certain operation is being performed;
+```php
+public function setup() {
+ // ...
+ $this->crud->operation('list', function() {
+ $this->crud->addColumn('name');
+ });
+}
+```
+
+
+### List Operation
+
+
+#### Columns
+
+Manipulate what columns are shown in the table view.
+
+- **addColumn()** - add a column, at the end of the stack
+```php
+$this->crud->addColumn($column_definition_array);
+```
+
+- **addColumns()** - add multiple columns, at the end of the stack
+```php
+$this->crud->addColumns([$column_definition_array, $another_column_definition_array]);
+```
+
+- **modifyColumn()** - change column attributes
+```php
+$this->crud->modifyColumn($name, $modifs_array);
+```
+
+- **removeColumn()** - remove one column from all operations
+```php
+$this->crud->removeColumn('column_name');
+```
+
+- **removeColumns()** - remove multiple columns from all operations
+```php
+$this->crud->removeColumns(['column_name_1', 'column_name_2']); // remove an array of columns from the stack
+```
+
+- **setColumnDetails()** - change the attributes of one column; alias of ```modifyColumn()```;
+```php
+$this->crud->setColumnDetails('column_name', ['attribute' => 'value']);
+```
+
+- **setColumnsDetails()** - change the attributes of multiple columns; alias of ```modifyColumn()```;
+```php
+$this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
+```
+
+- **setColumns()** - remove previously set columns and only use the ones give now;
+```php
+$this->crud->setColumns();
+// sets the columns you want in the table view, either as array of column names, or multidimensional array with all columns detailed with their types
+```
+
+- **Chained - beforeColumn()** - insert current column _before_ the given column
+```php
+// ------ REORDER COLUMNS
+$this->crud->addColumn()->beforeColumn('name');
+```
+
+- **Chained - afterColumn()** - insert current column _after_ the given column
+```php
+$this->crud->addColumn()->afterColumn('name');
+```
+
+- **Chained - makeFirstColumn()** - make this column the first one in the list
+```php
+$this->crud->addColumn()->makeFirstColumn();
+// Please note: you need to also specify priority 1 in your addColumn statement for details_row or responsive expand buttons to show
+```
+
+
+#### Buttons
+
+- **addButton()** - add a button in the given stack
+```php
+$this->crud->addButton($stack, $name, $type, $content, $position);
+// stacks: top, line, bottom
+// types: view, model_function
+// positions: beginning, end (defaults to 'beginning' for the 'line' stack, 'end' for the others);
+```
+
+- **addButtonFromModelFunction()** - add a button whose HTML is returned by a method in the CRUD model
+```php
+$this->crud->addButtonFromModelFunction($stack, $name, $model_function_name, $position);
+```
+
+- **addButtonFromView()** - add a button whose HTML is in a view placed at ```resources\views\vendor\backpack\crud\buttons```
+```php
+$this->crud->addButtonFromView($stack, $name, $view, $position);
+```
+
+- **modifyButton()** - modify the attributes of a button
+```php
+$this->crud->modifyButton($name, $modifications);
+```
+
+- **removeButton()** - remove a button from whatever stack it's in
+```php
+$this->crud->removeButton($name); // remove a single button
+$this->crud->removeButtons($names); // or multiple
+```
+
+- **removeButtonFromStack()** - remove a button from a particular stack
+```php
+$this->crud->removeButtonFromStack($name, $stack);
+```
+
+- **removeAllButtons()** - remove all buttons from any stack
+```php
+$this->crud->removeAllButtons();
+```
+
+- **removeAllButtonsFromStack()** - remove all buttons from a particular stack
+```php
+$this->crud->removeAllButtonsFromStack($stack);
+```
+
+
+#### Filters
+
+Manipulate what filters are shown in the table view. Check out [CRUD > Operations > ListEntries > Filters](/docs/{{version}}/crud-filters) to see examples of ```$filter_definition_array```
+
+- **addFilter()** - add a filter to the list view
+```php
+$this->crud->addFilter($filter_definition_array, $values, $filter_logic);
+```
+
+- **modifyFilter()** - change the attributes of a filter
+```php
+$this->crud->modifyFilter($name, $modifs_array);
+```
+
+- **removeFilter()** - remove a certain filter from the list view
+```php
+$this->crud->removeFilter($name);
+```
+
+- **removeAllFilters()** - remove all filters from the list view
+```php
+$this->crud->removeAllFilters();
+```
+
+- **filters()** - get all the registered filters for the list view
+```php
+$this->crud->filters();
+```
+
+
+#### Details Row
+
+Shows a ```+``` (plus sign) next to each table row, so that the user can expand that row and reveal details. You are responsible for creating the view with those details.
+
+- **enableDetailsRow()** - show the + sign in the table view
+```php
+$this->crud->enableDetailsRow();
+// NOTE: you also need to do allow access to the right users:
+$this->crud->allowAccess('details_row');
+// NOTE: you also need to do overwrite the showDetailsRow($id) method in your EntityCrudController to show whatever you'd like in the details row OR overwrite the views/backpack/crud/details_row.blade.php
+$this->crud->setDetailsRowView('your-view');
+```
+
+- **disableDetailsRow()** - hide the + sign in the table view
+```php
+$this->crud->disableDetailsRow();
+```
+
+
+#### Export Buttons
+
+Please note it will only export the current _page_ of results. So in order to export all entries the user needs to make the current page show "All" entries from the top-left picker.
+
+- **enableExportButtons()** - Show export to PDF, CSV, XLS and Print buttons on the table view
+```php
+$this->crud->enableExportButtons();
+```
+
+
+#### Responsive Table
+
+- **disableResponsiveTable()** - stop the listEntries view from showing/hiding columns depending on viewport width
+```php
+$this->crud->disableResponsiveTable();
+```
+
+- **enableResponsiveTable()** - make the listEntries view show/hide columns depending on viewport width
+```php
+$this->crud->enableResponsiveTable();
+```
+
+
+#### Persistent Table
+
+- **enablePersistentTable()** - make the listEntries remember the filters, search and pagination for a user, even if he leaves the page, for 2 hours
+```php
+$this->crud->enablePersistentTable();
+```
+
+- **disablePersistentTable()** - stop the listEntries from remembering the filters, search and pagination for a user, even if he leaves the page
+```php
+$this->crud->disablePersistentTable();
+```
+
+
+#### Page Length
+
+- **setDefaultPageLength()** - change the number of items per page in the list view
+```php
+$this->crud->setDefaultPageLength(10);
+```
+
+- **setPageLengthMenu()** - change the entire page length menu in the list view
+```php
+$this->crud->setPageLengthMenu([100, 200, 300]);
+```
+
+
+#### Actions Column
+
+- **setActionsColumnPriority()** - make the actions column (in the table view) hide when not enough space is available, by giving it an unreasonable priority
+```php
+$this->crud->setActionsColumnPriority(10000);
+```
+
+
+#### Custom / Advanced Queries
+
+- **addClause()** - change what entries are shown in the table view; this allows _developers_ to forcibly change the query used by the table view, as opposed to filters, that allow _users_ to change the query with new inputs;
+```php
+$this->crud->addClause('active'); // apply local scope
+$this->crud->addClause('type', 'car'); // apply local dynamic scope
+$this->crud->addClause('where', 'name', '=', 'car');
+$this->crud->addClause('whereName', 'car');
+$this->crud->addClause('whereHas', 'posts', function($query) {
+ $query->activePosts();
+ });
+```
+
+- **groupBy()** - shorthand to add a **groupBy** clause to the query
+```php
+$this->crud->groupBy();
+```
+
+- **limit()** - shorthand to add a **limit** clause to the query
+```php
+$this->crud->limit();
+```
+
+- **orderBy()** - shorthand to add an **orderBy** clause to the query
+```php
+$this->crud->orderBy();
+```
+
+
+### Show Operation
+
+Use [the same Columns API as for the ListEntries operation](#columns-api), but inside your ```show()``` method.
+
+
+### Create & Update Operations
+
+Manipulate what fields are shown in the create / update forms. Check out [CRUD > Operations > Create & Update > Fields](/docs/{{version}}/crud-fields) in the docs to see examples of ```$field_definition_array```.
+
+**Note:** The call is being performed for the current operation. So it's important to pay attention _where_ you're calling fields. Most likely, you'll want to do this inside ```setupCreateOperation()``` or ```setupUpdateOperation()```.
+
+- **addField()** - add one field
+```php
+$this->crud->addField($field_definition_array);
+$this->crud->addField('db_column_name'); // a lazy way to add fields: let the CRUD decide what field type it is and set it automatically, along with the field label
+```
+
+- **addFields()** - add multiple fields
+```php
+$this->crud->addFields($array_of_fields_definition_arrays);
+```
+
+- **modifyField()** - change the attributes of an existing field
+```php
+$this->crud->modifyField($name, $modifs_array);
+```
+
+- **removeField()** - remove a given field from the current operation
+```php
+$this->crud->removeField('name');
+```
+
+- **removeFields()** - remove multiple fields from the current operation
+```php
+$this->crud->removeFields($array_of_names);
+```
+
+- **removeAllFields()** - remove all registered fields
+```php
+$this->crud->removeAllFields();
+```
+- **Chained - beforeField()** - add a field _before_ a given field
+```php
+$this->crud->addField()->beforeField('name');
+```
+
+- **Chained - afterField()** - add a field _after_ a given field
+```php
+$this->crud->addField()->afterField('name');
+```
+
+- **setRequiredFields()** - check the FormRequests used in this EntityCrudController for required fields, and add an asterisk to them in the create or edit forms
+```php
+$this->crud->setRequiredFields(StoreRequest::class);
+```
+
+- **setValidation()** - makes sure validation and authorization in the FormRequest you've passed is being performed; also uses that file to figure out asterisk to show in the forms (calls ```setRequiredFields()``` above):
+```php
+$this->crud->setValidation(ArticleRequest::class);
+```
+
+
+### Reorder Operation
+
+Show a reorder button in the table view, next to Add. Provides an interface to reorder & nest elements, provided the ```parent_id```, ```lft```, ```rgt```, ```depth``` columns are in the database, and ```$fillable``` on the model.
+
+```php
+$this->crud->set('reorder.label', 'name'); // which model attribute to use for labels
+$this->crud->set('reorder.max_level', 3); // maximum nesting depth; this example will prevent the user from creating trees deeper than 3 levels;
+```
+
+- **disableReorder()** - disable the Reorder functionality
+```php
+$this->crud->disableReorder();
+```
+
+- **isReorderEnabled()** - returns ```true```/```false``` if the Reorder operation is enabled or not
+```php
+$this->crud->isReorderEnabled();
+```
+
+
+### Revise Operation
+
+A.k.a. Audit Trail. Tracks all changes to an entry and provides an interface to revert to a previous state. This operation is not installed by default - please check out [Revise Operation](/docs/{{version}}/crud-operation-revisions) for the installation & usage steps.
+
+
+## All Operations
+
+### Access
+
+Prevent or allow users from accessing different CRUD operations.
+
+- **allowAccess()** - give users access to one or multiple operations
+```php
+$this->crud->allowAccess('list');
+$this->crud->allowAccess(['list', 'create', 'delete']);
+```
+
+- **denyAccess()** - prevent users from accessing one or multiple operations
+```php
+$this->crud->denyAccess('list');
+$this->crud->denyAccess(['list', 'create', 'delete']);
+```
+
+- **hasAccess()** - check if the current user has access to one or multiple operations
+```php
+$this->crud->hasAccess('something'); // returns true/false
+$this->crud->hasAccessOrFail('something'); // throws 403 error
+$this->crud->hasAccessToAll(['create', 'update']); // returns true/false
+$this->crud->hasAccessToAny(['create', 'update']); // returns true/false
+```
+
+### Eager Loading Relationships
+
+- **with()** - when the current entry is loaded (in any operation) also get its relationships, so that only one query is made to the database per entry
+```php
+$this->crud->with('relationship_name');
+```
+
+### Custom Views
+
+- **setShowView()**, **setEditView()**, **setCreateView()**, **setListView()**, **setReorderView()**, **setRevisionsView()**, **setRevisionsTimelineView()**, **setDetailsRowView()** - set the view for a certain CRUD operation or feature
+
+```php
+// use a custom view for a CRUD operation
+$this->crud->setShowView('path.to.your.view');
+$this->crud->setEditView('path.to.your.view');
+$this->crud->setCreateView('path.to.your.view');
+$this->crud->setListView('path.to.your.view');
+$this->crud->setReorderView('path.to.your.view');
+$this->crud->setRevisionsView('path.to.your.view');
+$this->crud->setRevisionsTimelineView('path.to.your.view');
+$this->crud->setDetailsRowView('path.to.your.view');
+
+// more generally, you can use the Settings API:
+$this->crud->set('create.view', 'path.to.your.view');
+
+// if you want to load something from the /resources/vendor/backpack/crud directory, you can do
+$this->crud->set('create.view', 'crud::yourfolder.yourview');
+// or
+$this->crud->set('create.view', 'resources.vendor.backpack.crud.yourfolder.yourview');
+```
+
+### Content Class
+
+- **setShowContentClass()**, **setEditContentClass()**, **setCreateContentClass()**, **setListContentClass()**, **setReorderContentClass()**, **setRevisionsContentClass()**, **setRevisionsTimelineContentClass()** - set the CSS class for an operation view, to make the main area bigger or smaller:
+
+```php
+// use a custom view for a CRUD operation
+$this->crud->setShowContentClass('col-md-8');
+$this->crud->setEditContentClass('col-md-8');
+$this->crud->setCreateContentClass('col-md-8');
+$this->crud->setListContentClass('col-md-8');
+$this->crud->setReorderContentClass('col-md-8');
+$this->crud->setRevisionsContentClass('col-md-8');
+$this->crud->setRevisionsTimelineContentClass('col-md-8');
+
+// more generally, you can use the Settings API:
+$this->crud->set('create.contentClass', 'col-md-12');
+```
+
+### Getters
+
+- **getEntry()** - get a certain entry of the current model type
+```php
+$this->crud->getEntry($entry_id);
+```
+- **getEntries()** - get all entries using the current CRUD query
+```php
+$this->crud->getEntries();
+```
+
+- **getFields()** - get all fields for a certain operation, or for both
+```php
+$this->crud->getFields('create/update/both');
+```
+
+- **getCurrentEntry()** - get the current entry, for operations that work on a single entry
+```php
+$this->crud->getCurrentEntry();
+// ex: in your update() method, after calling parent::updateCrud()
+```
+
+### Operations
+
+- **getOperation()** - get the name of the operation that is currently being performed
+```php
+$this->crud->getOperation();
+```
+
+- **setOperation()** - set the name of the operation that is currently being performed
+```php
+$this->crud->setOperation('ListEntries');
+```
+
+### Actions
+
+An action is the controller method that is currently being run.
+
+- **getActionMethod()** - returns the method on the controller that was called by the route; ex: ```create()```, ```update()```, ```edit()``` etc;
+```php
+$this->crud->getActionMethod();
+```
+
+- **actionIs()** - checks if the given controller method is the one called by the route
+```php
+$this->crud->actionIs('create');
+```
+
+### Title, Heading, Subheading
+
+Legend:
+- _operation_ - a collection of functions in a CrudController, that together allow the admin to perform something on the current model;
+- _action_ - a method (aka function) of an operation; it is the actual PHP function's name;
+
+- **getTitle()** - get the Title for the create action
+```php
+$this->crud->getTitle('create');
+```
+
+- **getHeading()** - get the Heading for the create action
+```php
+$this->crud->getHeading('create');
+```
+
+- **getSubheading()** - get the Subheading for the create action
+```php
+$this->crud->getSubheading('create');
+```
+
+- **setTitle()** - set the Title for the create action
+```php
+$this->crud->setTitle('some string', 'create');
+```
+
+- **setHeading()** - set the Heading for the create action
+```php
+$this->crud->setHeading('some string', 'create');
+```
+
+- **setSubheading()** - set the Subheading for the create action
+```php
+$this->crud->setSubheading('some string', 'create');
+```
+
+### CrudPanel Basic Info
+
+- **setModel()** - set the Eloquent object that should be used for all operations
+```php
+$this->crud->setModel("App\Models\Example");
+```
+
+- **setRoute()** - set the main route to this CRUD
+```php
+$this->crud->setRoute("admin/example");
+// OR $this->crud->setRouteName("admin.example");
+```
+
+- **setEntityNameStrings()** - set how the entity name should be shown to the user, in singular and in plural
+```php
+$this->crud->setEntityNameStrings("example", "examples");
+```
diff --git a/4.1/crud-basics.md b/4.1/crud-basics.md
new file mode 100644
index 00000000..cd734260
--- /dev/null
+++ b/4.1/crud-basics.md
@@ -0,0 +1,46 @@
+# Basics
+
+---
+
+Backpack\CRUD provides a fast way to build administration panels - places where your administrators can Create, Read, Update, Delete entries for a specific Eloquent model. **One CRUD Panel provides functionality for one Eloquent Model.**
+
+
+## Requirements
+
+In order to create a CRUD Panel, you'll need:
+- **a table in the database** (and maybe connection tables for relationships);
+- **an Eloquent Model** that points to that db table;
+
+If you don't already have the models, don't worry, Backpack also includes a faster way to generate database migrations and models.
+
+
+## Architecture
+
+A Backpack CRUD Panel uses _the same elements_ you would have created for an administration panel, if you were doing it from scratch:
+- a **controller** - holds the logic for the all operations an admin can perform on that Eloquent model; will be generated in ```app/Http/Controllers/Admin```;
+- a **request** file - used to validate Create and Update forms; will be generated in ```app/Http/Requests```;
+- a resource **route** - points to the controller above; will be generated in ```routes/backpack/custom.php```;
+
+**The only difference** between building it from scratch and using Backpack\CRUD** is that:
+- your controller will be extending ```Backpack\CRUD\app\Http\Controllers\CrudController```**, which allow you to easily add traits that handle the most common operations: Create, Update, Delete, List, Show, Reorder, Revisions.
+- your model will ```use \Backpack\CRUD\CrudTrait```;
+
+This simple architecture (```ProductCrudController extends CrudController```) means:
+- **your CRUD Panel will not be a _black box_**; you can easily see the logic for each operation, by checking the methods on this controller, or the traits you'll be using;
+- **you can _easily_ overwrite what happens inside each operation**;
+- **you can _easily_ add custom operations**;
+
+For example:
+- want to change how a single ```Product``` is shown to the admin? just create a method called ```show()``` in your ```ProductCrudController```; simple OOP dictates that your method will be picked up, instead of the one in CrudController; some goes for ```create()```, ```store()```, etc - you have complete control;
+- want to create a new "Publish" operation on a ```Product```? your ```ProductCrudController``` is a great place for that logic; just create a custom ```publish()``` method and a route that points to it;
+
+
+## Files
+
+For a ```Tag``` entity, your CRUD Panel would consist of:
+- a controller (```app/Http/Controllers/Admin/TagCrudController.php```);
+- a request (```app/Http/Requests/TagCrudRequest.php```);
+- a route inside ```routes/backpack/custom.php```;
+- your existing model (```app/Models/Tag.php```);
+
+To further your understanding of how a CRUD Panel works, [read more about this example in the tutorial](/docs/{{version}}/crud-tutorial).
diff --git a/4.1/crud-buttons.md b/4.1/crud-buttons.md
new file mode 100644
index 00000000..08e7b037
--- /dev/null
+++ b/4.1/crud-buttons.md
@@ -0,0 +1,202 @@
+# Buttons
+
+---
+
+
+## About
+
+Buttons are used inside the ListEdit operation, to allow the admin to trigger other operations. Some point to entirely new routes (```create```, ```update```, ```show```), others perform the operation on the current page using AJAX (```delete```).
+
+
+### Button Stacks
+
+The ShowList operation has 3 places where buttons can be placed:
+ - ```top``` (where the Add button is)
+ - ```line``` (where the Edit and Delete buttons are)
+ - ```bottom``` (after the table)
+
+When adding a button to the stack, you can choose whether to insert it at the ```beginning``` or ```end``` of the stack by specifying that as a last parameter.
+
+
+### Default Buttons
+
+Backpack adds a few buttons by default:
+- ```create``` to the ```top``` stack;
+- ```update``` and ```delete``` to the ```line``` stack;
+
+Default buttons are invisible if an operation has been disabled. For example, you can:
+- hide the "delete" button using ```$this->crud->denyAccess('delete')```;
+- show a "preview" button by using ```$this->crud->allowAccess('show')```;
+
+
+### Buttons API
+
+Here are a few things you can call in your EntityCrudController's ```setupListOperation()``` method, to manipulate buttons:
+
+```php
+// possible positions: 'beginning' and 'end'; defaults to 'beginning' for the 'line' stack, 'end' for the others;
+
+// add a button; possible types are: view, model_function
+$this->crud->addButton($stack, $name, $type, $content, $position);
+
+// add a button whose HTML is returned by a method in the CRUD model
+$this->crud->addButtonFromModelFunction($stack, $name, $model_function_name, $position);
+
+// add a button whose HTML is in a view placed at resources\views\vendor\backpack\crud\buttons
+$this->crud->addButtonFromView($stack, $name, $view, $position);
+
+// remove a button
+$this->crud->removeButton($name);
+
+// remove a button for a certain stack (top, line, bottom)
+$this->crud->removeButtonFromStack($name, $stack);
+```
+
+### Overwriting a Default Button
+
+Before showing any buttons, Backpack will check your ```resources\views\vendor\backpack\crud\buttons``` directory, to see if you've overwritten any default buttons. If it finds a blade file with the same name there as the default buttons, it will use your blade file, instead of the default.
+
+That means **you can overwrite an existing button simply by creating a blade file with the same name inside this directory**.
+
+
+### Creating a Custom Button
+
+To create a custom button:
+- create a new blade file in ```resources\views\vendor\backpack\crud\buttons```;
+- add that button using the ```addButton()``` syntax above, in the EntityCrudControllers you want, inside the ```setupListOperation()``` method;
+
+In this blade file, you can use:
+- ```$entry``` - the database entry you're showing (only inside the ```line``` stack);
+- ```$crud``` - the entire CrudPanel object;
+- ```$button``` - the button you're currently showing;
+
+Note: If you've opted to add a button from a model function (not a blade file), inside your model function you can use `$this` to get the current entry (so for example, you can do `$this->id`.
+
+
+## Examples
+
+
+### Adding a Custom Button with a Blade File
+
+Let's say we want to create a simple ```moderate.blade.php``` button. This button would just open a ```user/{id}/moderate/``` route, which would point to ```UserCrudController::moderate()```. The steps would be:
+
+- Create the ```resources\views\vendor\backpack\crud\buttons\moderate.blade.php``` file:
+```php
+@if ($crud->hasAccess('update'))
+ Moderate
+@endif
+```
+- Add the new route, next to ```UserCrudController```'s route (most likely inside ```routes/backpack/custom.php```):
+```php
+Route::get('user/{id}/moderate', 'UserCrudController@moderate');
+```
+
+- We can now add a ```moderate()``` method to our ```UserCrudController```, which would moderate the user, and redirect back.
+```php
+public function moderate()
+{
+ // show a form that does something
+}
+```
+
+- Now we can actually add this button to any of ```UserCrudController::setupListOperation()```:
+```php
+$this->crud->addButtonFromView('line', 'moderate', 'moderate', 'beginning');
+```
+
+
+### Adding a Custom Button without a Blade File
+
+Instead of creating a blade file for your button, you can use a function on your model to output the button's HTML.
+
+In your ```ArticleCrudController::setupListOperation()```:
+```php
+// add a button whose HTML is returned by a method in the CRUD model
+$this->crud->addButtonFromModelFunction('line', 'open_google', 'openGoogle', 'beginning');
+```
+
+In your ```Article``` model:
+
+```php
+public function openGoogle($crud = false)
+{
+ return ' Google it';
+}
+```
+
+
+
+### Adding a Custom Button with Javascript to the "top" stack
+
+Let's say we want to create an ```import.blade.php``` button. For simplicity, this button would just run an AJAX call which handles everything, and shows a status report to the user through notification bubbles.
+
+The "top" buttons are not bound to any certain entry, like buttons from the "list" stack. They can only do general things. And if they do general things, it's _generally_ recommended that you move their javascript to the bottom of the page. You can easily do that with ```@push('after_scripts')```, because the Backpack default layout has an ```after_scripts``` stack. This way, you can make sure your Javascript is moved at the bottom of the page, after all other Javascript has been loaded (jQuery, DataTables, etc). Check out the example below.
+
+The steps would be:
+
+- Create the ```resources\views\vendor\backpack\crud\buttons\import.blade.php``` file:
+
+```php
+@if ($crud->hasAccess('create'))
+
+ Import {{ $crud->entity_name }}
+
+@endif
+
+@push('after_scripts')
+
+@endpush
+```
+- Add the new route, next to ```UserCrudController```'s route (most likely inside ```routes/backpack/custom.php```):
+```php
+Route::get('user/import', 'UserCrudController@import');
+```
+
+- We can now add a ```import()``` method to our ```UserCrudController```, which would import the users.
+```php
+public function import()
+{
+ // whatever you decide to do
+}
+```
+
+- Now we can actually add this button to any of ```UserCrudController::setupListOperation()```:
+```php
+$this->crud->addButtonFromView('top', 'import', 'import', 'end');
+```
diff --git a/4.1/crud-cheat-sheet.md b/4.1/crud-cheat-sheet.md
new file mode 100644
index 00000000..7f507e6d
--- /dev/null
+++ b/4.1/crud-cheat-sheet.md
@@ -0,0 +1,336 @@
+# CRUD API Cheat Sheet
+
+---
+
+Here are all the functions you will be using **inside your EntityCrudController's ```setup()``` method**, grouped by the operation you will most likely use them for.
+
+## Operations
+
+
+### ListEntries
+
+
+#### Columns
+
+Methods: addColumn(), addColumns(), modifyColumn(), removeColumn(), removeColumns(), setColumnDetails(), setColumnsDetails(), setColumns(), beforeColumn(), afterColumn(), makeFirstColumn()
+
+```php
+// Manipulate what columns are shown in the table view.
+$this->crud->addColumn($column_definition_array); // add a column, at the end of the stack
+$this->crud->addColumns([$column_definition_array, $another_column_definition_array]); // add multiple columns, at the end of the stack
+$this->crud->modifyColumn($name, $modifs_array);
+$this->crud->removeColumn('column_name'); // remove a column from the stack
+$this->crud->removeColumns(['column_name_1', 'column_name_2']); // remove an array of columns from the stack
+$this->crud->setColumnDetails('column_name', ['attribute' => 'value']);
+$this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
+
+$this->crud->setColumns(); // set the columns you want in the table view, either as array of column names, or multidimensional array with all columns detailed with their types
+
+// ------ REORDER COLUMNS
+$this->crud->addColumn()->beforeColumn('name'); // will show this before the given column
+$this->crud->addColumn()->afterColumn('name'); // will show this after the given column
+
+$this->crud->addColumn()->makeFirstColumn();
+ // will make this column the first one in the list
+ // you need to also specify priority 1 in your addColumn statement for details_row or responsive expand buttons to show
+```
+
+
+#### Buttons
+
+Methods: addButton(), addButtonFromModelFunction(), addButtonFromView(), removeButton(), removeButtonFromStack()
+
+```php
+// possible positions: 'beginning' and 'end'; defaults to 'beginning' for the 'line' stack, 'end' for the others;
+$this->crud->addButton($stack, $name, $type, $content, $position); // add a button; possible types are: view, model_function
+$this->crud->addButtonFromModelFunction($stack, $name, $model_function_name, $position); // add a button whose HTML is returned by a method in the CRUD model
+$this->crud->addButtonFromView($stack, $name, $view, $position); // add a button whose HTML is in a view placed at resources\views\vendor\backpack\crud\buttons
+$this->crud->removeButton($name);
+$this->crud->removeButtonFromStack($name, $stack);
+```
+
+
+#### Filters
+
+Methods: addFilter(), modifyFilter(), removeFilter(), removeAllFilters(), filters()
+
+```php
+// Manipulate what filters are shown in the table view.
+//
+// Note: check out CRUD > Features > Filters in the docs to see examples of $filter_definition_array
+$this->crud->addFilter($filter_definition_array, $values, $filter_logic);
+$this->crud->modifyFilter($name, $modifs_array);
+$this->crud->removeFilter($name);
+$this->crud->removeAllFilters();
+$this->crud->filters(); // gets all the filters
+```
+
+
+#### Details Row
+
+Methods: enableDetailsRow(), disableDetailsRow()
+
+```php
+// Shows a + sign next to each table row, so that the user can expand that row and reveal details. You are responsible for creating the view with those details.
+$this->crud->enableDetailsRow();
+// NOTE: you also need to do allow access to the right users: $this->crud->allowAccess('details_row');
+// NOTE: you also need to do overwrite the showDetailsRow($id) method in your EntityCrudController to show whatever you'd like in the details row OR overwrite the views/backpack/crud/details_row.blade.php
+
+$this->crud->disableDetailsRow();
+```
+
+
+#### Export Buttons
+
+Methods: enableExportButtons()
+
+```php
+// Show export to PDF, CSV, XLS and Print buttons on the table view. Please note it will only export the current _page_ of results. So in order to export all entries the user needs to make the current page show "All" entries from the top-left picker.
+$this->crud->enableExportButtons();
+```
+
+
+#### Responsive Table
+
+Methods: enableResponsiveTable(), disableResponsiveTable()
+
+```php
+$this->crud->disableResponsiveTable();
+$this->crud->enableResponsiveTable();
+```
+
+
+#### Persistent Table
+
+Methods: enablePersistenTable(), disablePersistenTable()
+
+```php
+$this->crud->disablePersistentTable();
+$this->crud->enablePersistentTable();
+```
+
+
+#### Page Length
+
+Methods: setDetaultPageLength(), setPageLengthMenu()
+
+```php
+// you can define the default page length. If it does not exist we will add it to the pagination array.
+$this->crud->setDefaultPageLength(10);
+
+// you can configure the paginator shown to the user in various ways
+
+// values and labels, 1st array the values, 2nd array the labels:
+$this->crud->setPageLengthMenu([[100, 200, 300], ['one hundred', 'two hundred', 'three hundred']]);
+
+// values and labels in one array:
+$this->crud->setPageLengthMenu([100 => 'one hundred', 200 => 'two hundred', 300 => 'three hundred']);
+
+// only values, we will use the values as labels:
+$this->crud->setPageLengthMenu([100, 200, 300]); // OR
+$this->crud->setPageLengthMenu([[100, 200, 300]]);
+
+// only one option available:
+$this->crud->setPageLengthMenu(10);
+```
+
+NOTE: Do not use 0 as a key, if you want to represent "ALL" use -1 instead.
+
+
+#### Actions Column
+
+Methods: setActionColumnPriority()
+
+```php
+// make the actions column (in the table view) hide when not enough space is available, by giving it an unreasonable priority
+$this->crud->setActionsColumnPriority(10000);
+```
+
+
+#### Custom / Advanced Queries
+
+Methods: addClause(), groupBy(), limit(), orderBy()
+
+```php
+// Change what entries are shown in the table view.
+// This changes all queries on the table view,
+// as opposed to filters, who only change it when that filter is applied.
+$this->crud->addClause('active'); // apply local scope
+$this->crud->addClause('type', 'car'); // apply local dynamic scope
+$this->crud->addClause('where', 'name', '=', 'car');
+$this->crud->addClause('whereName', 'car');
+$this->crud->addClause('whereHas', 'posts', function($query) {
+ $query->activePosts();
+ });
+$this->crud->groupBy();
+$this->crud->limit();
+
+$this->crud->orderBy();
+// please note it's generally a good idea to use crud->orderBy() inside "if (!$this->crud->getRequest()->has('order')) {}"; that way, your custom order is applied ONLY IF the user hasn't forced another order (by clicking a column heading)
+```
+
+
+### Show
+
+Use the same Columns API as for the ListEntries operation, but inside your ```show()``` method.
+
+
+### Create & Update Operations
+
+Methods: addField(), addFields(), modifyField(), modifyFields(), removeField(), removeFields(), removeAllFields(), beforeField(), afterField()
+
+```php
+// ------
+// FIELDS
+// ------
+// Manipulate what fields are shown in the create / update forms.
+//
+// Note: check out CRUD > Features > Field Types in the docs to see examples of $field_definition_array
+
+$this->crud->addField($field_definition_array);
+$this->crud->addField('db_column_name'); // a lazy way to add fields: let the CRUD decide what field type it is and set it automatically, along with the field label
+$this->crud->addFields($array_of_fields_definition_arrays);
+$this->crud->modifyField($name, $modifs_array);
+$this->crud->removeField('name');
+$this->crud->removeFields($array_of_names);
+$this->crud->removeAllFields();
+
+// ------ REORDER FIELDS
+$this->crud->addField()->beforeField('name'); // will show this before the given field
+$this->crud->addField()->afterField('name'); // will show this after the given field
+```
+
+
+### Reorder
+
+Methods: enableReorder(), disableReorder(), isReorderEnabled()
+
+```php
+ protected function setupReorderOperation()
+ {
+ // model attribute to be shown on draggable items
+ $this->crud->set('reorder.label', 'name');
+ // maximum number of nesting allowed
+ $this->crud->set('reorder.max_level', 2);
+
+ // extras:
+ // $this->crud->disableReorder();
+ // $this->crud->isReorderEnabled();
+ }
+```
+
+
+### Revisions
+
+```php
+// -------------------------
+// REVISIONS aka Audit Trail
+// -------------------------
+// Tracks all changes to an entry and provides an interface to revert to a previous state.
+//
+// IMPORTANT: You also need to use \Venturecraft\Revisionable\RevisionableTrait;
+// Please check out: https://backpackforlaravel.com/docs/crud-operation-revisions
+$this->crud->allowAccess('revisions');
+```
+
+
+## All Operations
+
+Methods: allowAccess(), denyAccess(), hasAccess(), hasAccessOrFail(), hasAccessToAll(), hasAccessToAny(), setShowView(), setEditView(), setCreateView(), setListView(), setReorderView(), setRevisionsView, setRevisionsTimelineView(), setDetailsRowView(), getEntry(), getFields(), getColumns(), getCurrentEntry(), getTitle(), setTitle(), getHeading(), setHeading(), getSubheading(), setSubheading(),
+
+```php
+// ------
+// ACCESS
+// ------
+// Prevent or allow users from accessing different CRUD operations.
+
+$this->crud->allowAccess('list');
+$this->crud->allowAccess(['list', 'create', 'delete']);
+$this->crud->denyAccess('list');
+$this->crud->denyAccess(['list', 'create', 'delete']);
+
+$this->crud->hasAccess('add'); // returns true/false
+$this->crud->hasAccessOrFail('add'); // throws 403 error
+$this->crud->hasAccessToAll(['create', 'update']); // returns true/false
+$this->crud->hasAccessToAny(['create', 'update']); // returns true/false
+
+// -------------
+// EAGER LOADING
+// -------------
+
+// eager load a relationship
+$this->crud->with('relationship_name');
+
+// ------------
+// CUSTOM VIEWS
+// ------------
+
+// use a custom view for a CRUD operation
+$this->crud->setShowView('your-view');
+$this->crud->setEditView('your-view');
+$this->crud->setCreateView('your-view');
+$this->crud->setListView('your-view');
+$this->crud->setReorderView('your-view');
+$this->crud->setRevisionsView('your-view');
+$this->crud->setRevisionsTimelineView('your-view');
+$this->crud->setDetailsRowView('your-view');
+
+// -------------
+// CONTENT CLASS
+// -------------
+
+// use a custom CSS class for the content of a CRUD operation
+$this->crud->setShowContentClass('col-md-12');
+$this->crud->setEditContentClass('col-md-12');
+$this->crud->setCreateContentClass('col-md-12');
+$this->crud->setListContentClass('col-md-12');
+$this->crud->setReorderContentClass('col-md-12');
+$this->crud->setRevisionsContentClass('col-md-12');
+$this->crud->setRevisionsTimelineContentClass('col-md-12');
+
+// -------
+// GETTERS
+// -------
+
+$this->crud->getEntry($entry_id);
+$this->crud->getEntries();
+
+$this->crud->getFields('create/update/both');
+
+// in your update() method, after calling parent::updateCrud()
+$this->crud->getCurrentEntry();
+
+// -------
+// OPERATIONS
+// -------
+
+$this->crud->setOperation('list');
+$this->crud->getOperation();
+
+// -------
+// ACTIONS
+// -------
+
+$this->crud->getActionMethod(); // returns the method on the controller that was called by the route; ex: create(), update(), edit() etc;
+$this->crud->actionIs('create'); // checks if the controller method given is the one called by the route
+
+$this->crud->getTitle('create'); // get the Title for the create action
+$this->crud->getHeading('create'); // get the Heading for the create action
+$this->crud->getSubheading('create'); // get the Subheading for the create action
+
+$this->crud->setTitle('some string', 'create'); // set the Title for the create action
+$this->crud->setHeading('some string', 'create'); // set the Heading for the create action
+$this->crud->setSubheading('some string', 'create'); // set the Subheading for the create action
+
+// ---------------------------
+// CrudPanel Basic Information
+// ---------------------------
+$this->crud->setModel("App\Models\Example");
+$this->crud->setRoute("admin/example");
+// OR $this->crud->setRouteName("admin.example");
+$this->crud->setEntityNameStrings("example", "examples");
+
+// check the FormRequests used in that EntityCrudController for required fields, and add an asterisk to them in the create/edit form
+$this->crud->setRequiredFields(StoreRequest::class, 'create');
+$this->crud->setRequiredFields(UpdateRequest::class, 'edit');
+```
diff --git a/4.1/crud-columns.md b/4.1/crud-columns.md
new file mode 100644
index 00000000..117a482f
--- /dev/null
+++ b/4.1/crud-columns.md
@@ -0,0 +1,937 @@
+# Columns
+
+---
+
+
+## About
+
+A column shows the information of an Eloquent attribute, in a user-friendly format.
+
+It's used inside default operations to:
+- show a table cell in **ListEntries**;
+- show an attribute value in **Show**;
+
+A column consists of only one file - a blade file with the same name as the column type (ex: ```text.blade.php```). Backpack provides you with [default column types](#default-column-types) for the common use cases, but you can easily [change how a default field type works](#overwriting-default-column-types), or [create an entirely new field type](#creating-a-custom-column-type).
+
+
+### Mandatory Attributes
+
+When passing a column array, you need to specify at least these attributes:
+```php
+[
+ 'name' => 'options', // the db column name (attribute name)
+ 'label' => "Options", // the human-readable label for it
+ 'type' => 'text' // the kind of column to show
+],
+```
+
+
+### Optional Attributes
+
+- [```searchLogic```](#custom-search-logic)
+- [```orderLogic```](#custom-order-logic)
+- [```orderable```](#custom-order-logic)
+- [```wrapper```](#custom-wrapper-for-columns)
+- [```visibleInTable```](#choose-where-columns-are-visible)
+- [```visibleInModal```](#choose-where-columns-are-visible)
+- [```visibleInExport```](#choose-where-columns-are-visible)
+- [```visibleInShow```](#choose-where-columns-are-visible)
+- [```priority```](#define-which-columns-to-hide-in-responsive-table)
+
+
+### Columns API
+
+Inside your ```setupListOperation()``` or ```setupShowOperation()``` method, there are a few calls you can make to configure or manipulate columns:
+
+```php
+// add a column, at the end of the stack
+$this->crud->addColumn($column_definition_array);
+
+// add multiple columns, at the end of the stack
+$this->crud->addColumns([$column_definition_array, $another_column_definition_array]);
+
+// remove a column from the stack
+$this->crud->removeColumn('column_name');
+
+// remove an array of columns from the stack
+$this->crud->removeColumns(['column_name_1', 'column_name_2']);
+
+// change the attributes of a column
+$this->crud->modifyColumn($name, $modifs_array);
+$this->crud->setColumnDetails('column_name', ['attribute' => 'value']);
+
+// change the attributes of multiple columns
+$this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
+
+// forget what columns have been previously defined, only use these columns
+$this->crud->setColumns([$column_definition_array, $another_column_definition_array]);
+
+// -------------------
+// New in Backpack 4.1
+// -------------------
+// add a column with this name
+$this->crud->column('price');
+
+// change the type and prefix attributes on the 'price' column
+$this->crud->column('price')->type('number')->prefix('$');
+```
+
+In addition, to manipulate the order columns are shown in, you can:
+
+```php
+// add this column before a given column
+$this->crud->addColumn('text')->beforeColumn('name');
+
+// add this column after a given column
+$this->crud->addColumn()->afterColumn('name');
+
+// make this column the first one in the list
+$this->crud->addColumn()->makeFirstColumn();
+```
+
+
+## Default Column Types
+
+
+### array
+
+Enumerate an array stored in the db column as JSON.
+```php
+[
+ 'name' => 'options', // The db column name
+ 'label' => 'Options', // Table column heading
+ 'type' => 'array'
+],
+```
+
+
+
+
+### array_count
+
+Count the items in an array stored in the db column as JSON.
+
+```php
+[
+ 'name' => 'options', // The db column name
+ 'label' => 'Options', // Table column heading
+ 'type' => 'array_count',
+ // 'suffix' => 'options', // if you want it to show "2 options" instead of "2 items"
+],
+```
+
+
+
+
+### boolean
+
+Show Yes/No (or custom text) instead of 1/0.
+
+```php
+[
+ 'name' => 'name',
+ 'label' => 'Status',
+ 'type' => 'boolean',
+ // optionally override the Yes/No texts
+ // 'options' => [0 => 'Active', 1 => 'Inactive']
+],
+```
+
+
+
+
+### check
+
+Show a favicon with a checked or unchecked box, depending on the given boolean.
+```php
+[
+ 'name' => 'featured', // The db column name
+ 'label' => 'Featured', // Table column heading
+ 'type' => 'check'
+],
+```
+
+
+
+
+### checkbox
+
+Shows a checkbox (the form element), and inserts the js logic needed to select/deselect multiple entries. It is mostly used for [the Bulk Delete action](/docs/{{version}}/crud-operation-delete#delete-multiple-items-bulk-delete), and [custom bulk actions](/docs/{{version}}/crud-operations#creating-a-new-operation-with-a-bulk-action-no-interface).
+
+Shorthand:
+```php
+$this->crud->enableBulkActions();
+```
+(will also add an empty custom_html column)
+
+Verbose:
+```php
+$this->crud->addColumn([
+ 'type' => 'checkbox',
+ 'name' => 'bulk_actions',
+ 'label' => ' ',
+ 'priority' => 1,
+ 'searchLogic' => false,
+ 'orderable' => false,
+ 'visibleInModal' => false,
+])->makeFirstColumn();
+```
+
+
+
+
+### closure
+
+
+Show custom HTML based on a closure you specify in your EntityCrudController. Please note this column does not escape HTML before rendering. You need to do that yourself, if you consider it necessary.
+
+```php
+[
+ 'name' => 'created_at',
+ 'label' => 'Created At',
+ 'type' => 'closure',
+ 'function' => function($entry) {
+ return 'Created on '.$entry->created_at;
+ }
+],
+```
+
+
+
+
+### custom_html
+
+
+Show the HTML that you provide in the page. You can optionaly escape the text when displaying it on page.
+
+```php
+[
+ 'name' => 'my_custom_html',
+ 'label' => 'Custom HTML',
+ 'type' => 'custom_html',
+ 'value' => 'Something',
+ 'escaped' => false //optional, if the "value" should be escaped when displayed in the page.
+],
+```
+
+
+
+
+### date
+
+
+The date column will show a localized date in the default date format (as specified in the ```config/backpack/base.php``` file), whether the attribute is casted as date in the model or not.
+
+Note that the ```format``` attribute uses ISO date formatting parameters and not PHP ```date()``` formatters. See for more information.
+
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => 'Tag Name', // Table column heading
+ 'type' => 'date',
+ // 'format' => 'l j F Y', // use something else than the base.default_date_format config value
+],
+```
+
+
+
+
+### datetime
+
+
+The date column will show a localized datetime in the default datetime format (as specified in the ```config/backpack/base.php``` file), whether the attribute is casted as datetime in the model or not.
+
+Note that the ```format``` attribute uses ISO date formatting parameters and not PHP ```date()``` formatters. See for more information.
+
+
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => 'Tag Name', // Table column heading
+ 'type' => 'datetime',
+ // 'format' => 'l j F Y H:i:s', // use something else than the base.default_datetime_format config value
+],
+```
+
+
+
+
+### email
+
+The email column will output the email address in the database (truncated to 254 characters if needed), with a ```mailto:``` link towards the full email. Its definition is:
+```php
+[
+ 'name' => 'email', // The db column name
+ 'label' => 'Email Address', // Table column heading
+ 'type' => 'email',
+ // 'limit' => 500, // if you want to truncate the text to a different number of characters
+],
+```
+
+
+
+
+### image
+
+
+Show a thumbnail image.
+
+```php
+[
+ 'name' => 'profile_image', // The db column name
+ 'label' => 'Profile image', // Table column heading
+ 'type' => 'image',
+ // 'prefix' => 'folder/subfolder/',
+ // image from a different disk (like s3 bucket)
+ // 'disk' => 'disk-name',
+ // optional width/height if 25px is not ok with you
+ // 'height' => '30px',
+ // 'width' => '30px',
+],
+```
+
+
+
+
+### json
+
+
+Display database stored JSON in a prettier way to your users.
+
+```php
+[
+ 'name' => 'my_json_column_name',
+ 'label' => 'JSON',
+ 'type' => 'json',
+ 'escaped' => false //optional, if the "value" should be escaped when displayed in the page.
+],
+```
+
+
+
+
+### markdown
+
+
+Convert a markdown string to HTML, using ```Illuminate\Mail\Markdown```. Since Markdown is usually used for long texts, this column is most helpful in the "Show" operation - not so much in the "ListEntries" operation, where only short snippets make sense.
+
+```php
+[
+ 'name' => 'text', // The db column name
+ 'label' => 'Text', // Table column heading
+ 'type' => 'markdown',
+],
+```
+
+
+
+
+### model_function
+
+
+The model_function column will output a function on your main model. Its definition is:
+```php
+[
+ // run a function on the CRUD model and show its return value
+ 'name' => 'url',
+ 'label' => 'URL', // Table column heading
+ 'type' => 'model_function',
+ 'function_name' => 'getSlugWithLink', // the method in your Model
+ // 'function_parameters' => [$one, $two], // pass one/more parameters to that method
+ // 'limit' => 100, // Limit the number of characters shown
+],
+```
+For this example, if your model would feature this method, it would return the link to that entity:
+```php
+public function getSlugWithLink() {
+ return ''.$this->slug.'';
+}
+```
+
+**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent JS and CSS from reaching your DB in the first place.
+
+
+
+
+### model_function_attribute
+
+
+If the function you're trying to use returns an object, not a string, you can use the model_function_attribute column, which will output the attribute on the function result. Its definition is:
+```php
+[
+ 'name' => 'url',
+ 'label' => 'URL', // Table column heading
+ 'type' => 'model_function_attribute',
+ 'function_name' => 'getSlugWithLink', // the method in your Model
+ // 'function_parameters' => [$one, $two], // pass one/more parameters to that method
+ 'attribute' => 'route',
+ // 'limit' => 100, // Limit the number of characters shown
+],
+```
+
+**Note:** When displaying this column's value, the text is not escaped. That is intentional. This way, you can use it to show labels, color text, italic, bold, links, etc. If you might have malicious JS or CSS in your values, you can create a new escaped field yourself. But it's probably better to treat the problem at the source, and prevent JS and CSS from reaching your DB in the first place.
+
+
+
+
+### multidimensional_array
+
+
+Enumerate the values in a multidimensional array, stored in the db as JSON.
+
+```php
+[
+ 'name' => 'options', // The db column name
+ 'label' => 'Options', // Table column heading
+ 'type' => 'multidimensional_array',
+ 'visible_key' => 'name' // The key to the attribute you would like shown in the enumeration
+],
+```
+
+
+
+
+### number
+
+
+The text column will just output the number value of a db column (or model attribute). Its definition is:
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => 'Tag Name', // Table column heading
+ 'type' => 'number',
+ // 'prefix' => '$',
+ // 'suffix' => ' EUR',
+ // 'decimals' => 2,
+ // 'dec_point' => ',',
+ // 'thousands_sep' => '.',
+ // decimals, dec_point and thousands_sep are used to format the number;
+ // for details on how they work check out PHP's number_format() method, they're passed directly to it;
+ // https://www.php.net/manual/en/function.number-format.php
+],
+```
+
+
+
+
+### phone
+
+The phone column will output the phone number from the database (truncated to 254 characters if needed), with a ```tel:``` link so that users on mobile can click them to call (or with Skype or similar browser extensions). Its definition is:
+```php
+[
+ 'name' => 'phone', // The db column name
+ 'label' => 'Phone number', // Table column heading
+ 'type' => 'phone',
+ // 'limit' => 10, // if you want to truncate the phone number to a different number of characters
+],
+```
+
+
+
+
+### radio
+
+
+Show a pretty text instead of the database value, according to an associative array. Usually used as a column for the "radio" field type.
+
+```php
+[
+ 'name' => 'status',
+ 'label' => 'Status',
+ 'type' => 'radio',
+ 'options' => [
+ 0 => 'Draft',
+ 1 => 'Published'
+ ]
+],
+```
+
+This example will show:
+- "Draft" when the value stored in the db is 0;
+- "Published" when the value stored in the db is 1;
+
+
+
+
+### relationship
+
+Output the related entries, no matter the relationship:
+- 1-n relationships - outputs the name of its one connected entity;
+- n-n relationships - enumerates the names of all its connected entities;
+
+Its name and definition is the same as for the relationship *field type*:
+```php
+[
+ // any type of relationship
+ 'name' => 'tags', // name of relationship method in the model
+ 'type' => 'relationship',
+ 'label' => 'Tags', // Table column heading
+ // OPTIONAL
+ // 'entity' => 'tags', // the method that defines the relationship in your Model
+ // 'attribute' => 'name', // foreign key attribute that is shown to user
+ // 'model' => App\Models\Category::class, // foreign key model
+],
+```
+
+Backpack tries to guess which attribute to show for the related item. Something that the end-user will recognize as unique. If it's something common like "name" or "title" it will guess it. If not, you can manually specify the ```attribute``` inside the column definition, or you can add ```public $identifiableAttribute = 'column_name';``` to your model, and Backpack will use that column as the one the user finds identifiable. It will use it here, and it will use it everywhere you haven't explicitly asked for a different attribute.
+
+
+
+
+### relationship_count
+
+Shows the number of items that are related to the current entry, for a particular relationship.
+
+```php
+[
+ // relationship count
+ 'name' => 'tags', // name of relationship method in the model
+ 'type' => 'relationship_count',
+ 'label' => 'Tags', // Table column heading
+ // OPTIONAL
+ // 'suffix' => ' tags', // to show "123 tags" instead of "123 items"
+],
+```
+
+**Important Note:** This column will load ALL related items onto the page. Which is not a problem normally, for small tables. But if your related table has thousands or millions of entries, it will considerably slow down the page. For a much more performant option, with the same result, you can add a fake column to the results using Laravel's `withCount()` method, then use the `text` column to show that number. That will be a lot faster, and the end-result is identical from the user's perspective. For the same example above (number of tags) this is how it will look:
+```
+$this->crud->query->withCount('tags'); // this will add a tags_count column to the results
+$this->crud->addColumn([
+ 'name' => 'tags_count', // name of relationship method in the model
+ 'type' => 'text',
+ 'label' => 'Tags', // Table column heading
+ 'suffix' => ' tags', // to show "123 tags" instead of "123"
+]);
+```
+
+
+
+
+### row_number
+
+
+Show the row number (index). The number depends strictly on the result set (x records per page, pagination, search, filters, etc). It does not get any information from the database. It is not searchable. It is only useful to show the current row number.
+
+```php
+$this->crud->addColumn([
+ 'name' => 'row_number',
+ 'type' => 'row_number',
+ 'label' => '#',
+ 'orderable' => false,
+])->makeFirstColumn();
+```
+
+Notes:
+- you can have a different ```name```; just make sure your model doesn't have that attribute;
+- you can have a different label;
+- you can place the column as second / third / etc if you remove ```makeFirstColumn()```;
+- this column type allows the use of suffix/prefix just like the text column type;
+- if upon placement you notice it always shows ```false``` then please note there have been changes in the ```search()``` method - you need to add another parameter to your ```getEntriesAsJsonForDatatables()``` call;
+
+
+
+
+### select
+
+The select column will output its connected entity. Used for relationships like hasOne() and belongsTo(). Its name and definition is the same as for the select *field type*:
+```php
+[
+ // 1-n relationship
+ 'label' => 'Parent', // Table column heading
+ 'type' => 'select',
+ 'name' => 'parent_id', // the column that contains the ID of that connected entity;
+ 'entity' => 'parent', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'model' => "App\Models\Category", // foreign key model
+],
+```
+
+
+
+### select_from_array
+
+Show a particular text depending on the value of the attribute.
+
+```php
+[
+ // select_from_array
+ 'name' => 'status',
+ 'label' => 'Status',
+ 'type' => 'select_from_array',
+ 'options' => ['draft' => 'Draft (invisible)', 'published' => 'Published (visible)'],
+],
+```
+
+
+
+
+### select_multiple
+
+The select_multiple column will output a comma separated list of its connected entities. Used for relationships like hasMany() and belongsToMany(). Its name and definition is the same as the select_multiple field:
+```php
+[
+ // n-n relationship (with pivot table)
+ 'label' => 'Tags', // Table column heading
+ 'type' => 'select_multiple',
+ 'name' => 'tags', // the method that defines the relationship in your Model
+ 'entity' => 'tags', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'model' => 'App\Models\Tag', // foreign key model
+],
+```
+
+
+
+
+### table
+
+
+The ```table``` column will output a condensed table, when used on an attribute that stores a JSON array or object. It is meant to be used inside the show functionality (not list, though it also works there).
+
+Its definition is very similar to the [table *field type*](/docs/{{version}}/crud-fields#table).
+
+```php
+[
+ 'name' => 'features',
+ 'label' => 'Features',
+ 'type' => 'table',
+ 'columns' => [
+ 'name' => 'Name',
+ 'description' => 'Description',
+ 'price' => 'Price',
+ 'obs' => 'Observations'
+ ]
+],
+```
+
+
+
+
+### text
+
+The text column will just output the text value of a db column (or model attribute). Its definition is:
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => 'Tag Name', // Table column heading
+ // 'prefix' => 'Name: ',
+ // 'suffix' => '(user)',
+ // 'limit' => 120, // character limit; default is 50,
+],
+```
+
+**Advanced use case:** The ```text``` column type can also show the attribute of a 1-1 relationship. If you have a relationship (like ```parent()```) set up in your Model, you can use relationship and attribute in the ```name```, using dot notation:
+```php
+[
+ 'name' => 'parent.title',
+ 'label' => 'Title',
+ 'type' => 'text'
+],
+```
+
+
+
+
+### textarea
+The text column will just output the text value of a db column (or model attribute) in a textarea field. Its definition is:
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => 'Tag Name', // Table column heading
+ // 'prefix' => 'Name: ',
+ // 'suffix' => '(user)',
+ // 'limit' => 120, // character limit; default is 50
+ // 'escaped' => false //if the text should be escaped
+],
+```
+
+
+### upload_multiple
+
+
+The ```table``` column will output a list of files and links, when used on an attribute that stores a JSON array of file paths. It is meant to be used inside the show functionality (not list, though it also works there), to preview files uploaded with the ```upload_multiple``` field type.
+
+Its definition is very similar to the [upload_multiple *field type*](/docs/{{version}}/crud-fields#upload_multiple).
+
+```php
+[
+ 'name' => 'photos',
+ 'label' => 'Photos',
+ 'type' => 'upload_multiple',
+ // 'disk' => 'public', // filesystem disk if you're using S3 or something custom
+],
+```
+
+
+
+
+### video
+
+
+Display a small screenshot for a Youtube or Vimeo video, stored in the database as JSON using the "video" field type.
+
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => 'Tag Name', // Table column heading
+ 'type' => 'video',
+],
+```
+
+
+
+
+### view
+
+Display any custom column type you want. Usually used by Backpack package developers, to use views from within their packages, instead of having to publish the views.
+
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => 'Tag Name', // Table column heading
+ 'type' => 'view',
+ 'view' => 'package::columns.column_type_name', // or path to blade file
+],
+```
+
+
+
+
+## Overwriting Default Column Types
+
+You can overwrite a column type by placing a file with the same name in your ```resources\views\vendor\backpack\crud\columns``` directory. When a file is there, Backpack will pick that one up, instead of the one in the package. You can do that from command line using ```php artisan backpack:publish crud/columns/column-file-name```
+
+Examples:
+- creating a ```resources\views\vendor\backpack\crud\columns\number.blade.php``` file would overwrite the ```number``` column functionality;
+- ```php artisan backpack:publish crud/columns/text``` will take the view from the package and copy it to the directory above, so you can edit it;
+
+>Keep in mind that when you're overwriting a default column type, you're forfeiting any future updates for that column. We can't push updates to a file that you're no longer using.
+
+
+
+
+## Creating a Custom Column Type
+
+Columns consist of only one file - a blade file with the same name as the column type (ex: ```text.blade.php```). You can create one by placing a new blad file inside ```resources\views\vendor\backpack\crud\columns```. Be careful to choose a distinctive name, otherwise you might be overwriting a default column type (see above).
+
+For example, you can create a ```markdown.blade.php```:
+```php
+{!! \Markdown::convertToHtml($entry->{$column['name']}) !!}
+```
+
+The most useful variables you'll have in this file here are:
+- ```$entry``` - the database entry you're showing (Eloquent object);
+- ```$crud``` - the entire CrudPanel object, with settings, options and variables;
+
+By default, custom columns are not searchable. In order to make your column searchable you need to [specify a custom ```searchLogic``` in your declaration](#custom-search-logic).
+
+
+
+
+
+## Advanced Columns Use
+
+
+### Custom Search Logic for Columns
+
+If your column points to something atypical (not a value that is stored as plain text in the database column, maybe a model function, or a JSON, or something else), you might find that the search doesn't work for that column. You can choose which columns are searchable, and what those columns actually search, by using the column's ```searchLogic``` attribute:
+
+```php
+// column with custom search logic
+$this->crud->addColumn([
+ 'name' => 'slug_or_title',
+ 'label' => 'Title',
+ 'searchLogic' => function ($query, $column, $searchTerm) {
+ $query->orWhere('title', 'like', '%'.$searchTerm.'%');
+ }
+]);
+
+
+// 1-n relationship column with custom search logic
+$this->crud->addColumn([
+ 'label' => 'Cruise Ship',
+ 'type' => 'select',
+ 'name' => 'cruise_ship_id',
+ 'entity' => 'cruise_ship',
+ 'attribute' => 'cruise_ship_name_date', // combined name & date column
+ 'model' => 'App\Models\CruiseShip',
+ 'searchLogic' => function ($query, $column, $searchTerm) {
+ $query->orWhereHas('cruise_ship', function ($q) use ($column, $searchTerm) {
+ $q->where('name', 'like', '%'.$searchTerm.'%')
+ ->orWhereDate('depart_at', '=', date($searchTerm));
+ });
+ }
+]);
+
+
+// column that doesn't need to be searchable
+$this->crud->addColumn([
+ 'name' => 'slug_or_title',
+ 'label' => 'Title',
+ 'searchLogic' => false
+]);
+
+// column whose search logic should behave like it were a 'text' column type
+$this->crud->addColumn([
+ 'name' => 'slug_or_title',
+ 'label' => 'Title',
+ 'searchLogic' => 'text'
+]);
+```
+
+
+### Custom Order Logic for Columns
+
+If your column points to something atypical (not a value that is stored as plain text in the database column, maybe a model function, or a JSON, or something else), you might find that the ordering doesn't work for that column. You can choose which columns are orderable, and how those columns actually get ordered, by using the column's ```orderLogic``` attribute.
+
+For example, to order Articles not by its Category ID (as default, but by the Category Name), you can do:
+
+```php
+$this->crud->addColumn([
+ // Select
+ 'label' => 'Category',
+ 'type' => 'select',
+ 'name' => 'category_id', // the db column for the foreign key
+ 'entity' => 'category', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'orderable' => true,
+ 'orderLogic' => function ($query, $column, $columnDirection) {
+ return $query->leftJoin('categories', 'categories.id', '=', 'articles.select')
+ ->orderBy('categories.name', $columnDirection)->select('articles.*');
+ }
+]);
+```
+
+
+
+### Wrap Column Text in an HTML Element
+
+Sometimes the text that the column echoes is not enough. You want to add interactivity to it, by adding a link to that column. Or you want to show the value in a green/yellow/red badge so it stands out. You can do both of that - with the ```wrapper``` attribute, which most columns support.
+
+For example, you can wrap the text in an anchor element, to point to that Article's Show operation:
+
+```php
+$this->crud->addColumn([
+ // Select
+ 'label' => 'Category',
+ 'type' => 'select',
+ 'name' => 'category_id', // the db column for the foreign key
+ 'entity' => 'category', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'wrapper' => [
+ // 'element' => 'a', // the element will default to "a" so you can skip it here
+ 'href' => function ($crud, $column, $entry, $related_key) {
+ return backpack_url('http://github.com/article/'.$related_key.'/show');
+ },
+ // 'target' => '_blank',
+ // 'class' => 'some-class',
+ ],
+]);
+```
+
+If you specify ```wrapper``` to a column, the entries in that column will be wrapped in the element you specify. Note that:
+- To get an HTML anchor (a link), you can specify ```a``` for the element (but that's also the default); to get a paragraph you'd specify ```p``` for the element; to get an inline element you'd specify ```span``` for the element; etc;
+- Anything you declare in the ```wrapper``` array (other than ```element```) will be used as HTML attributes for that element (ex: ```class```, ```style```, ```target``` etc);
+- Each wrapper attribute, including the element itself, can be declared as a string OR as a callback;
+
+Let's take another example, and wrap a boolean column into a green/red span:
+
+```php
+$this->crud->addColumn([
+ 'name' => 'published',
+ 'label' => 'Published',
+ 'type' => 'boolean',
+ 'options' => [0 => 'No', 1 => 'Yes'], // optional
+ 'wrapper' => [
+ 'element' => 'span',
+ 'class' => function ($crud, $column, $entry, $related_key) {
+ if ($column['text'] == 'Yes') {
+ return 'badge badge-success';
+ }
+
+ return 'badge badge-default';
+ },
+ ],
+]);
+```
+
+
+
+### Choose Where Columns are Visible
+
+Starting with Backpack\CRUD 3.5.0, you can choose to show/hide columns in different contexts. You can pass ```true``` / ```false``` to the column attributes below, and Backpack will know to show the column or not, in different contexts:
+
+```php
+$this->crud->addColumn([
+ 'name' => 'description',
+ 'visibleInTable' => false, // no point, since it's a large text
+ 'visibleInModal' => false, // would make the modal too big
+ 'visibleInExport' => false, // not important enough
+ 'visibleInShow' => true, // boolean or closure - function($entry) { return $entry->isAdmin(); }
+]);
+```
+
+This also allows you to do tricky things like:
+- add a column that's hidden from the table view, but WILL get exported;
+- adding a column that's hidden everywhere, but searchable (even with a custom ```searchLogic```);
+
+
+### Multiple Columns With the Same Name
+
+Starting with Backpack\CRUD 3.3 (Nov 2017), you can have multiple columns with the same name, by specifying a unique ```key``` property. So if you want to use the same column name twice, you can do that. Notice below we have the same name for both columns, but one of them has a ```key```. This additional key will be used as an array key, if provided.
+
+```php
+// column that shows the parent's first name
+$this->crud->addColumn([
+ 'label' => 'Parent First Name', // Table column heading
+ 'type' => 'select',
+ 'name' => 'parent_id', // the column that contains the ID of that connected entity;
+ 'entity' => 'parent', // the method that defines the relationship in your Model
+ 'attribute' => 'first_name', // foreign key attribute that is shown to user
+ 'model' => 'App\Models\User', // foreign key model
+]);
+
+// column that shows the parent's last name
+$this->crud->addColumn([
+ 'label' => 'Parent Last Name', // Table column heading
+ 'type' => 'select',
+ 'name' => 'parent_id', // the column that contains the ID of that connected entity;
+ 'key' => 'parent_last_name', // the column that contains the ID of that connected entity;
+ 'entity' => 'parent', // the method that defines the relationship in your Model
+ 'attribute' => 'last_name', // foreign key attribute that is shown to user
+ 'model' => 'App\Models\User', // foreign key model
+]);
+```
+
+
+### Define which columns to show or hide in the responsive table
+
+By default, DataTables-responsive will try his best to show:
+- **the first column** (since that usually is the most important for the user, plus it holds the modal button and the details_row button so it's crucial for usability);
+- **the last column** (the actions column, where the action buttons reside);
+
+When giving priorities, lower is better. So a column with priority 4 will be hidden BEFORE a column with priority 2. The first and last columns have a priority of 1. You can define a different priority for a column using the ```priority``` attribute. For example:
+
+```php
+$this->crud->addColumn([
+ 'name' => 'details',
+ 'type' => 'text',
+ 'label' => 'Details',
+ 'priority' => 2,
+]);
+$this->crud->addColumn([
+ 'name' => 'obs',
+ 'type' => 'text',
+ 'label' => 'Observations',
+ 'priority' => 3,
+]);
+```
+In the example above, depending on how much space it's got in the viewport, DataTables will first hide the ```obs``` column, then ```details```, then the last column, then the first column.
+
+You can make the last column be less important (and hide) by giving it an unreasonable priority:
+
+```php
+$this->crud->setActionsColumnPriority(10000);
+```
+
+>Note that responsive tables adopt special behavior if the table is not able to show all columns. This includes displaying a vertical ellipsis to the left of the row, and making the row clickable to reveal more detail. This behavior is automatic and is not manually controllable via a field property.
diff --git a/4.1/crud-fields.md b/4.1/crud-fields.md
new file mode 100644
index 00000000..3a5ff7dd
--- /dev/null
+++ b/4.1/crud-fields.md
@@ -0,0 +1,2399 @@
+# Fields
+
+---
+
+
+## About
+
+Field types define how the admin can manipulate an entry's values. They're used by the Create and Update operations.
+
+Think of the field type as the type of input: ``````. But for most entities, you won't just need text inputs - you'll need datepickers, upload buttons, 1-n relationship, n-n relationships, textareas, etc.
+
+We have a lot of default field types, detailed below. If you don't find what you're looking for, you can [create a custom field type](/docs/{{version}}/crud-fields#creating-a-custom-field-type). Or if you just want to tweak a default field type a little bit, you can [overwrite default field types](/docs/{{version}}/crud-fields#overwriting-default-field-types).
+
+> NOTE: Starting with Backpack 4.1, if the _field name_ is the exact same as a relation method in the model, Backpack will assume you're adding a field for that relationship and infer relation attributes from it. To disable this behaviour, you can use `'entity' => false` in your field definition.
+
+
+### Fields API
+
+To manipulate fields, you can use the methods below. The action will be performed on the currently running operation. So make sure you run these methods inside ```setupCreateOperation()```, ```setupUpdateOperation()``` or in ```setup()``` inside operation blocks:
+
+```php
+// add a field to both Create and Update operation
+$this->crud->addField($field_definition_array);
+
+// add a field only to the Update operation
+$this->crud->addField($field_definition_array);
+
+// shorthand: add a text field to both Create and Update operations
+$this->crud->addField('db_column_name');
+
+// add multiple fields
+$this->crud->addFields([$field_definition_array_1, $field_definition_array_2]);
+
+// change the attributes of a field
+$this->crud->modifyField($name, $modifs_array);
+
+// remove a field from both operations
+$this->crud->removeField('name');
+
+// remove multiple fields from both operations
+$this->crud->removeFields($array_of_names);
+
+// remove all fields from all operations
+$this->crud->removeAllFields();
+
+// FIELD ORDER
+
+// add a field before a given field
+$this->crud->addField($field_definition_array)->beforeField('name');
+
+// add a field after a given field
+$this->crud->addField($field_definition_array)->afterField('name');
+
+
+// -------------------
+// New in Backpack 4.1
+// -------------------
+// add a field with this name
+$this->crud->field('price');
+
+// change the type attribute on the 'price' field
+$this->crud->field('price')->type('number');
+```
+
+
+### Field Attributes
+
+
+#### Mandatory Field Attributes
+
+**The only attribute that's mandatory when you define a field is its `name`**, which will be used:
+- inside the inputs, as ``;
+- to store the information in the database, so your `name` should correspond to a database column (if the field type doesn't have different instructions);
+
+Every other field attribute other than `name`, Backpack 4.1+ will try to guess.
+
+
+#### Recommended Field Attributes
+
+Normally developers define the following attributes for all fields:
+- the ```name``` of the column in the database (ex: "title")
+- the human-readable ```label``` for the input (ex: "Title")
+- the ```type``` of the input (ex: "text")
+
+So at minimum, your field definition array should look like:
+```php
+[
+ 'name' => 'description',
+ 'type' => 'textarea',
+ 'label' => 'Article Description',
+]
+```
+
+Please note that `label` and `type` are not _mandatory_, just _recommended_:
+- `label` can be omitted, and Backpack will try to construct it from the `name`;
+- `type` can be omitted, and Backpack will try to guess it from the column type, or if there's a relationship on the Model with the same `name`;
+
+
+#### Optional - Field Attributes for Presentation Purposes
+
+There are a few optional attributes on most default field types, that you can use to easily achieve a few common customizations:
+
+```php
+[
+ 'prefix' => '',
+ 'suffix' => '',
+ 'default' => 'some value', // set a default value
+ 'hint' => 'Some hint text', // helpful text, shows up after the input
+ 'attributes' => [
+ 'placeholder' => 'Some text when empty',
+ 'class' => 'form-control some-class',
+ 'readonly' => 'readonly',
+ 'disabled' => 'disabled',
+ ], // change the HTML attributes of your input
+ 'wrapper' => [
+ 'class' => 'form-group col-md-12'
+ ], // change the HTML attributes for the field wrapper - mostly for resizing fields
+]
+```
+
+These will help you:
+
+- **prefix** - add a text or icon _before_ the actual input;
+- **suffix** - add a text or icon _after_ the actual input;
+- **default** - specify a default value for the input, on create;
+- **hint** - add descriptive text for this input;
+- **attributes** - change or add actual HTML attributes of the input (ex: readonly, disabled, class, placeholder, etc);
+- **wrapper** - change or add actual HTML attributes to the div that contains the input;
+
+
+#### Optional - Fake Field Attributes (stores fake attributes as JSON in the database)
+
+In case you want to store insignificant information for an entry that doesn't need a database column, you can add any number of Fake Fields, and all their information will be stored inside one column in the db, as JSON. By default, an ```extras``` column is assumed on the database table, but you can change that.
+
+**Step 1.** Use the fake attribute on your field:
+```php
+[
+ 'name' => 'name', // JSON variable name
+ 'label' => "Tag Name", // human-readable label for the input
+
+ 'fake' => true, // show the field, but don't store it in the database column above
+ 'store_in' => 'extras' // [optional] the database column name where you want the fake fields to ACTUALLY be stored as a JSON array
+],
+```
+
+**Step 2.** On your model, make sure the db columns where you store the JSONs (by default only ```extras```):
+- are in your ```$fillable``` property;
+- are on a new ```$fakeColumns``` property (create it now);
+- are casted as array in ```$casts```;
+
+>If you need your fakes to also be translatable, remember to also place ```extras``` in your model's ```$translatable``` property and remove it from ```$casts```.
+
+Example:
+```php
+[
+ 'name' => 'meta_title',
+ 'label' => "Meta Title",
+ 'fake' => true,
+ 'store_in' => 'metas' // [optional]
+],
+[
+ 'name' => 'meta_description',
+ 'label' => "Meta Description",
+ 'fake' => true,
+ 'store_in' => 'metas' // [optional]
+],
+[
+ 'name' => 'meta_keywords',
+ 'label' => "Meta Keywords",
+ 'fake' => true,
+ 'store_in' => 'metas' // [optional]
+],
+```
+
+In this example, these 3 fields will show up in the create & update forms, the CRUD will process as usual, but in the database these values won't be stored in the ```meta_title```, ```meta_description``` and ```meta_keywords``` columns. They will be stored in the ```metas``` column as a JSON array:
+
+```php
+{"meta_title":"title","meta_description":"desc","meta_keywords":"keywords"}
+```
+
+If the ```store_in``` attribute wasn't used, they would have been stored in the ```extras``` column.
+
+
+#### Optional - Tab Attribute Splits Forms into Tabs
+
+You can now split your create/edit inputs into multiple tabs.
+
+
+
+In order to use this feature, you just need to specify the tab name for each of your fields. Example:
+
+```php
+// select_from_array
+$this->crud->addField([
+ 'name' => 'select_from_array',
+ 'label' => "Select from array",
+ 'type' => 'select_from_array',
+ 'options' => ['one' => 'One', 'two' => 'Two', 'three' => 'Three'],
+ 'allows_null' => false,
+ 'allows_multiple' => true,
+ 'tab' => 'Tab name here',
+]);
+```
+
+If you forget to specify a tab name for a field, Backpack will place it above all tabs.
+
+
+
+#### Optional - Attributes for Fields Containing Related Entries
+
+When a field works with related entities (relationships like `BelongsTo`, `HasOne`, `HasMany`, `BelongsToMany`, etc), Backpack needs to know how the current model (being create/edited) and the other model (that shows up in the field) are related. And it stores that information in a few additional field attributes, right after you add the field.
+
+*Normally, Backpack 4.1+ will guess all this relationship information for you.* If you have your relationships properly defined in your Models, you can just use a relationship field the same way you would a normal field. Pretend that _the method in your Model that defines your relationship_ is a real column, and Backpack will do all the work for you.
+
+But if you want to overwrite any of the relationship attributes Backpack guesses, here they are:
+- `entity` - points to the method on the model that contains the relationship; having this defined, Backpack will try to guess from it all other field attributes; ex: `category` or `tags`;
+- `model` - the classname (including namespace) of the related model (ex: `App\Models\Category`); usually deduced from the relationship function in the model;
+- `attribute` - the attribute on the related model (aka foreign attribute) that will be show to the user; for example, you wouldn't want a dropdown of categories showing IDs - no, you'd want to show the category names; in this case, the `attribute` will be `name`; usually deduced using the [identifiable attribute functionality explained below](#identifiable-attribute);
+- `multiple` - boolean, allows the user to pick one or multiple items; usually deduced depending on whether it's a 1-to-n or n-n relationship;
+- `pivot` - boolean, instructs Backpack to store the information inside a pivot table; usually deduced depending on whether it's a 1-to-n or n-n relationship;
+- `relation_type` - text, deduced from `entity`; not a good idea to overwrite;
+
+If you do need a field that contains relationships to behave a certain way, it's usually enough to just specify a different `entity`. However, you _can_ specify any of the attributes above, and Backpack will take your value for it, instead of trying to guess one.
+
+
+
+** Identifiable Attribute for Relationship Fields**
+
+Fields that work with relationships will allow you to select which ```attribute``` on the related entry you want to show to the user. All relationship fields (relationship, select, select2, select_multiple, select2_multiple, select2_from_ajax, select2_from_ajax_multiple) let you define the ```attribute``` for this specific purpose.
+
+For example, when the admin creates an ```Article``` they'll have to select a ```Category``` from a dropdown. It's important to show an attribute for ```Category``` that will help the admin easily identify the category, even if it's not the ID. In this example, it would probably be the category name - that's what you'd like the dropdown to show.
+
+In Backpack, you can explicitly define this, by giving the field an ```attribute```. But you can also NOT explicitly define this - Backpack will try to guess it. If you don't like what Backpack guessed would be a good identifiable attribute, you can either:
+- (A) explicitly define an ```attribute``` for that field, or
+- (B) you can specify the identifiable attribute in your model, and all fields will pick this up:
+
+```php
+
+use Backpack\CRUD\app\Models\Traits\CrudTrait;
+
+class Category
+{
+ use CrudTrait;
+
+ // you can define this
+
+ /**
+ * Attribute shown on the element to identify this model.
+ *
+ * @var string
+ */
+ protected $identifiableAttribute = 'title';
+
+ // or for more complicated use cases you can do
+
+ /**
+ * Get the attribute shown on the element to identify this model.
+ *
+ * @return string
+ */
+ public function identifiableAttribute()
+ {
+ // process stuff here
+ return 'whatever_you_want_even_an_accessor';
+ }
+}
+```
+
+
+
+## Default Field Types
+
+
+### address_algolia
+
+Use [Algolia Places autocomplete](https://community.algolia.com/places/) to help users type their address faster. With the ```store_as_json``` option, it will store the address, postcode, city, country, latitude and longitude in a JSON in the database. Without it, it will just store the address string. For information stored as JSON in the database, it's recommended that you use [attribute casting](https://mattstauffer.co/blog/laravel-5.0-eloquent-attribute-casting) to ```array``` or ```object```. That way, every time you get the info from the database you'd get it in a usable format.
+
+```php
+[ // Address algolia
+ 'name' => 'address',
+ 'label' => 'Address',
+ 'type' => 'address_algolia',
+ // optional
+ 'store_as_json' => true
+],
+```
+
+> **Algolia is killing Places.** Please note that Algolia Places **will stop working in May 2022**, as reported in [this announcement](https://www.algolia.com/blog/product/sunseting-our-places-feature/). For that reason, it's probably a good idea to use the `address_google` field instead (it's right after this one).
+
+
+Input preview:
+
+
+
+
+
+
+### address_google
+
+Use [Google Places Search](https://developers.google.com/places/web-service/search) to help users type their address faster. With the ```store_as_json``` option, it will store the address, postcode, city, country, latitude and longitude in a JSON in the database. Without it, it will just store the complete address string.
+
+```php
+[ // Address google
+ 'name' => 'address',
+ 'label' => 'Address',
+ 'type' => 'address_google',
+ // optional
+ 'store_as_json' => true
+],
+```
+
+Using Google Places API is dependent on using an API Key. Please [get an API key](https://console.cloud.google.com/apis/credentials) - you do have to configure billing, but you qualify for $200/mo free usage, which covers most use cases. Then copy-paste that key as your ```services.google_places.key``` value. So inside your ```config/services.php``` please add the items below:
+
+```php
+'google_places' => [
+ 'key' => 'the-key-you-got-from-google-places'
+],
+```
+
+> **Use attribute casting.** For information stored as JSON in the database, it's recommended that you use [attribute casting](https://mattstauffer.co/blog/laravel-5.0-eloquent-attribute-casting) to ```array``` or ```object```. That way, every time you get the info from the database you'd get it in a usable format. Also, it is heavily recommended that your database column can hold a large JSON - so use `text` rather than `string` in your migration (in MySQL this translates to `text` instead of `varchar`).
+
+Input preview:
+
+
+
+
+
+
+### browse
+
+This button allows the admin to open [elFinder](http://elfinder.org/) and select a file from there. Run ```composer require backpack/filemanager && php artisan backpack:filemanager:install``` to install [FileManager](https://github.com/laravel-backpack/filemanager), then you can use the field:
+
+```php
+[ // Browse
+ 'name' => 'image',
+ 'label' => 'Image',
+ 'type' => 'browse'
+],
+```
+
+
+Input preview:
+
+
+
+Onclick preview:
+
+
+
+
+
+
+### browse_multiple
+
+Open elFinder and select multiple files from there. Run ```composer require backpack/filemanager && php artisan backpack:filemanager:install``` to install [FileManager](https://github.com/laravel-backpack/filemanager), then you can use the field:
+
+```php
+[ // Browse multiple
+ 'name' => 'files',
+ 'label' => 'Files',
+ 'type' => 'browse_multiple',
+ // 'multiple' => true, // enable/disable the multiple selection functionality
+ // 'sortable' => false, // enable/disable the reordering with drag&drop
+ // 'mime_types' => null, // visible mime prefixes; ex. ['image'] or ['application/pdf']
+],
+```
+
+The field assumes you've cast your attribute as ```array``` on your model. That way, when you do ```$entry->files``` you get a nice array.
+**NOTE:** If you use `multiple => false` you should NOT cast your attribute as ```array```
+
+Input preview:
+
+
+
+
+
+
+### base64_image
+
+Upload an image and store it in the database as Base64. Notes:
+- make sure the column type is LONGBLOB;
+- detailed [instructions and customizations here](https://github.com/Laravel-Backpack/CRUD/pull/56#issue-164712261);
+
+```php
+// base64_image
+$this->crud->addField([
+ 'label' => "Profile Image",
+ 'name' => "image",
+ 'filename' => "image_filename", // set to null if not needed
+ 'type' => 'base64_image',
+ 'aspect_ratio' => 1, // set to 0 to allow any aspect ratio
+ 'crop' => true, // set to true to allow cropping, false to disable
+ 'src' => NULL, // null to read straight from DB, otherwise set to model accessor function
+]);
+```
+
+Input preview:
+
+
+
+
+
+
+### checkbox
+
+Checkbox for true/false.
+
+```php
+[ // Checkbox
+ 'name' => 'active',
+ 'label' => 'Active',
+ 'type' => 'checkbox'
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### checklist
+
+Show a list of checkboxes, for the user to check one or more of them.
+
+```php
+[ // Checklist
+ 'label' => 'Roles',
+ 'type' => 'checklist',
+ 'name' => 'roles',
+ 'entity' => 'roles',
+ 'attribute' => 'name',
+ 'model' => "Backpack\PermissionManager\app\Models\Role",
+ 'pivot' => true,
+],
+```
+
+**Note: If you don't use a pivot table (pivot = false), you need to cast your db column as `array` in your model,by adding your column to your model's `$casts`. **
+
+Input preview:
+
+
+
+
+
+
+### checklist_dependency
+
+```php
+[ // two interconnected entities
+ 'label' => 'User Role Permissions',
+ 'field_unique_name' => 'user_role_permission',
+ 'type' => 'checklist_dependency',
+ 'name' => ['roles', 'permissions'], // the methods that define the relationship in your Models
+ 'subfields' => [
+ 'primary' => [
+ 'label' => 'Roles',
+ 'name' => 'roles', // the method that defines the relationship in your Model
+ 'entity' => 'roles', // the method that defines the relationship in your Model
+ 'entity_secondary' => 'permissions', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'model' => "Backpack\PermissionManager\app\Models\Role", // foreign key model
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?]
+ 'number_columns' => 3, //can be 1,2,3,4,6
+ ],
+ 'secondary' => [
+ 'label' => 'Permission',
+ 'name' => 'permissions', // the method that defines the relationship in your Model
+ 'entity' => 'permissions', // the method that defines the relationship in your Model
+ 'entity_primary' => 'roles', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'model' => "Backpack\PermissionManager\app\Models\Permission", // foreign key model
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?]
+ 'number_columns' => 3, //can be 1,2,3,4,6
+ ],
+ ],
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### ckeditor
+
+Show a wysiwyg CKEditor to the user.
+
+```php
+[ // CKEditor
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'ckeditor',
+
+ // optional:
+ 'extra_plugins' => ['oembed', 'widget'],
+ 'options' => [
+ 'autoGrow_minHeight' => 200,
+ 'autoGrow_bottomSpace' => 50,
+ 'removePlugins' => 'resize,maximize',
+ ]
+],
+```
+
+If you'd like to be able to select files from elFinder, you need to also run ```composer require backpack/filemanager``` to install elFinder.
+
+Input preview:
+
+
+
+
+
+
+### color
+
+```php
+[ // Color
+ 'name' => 'background_color',
+ 'label' => 'Background Color',
+ 'type' => 'color',
+ 'default' => '#000000',
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### color_picker
+
+Show a pretty colour picker using [Bootstrap Colorpicker](https://itsjavi.com/bootstrap-colorpicker/).
+
+```php
+[ // color_picker
+ 'label' => 'Background Color',
+ 'name' => 'background_color',
+ 'type' => 'color_picker',
+ 'default' => '#000000',
+
+ // optional
+ // Anything your define inside `color_picker_options` will be passed as JS
+ // to the JavaScript plugin. For more information about the options available
+ // please see the plugin docs at:
+ // ### https://itsjavi.com/bootstrap-colorpicker/module-options.html
+ 'color_picker_options' => [
+ 'customClass' => 'custom-class',
+ 'horizontal' => true,
+ 'extensions' => [
+ [
+ 'name' => 'swatches', // extension name to load
+ 'options' => [ // extension options
+ 'colors' => [
+ 'primary' => '#337ab7',
+ 'success' => '#5cb85c',
+ 'info' => '#5bc0de',
+ 'warning' => '#f0ad4e',
+ 'danger' => '#d9534f'
+ ],
+ 'namesAsValues' => false
+ ]
+ ]
+ ]
+ ]
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### custom_html
+
+Allows you to insert custom HTML in the create/update forms. Usually used in forms with a lot of fields, to separate them using h1-h5, hr, etc, but can be used for any HTML.
+
+```php
+[ // CustomHTML
+ 'name' => 'separator',
+ 'type' => 'custom_html',
+ 'value' => ''
+],
+```
+
+
+### date
+
+```php
+[ // Date
+ 'name' => 'birthday',
+ 'label' => 'Birthday',
+ 'type' => 'date'
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### date_picker
+
+Show a pretty [Bootstrap Datepicker](http://bootstrap-datepicker.readthedocs.io/en/latest/).
+
+```php
+[ // date_picker
+ 'name' => 'date',
+ 'type' => 'date_picker',
+ 'label' => 'Date',
+
+ // optional:
+ 'date_picker_options' => [
+ 'todayBtn' => 'linked',
+ 'format' => 'dd-mm-yyyy',
+ 'language' => 'fr'
+ ],
+],
+```
+
+Please note it is recommended that you use [attribute casting](https://laravel.com/docs/5.3/eloquent-mutators#attribute-casting) on your model (cast to date).
+
+
+Input preview:
+
+
+
+
+
+
+### date_range
+
+Starting with Backpack\CRUD 3.1.59
+
+Show a DateRangePicker and let the user choose a start date and end date.
+
+```php
+[ // date_range
+ 'name' => ['start_date', 'end_date'], // db columns for start_date & end_date
+ 'label' => 'Event Date Range',
+ 'type' => 'date_range',
+
+ // OPTIONALS
+ // default values for start_date & end_date
+ 'default' => ['2019-03-28 01:01', '2019-04-05 02:00'],
+ // options sent to daterangepicker.js
+ 'date_range_options' => [
+ 'drops' => 'down', // can be one of [down/up/auto]
+ 'timePicker' => true,
+ 'locale' => ['format' => 'DD/MM/YYYY HH:mm']
+ ]
+],
+```
+
+Please note it is recommended that you use [attribute casting](https://laravel.com/docs/5.3/eloquent-mutators#attribute-casting) on your model (cast to date).
+
+Your end result will look like this:
+
+Input preview:
+
+
+
+
+
+
+### datetime
+
+```php
+[ // DateTime
+ 'name' => 'start',
+ 'label' => 'Event start',
+ 'type' => 'datetime'
+],
+```
+
+**Please note:** if you're using datetime [attribute casting](https://laravel.com/docs/5.3/eloquent-mutators#attribute-casting) on your model, you also need to place this mutator inside your model:
+```php
+ public function setDatetimeAttribute($value) {
+ $this->attributes['datetime'] = \Carbon\Carbon::parse($value);
+ }
+```
+Otherwise the input's datetime-local format will cause some errors.
+
+Input preview:
+
+
+
+
+
+
+### datetime_picker
+
+Show a [Bootstrap Datetime Picker](https://eonasdan.github.io/bootstrap-datetimepicker/).
+
+```php
+[ // DateTime
+ 'name' => 'start',
+ 'label' => 'Event start',
+ 'type' => 'datetime_picker',
+
+ // optional:
+ 'datetime_picker_options' => [
+ 'format' => 'DD/MM/YYYY HH:mm',
+ 'language' => 'pt',
+ 'tooltips' => [ //use this to translate the tooltips in the field
+ 'today' => 'Hoje',
+ 'selectDate' => 'Selecione a data',
+ // available tooltips: today, clear, close, selectMonth, prevMonth, nextMonth, selectYear, prevYear, nextYear, selectDecade, prevDecade, nextDecade, prevCentury, nextCentury, pickHour, incrementHour, decrementHour, pickMinute, incrementMinute, decrementMinute, pickSecond, incrementSecond, decrementSecond, togglePeriod, selectTime, selectDate
+ ]
+ ],
+ 'allows_null' => true,
+ // 'default' => '2017-05-12 11:59:59',
+],
+```
+
+**Please note:** if you're using date [attribute casting](https://laravel.com/docs/5.3/eloquent-mutators#attribute-casting) on your model, you may also need to place this mutator inside your model:
+```php
+ public function setDatetimeAttribute($value) {
+ $this->attributes['datetime'] = \Carbon\Carbon::parse($value);
+ }
+```
+Otherwise the input's datetime-local format will cause some errors. Remember to change "datetime" with the name of your attribute (column name).
+
+Input preview:
+
+
+
+
+
+
+### easymde
+
+Show an [EasyMDE - Markdown Editor](https://github.com/Ionaru/easy-markdown-editor) to the user. EasyMDE is a well-maintained fork of SimpleMDE.
+
+```php
+[ // easymde
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'easymde',
+ // optional
+ // 'easymdeAttributes' => [
+ // 'promptURLs' => true,
+ // 'status' => false,
+ // 'spellChecker' => false,
+ // 'forceSync' => true,
+ // ],
+ // 'easymdeAttributesRaw' => $some_json
+],
+```
+
+> NOTE: The contents displayed in this editor are NOT stripped, sanitized or escaped by default. Whenever you store Markdown or HTML inside your database, it's HIGHLY recommended that you sanitize the input or output. Laravel makes it super-easy to do that on the model using [accessors](https://laravel.com/docs/8.x/eloquent-mutators#accessors-and-mutators). If you do NOT trust the admins who have access to this field (or end-users can also store information to this db column), please make sure this attribute is always escaped, before it's shown. You can do that by running the value through `strip_tags()` in an accessor on the model (here's [an example](https://github.com/Laravel-Backpack/demo/commit/509c0bf0d8b9ee6a52c50f0d2caed65f1f986385)) or better yet, using an [HTML Purifier package](https://github.com/mewebstudio/Purifier) (here's [an example](https://github.com/Laravel-Backpack/demo/commit/7342cffb418bb568b9e4ee279859685ddc0456c1)).
+
+Input preview:
+
+
+
+
+
+
+### email
+
+```php
+[ // Email
+ 'name' => 'email',
+ 'label' => 'Email Address',
+ 'type' => 'email'
+],
+```
+
+Input preview:
+
+
+
+
+
+
+
+### enum
+
+Show a select with the values in the database for that ENUM field. Requires that the db column type is "enum". If the db column allows null, the " - " value will also show up in the select.
+
+```php
+[ // Enum
+ 'name' => 'status',
+ 'label' => 'Status',
+ 'type' => 'enum'
+],
+```
+
+PLEASE NOTE the enum field only works for MySQL databases.
+
+Input preview:
+
+
+
+
+
+
+### hidden
+
+Include an in the form.
+
+```php
+[ // Hidden
+ 'name' => 'status',
+ 'type' => 'hidden',
+ 'value' => 'active',
+],
+```
+
+
+
+
+### icon_picker
+
+Show an icon picker. Supported icon sets are fontawesome, lineawesome, glyphicon, ionicon, weathericon, mapicon, octicon, typicon, elusiveicon, materialdesign as per the jQuery plugin, [bootstrap-iconpicker](http://victor-valencia.github.io/bootstrap-iconpicker/).
+
+The stored value will be the class name (ex: fa-home).
+
+```php
+[ // icon_picker
+ 'label' => "Icon",
+ 'name' => 'icon',
+ 'type' => 'icon_picker',
+ 'iconset' => 'fontawesome' // options: fontawesome, lineawesome, glyphicon, ionicon, weathericon, mapicon, octicon, typicon, elusiveicon, materialdesign
+],
+```
+
+Your input will look like button, with a dropdown where the user can search or pick an icon:
+
+Input preview:
+
+
+
+
+
+
+### image
+
+Upload an image and store it on the disk.
+
+**Step 1.** Show the field.
+```php
+// image
+$this->crud->addField([
+ 'label' => "Profile Image",
+ 'name' => "image",
+ 'type' => 'image',
+ 'crop' => true, // set to true to allow cropping, false to disable
+ 'aspect_ratio' => 1, // omit or set to 0 to allow any aspect ratio
+ // 'disk' => 's3_bucket', // in case you need to show images from a different disk
+ // 'prefix' => 'uploads/images/profile_pictures/' // in case your db value is only the file name (no path), you can use this to prepend your path to the image src (in HTML), before it's shown to the user;
+]);
+```
+
+**Step 2.** Add a [mutator](https://laravel.com/docs/7.x/eloquent-mutators#defining-a-mutator) to your Model, where you pick up the uploaded file and store it wherever you want. You can use this boilerplate code and modify it to match your use case.
+
+**NOTE: The code below requires that you have ```intervention/image``` installed. If you don't, please do ```composer require intervention/image``` first.**
+
+```php
+// ..
+
+use Illuminate\Support\Str;
+use Intervention\Image\ImageManagerStatic as Image;
+
+// ..
+
+Class Product extends Model
+{
+ // ..
+
+ public function setImageAttribute($value)
+ {
+ $attribute_name = "image";
+ // or use your own disk, defined in config/filesystems.php
+ $disk = config('backpack.base.root_disk_name');
+ // destination path relative to the disk above
+ $destination_path = "public/uploads/folder_1/folder_2";
+
+ // if the image was erased
+ if ($value==null) {
+ // delete the image from disk
+ \Storage::disk($disk)->delete($this->{$attribute_name});
+
+ // set null in the database column
+ $this->attributes[$attribute_name] = null;
+ }
+
+ // if a base64 was sent, store it in the db
+ if (Str::startsWith($value, 'data:image'))
+ {
+ // 0. Make the image
+ $image = \Image::make($value)->encode('jpg', 90);
+
+ // 1. Generate a filename.
+ $filename = md5($value.time()).'.jpg';
+
+ // 2. Store the image on disk.
+ \Storage::disk($disk)->put($destination_path.'/'.$filename, $image->stream());
+
+ // 3. Delete the previous image, if there was one.
+ \Storage::disk($disk)->delete($this->{$attribute_name});
+
+ // 4. Save the public path to the database
+ // but first, remove "public/" from the path, since we're pointing to it
+ // from the root folder; that way, what gets saved in the db
+ // is the public URL (everything that comes after the domain name)
+ $public_destination_path = Str::replaceFirst('public/', '', $destination_path);
+ $this->attributes[$attribute_name] = $public_destination_path.'/'.$filename;
+ }
+ }
+
+// ..
+```
+> **The uploaded images are not deleted for you.** If you delete an entry (using the CRUD or anywhere inside your app), the image file won't be deleted from the disk.
+> If you're NOT using soft deletes on that Model and want the image to be deleted at the same time the entry is, just specify that in your Model's ```deleting``` event:
+> ```php
+> public static function boot()
+> {
+> parent::boot();
+> static::deleted(function($obj) {
+> \Storage::disk('public_folder')->delete($obj->image);
+> });
+> }
+> ```
+
+**A note about aspect_ratio**
+The value for aspect ratio is a float that represents the ratio of the cropping rectangle height and width. By way of example,
+
+- Square = 1
+- Landscape = 2
+- Portrait = 0.5
+
+And you can, of course, use any value for more extreme rectangles.
+
+Input preview:
+
+
+
+> NOTE: if you are having trouble uploading big images, please check your php extensions **apcu** and/or **opcache**, users have reported some issues with these extensions when trying to upload very big images. REFS: https://github.com/Laravel-Backpack/CRUD/issues/3457
+
+
+
+
+### month
+
+```php
+[ // Month
+ 'name' => 'month',
+ 'label' => 'Month',
+ 'type' => 'month'
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### number
+
+Shows an input type=number to the user, with optional prefix and suffix:
+
+```php
+[ // Number
+ 'name' => 'number',
+ 'label' => 'Number',
+ 'type' => 'number',
+
+ // optionals
+ // 'attributes' => ["step" => "any"], // allow decimals
+ // 'prefix' => "$",
+ // 'suffix' => ".00",
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### page_or_link
+
+Select an existing page from PageManager or an internal or external link. It's used in the MenuManager package, but can be used in any other model just as well. Its definition looks like this:
+```php
+[ // PageOrLink
+ 'name' => ['type', 'link', 'page_id'],
+ 'label' => "Type",
+ 'type' => 'page_or_link',
+ 'page_model' => '\Backpack\PageManager\app\Models\Page'
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### password
+
+```php
+[ // Password
+ 'name' => 'password',
+ 'label' => 'Password',
+ 'type' => 'password'
+],
+```
+
+Input preview:
+
+
+
+
+Please note that this will NOT hash/encrypt the string before it stores it to the database. You need to hash the password manually. The most popular way to do that are:
+
+1. Using [a mutator on your Model](https://laravel.com/docs/7.x/eloquent-mutators#defining-a-mutator). For example:
+
+```php
+public function setPasswordAttribute($value) {
+ $this->attributes['password'] = Hash::make($value);
+}
+```
+
+2. By overwriting the Create/Update operation methods, inside the Controller. There's a working example [in our PermissionManager package](https://github.com/Laravel-Backpack/PermissionManager/blob/master/src/app/Http/Controllers/UserCrudController.php#L103-L124) but the gist of it is this:
+
+```php
+ use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation { store as traitStore; }
+
+ public function store()
+ {
+ $this->crud->setRequest($this->crud->validateRequest());
+
+ /** @var \Illuminate\Http\Request $request */
+ $request = $this->crud->getRequest();
+
+ // Encrypt password if specified.
+ if ($request->input('password')) {
+ $request->request->set('password', Hash::make($request->input('password')));
+ } else {
+ $request->request->remove('password');
+ }
+
+ $this->crud->setRequest($request);
+ $this->crud->unsetValidation(); // Validation has already been run
+
+ return $this->traitStore();
+ }
+```
+
+
+
+
+
+### radio
+
+Show radios according to an associative array you give the input and let the user pick from them. You can choose for the radio options to be displayed inline or one-per-line.
+
+```php
+[ // radio
+ 'name' => 'status', // the name of the db column
+ 'label' => 'Status', // the input label
+ 'type' => 'radio',
+ 'options' => [
+ // the key will be stored in the db, the value will be shown as label;
+ 0 => "Draft",
+ 1 => "Published"
+ ],
+ // optional
+ //'inline' => false, // show the radios all on the same line?
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### range
+
+Shows an HTML5 range element, allowing the user to drag a cursor left-right, to pick a number from a defined range.
+
+```php
+[ // Range
+ 'name' => 'range',
+ 'label' => 'Range',
+ 'type' => 'range',
+ //optional
+ 'attributes' => [
+ 'min' => 0,
+ 'max' => 10,
+ ],
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### relationship
+
+Allows the user to choose one/more entries of an Eloquent Model that has a relationship with the current model, using a ```select2``` input. In order to work, this field needs the relationships to be properly defined on the Eloquent models (```hasOne```, ```belongsTo```, ```belongsToMany``` etc).
+
+Input preview (for both 1-n and n-n relationships):
+
+
+
+
+Take a look at the examples below to understand the correct syntax for your use case.
+
+**Example 1. Few options (0-100). Entries are loaded onpage, using a simple Eloquent query. No AJAX.**
+```php
+[ // relationship
+ 'type' => "relationship",
+ 'name' => 'category', // the method on your model that defines the relationship
+
+ // OPTIONALS:
+ // 'label' => "Category",
+ // 'attribute' => "name", // foreign key attribute that is shown to user (identifiable attribute)
+ // 'entity' => 'category', // the method that defines the relationship in your Model
+ // 'model' => "App\Models\Category", // foreign key Eloquent model
+ // 'placeholder' => "Select a category", // placeholder for the select2 input
+ ],
+```
+
+For more information about the optional attributes that fields use when they interact with related entries - [look here](#optional-attributes-for-fields-containing-related-entries).
+
+**Example 2. Many options. Entries are loaded using AJAX.**
+
+If your related entry can have hundreds, thousands or millions of entries, it's not practical to load the options using an Eloquent query onpage, because the Create/Update page would be very slow to load. In this case, you should instruct ```select2``` to fetch the entries using AJAX calls. To do that, in your ```relationship``` field definition you should add ```'ajax' => true```:
+
+```php
+[ // relationship
+ 'type' => "relationship",
+ 'name' => 'category', // the method on your model that defines the relationship
+ 'ajax' => true,
+
+ // OPTIONALS:
+ // 'label' => "Category",
+ // 'attribute' => "name", // foreign key attribute that is shown to user (identifiable attribute)
+ // 'entity' => 'category', // the method that defines the relationship in your Model
+ // 'model' => "App\Models\Category", // foreign key Eloquent model
+ // 'placeholder' => "Select a category", // placeholder for the select2 input
+
+ // AJAX OPTIONALS:
+ // 'delay' => 500, // the minimum amount of time between ajax requests when searching in the field
+ // 'data_source' => url("http://github.com/fetch/category"), // url to controller search function (with /{id} should return model)
+ // 'minimum_input_length' => 2, // minimum characters to type before querying results
+ // 'dependencies' => ['category'], // when a dependency changes, this select2 is reset to null
+ // 'include_all_form_fields' => false, // optional - only send the current field through AJAX (for a smaller payload if you're not using multiple chained select2s)
+ ],
+```
+
+Then, you need to create the route and method that allows ```select2``` to search and fetch the results of that search. Fortunately, the ```FetchOperation``` allows you to easily do just that. Inside the CrudController where you've defined the ```relationship``` field, use the ```FetchOperation``` trait, and define a new method that will respond to AJAX queries:
+
+```php
+ use \Backpack\CRUD\app\Http\Controllers\Operations\FetchOperation;
+
+ public function fetchCategory()
+ {
+ return $this->fetch(\App\Models\Category::class);
+ }
+```
+
+This will set up a ```/fetch/category``` route, which points to ```fetchCategory()```, which returns the search results in a format ```select2``` likes. For more on how this operation works, and how you can customize it, check out the [FetchOperation docs](/docs/{{version}}/crud-operation-fetch).
+
+**Additional operation. InlineCreate - lets the user create a related entry in a modal.**
+
+Searching with AJAX provides a great UX. But what if the user doesn't find what they're looking for? In that case, it would be useful to add a related entry on-the-fly, without leaving the form. If you are using the Fetch operation to get the entries, you're already halfway there. In addition, you only need two additional steps:
+
+```php
+// Inside ArticleCrudController
+// for 1-n relationships (ex: category)
+[ // relationship
+ 'type' => "relationship",
+ 'name' => 'category', // the method on your model that defines the relationship
+ 'ajax' => true,
+ 'inline_create' => true,
+],
+// Inside ArticleCrudController
+// for n-n relationships (ex: tags)
+[ // relationship
+ 'type' => "relationship",
+ 'name' => 'tags', // the method on your model that defines the relationship
+ 'ajax' => true,
+ 'inline_create' => [ 'entity' => 'tag' ] // you need to specify the entity in singular
+],
+```
+
+Now, on the CrudController of that secondary entity the user will be able to create on-the-fly (ex: ```CategoryCrudController``` or ```TagCrudController```, you'll need to enable the InlineCreate operation:
+```php
+class CategoryCrudController extends CrudController
+{
+ use \Backpack\CRUD\app\Http\Controllers\Operations\InlineCreateOperation;
+
+ // ...
+}
+```
+
+This ```InlineCreateOperation``` will allow us to show _the same fields that are inside the Create operation_, inside a new operation _InlineCreate_, that is available in a modal. For more information, check out the [InlineCreate Operation docs](/docs/{{version}}/crud-operation-inline-create).
+
+Remember, ```FetchOperation``` is still needed on the main crud (ex: ```ArticleCrudController```) so that the entries are fetched by ```select2``` using AJAX.
+
+
+
+
+### repeatable
+
+Shows a group of inputs to the user, and allows the user to add or remove groups of that kind:
+
+
+
+Clicking on the "New Item" button will add another group with the same fields (in the example, another Testimonial). The end result is a JSON with the values for those fields, nicely grouped.
+
+You can use most field types inside the field groups, add as many fields you need, and change their width using ```wrapper``` like you would do outside the repeatable field. But please note that:
+- **all fields defined inside a field group need to have their definition valid and complete**; you can't use shorthands, you shouldn't assume fields will guess attributes for you;
+- some field types do not make sense to be included inside a field group (for example, relationship fields might not make sense; they will work if the relationship is defined on the main model, but upon save the selected entries will NOT be saved as usual, they will be saved as JSON; you can intercept the saving if you want and do whatever you want);
+- a few fields _make sense_, but _cannot_ work inside a repeatable group (ex: upload, upload_multiple); [see the notes inside the PR](https://github.com/Laravel-Backpack/CRUD/pull/2266#issuecomment-559436214) for more details, and a complete list of the fields; the few fields that do not work inside repeatable have sensible alternatives;
+- you _can_ add validation to subfields, but naturally it'll be a little different; for a quick example of how to add validation to your repeatable fields, check out our Demo, particularly [`DummyRequest.php`](https://github.com/Laravel-Backpack/demo/blob/master/app/Http/Requests/DummyRequest.php#L31-L61);
+
+
+```php
+[ // repeatable
+ 'name' => 'testimonials',
+ 'label' => 'Testimonials',
+ 'type' => 'repeatable',
+ 'fields' => [
+ [
+ 'name' => 'name',
+ 'type' => 'text',
+ 'label' => 'Name',
+ 'wrapper' => ['class' => 'form-group col-md-4'],
+ ],
+ [
+ 'name' => 'position',
+ 'type' => 'text',
+ 'label' => 'Position',
+ 'wrapper' => ['class' => 'form-group col-md-4'],
+ ],
+ [
+ 'name' => 'company',
+ 'type' => 'text',
+ 'label' => 'Company',
+ 'wrapper' => ['class' => 'form-group col-md-4'],
+ ],
+ [
+ 'name' => 'quote',
+ 'type' => 'ckeditor',
+ 'label' => 'Quote',
+ ],
+ ],
+
+ // optional
+ 'new_item_label' => 'Add Group', // customize the text of the button
+ 'init_rows' => 2, // number of empty rows to be initialized, by default 1
+ 'min_rows' => 2, // minimum rows allowed, when reached the "delete" buttons will be hidden
+ 'max_rows' => 2, // maximum rows allowed, when reached the "new item" button will be hidden
+
+],
+```
+
+
+
+
+
+### select (1-n relationship)
+
+Show a Select with the names of the connected entity and let the user select one of them.
+Your relationships should already be defined on your models as hasOne() or belongsTo().
+
+```php
+[ // Select
+ 'label' => "Category",
+ 'type' => 'select',
+ 'name' => 'category_id', // the db column for the foreign key
+
+ // optional
+ // 'entity' should point to the method that defines the relationship in your Model
+ // defining entity will make Backpack guess 'model' and 'attribute'
+ 'entity' => 'category',
+
+ // optional - manually specify the related model and attribute
+ 'model' => "App\Models\Category", // related model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+
+ // optional - force the related options to be a custom query, instead of all();
+ 'options' => (function ($query) {
+ return $query->orderBy('name', 'ASC')->where('depth', 1)->get();
+ }), // you can use this to filter the results show in the select
+],
+```
+
+For more information about the optional attributes that fields use when they interact with related entries - [look here](#optional-attributes-for-fields-containing-related-entries).
+
+Input preview:
+
+
+
+
+
+
+
+
+### select_grouped
+
+Display a select where the options are grouped by a second entity (like Categories).
+
+```php
+[ // select_grouped
+ 'label' => 'Articles grouped by categories',
+ 'type' => 'select_grouped', //https://github.com/Laravel-Backpack/CRUD/issues/502
+ 'name' => 'article_id',
+ 'entity' => 'article',
+ 'attribute' => 'title',
+ 'group_by' => 'category', // the relationship to entity you want to use for grouping
+ 'group_by_attribute' => 'name', // the attribute on related model, that you want shown
+ 'group_by_relationship_back' => 'articles', // relationship from related model back to this model
+],
+```
+
+For more information about the optional attributes that fields use when they interact with related entries - [look here](#optional-attributes-for-fields-containing-related-entries).
+
+Input preview:
+
+
+
+
+
+
+### select2 (1-n relationship)
+
+Works just like the SELECT field, but prettier. Shows a Select2 with the names of the connected entity and let the user select one of them.
+Your relationships should already be defined on your models as hasOne() or belongsTo().
+
+```php
+[ // Select2
+ 'label' => "Category",
+ 'type' => 'select2',
+ 'name' => 'category_id', // the db column for the foreign key
+
+ // optional
+ 'entity' => 'category', // the method that defines the relationship in your Model
+ 'model' => "App\Models\Category", // foreign key model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'default' => 2, // set the default value of the select2
+
+ // also optional
+ 'options' => (function ($query) {
+ return $query->orderBy('name', 'ASC')->where('depth', 1)->get();
+ }), // force the related options to be a custom query, instead of all(); you can use this to filter the results show in the select
+],
+```
+
+For more information about the optional attributes that fields use when they interact with related entries - [look here](#optional-attributes-for-fields-containing-related-entries).
+
+Input preview:
+
+
+
+
+
+
+### select_multiple (n-n relationship)
+
+Show a Select with the names of the connected entity and let the user select any number of them.
+Your relationship should already be defined on your models as belongsToMany().
+
+```php
+[ // SelectMultiple = n-n relationship (with pivot table)
+ 'label' => "Tags",
+ 'type' => 'select_multiple',
+ 'name' => 'tags', // the method that defines the relationship in your Model
+
+ // optional
+ 'entity' => 'tags', // the method that defines the relationship in your Model
+ 'model' => "App\Models\Tag", // foreign key model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
+
+ // also optional
+ 'options' => (function ($query) {
+ return $query->orderBy('name', 'ASC')->where('depth', 1)->get();
+ }), // force the related options to be a custom query, instead of all(); you can use this to filter the results show in the select
+],
+```
+
+For more information about the optional attributes that fields use when they interact with related entries - [look here](#optional-attributes-for-fields-containing-related-entries).
+
+Input preview:
+
+
+
+
+
+
+
+### select2_multiple (n-n relationship)
+
+[Works just like the SELECT field, but prettier]
+
+Shows a Select2 with the names of the connected entity and let the user select any number of them.
+Your relationship should already be defined on your models as belongsToMany().
+
+```php
+[ // Select2Multiple = n-n relationship (with pivot table)
+ 'label' => "Tags",
+ 'type' => 'select2_multiple',
+ 'name' => 'tags', // the method that defines the relationship in your Model
+
+ // optional
+ 'entity' => 'tags', // the method that defines the relationship in your Model
+ 'model' => "App\Models\Tag", // foreign key model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
+ // 'select_all' => true, // show Select All and Clear buttons?
+
+ // optional
+ 'options' => (function ($query) {
+ return $query->orderBy('name', 'ASC')->where('depth', 1)->get();
+ }), // force the related options to be a custom query, instead of all(); you can use this to filter the results show in the select
+],
+```
+
+For more information about the optional attributes that fields use when they interact with related entries - [look here](#optional-attributes-for-fields-containing-related-entries).
+
+Input preview:
+
+
+
+
+
+
+### select2_nested
+
+Display a select2 with the values ordered hierarchically and indented, for an entity where you use Reorder. Please mind that the connected model needs:
+- a ```children()``` relationship pointing to itself;
+- the usual ```lft```, ```rgt```, ```depth``` attributes;
+
+```php
+[ // select2_nested
+ 'name' => 'category_id',
+ 'label' => "Category",
+ 'type' => 'select2_nested',
+ 'entity' => 'category', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+
+ // optional
+ 'model' => "App\Models\Category", // force foreign key model
+],
+```
+
+For more information about the optional attributes that fields use when they interact with related entries - [look here](#optional-attributes-for-fields-containing-related-entries).
+
+Input preview:
+
+
+
+
+
+
+### select2_grouped
+
+Display a select2 where the options are grouped by a second entity (like Categories).
+
+```php
+[ // select2_grouped
+ 'label' => 'Articles grouped by categories',
+ 'type' => 'select2_grouped', //https://github.com/Laravel-Backpack/CRUD/issues/502
+ 'name' => 'article_id',
+ 'entity' => 'article', // the method that defines the relationship in your Model
+ 'attribute' => 'title',
+ 'group_by' => 'category', // the relationship to entity you want to use for grouping
+ 'group_by_attribute' => 'name', // the attribute on related model, that you want shown
+ 'group_by_relationship_back' => 'articles', // relationship from related model back to this model
+],
+```
+
+For more information about the optional attributes that fields use when they interact with related entries - [look here](#optional-attributes-for-fields-containing-related-entries).
+
+Input preview:
+
+
+
+
+
+
+
+### select_and_order
+
+Display items on two columns and let the user drag&drop between them to choose which items are selected and which are not, and reorder the selected items with drag&drop.
+
+Its definition is exactly as ```select_from_array```, but the value will be stored as JSON in the database: ```["3","5","7","6"]```, so it needs the attribute to be cast to array on the Model:
+
+```php
+protected $casts = [
+ 'featured' => 'array'
+];
+```
+
+Definition:
+
+```php
+[ // select_and_order
+ 'name' => 'featured',
+ 'label' => "Featured",
+ 'type' => 'select_and_order',
+ 'options' => [
+ 1 => "Option 1",
+ 2 => "Option 2"
+ ]
+],
+```
+
+Also possible:
+
+```php
+[ // select_and_order
+ 'name' => 'featured',
+ 'label' => 'Featured',
+ 'type' => 'select_and_order',
+ 'options' => Product::get()->pluck('title','id')->toArray(),
+],
+```
+
+Input preview:
+
+
+
+
+
+
+
+### select_from_array
+
+Display a select with the values you want:
+
+```php
+[ // select_from_array
+ 'name' => 'template',
+ 'label' => "Template",
+ 'type' => 'select_from_array',
+ 'options' => ['one' => 'One', 'two' => 'Two'],
+ 'allows_null' => false,
+ 'default' => 'one',
+ // 'allows_multiple' => true, // OPTIONAL; needs you to cast this to array in your model;
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### select2_from_array
+
+Display a select2 with the values you want:
+
+```php
+[ // select2_from_array
+ 'name' => 'template',
+ 'label' => "Template",
+ 'type' => 'select2_from_array',
+ 'options' => ['one' => 'One', 'two' => 'Two'],
+ 'allows_null' => false,
+ 'default' => 'one',
+ // 'allows_multiple' => true, // OPTIONAL; needs you to cast this to array in your model;
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### select2_from_ajax
+
+Display a select2 that takes its values from an AJAX call.
+
+```php
+[ // 1-n relationship
+ 'label' => "End", // Table column heading
+ 'type' => "select2_from_ajax",
+ 'name' => 'category_id', // the column that contains the ID of that connected entity
+ 'entity' => 'category', // the method that defines the relationship in your Model
+ 'attribute' => "name", // foreign key attribute that is shown to user
+ 'data_source' => url("http://github.com/api/category"), // url to controller search function (with /{id} should return model)
+
+ // OPTIONAL
+ // 'delay' => 500, // the minimum amount of time between ajax requests when searching in the field
+ // 'placeholder' => "Select a category", // placeholder for the select
+ // 'minimum_input_length' => 2, // minimum characters to type before querying results
+ // 'model' => "App\Models\Category", // foreign key model
+ // 'dependencies' => ['category'], // when a dependency changes, this select2 is reset to null
+ // 'method' => 'GET', // optional - HTTP method to use for the AJAX call (GET, POST)
+ // 'include_all_form_fields' => false, // optional - only send the current field through AJAX (for a smaller payload if you're not using multiple chained select2s)
+],
+```
+
+For more information about the optional attributes that fields use when they interact with related entries - [look here](#optional-attributes-for-fields-containing-related-entries).
+
+Of course, you also need to create make the data_source above respond to AJAX calls. You can use the [FetchOperation](https://backpackforlaravel.com/docs/4.1/crud-operation-fetch) to quickly do that in your current CrudController, or you can set up your custom API by creating a custom Route and Controller. Here's an example:
+
+```php
+Route::get('/api/category', 'Api\CategoryController@index');
+```
+
+```php
+input('q');
+
+ if ($search_term)
+ {
+ $results = Category::where('name', 'LIKE', '%'.$search_term.'%')->paginate(10);
+ }
+ else
+ {
+ $results = Category::paginate(10);
+ }
+
+ return $results;
+ }
+}
+```
+
+**Note:** If you want to also make this field work inside `repeatable` too, your API endpoint will also need to respond to the `keys` parameter, with the actual items that have those keys. For example:
+
+```php
+ if ($request->has('keys')) {
+ return Category::findMany($request->input('keys'));
+ }
+```
+
+Input preview:
+
+
+
+
+
+
+### select2_from_ajax_multiple
+
+Display a select2 that takes its values from an AJAX call. Same as [select2_from_ajax](#section-select2_from_ajax) above, but allows for multiple items to be selected. The only difference in the field definition is the "pivot" attribute.
+
+```php
+[ // n-n relationship
+ 'label' => "Cities", // Table column heading
+ 'type' => "select2_from_ajax_multiple",
+ 'name' => 'cities', // a unique identifier (usually the method that defines the relationship in your Model)
+ 'entity' => 'cities', // the method that defines the relationship in your Model
+ 'attribute' => "name", // foreign key attribute that is shown to user
+ 'data_source' => url("http://github.com/api/city"), // url to controller search function (with /{id} should return model)
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
+
+ // OPTIONAL
+ 'delay' => 500, // the minimum amount of time between ajax requests when searching in the field
+ 'model' => "App\Models\City", // foreign key model
+ 'placeholder' => "Select a city", // placeholder for the select
+ 'minimum_input_length' => 2, // minimum characters to type before querying results
+ // 'include_all_form_fields' => false, // optional - only send the current field through AJAX (for a smaller payload if you're not using multiple chained select2s)
+],
+```
+
+For more information about the optional attributes that fields use when they interact with related entries - [look here](#optional-attributes-for-fields-containing-related-entries).
+
+Of course, you also need to create a controller and routes for the data_source above. Here's an example:
+
+```php
+Route::get('/api/city', 'Api\CityController@index');
+Route::get('/api/city/{id}', 'Api\CityController@show');
+```
+
+```php
+input('q');
+ $page = $request->input('page');
+
+ if ($search_term)
+ {
+ $results = City::where('name', 'LIKE', '%'.$search_term.'%')->paginate(10);
+ }
+ else
+ {
+ $results = City::paginate(10);
+ }
+
+ return $results;
+ }
+
+ public function show($id)
+ {
+ return City::find($id);
+ }
+}
+```
+
+Input preview:
+
+
+
+**Note:** If you want to also make this field work inside `repeatable` too, your API endpoint will also need to respond to the `keys` parameter, with the actual items that have those keys. For example:
+
+```php
+ if ($request->has('keys')) {
+ return City::findMany($request->input('keys'));
+ }
+```
+
+
+
+
+
+### simplemde
+
+Show a [SimpleMDE markdown editor](https://simplemde.com/) to the user.
+
+> **NOTE:** SimpleMDE works, but it has not received any updates in 4 years. We recommend you use EasyMDE instead, a fork of SimpleMDE that seems to be well looked after. Check out the [```easymde``` field type](#easymde) for Backpack - it works exactly the same as this one.
+
+```php
+[ // SimpleMDE
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'simplemde',
+ // optional
+ // 'simplemdeAttributes' => [
+ // 'promptURLs' => true,
+ // 'status' => false,
+ // 'spellChecker' => false,
+ // 'forceSync' => true,
+ // ],
+ // 'simplemdeAttributesRaw' => $some_json
+],
+```
+
+> NOTE: The contents displayed in this editor are NOT stripped, sanitized or escaped by default. Whenever you store Markdown or HTML inside your database, it's HIGHLY recommended that you sanitize the input or output. Laravel makes it super-easy to do that on the model using [accessors](https://laravel.com/docs/8.x/eloquent-mutators#accessors-and-mutators). If you do NOT trust the admins who have access to this field (or end-users can also store information to this db column), please make sure this attribute is always escaped, before it's shown. You can do that by running the value through `strip_tags()` in an accessor on the model (here's [an example](https://github.com/Laravel-Backpack/demo/commit/509c0bf0d8b9ee6a52c50f0d2caed65f1f986385)) or better yet, using an [HTML Purifier package](https://github.com/mewebstudio/Purifier) (here's [an example](https://github.com/Laravel-Backpack/demo/commit/7342cffb418bb568b9e4ee279859685ddc0456c1)).
+
+Input preview:
+
+
+
+
+
+
+### summernote
+
+Show a [Summernote wysiwyg editor](http://summernote.org/) to the user.
+
+```php
+[ // Summernote
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'summernote',
+ 'options' => [],
+],
+
+// the summernote field works with the default configuration options but allow developer to configure to his needs
+// optional configuration check https://summernote.org/deep-dive/ for a list of available configs
+[
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'summernote',
+ 'options' => [
+ 'toolbar' => [
+ ['font', ['bold', 'underline', 'italic']]
+ ]
+ ],
+],
+
+```
+
+> NOTE: Summernote does NOT sanitize the input. If you do not trust the users of this field, you should sanitize the input or output using something like HTML Purifier. Personally we like to use install [mewebstudio/Purifier](https://github.com/mewebstudio/Purifier) and add an [accessor or mutator](https://laravel.com/docs/8.x/eloquent-mutators#accessors-and-mutators) on the Model, so that wherever the model is created from (admin panel or app), the output will always be clean. [Example here](https://github.com/Laravel-Backpack/demo/commit/7342cffb418bb568b9e4ee279859685ddc0456c1).
+
+Input preview:
+
+
+
+
+
+
+### table
+
+Show a table with multiple inputs per row and store the values as JSON array of objects in the database. The user can add more rows and reorder the rows as they please.
+
+```php
+[ // Table
+ 'name' => 'options',
+ 'label' => 'Options',
+ 'type' => 'table',
+ 'entity_singular' => 'option', // used on the "Add X" button
+ 'columns' => [
+ 'name' => 'Name',
+ 'desc' => 'Description',
+ 'price' => 'Price'
+ ],
+ 'max' => 5, // maximum rows allowed in the table
+ 'min' => 0, // minimum rows allowed in the table
+],
+```
+
+>It's highly recommended that you use [attribute casting](https://mattstauffer.co/blog/laravel-5.0-eloquent-attribute-casting) on your model when working with JSON arrays stored in database columns, and cast this attribute to either ```object``` or ```array``` in your Model.
+
+Input preview:
+
+
+
+
+
+
+### text
+
+The basic field type, all it needs is the two mandatory parameters: name and label.
+
+```php
+[ // Text
+ 'name' => 'title',
+ 'label' => "Title",
+ 'type' => 'text',
+
+ // optional
+ //'prefix' => '',
+ //'suffix' => '',
+ //'default' => 'some value', // default value
+ //'hint' => 'Some hint text', // helpful text, show up after input
+ //'attributes' => [
+ //'placeholder' => 'Some text when empty',
+ //'class' => 'form-control some-class',
+ //'readonly' => 'readonly',
+ //'disabled' => 'disabled',
+ //], // extra HTML attributes and values your input might need
+ //'wrapper' => [
+ //'class' => 'form-group col-md-12'
+ //], // extra HTML attributes for the field wrapper - mostly for resizing fields
+
+],
+```
+
+You can use the optional 'prefix' and 'suffix' attributes to display something before and after the input, like icons, path prefix, etc:
+
+Input preview:
+
+
+
+
+
+
+### textarea
+
+Show a textarea to the user.
+
+```php
+[ // Textarea
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'textarea'
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### time
+
+```php
+[ // Time
+ 'name' => 'start',
+ 'label' => 'Start time',
+ 'type' => 'time'
+],
+```
+
+
+
+
+### tinymce
+
+Show a wysiwyg (TinyMCE) to the user.
+
+```php
+[ // TinyMCE
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'tinymce',
+ // optional overwrite of the configuration array
+ // 'options' => [ 'selector' => 'textarea.tinymce', 'skin' => 'dick-light', 'plugins' => 'image,link,media,anchor' ],
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### upload
+
+**Step 1.** Show a file input to the user:
+```php
+[ // Upload
+ 'name' => 'image',
+ 'label' => 'Image',
+ 'type' => 'upload',
+ 'upload' => true,
+ 'disk' => 'uploads', // if you store files in the /public folder, please omit this; if you store them in /storage or S3, please specify it;
+ // optional:
+ 'temporary' => 10 // if using a service, such as S3, that requires you to make temporary URLs this will make a URL that is valid for the number of minutes specified
+],
+```
+
+**Step 2.** In order to save/update/delete the file from disk&db, we need to create [a mutator](https://laravel.com/docs/5.3/eloquent-mutators#defining-a-mutator) on your model:
+```php
+public function setImageAttribute($value)
+ {
+ $attribute_name = "image";
+ $disk = "public";
+ $destination_path = "folder_1/subfolder_1";
+
+ $this->uploadFileToDisk($value, $attribute_name, $disk, $destination_path);
+
+ // return $this->attributes[{$attribute_name}]; // uncomment if this is a translatable field
+ }
+```
+
+**How it works:**
+
+The field sends the file, through a Request, to the Controller. The Controller then tries to create/update the Model. That's when the mutator on your model will run. That also means we can do any [file validation](https://laravel.com/docs/5.3/validation#rule-file) (```file```, ```image```, ```mimetypes```, ```mimes```) in the Request, before the file is stored on the disk.
+
+>NOTE: If this field is mandatory (required in validation) please use the [sometimes laravel validation rule](https://laravel.com/docs/5.8/validation#conditionally-adding-rules) together with **required** in your validation. (sometimes|required|file etc... )
+
+[The ```uploadFileToDisk()``` method](https://github.com/Laravel-Backpack/CRUD/blob/master/src/app/Models/Traits/HasUploadFields.php#L31-L59) will take care of everything for most use cases:
+
+```php
+/**
+ * Handle file upload and DB storage for a file:
+ * - on CREATE
+ * - stores the file at the destination path
+ * - generates a name
+ * - stores the full path in the DB;
+ * - on UPDATE
+ * - if the value is null, deletes the file and sets null in the DB
+ * - if the value is different, stores the different file and updates DB value
+ * /
+public function uploadFileToDisk($value, $attribute_name, $disk, $destination_path) {}
+```
+
+If you wish to have a different functionality, you can delete the method call from your mutator and do your own thing.
+
+>**The uploaded files are not deleted for you.** When you delete an entry (whether through CRUD or the application), the uploaded files will not be deleted.
+
+If you're NOT using soft deletes on that Model and want the file to be deleted at the same time the entry is, just specify that in your Model's ```deleting``` event:
+```php
+ public static function boot()
+ {
+ parent::boot();
+ static::deleting(function($obj) {
+ \Storage::disk('public_folder')->delete($obj->image);
+ });
+ }
+```
+
+Input preview:
+
+
+
+
+
+
+### upload_multiple
+
+Shows a multiple file input to the user and stores the values as a JSON array in the database.
+
+**Step 0.** Make sure the db column can hold the amount of text this field will have. For example, for MySQL, VARCHAR(255) might not be enough all the time (for 3+ files), so it's better to go with TEXT. Make sure you're using a big column type in your migration or db.
+
+**Step 1.** Show a multiple file input to the user:
+```php
+[ // Upload
+ 'name' => 'photos',
+ 'label' => 'Photos',
+ 'type' => 'upload_multiple',
+ 'upload' => true,
+ 'disk' => 'uploads', // if you store files in the /public folder, please omit this; if you store them in /storage or S3, please specify it;
+ // optional:
+ 'temporary' => 10 // if using a service, such as S3, that requires you to make temporary URLs this will make a URL that is valid for the number of minutes specified
+],
+```
+
+**Step 2.** In order to save/update/delete the files from disk&db, we need to create [a mutator](https://laravel.com/docs/5.3/eloquent-mutators#defining-a-mutator) on your model:
+```php
+public function setPhotosAttribute($value)
+ {
+ $attribute_name = "photos";
+ $disk = "public";
+ $destination_path = "folder_1/subfolder_1";
+
+ $this->uploadMultipleFilesToDisk($value, $attribute_name, $disk, $destination_path);
+ }
+```
+
+**Step 3.** Since the filenames are stored in the database as a JSON array, we're going to use [attribute casting](https://laravel.com/docs/5.3/eloquent-mutators#attribute-casting) on your model, so every time we get the filenames array from the database it's converted from a JSON array to a PHP array:
+```php
+ protected $casts = [
+ 'photos' => 'array'
+ ];
+```
+
+**How it works:**
+
+The field sends the files, through a Request, to the Controller. The Controller then tries to create/update the Model. That's when the mutator on your model will run. That also means we can do any [file validation](https://laravel.com/docs/5.3/validation#rule-file) (```file```, ```image```, ```mimetypes```, ```mimes```) in the Request, before the files are stored on the disk.
+
+[The ```uploadMultipleFilesToDisk()``` method](https://github.com/Laravel-Backpack/CRUD/blob/master/src/app/Models/Traits/HasUploadFields.php#L76-L113) will take care of everything for most use cases:
+
+```
+/**
+ * Handle multiple file upload and DB storage:
+ * - if files are sent
+ * - stores the files at the destination path
+ * - generates random names
+ * - stores the full path in the DB, as JSON array;
+ * - if a hidden input is sent to clear one or more files
+ * - deletes the file
+ * - removes that file from the DB.
+ * /
+public function uploadMultipleFilesToDisk($value, $attribute_name, $disk, $destination_path) {}
+```
+
+If you wish to have a different functionality, you can delete the method call from your mutator and do your own thing.
+
+>**The uploaded files are not deleted for you.** When you delete an entry (whether through CRUD or the application), the uploaded files will not be deleted.
+
+If you're NOT using soft deletes on that Model and want the files to be deleted at the same time the entry is, just specify that in your Model's ```deleting``` event:
+```php
+ public static function boot()
+ {
+ parent::boot();
+ static::deleting(function($obj) {
+ if (count((array)$obj->photos)) {
+ foreach ($obj->photos as $file_path) {
+ \Storage::disk('public_folder')->delete($file_path);
+ }
+ }
+ });
+ }
+```
+
+You might notice the field is using a ```clear_photos``` variable. Don't worry, you don't need it in your db table. That's just used to delete photos upon "update". If you use ```$fillable``` on your model, just don't include it. If you use ```$guarded``` on your model, place it in guarded.
+
+Input preview:
+
+
+
+
+### url
+
+```php
+[ // URL
+ 'name' => 'link',
+ 'label' => 'Link to video file',
+ 'type' => 'url'
+],
+```
+
+
+
+
+### video
+
+Allow the user to paste a YouTube/Vimeo link. That will get the video information with JavaScript and store it as a JSON in the database.
+
+Field definition:
+```php
+[ // URL
+ 'name' => 'video',
+ 'label' => 'Link to video file on YouTube or Vimeo',
+ 'type' => 'video',
+ 'youtube_api_key' => 'AIzaSycLRoVwovRmbIf_BH3X12IcTCudAErRlCE',
+],
+```
+
+An entry stored in the database will look like this:
+```
+$video = {
+ id: 234324,
+ title: 'my video title',
+ image: 'https://provider.com/image.jpg',
+ url: 'http://provider.com/video',
+ provider: 'youtube'
+}
+```
+
+So you should use [attribute casting](https://mattstauffer.co/blog/laravel-5.0-eloquent-attribute-casting) in your model, to cast the video as ```array``` or ```object```.
+
+Vimeo does not require an API key in order to query their DB, but YouTube does, even though their free quota is generous. You can get a free YouTube API Key inside [Google Developers Console](https://console.developers.google.com/) ([video tutorial here](https://www.youtube.com/watch?v=pP4zvduVAqo)). Please DO NOT use our API Key - create your own. The key above is there just for your convenience, to easily try out the field. As soon as you decide to use this field type, create an API Key and use _your_ API Key. Our key hits its ceiling every month, so if you use our key most of the time it won't work.
+
+
+
+
+
+### view
+
+Load a custom view in the form.
+
+```php
+[ // view
+ 'name' => 'custom-ajax-button',
+ 'type' => 'view',
+ 'view' => 'partials/custom-ajax-button'
+],
+```
+
+**Note:** the same functionality can be achieved using a [custom field type](/docs/{{version}}/crud-fields#creating-a-custom-field-type), or using the [custom_html field type](/docs/{{version}}/crud-fields#custom-html) (if the content is really simple).
+
+
+
+
+### week
+
+```php
+[ // Week
+ 'name' => 'first_week',
+ 'label' => 'First week',
+ 'type' => 'week'
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### wysiwyg
+
+Show a wysiwyg (CKEditor) to the user.
+
+```php
+[ // WYSIWYG Editor
+ 'name' => 'description',
+ 'label' => 'Description',
+ 'type' => 'wysiwyg'
+],
+```
+
+
+## Overwriting Default Field Types
+
+The actual field types are stored in the Backpack/CRUD package in ```/resources/views/fields```. If you need to change an existing field, you don't need to modify the package, you just need to add a blade file in your application in ```/resources/views/vendor/backpack/crud/fields```, with the same name. The package checks there first, and only if there's no file there, will it load it from the package.
+
+To quickly publish a field blade file in your project, you can use ```php artisan backpack:publish crud/fields/field_name```. For example, to publish the number field type, you'd type ```php artisan backpack:publish crud/fields/number```
+
+>Please keep in mind that if you're using _your_ file for a field type, you're not using the _package file_. So any updates we push to that file, you're not getting them. In most cases, it's recommended you create a custom field type for your use case, instead of overwriting default field types.
+
+
+## Creating a Custom Field Type
+
+If you need to extend the CRUD with a new field type, you create a new file in your application in ```/resources/views/vendor/backpack/crud/fields```. Use a name that's different from all default field types. That's it, you'll now be able to use it just like a default field type.
+
+Your field definition will be something like:
+
+```php
+[ // Custom Field
+ 'name' => 'address',
+ 'label' => 'Home address',
+ 'type' => 'address'
+ /// 'view_namespace' => 'yourpackage' // use a custom namespace of your package to load views within a custom view folder.
+],
+```
+
+And your blade file something like:
+```php
+
+@include('crud::fields.inc.wrapper_start')
+
+
+
+ {{-- HINT --}}
+ @if (isset($field['hint']))
+
{!! $field['hint'] !!}
+ @endif
+@include('crud::fields.inc.wrapper_end')
+
+
+@if ($crud->fieldTypeNotLoaded($field))
+ @php
+ $crud->markFieldTypeAsLoaded($field);
+ @endphp
+
+ {{-- FIELD EXTRA CSS --}}
+ {{-- push things in the after_styles section --}}
+ @push('crud_fields_styles')
+
+ @endpush
+
+
+ {{-- FIELD EXTRA JS --}}
+ {{-- push things in the after_scripts section --}}
+ @push('crud_fields_scripts')
+
+ @endpush
+@endif
+```
+
+Inside your custom field type, you can use these variables:
+- ```$crud``` - all the CRUD Panel settings, options and variables;
+- ```$entry``` - in the Update operation, the current entry being modified (the actual values);
+- ```$field``` - all attributes that have been passed for this field;
+
+If your field type uses JavaScript, we recommend you:
+- put a ```data-init-function="bpFieldInitMyCustomField"``` attribute on your input;
+- place your logic inside the scripts section mentioned above, inside ```function bpFieldInitMyCustomField(element) {}```; of course, you choose the name of the function but it has to match whatever you specified as data attribute on the input, and it has to be pretty unique; inside this method, you'll find that ```element``` is jQuery-wrapped object of the element where you specified ```data-init-function```; this should be enough for you to not have to use IDs, or any other tricks, to determine other elements inside the DOM - determine them in relation to the main element; if you want, you can choose to put the ```data-init-function``` attribute on a different element, like the wrapping div;
+
+
+
+## FAQs
+
+
+### What field should I use for a relationship?
+
+With so many field types, it can be a little overwhelming for a first-timer to quickly grasp what field type to use for your Eloquent relationship. Here's a list of what most people use, most of the times:
+
+#### hasOne (1-1 relationship)
+
+- example:
+ - `User -> Phone`
+ - a User has one Phone; a Phone can only belong to one User
+ - the foreign key is stored on the Phone (`user_id` on `phones` table)
+- how to use:
+ - [the `hasOne` relationship should be properly defined](https://laravel.com/docs/eloquent-relationships#one-to-one) in the User model;
+ - you can easily add fields for each individual attribute on the related entry; you just need to specify in the field name that the value should not be stored on the _main model_, but on _a related model_; you can do that using dot notation (`relationship_name.column_name`); note that the prefix (before the dot) is the **Relation** name, not the table name;
+ - all fields types should work fine - depending on your needs you could choose to add a [`text`](#text) field, [`number`](#number) field, [`textarea`](#textarea) field, [`select`](#select) field etc.;
+
+```php
+// inside UserCrudController::setupCreateOperation()
+CRUD::field('phone.number')->type('number');
+CRUD::field('phone.prefix')->type('text');
+CRUD::field('phone.type')->type('select_from_array')->options(['mobile' => 'Mobile Phone', 'landline' => 'Landline', 'fax' => 'Fax']);
+```
+
+#### belongsTo (n-1 relationship)
+
+- example:
+ - `Phone -> User`
+ - a Phone belongs to one User; a Phone can only belong to one User
+ - the foreign key is stored on the Phone (`user_id` on `phones` table)
+- how to use:
+ - [the `belongsTo` relationship should be properly defined](https://laravel.com/docs/eloquent-relationships#one-to-many-inverse) in the Phone model;
+ - you can easily add a dropdown to let the admin pick which User the Phone belongs; you can use any of the dropdown fields, but for convenience we've made a list here, and broken them down depending on aproximately how many entries the dropdown will have:
+ - for 0-10 dropdown items - we recommend you use the [`select`](#select) field;
+ - for 0-500 dropdown items - we recommend you use the [`select2`](#select2) or [`relationship`](#relationship) field;
+ - for 500-1.000.000+ dropdown items - we recommend you load the dropdown items using AJAX, by using the [`relationship`](#relationship) field and Fetch operation or by using the [`select2_from_ajax`](#select2-from-ajax) field;
+
+```php
+// inside PhoneCrudController::setupCreateOperation()
+CRUD::field('user'); // notice the name is the relationship name and backpack will auto-infer the field type as [`relationship`](#relationship)
+CRUD::field('user_id')->type('select')->model('App\Models\User')->attribute('name')->entity('user'); // notice the name is the foreign key attribute
+CRUD::field('user_id')->type('select2')->model('App\Models\User')->attribute('name')->entity('user'); // notice the name is the foreign key attribute
+```
+
+- notes:
+ - if you choose to use the [`relationship`](#relationship) field, you can also use [the InlineCreate operation](/docs/{{version}}/crud-operation-inline-create), which will add a [+ Add Item] button next to the dropdown, to let the admin create a User in a modal, without leaving the current Create Phone form;
+
+#### hasMany (1-n relationship)
+
+- example:
+ - `Post -> Comment`
+ - a Post has many Comments; a Comment can only belong to one Post
+ - the foreign key is stored on the Comment (`post_id` on `comments` table)
+- how to use:
+ - [the `hasMany` relationship should be properly defined](https://laravel.com/docs/eloquent-relationships#one-to-many) in the Post model;
+
+```php
+// inside PostCrudController::setupCreateOperation()
+CRUD::field('comments')->type('repeatable')->fields([['name' => 'comment_text']]); //note comment_text is one field in the comment table.
+```
+- you should use the [`repeatable`](#repeatable) field on the Post create/update form, to add Comments to your Posts, but you'll also need to modify your `store()` and `update()` methods to take that into account, and transform the JSON received from the [`repeatable`](#repeatable) field into actual entries in the database (and back); check out [this example here](https://gist.github.com/pxpm/d584a109037d3efc7519872ac2096334) for a full example on how to do it.
+
+- notes:
+ - you _cannot_ use [the InlineCreate operation](/docs/{{version}}/crud-operation-inline-create) to have show a [+ Add Item] button next to the dropdown; that's because the Comment needs a `post_id` (not nullable); and until the Save button is clicked to submit the Create Post form, there is no `post_id`;
+
+#### belongsToMany (n-n relationship)
+
+- example:
+ - `User -> Role`
+ - a User has many Roles; a Role can also have many Users
+ - the foreign key is stored on a pivot table (usually the `user_roles` table has both `user_id` and `role_id`)
+- how to use:
+ - [the `belongsToMany` relationship should be properly defined](https://laravel.com/docs/eloquent-relationships#many-to-many) in both the User and Role models;
+ - you can add a dropdown on your User to pick the Roles that are connected to it; for that, use the [`relationship`](#relationship), [`select_multiple`](#select-multiple), [`select2_multiple`](#select2-multiple) or [`select2_from_ajax_multiple`](#select2-from-ajax-multiple) fields;
+
+```php
+// inside UserCrudController::setupCreateOperation()
+CRUD::field('roles'); //use the relation name here and backpack will assume that it is a [`relationship`](#relationship) field type
+CRUD::field('roles')->type('select_multiple');
+CRUD::field('roles')->type('select2_multiple');
+
+// inside RoleCrudController::setupCreateOperation()
+CRUD::field('users')->type('relationship'); //if you omit the type here, since `users` is a relation in Role model it would be auto-infered by backpack
+CRUD::field('users')->type('select_multiple');
+CRUD::field('users')->type('select2_multiple');
+```
+- notes:
+ - if you choose to use the [`relationship`](#relationship) field type, you can also use [the InlineCreate operation](/docs/{{version}}/crud-operation-inline-create), which will add a [+ Add Item] button next to the dropdown, to let the admin create a User/Role in a modal, without leaving the current Create User/Role form;
+
+##### EXTRA: Saving aditional data in the pivot table
+- To be able to save aditional data in the pivot table you should use [`repeatable`](#repeatable) field, but you'll also need to modify your `store()` and `update()` methods to take that into account, and transform the JSON received from the [`repeatable`](#repeatable) field into actual entries in the database (and back); check out [this example here](https://gist.github.com/pxpm/516f55c303235b799ac4e38f1167094e) for a full example on how to do it.
+
+#### morphOne (1-1 polymorphic relationship)
+
+- example:
+ - Post/User -> Video.
+ - The User model and the Post model have 1 Video each.
+ - [the `morphOne` relationship should be properly defined](https://laravel.com/docs/8.x/eloquent-relationships#one-to-one-polymorphic-relations) in both the Post/User and Video models;
+
+You should now use the [`repeatable`](#repeatable) field on the Post/User create/update form, to add a `Video` to your models, but you'll also need to modify your `store()` and `update()` methods to take that into account, and transform the JSON received from the [`repeatable`](#repeatable) field into actual entries in the database (and back); check out [this example here](https://gist.github.com/pxpm/c49c4ebb3c8d8af8a5bcce3122622a61) for a full example on how to do it.
+
+#### morphMany (1-n polymorphic relationship)
+
+- example:
+ - Video/Post -> Comment.
+ - The Video model and the Post model can have multiple Comment model but the comment belong to only one of them.
+ - [the `morphMany` relationship should be properly defined](https://laravel.com/docs/8.x/eloquent-relationships#one-to-many-polymorphic-relations) in both the Post/Video and Comment models;
+
+You should now use the [`repeatable`](#repeatable) field on the Post/Video create/update form, to add one or more `Comment` to your models, but you'll also need to modify your `store()` and `update()` methods to take that into account, and transform the JSON received from the [`repeatable`](#repeatable) field into actual entries in the database (and back); check out [this example here](https://gist.github.com/pxpm/d7709df4e1fac04c0c329a2ad0b35a5b) for a full example on how to do it.
+
+#### morphToMany (n-n polymorphic relationship)
+
+- example:
+ - Video/Post -> Tag.
+ - The Video model and the Post model can have multiple Tag model and each Tag model can belong to one or more of them.
+ - [the `morphToMany` relationship should be properly defined](https://laravel.com/docs/8.x/eloquent-relationships#many-to-many-polymorphic-relations) in both the Post/Video and Tag models;
+
+```php
+CRUD::field('tags'); //will assume to be a relationship field type.
+CRUD::field('tags')->type('select2_multiple')->model('\Backpack\NewsCRUD\app\Models\Tag')->attribute('name');
+```
+
+- notes:
+ - if you choose to use the [`relationship`](#relationship) field type, you can also use [the InlineCreate operation](/docs/{{version}}/crud-operation-inline-create), which will add a [+ Add Item] button next to the dropdown, to let the admin create a User/Role in a modal, without leaving the current Create User/Role form;
+
+##### EXTRA: Saving aditional data in the pivot table
+
+You should now use the [`repeatable`](#repeatable) field on the Post/Video create/update form, to add one or more `Tag` to your models, but you'll also need to modify your `store()` and `update()` methods to take that into account, and transform the JSON received from the [`repeatable`](#repeatable) field into actual entries in the database (and back); check out [this example here](https://gist.github.com/pxpm/2a45de69d755f673e3fc5fa60b2b0441) for a full example on how to do it.
+
+#### hasOneThrough (1-1-1 relationship) and hasManyThrough (1-1-n relationship)
+
+- Both are "read" relations and should not be edited from the far side of the relation. To give some context imagine 3 models: Product, Category and Order.
+The Product has a Category (category_id), and the Order has a Product (product_id). We would use `HasOneThrough` in the `Order` model to get the `Category` through `Product` model.
diff --git a/4.1/crud-filters.md b/4.1/crud-filters.md
new file mode 100644
index 00000000..c31540a5
--- /dev/null
+++ b/4.1/crud-filters.md
@@ -0,0 +1,494 @@
+# Filters
+
+---
+
+
+## About
+
+Backpack CRUD allows you to show a filters bar right above the entries table. When selected or modified, they reload the DataTables results. The search will then search within the filtered elements.
+
+
+
+Just like with fields, columns or buttons, you can add existing filters or create a custom filter that fits to your particular needs. Everything's done inside your ```EntityCrudController::setupListOperation()```.
+
+
+### Filters API
+
+In order to manipulate filters, you can use:
+
+```php
+$this->crud->addFilter($options, $values, $filter_logic);
+
+$this->crud->removeFilter($name);
+$this->crud->removeAllFilters();
+
+$this->crud->filters(); // gets all the filters
+```
+
+
+### Adding a filter
+
+When adding a filter you need to specify the 3 parameters of the ```addFilter()``` method:
+- $options - an array of options (name, type, label are most important)
+- $values - filter values - can be an array or a closure
+- $filter_logic - what should happen if the filter is applied (usually add a clause to the query) - can be a closure, a string for a simple operation or false for a simple "where";
+
+Here's a simple example, with comments that explain what we're doing:
+```php
+// add a "simple" filter called Draft
+$this->crud->addFilter([
+ 'type' => 'simple',
+ 'name' => 'draft',
+ 'label' => 'Draft'
+],
+false, // the simple filter has no values, just the "Draft" label specified above
+function() { // if the filter is active (the GET parameter "draft" exits)
+ $this->crud->addClause('where', 'draft', '1');
+ // we've added a clause to the CRUD so that only elements with draft=1 are shown in the table
+ // an alternative syntax to this would have been
+ // $this->crud->query = $this->crud->query->where('draft', '1');
+ // another alternative syntax, in case you had a scopeDraft() on your model:
+ // $this->crud->addClause('draft');
+});
+```
+> Notes about the filter logic closure
+> - the code will only be run on the controller's ```index()``` or ```search()``` methods;
+> - you can get the filter value by specifying a parameter to the function (ex: ```$value```);
+> - you have access to other request variables using ```$this->crud->getRequest()```;
+> - you also have read/write access to public properties using ```$this->crud```;
+> - when building complicated "OR" logic, make sure the first "where" in your closure is a "where" and only the subsequent are "orWhere"; Laravel 5.3+ no longer converts the first "orWhere" into a "where";
+
+
+## Filter types
+
+
+### Simple
+
+Only shows a label and can be toggled on/off. Useful for things like active/inactive and easily paired with [Eloquent Scopes](https://laravel.com/docs/5.3/eloquent#local-scopes). The "Draft" and "Has Video" filters in the screenshot above are simple filters.
+
+```php
+// simple filter
+$this->crud->addFilter([
+ 'type' => 'simple',
+ 'name' => 'active',
+ 'label' => 'Active'
+],
+false,
+function() { // if the filter is active
+ // $this->crud->addClause('active'); // apply the "active" eloquent scope
+} );
+```
+
+
+
+
+### Text
+
+Shows a text input. Most useful for letting the user filter through information that's not shown as a column in the CRUD table - otherwise they could just use the DataTables search field.
+
+
+
+```php
+// simple filter
+$this->crud->addFilter([
+ 'type' => 'text',
+ 'name' => 'description',
+ 'label' => 'Description'
+],
+false,
+function($value) { // if the filter is active
+ // $this->crud->addClause('where', 'description', 'LIKE', "%$value%");
+});
+```
+
+
+
+
+### Date
+
+Show a datepicker. The user can select one day.
+
+
+
+```php
+// date filter
+$this->crud->addFilter([
+ 'type' => 'date',
+ 'name' => 'date',
+ 'label' => 'Date'
+],
+ false,
+function ($value) { // if the filter is active, apply these constraints
+ // $this->crud->addClause('where', 'date', $value);
+});
+```
+
+
+
+
+### Date range
+
+Show a daterange picker. The user can select a start date and an end date.
+
+
+
+```php
+// daterange filter
+$this->crud->addFilter([
+ 'type' => 'date_range',
+ 'name' => 'from_to',
+ 'label' => 'Date range'
+],
+false,
+function ($value) { // if the filter is active, apply these constraints
+ // $dates = json_decode($value);
+ // $this->crud->addClause('where', 'date', '>=', $dates->from);
+ // $this->crud->addClause('where', 'date', '<=', $dates->to . ' 23:59:59');
+});
+```
+
+
+
+
+### Dropdown
+
+Shows a list of elements (that you provide) in a dropdown. The user can only select one of these elements.
+
+
+
+```php
+// dropdown filter
+$this->crud->addFilter([
+ 'name' => 'status',
+ 'type' => 'dropdown',
+ 'label' => 'Status'
+], [
+ 1 => 'In stock',
+ 2 => 'In provider stock',
+ 3 => 'Available upon ordering',
+ 4 => 'Not available',
+], function($value) { // if the filter is active
+ // $this->crud->addClause('where', 'status', $value);
+});
+```
+
+
+
+
+### Select2
+
+Shows a select2 and allows the user to select one item from the list or search for an item. Useful when the values list is long (over 10 elements).
+
+
+
+```php
+// select2 filter
+$this->crud->addFilter([
+ 'name' => 'status',
+ 'type' => 'select2',
+ 'label' => 'Status'
+], function () {
+ return [
+ 1 => 'In stock',
+ 2 => 'In provider stock',
+ 3 => 'Available upon ordering',
+ 4 => 'Not available',
+ ];
+}, function ($value) { // if the filter is active
+ // $this->crud->addClause('where', 'status', $value);
+});
+```
+
+**Note:** If you want to pass all entries of a Laravel model to your filter, you can do it in the second parameter (the closure), with something like ```return \Backpack\NewsCRUD\app\Models\Category::all()->keyBy('id')->pluck('name', 'id')->toArray();```;
+
+
+
+
+### Select2_multiple
+
+Shows a select2 and allows the user to select one or more items from the list or search for an item. Useful when the values list is long (over 10 elements) and your user should be able to select multiple elements.
+
+
+
+```php
+// select2_multiple filter
+$this->crud->addFilter([
+ 'name' => 'status',
+ 'type' => 'select2_multiple',
+ 'label' => 'Status'
+], function() {
+ return [
+ 1 => 'In stock',
+ 2 => 'In provider stock',
+ 3 => 'Available upon ordering',
+ 4 => 'Not available',
+ ];
+}, function($values) { // if the filter is active
+ // $this->crud->addClause('whereIn', 'status', json_decode($values));
+});
+```
+
+
+
+
+### Select2_ajax
+
+Shows a select2 and allows the user to select one item from the list or search for an item. This list is fetched through an AJAX call by the select2. Useful when the values list is long (over 1000 elements).
+
+NOTE: if you want to setup your ajax routes using FetchOperation, have a look at: FetchOperation with ajax filter
+
+
+
+1. Add a route for the ajax search, right above your usual ```CRUD::resource()``` route. Example:
+
+```php
+Route::get('test/ajax-category-options', 'TestCrudController@categoryOptions');
+CRUD::resource('test', 'TestCrudController');
+```
+
+2. Add a method to your EntityCrudController that responds to a search term. The result should be an array with ```id => value```. Example for a 1-n relationship:
+
+```php
+public function categoryOptions(Request $request) {
+ $term = $request->input('term');
+ $options = App\Models\Category::where('name', 'like', '%'.$term.'%')->get()->pluck('name', 'id');
+ return $options;
+}
+```
+
+3. Add the select2_ajax filter and for the second parameter ("values") specify the exact route.
+
+```php
+// select2_ajax filter
+$this->crud->addFilter([
+ 'name' => 'category_id',
+ 'type' => 'select2_ajax',
+ 'label' => 'Category',
+ 'placeholder' => 'Pick a category'
+],
+url('http://github.com/admin/test/ajax-category-options'), // the ajax route
+function($value) { // if the filter is active
+ // $this->crud->addClause('where', 'category_id', $value);
+});
+```
+
+
+
+
+### Range
+
+Shows two number inputs, for min and max.
+
+
+
+```php
+$this->crud->addFilter([
+ 'name' => 'number',
+ 'type' => 'range',
+ 'label' => 'Range',
+ 'label_from' => 'min value',
+ 'label_to' => 'max value'
+],
+false,
+function($value) { // if the filter is active
+ $range = json_decode($value);
+ if ($range->from) {
+ $this->crud->addClause('where', 'number', '>=', (float) $range->from);
+ }
+ if ($range->to) {
+ $this->crud->addClause('where', 'number', '<=', (float) $range->to);
+ }
+});
+```
+
+
+
+
+### View
+
+Display any custom column filter you want. Usually used by Backpack package developers, to use views from within their packages, instead of having to publish them.
+
+```php
+// custom filter view
+$this->crud->addFilter([
+ 'name' => 'category_id',
+ 'type' => 'view',
+ 'view' => 'package::columns.column_type_name', // or path to blade file
+ 'label' => 'Category',
+ 'placeholder' => 'Pick a category',
+],
+false,
+function($value) { // if the filter is active
+ // $this->crud->addClause('where', 'category_id', $value);
+});
+```
+
+
+
+
+## Creating custom filters
+
+Creating a new filter type is as easy as using the template below and placing a new view in your ```resources/views/vendor/backpack/crud/filters``` folder. You can then call this new filter by its view's name (ex: ```custom_select.blade.php``` will mean your filter type is called ```custom_select```).
+
+The filters bar is actually a [bootstrap navbar](http://getbootstrap.com/components/#navbar) at its core, but slimmer. So adding a new filter will be just like adding a menu item (for the HTML). Start from the ```text``` filter below and build your functionality.
+
+Inside this file, you'll have:
+- ```$filter``` object - includes everything you've defined on the current field;
+- ```$crud``` - the CrudPanel object;
+
+```php
+{{-- Text Backpack CRUD filter --}}
+
+
+
+{{-- ########################################### --}}
+{{-- Extra CSS and JS for this particular filter --}}
+
+
+{{-- FILTERS EXTRA JS --}}
+{{-- push things in the after_scripts section --}}
+
+@push('crud_list_scripts')
+
+
+@endpush
+{{-- End of Extra CSS and JS --}}
+{{-- ########################################## --}}
+```
+
+
+
+
+## Examples
+
+Use a dropdown to filter by the values of a MySQL ENUM column:
+
+```php
+// select2 filter
+$this->crud->addFilter([
+ 'name' => 'published',
+ 'type' => 'select2',
+ 'label' => 'Published'
+], function() {
+ return \App\Models\Test::getEnumValuesAsAssociativeArray('published');
+}, function($value) { // if the filter is active
+ $this->crud->addClause('where', 'published', $value);
+});
+```
+
+Use a select2 to filter by a 1-n relationship:
+```php
+// select2 filter
+$this->crud->addFilter([
+ 'name' => 'category_id',
+ 'type' => 'select2',
+ 'label' => 'Category'
+], function() {
+ return \App\Models\Category::all()->pluck('name', 'id')->toArray();
+}, function($value) { // if the filter is active
+ $this->crud->addClause('where', 'category_id', $value);
+});
+```
+
+Use a select2_multiple to filter Products by an n-n relationship:
+```php
+// select2_multiple filter
+$this->crud->addFilter([
+ 'name' => 'tags',
+ 'type' => 'select2_multiple',
+ 'label' => 'Tags'
+], function() { // the options that show up in the select2
+ return Product::all()->pluck('name', 'id')->toArray();
+}, function($values) { // if the filter is active
+ foreach (json_decode($values) as $key => $value) {
+ $this->crud->query = $this->crud->query->whereHas('tags', function ($query) use ($value) {
+ $query->where('tag_id', $value);
+ });
+ }
+});
+```
+
+Use a simple filter to add a scope if the filter is active:
+```php
+// add a "simple" filter called Published
+$this->crud->addFilter([
+ 'type' => 'simple',
+ 'name' => 'published',
+ 'label' => 'Published'
+],
+false,
+function() { // if the filter is active (the GET parameter "published" exits)
+ $this->crud->addClause('published');
+});
+```
+
+Use a simple filter to show the softDeleted items (trashed):
+```php
+$this->crud->addFilter([
+ 'type' => 'simple',
+ 'name' => 'trashed',
+ 'label' => 'Trashed'
+],
+false,
+function($values) { // if the filter is active
+ $this->crud->query = $this->crud->query->onlyTrashed();
+});
+```
diff --git a/4.1/crud-fluent-syntax.md b/4.1/crud-fluent-syntax.md
new file mode 100644
index 00000000..f087704f
--- /dev/null
+++ b/4.1/crud-fluent-syntax.md
@@ -0,0 +1,722 @@
+# CRUD Fluent API
+
+---
+
+
+
+## About
+
+Starting with Backpack 4.1, working with Fields, Columns, Filters, Buttons and Widgets **inside your EntityCrudController** can also be done using a fluent syntax. For example, instead of doing:
+
+```php
+$this->crud->addField([ // Number
+ 'name' => 'price',
+ 'label' => 'Price',
+ 'type' => 'number',
+ 'prefix' => "$",
+ 'suffix' => ".00",
+]);
+```
+
+You can now do:
+```php
+$this->crud->field('price')
+ ->type('number')
+ ->label('Price')
+ ->prefix('$')
+ ->suffix('.00');
+```
+
+But you can go a little further, by using the CrudPanel class at the top of your controller with an alias:
+
+```php
+use Backpack\CRUD\app\Library\CrudPanel\CrudPanel as CRUD;
+
+CRUD::field('price')
+ ->type('number')
+ ->label('Price')
+ ->prefix('$')
+ ->suffix('.00');
+```
+
+Or maybe even condense it on just one line:
+```php
+CRUD::field('price')->type('number')->label('Price')->prefix('$')->suffix('.00');
+```
+
+Those who prefer this new fluent syntax do so because:
+- method chains have better highlighting and suggestions in most IDEs;
+- method chains take up slightly fewer lines of code than arrays;
+- method chains are faster to write & modify than arrays;
+- you no longer have to decide if you're adding or modifying a field, since ```CRUD::field()``` basically functions as a ```CRUD::addOrModifyField()```;
+- it allows us to add methods that are exclusive to the fluent syntax, that will make our lives easier; for example, to make a field take up only 6 bootstrap columns, using the non-fluent syntax you'd have to write ```'wrapper' => ['class' => 'form-group col-md-6'],``` - but using the fluent syntax you can just do ```size(6)```;
+
+But keep in mind that it does have downsides: it's more difficult to debug and arguably makes it more difficult to understand how the admin panel works. Developers who are not already comfortable with Backpack might not understand that:
+- referencing ```$this->crud``` is the same thing as ```CRUD``` because it's actually a ```singleton```, a "global" instance of the ```CrudPanel``` object, which gets defined in the Controller and is then read inside the views;
+- the fluent syntax merely turns those chained methods into an array, which gets stored inside ```$this->crud``` like it does with ```addField()``` or ```modifyField()```;
+
+
+## Fluent Fields
+
+These methods should be used inside your CrudController for operations that use Fields, most likely inside the ```setupCreateOperation()``` or ```setupUpdateOperation()``` methods.
+
+
+### General
+
+```field('name')``` - By specifying **field('name')** you add a field with that name to the current operation, at the end of the stack, or modify the field that already exists with that name; it accepts a single parameter, a string, that will become that field's ```name```; needs to be called directly, not chained;
+```php
+CRUD::field('name');
+```
+
+Anything you chain to the ```field()``` method gets turned into an attribute on that field. Except for the methods below.
+
+
+### Chained Methods
+
+If you chain the following methods to a ```CRUD::field('name')```, they will do something very specific instead of adding that attribute to the field:
+
+- ```->remove()``` - By chaining **remove()** on a field you remove it from the current operation;
+
+```php
+CRUD::field('name')->remove();
+```
+
+- ```->forget('attribute_name')``` - By chaining **forget('attribute_name')** to a field you remove that attribute from the field definition array;
+
+```php
+CRUD::field('name')->forget('suffix');
+```
+
+- ```->after('destination')``` - By chaining **after('destination_field_name')** you will move the current field after the given field;
+
+```php
+CRUD::field('name')->after('description');
+```
+
+- ```->before('destination')``` - By chaining **before('destination_field_name')** you will move the current field before the given field;
+
+```php
+CRUD::field('name')->before('description');
+```
+
+- ```->makeFirst()``` - By chaining **makeFirst()** you will make the current field the first one for the current operation;
+
+```php
+CRUD::field('name')->makeFirst();
+```
+
+- ```->makeLast()``` - By chaining **makeLast()** you will make the current field the last one for the current operation;
+
+```php
+CRUD::field('name')->makeLast();
+```
+
+- ```->size(6)``` - By chaining **size(4)** you will make the field span across this many bootstrap columns (instead of the default 12 columns which is a full row); it accepts a single parameter, an integer from 1 to 12; for more information and to see how you can create convenience methods like this one, see [the PR](https://github.com/Laravel-Backpack/CRUD/pull/2638);
+
+```php
+CRUD::field('name')->size(6);
+
+// alternative to
+CRUD::addField([
+ 'name' => 'name',
+ 'wrapper' => ['class' => 'form-group col-md-6'],
+]);
+```
+
+- Do you have an idea for a new chained method aka. convenience method? [Let us know](https://github.com/laravel-backpack/crud/issues).
+
+
+### Examples
+
+```php
+// a text field
+CRUD::field('last_name');
+
+// an email field, put inside a tab and resized to half the width
+CRUD::field('email')->type('email')->size(6)->tab('Simple');
+
+// a number field with prefix and suffix (stored as fake in extras)
+CRUD::field('price')->type('number')->prefix('$')->suffix(".00")->fake(true);
+
+// a date picker field with custom options
+CRUD::field('birthday')
+ ->type('date_picker')
+ ->label('Birthday')
+ ->date_picker_options([
+ 'todayBtn' => true,
+ 'format' => 'dd-mm-yyyy',
+ 'language' => 'en',
+ ])
+ ->size(6);
+
+// a select field, half the width
+CRUD::field('category_id')
+ ->type('select')
+ ->label('Category')
+ ->entity('category')
+ ->attribute('name')
+ // ->model('Backpack\NewsCRUD\app\Models\Category') // optional; guessed from entity;
+ // ->wrapper(['class' => 'form-group col-md-6']) // possible, but easier with size below;
+ ->size(6);
+
+// a select2_from_ajax field
+CRUD::field('article')
+ ->type('select2_from_ajax')
+ ->label("Article")
+ ->entity('article')
+ // ->attribute('title') // starting with Backpack 4.1 this is optional & guessed
+ // ->model('Backpack\NewsCRUD\app\Models\Article') // optional; guessed;
+ ->data_source(url('http://github.com/api/article'))
+ ->placeholder('Select an article')
+ ->minimum_input_length(2);
+
+// a relationship field for an n-n relationship
+// also uses the Fetch and InlineCreate operations
+CRUD::field('products')
+ ->type('relationship')
+ ->label('Products')
+ // ->entity('products') // optional
+ // ->attribute('name') // optional
+ ->ajax(true)
+ ->data_source(backpack_url('http://github.com/monster/fetch/product'))
+ ->inline_create(['entity' => 'product'])
+ // ->wrapper(['class' => 'form-group col-md-6'])
+ ->tab('Others');
+```
+
+
+## Fluent Columns
+
+These methods should be used inside your CrudController for operations that use Columns, most likely inside the ```setupListOperation()``` or ```setupShowOperation()``` methods.
+
+
+
+### General
+
+- ```column('name')``` - By specifying **column('name')** you add a column with that name to the current operation, at the end of the stack, or modify the column that already exists with that name; takes a single parameter, a string, that will become that column's ```name``` and ```key```; needs to be called directly, not chained;
+```php
+CRUD::column('name');
+```
+
+Anything you chain to the ```column()``` method gets turned into an attribute on that column. Except for the methods below:
+
+
+
+### Chained Methods
+
+If you chain the following methods to a ```CRUD::column('name')```, they will do something very specific instead of adding that attribute to the column:
+
+- ```->remove()``` - By chaining **remove()** on a column you remove it from the current operation;
+
+```php
+CRUD::column('name')->remove();
+```
+
+- ```->forget('attribute_name')``` - By chaining **forget('attribute_name')** to a column you remove that attribute from the column definition array;
+
+```php
+CRUD::column('name')->forget('suffix');
+```
+
+- ```->after('destination')``` - By chaining **after('destination_column_name')** you will move the current column after the given column;
+
+```php
+CRUD::column('name')->after('description');
+```
+
+- ```->before('destination')``` - By chaining **before('destination_column_name')** you will move the current column before the given column;
+
+```php
+CRUD::column('name')->before('description');
+```
+
+- ```->makeFirst()``` - By chaining **makeFirst()** you will make the current column the first one for the current operation;
+
+```php
+CRUD::column('name')->makeFirst();
+```
+
+- ```->makeLast()``` - By chaining **makeLast()** you will make the current column the last one for the current operation;
+
+```php
+CRUD::column('name')->makeLast();
+```
+
+
+
+### Examples
+
+```php
+// a text column
+CRUD::column('last_name');
+
+// a textarea column
+CRUD::column('description')->type('textarea');
+
+// an image column
+CRUD::column('profile_photo')->type('image');
+
+// a select column with links
+CRUD::column('select')
+ ->type('select')
+ ->entity('category')
+ ->attribute('name')
+ ->model("Backpack\NewsCRUD\app\Models\Category")
+ ->wrapper([
+ 'href' => function ($crud, $column, $entry, $related_key) {
+ return backpack_url('http://github.com/category/'.$related_key.'/show');
+ },
+ ]);
+
+// a select_multiple column
+CRUD::column('tags')->type('select_multiple')->entity('tags');
+
+// a select_multiple column with everything explicitly defined, plus links
+CRUD::column('tags')
+ ->type('select_multiple')
+ ->label('Select_multiple')
+ ->entity('tags')
+ ->attribute('name')
+ ->model('Backpack\NewsCRUD\app\Models\Tag')
+ ->wrapper([
+ 'href' => function ($crud, $column, $entry, $related_key) {
+ return backpack_url('http://github.com/tag/'.$related_key.'/show');
+ },
+ ]);
+
+// a checkbox column that turns a boolean into green labels if true
+CRUD::column('active')
+ ->type('boolean')
+ ->label('Active')
+ ->options([0 => 'Yes', 1 => 'No'])
+ ->wrapper([
+ 'element' => 'span',
+ 'class' => function ($crud, $column, $entry, $related_key) {
+ if ($column['text'] == 'Yes') {
+ return 'badge badge-success';
+ }
+
+ return 'badge badge-default';
+ },
+ ]);
+
+// a select_from_array column
+CRUD::column('status')
+ ->type('select_from_array')
+ ->label('Status')
+ ->options(['1' => 'New', '2' => 'Processing', '3' => 'Delivered']);
+
+// a model function column, with custom search logic
+CRUD::column('text_and_email')
+ ->type('model_function')
+ ->label('Text and Email')
+ ->function_name('getTextAndEmailAttribute')
+ ->searchLogic(function ($query, $column, $searchTerm) {
+ $query->orWhere('email', 'like', '%'.$searchTerm.'%');
+ $query->orWhere('text', 'like', '%'.$searchTerm.'%');
+ });
+```
+
+
+## Fluent Buttons
+
+These methods should be used inside your CrudController for operations that use Buttons, most likely inside the ```setupListOperation()``` or ```setupShowOperation()``` methods.
+
+
+
+### General
+
+- ```button('name')``` - By specifying **button('name')** you add a button with that name to the current operation, at the end of the stack, or modify the button that already exists with that name; takes a single parameter, a string, that will become that button's ```name```; needs to be called directly, not chained;
+```php
+CRUD::button('name');
+```
+
+Anything you chain to the ```button()``` method gets turned into an attribute on that button. Except for the methods listed below. Keep in mind in most cases you will still need to chain ```stack```, ```view``` and maybe ```type``` to this method, to define those attributes. Details in the examples section below.
+
+
+
+### Chained Methods
+
+If you chain the following methods to a ```CRUD::button('name')```, they will do something very specific instead of adding that attribute to the button:
+
+- ```->remove()``` - By chaining **remove()** on a button you remove it from the current operation;
+
+```php
+CRUD::button('name')->remove();
+```
+
+- ```->forget('attribute_name')``` - By chaining **forget('attribute_name')** to a button you remove that attribute from the button;
+
+```php
+CRUD::button('name')->forget('suffix');
+```
+
+- ```->after('destination')``` - By chaining **after('destination_button_name')** you will move the current button after the given button;
+
+```php
+CRUD::button('name')->after('description');
+```
+
+- ```->before('destination')``` - By chaining **before('destination_button_name')** you will move the current button before the given button;
+
+```php
+CRUD::button('name')->before('description');
+```
+
+- ```->makeFirst()``` - By chaining **makeFirst()** you will make the current button the first one for the current operation;
+
+```php
+CRUD::button('name')->makeFirst();
+```
+
+- ```->makeLast()``` - By chaining **makeLast()** you will make the current button the last one for the current operation;
+
+```php
+CRUD::button('name')->makeLast();
+```
+
+
+
+### Examples
+
+```php
+// ---------
+// Example 1
+// ---------
+// instead of
+$this->crud->addButton('top', 'create', 'view', 'crud::buttons.create');
+// you can now do
+CRUD::button('create')->stack('top')->view('crud::buttons.create');
+
+// ---------
+// Example 2
+// ---------
+// instead of
+$this->crud->addButton('line', 'update', 'view', 'crud::buttons.update', 'end');
+// you can now do
+CRUD::button('edit')->stack('line')->view('crud::buttons.edit');
+
+// ---------
+// Example 3
+// ---------
+// instead of
+$this->crud->addButtonFromModelFunction('line', 'open_google', 'openGoogle', 'beginning');
+// you can now do
+CRUD::button('open_google')
+ ->stack('line')
+ ->type('model_function')
+ ->content('openGoogle')
+ ->makeFirst();
+
+// ---------
+// Example 4
+// ---------
+// instead of
+$this->crud->addButtonFromView('top', 'create', 'crud::buttons.create', 'beginning');
+// you can now do
+CRUD::button('create')->stack('top')->view('crud::buttons.create');
+
+// ---------
+// Example 5
+// ---------
+// instead of
+$this->crud->removeButton('create');
+// you can now do
+CRUD::button('create')->remove();
+
+// ------
+// Extras
+// ------
+// but you don't have to give it a name, so you can also do
+CRUD::button()->stack('line')->type('model_function')->content('openGoogle')->makeFirst();
+// and we also have helpers for setting both the type to view/model_function and its content
+CRUD::button()->stack('line')->modelFunction('openGoogle')->makeFirst();
+
+// -------
+// Aliases
+// -------
+// the "stack" attribute can also be set using the "group", "section" and "to" aliases
+// all of the calls below do the exact same thing
+CRUD::buton('create')->stack('top')->view('crud::butons.create');
+CRUD::buton('create')->to('top')->view('crud::butons.create');
+CRUD::buton('create')->group('top')->view('crud::butons.create');
+CRUD::buton('create')->section('top')->view('crud::butons.create');
+```
+
+
+
+## Fluent Filters
+
+
+These methods should be used inside your CrudController for operations that use Filters, most likely inside ```setupListOperation()```.
+
+
+
+### General
+
+```filter('name')``` - By specifying **filter('name')** you add a filter with that name to the current operation, at the end of the stack, or modify the filter that already exists with that name; takes a single parameter, a string, that will become that filter's ```name```; needs to be called directly, not chained;
+```php
+CRUD::filter('name');
+```
+
+Anything you chain to the ```filter()``` method gets turned into an attribute on that filter. Except for the methods listed below. Keep in mind in most cases you will still need to chain ```type```, ```logic```, ```fallbackLogic``` and maybe ```apply``` to this method, to define those attributes and apply the appropriate logic. Details in the examples section below.
+
+
+### Main Chained Methods
+
+- ```->type('date')``` - By chaining **type()** on a filter you make sure you use that filter type; it accepts a string that represents the type of filter you want to use;
+
+```php
+CRUD::filter('birthday')->type('date');
+```
+
+- ```->label('Name')``` - By chaining **label()** on a filter you define what is shown to the user as the filter label; it accepts a string;
+
+```php
+CRUD::filter('name')->label('Name');
+```
+
+- ```->logic(function($value) {})``` - By chaining **logic()** on a filter you define should be done when that filter is active; it accepts a closure that is called when the filter is active - either immediately by further chaining ```apply()``` on the filter, or automatically after all filters are defined, by the List operation itself; you can also use ```->whenActive()``` or ```->ifActive()``` which are its aliases:
+
+```php
+// logic method
+CRUD::filter('active')
+ ->type('simple')
+ ->logic(function ($value) {
+ $this->crud->addClause('where', 'active', '1');
+ })->apply();
+
+// whenActive alias
+CRUD::filter('active')
+ ->type('simple')
+ ->whenActive(function ($value) {
+ $this->crud->addClause('where', 'active', '1');
+ })->apply();
+
+// ifActive alias, left to be applied by the operation itself
+CRUD::filter('active')
+ ->type('simple')
+ ->whenActive(function ($value) {
+ $this->crud->addClause('where', 'active', '1');
+ });
+```
+
+- ```->fallbackLogic(function($value) {})``` - By chaining **fallbackLogic()** on a filter you define should be done when that filter is NOT active; it accepts a closure that is called when the filter is NOT active - either immediately by further chaining ```apply()``` on the filter, or automatically after all filters are defined, by the List operation itself; you can also use ```->else()```, ```->whenInactive()```, ```->whenNotActive()```, ```->ifInactive()``` and ```->ifNotActive()``` which are its aliases:
+
+```php
+// fallbackLogic method, applied immediately
+CRUD::filter('active')
+ ->type('simple')
+ ->logic(function ($value) {
+ $this->crud->addClause('where', 'active', '1');
+ })->fallbackLogic(function ($value) {
+ $this->crud->addClause('where', 'active', '0');
+ })->apply();
+
+// else alias, left to be applied by the operation itself
+CRUD::filter('active')
+ ->type('simple')
+ ->label('Simple')
+ ->ifActive(function ($value) {
+ $this->crud->addClause('where', 'active', '1');
+ })->else(function ($value) {
+ $this->crud->addClause('where', 'active', '0');
+ });
+```
+
+
+### Other Chained Methods
+
+If you chain the following methods to a ```CRUD::filter('name')```, they will do something very specific instead of adding that attribute to the filter:
+
+- ```->remove()``` - By chaining **remove()** on a filter you remove it from the current operation;
+
+```php
+CRUD::filter('name')->remove();
+```
+
+- ```->forget('attribute_name')``` - By chaining **forget('attribute_name')** to a filter you remove that attribute from the filter;
+
+```php
+CRUD::filter('name')->forget('suffix');
+```
+
+- ```->after('destination')``` - By chaining **after('destination_filter_name')** you will move the current filter after the given filter;
+
+```php
+CRUD::filter('name')->after('description');
+```
+
+- ```->before('destination')``` - By chaining **before('destination_filter_name')** you will move the current filter before the given filter;
+
+```php
+CRUD::filter('name')->before('description');
+```
+
+- ```->makeFirst()``` - By chaining **makeFirst()** you will make the current filter the first one for the current operation;
+
+```php
+CRUD::filter('name')->makeFirst();
+```
+
+- ```->makeLast()``` - By chaining **makeLast()** you will make the current filter the last one for the current operation;
+
+```php
+CRUD::filter('name')->makeLast();
+```
+
+
+
+### Examples
+
+```php
+// instead of
+CRUD::addFilter([
+ 'type' => 'simple',
+ 'name' => 'checkbox',
+ 'label' => 'Simple',
+],
+false,
+function () {
+ $this->crud->addClause('where', 'checkbox', '1');
+});
+
+// you can do
+CRUD::filter('checkbox')
+ ->type('simple')
+ ->label('Simple')
+ ->logic(function($value) {
+ $this->crud->addClause('where', 'checkbox', '1');
+ })->apply();
+
+// or
+CRUD::filter('checkbox')
+ ->type('simple')
+ ->label('Simple')
+ ->whenActive(function($value) { // filter logic
+ $this->crud->addClause('where', 'checkbox', '1');
+ })->whenInactive(function($value) { // fallback logic
+ $this->crud->addClause('inactive');
+ })->apply();
+
+// or
+CRUD::filter('checkbox')
+ ->type('simple')
+ ->label('Simple')
+ ->ifActive(function($value) { // filter logic
+ $this->crud->addClause('where', 'checkbox', '1');
+ })->else(function($value) { // fallback logic
+ $this->crud->addClause('inactive');
+ })->apply();
+
+// -------------------
+// you can also now do
+// -------------------
+CRUD::filter('select_from_array')->label('Modified Dropdown');
+CRUD::filter('select_from_array')->whenActive(function($value) {
+ dd('select_from_array filter logic got modified');
+})->apply();
+CRUD::filter('select_from_array')->remove();
+CRUD::filter('select_from_array')->forget('label');
+CRUD::filter('select_from_array')->after('text');
+CRUD::filter('select_from_array')->before('text');
+CRUD::filter('select_from_array')->makeFirst();
+CRUD::filter('select_from_array')->makeLast();
+
+// --------------
+// other examples
+// --------------
+// checkbox filter
+CRUD::filter('checkbox')
+ ->type('simple')
+ ->label('Simple')
+ ->logic(function($value) {
+ $this->crud->addClause('where', 'checkbox', '1');
+ })->apply();
+
+// select_from_array filter
+CRUD::filter('select_from_array')
+ ->type('dropdown')
+ ->label('DropDOWN')
+ ->values([
+ 'one' => 'One',
+ 'two' => 'Two',
+ 'three' => 'Three'
+ ])
+ ->whenActive(function($value) {
+ $this->crud->addClause('where', 'select_from_array', $value);
+ })
+ ->apply();
+
+// text filter
+CRUD::filter('text')
+ ->type('text')
+ ->label('Text')
+ ->whenActive(function($value) {
+ $this->crud->addClause('where', 'text', 'LIKE', "%$value%");
+ })->apply();
+
+// number filter
+CRUD::filter('number')
+ ->type('range')
+ ->label('Range')->label_from('min value')->label_to('max value')
+ ->whenActive(function($value) {
+ $range = json_decode($value);
+ if ($range->from && $range->to) {
+ $this->crud->addClause('where', 'number', '>=', (float) $range->from);
+ $this->crud->addClause('where', 'number', '<=', (float) $range->to);
+ }
+ })->apply();
+
+// date filter
+CRUD::filter('date')
+ ->type('date')
+ ->label('Date')
+ ->whenActive(function($value) {
+ $this->crud->addClause('where', 'date', '=', $value);
+ })->apply();
+
+// date_range filter
+CRUD::filter('date_range')
+ ->type('date_range')
+ ->label('Date range')
+ ->whenActive(function($value) {
+ $dates = json_decode($value);
+ $this->crud->addClause('where', 'date', '>=', $dates->from);
+ $this->crud->addClause('where', 'date', '<=', $dates->to);
+ })->apply();
+
+// select2 filter
+CRUD::filter('select2')
+ ->type('select2')
+ ->label('Select2')
+ ->values(function() {
+ return \Backpack\NewsCRUD\app\Models\Category::all()->keyBy('id')->pluck('name', 'id')->toArray();
+ })
+ ->whenActive(function($value) {
+ $this->crud->addClause('where', 'select2', $value);
+ })->apply();
+
+// select2_multiple filter
+CRUD::filter('select2_multiple')
+ ->type('select2_multiple')
+ ->label('S2 multiple')
+ ->values(function() {
+ return \Backpack\NewsCRUD\app\Models\Category::all()->keyBy('id')->pluck('name', 'id')->toArray();
+ })
+ ->whenActive(function($value) {
+ foreach (json_decode($values) as $key => $value) {
+ $this->crud->addClause('orWhere', 'select2', $value);
+ }
+ })->apply();
+
+// select2_from_ajax filter
+CRUD::filter('select2_from_ajax')
+ ->type('select2_ajax')
+ ->label('S2 Ajax')
+ ->placeholder('Pick an article')
+ ->values('api/article-search')
+ ->whenActive(function($value) {
+ $this->crud->addClause('where', 'select2_from_ajax', $value);
+ })->apply();
+```
diff --git a/4.1/crud-how-to.md b/4.1/crud-how-to.md
new file mode 100644
index 00000000..31540bf1
--- /dev/null
+++ b/4.1/crud-how-to.md
@@ -0,0 +1,363 @@
+# FAQs for CRUDs
+
+---
+
+In addition the usual CRUD functionality, Backpack also allows you to do a few more complicated things:
+
+
+
+## How To
+
+
+### Customize Views for each CRUD Panel
+
+Backpack loads its views through a double-fallback mechanism:
+- by default, it will load the views in the vendor folder (the package views);
+- if you've included views with the exact same name in your ```resources/views/vendor/backpack/crud``` folder, it will pick up those instead; you can use this method to overwrite a blade file for all CRUDs;
+- alternatively, if you only want to change a blade file for one CRUD, you can use the methods below in your ```setup()``` method, to change a particular view:
+```php
+$this->crud->setShowView('your-view');
+$this->crud->setEditView('your-view');
+$this->crud->setCreateView('your-view');
+$this->crud->setListView('your-view');
+$this->crud->setReorderView('your-view');
+$this->crud->setDetailsRowView('your-view');
+```
+
+
+### Customize CSS and JS for Default CRUD Operations
+
+Each default Backpack operation has its own CSS and JS file, in:
+- ```public/packages/backpack/crud/css```
+- ```public/packages/backpack/crud/js```
+
+Backpack will pick it up in that operation's view (ex: ```create.css``` or ```list.js```).
+
+
+### Add Extra CRUD Routes
+
+Starting with Backpack\CRUD 4.0, routes are defined inside the Controller, in methods that look like ```setupOperationNameRoutes()```; you can use this naming convention to setup extra routes, for your custom operations:
+
+```php
+protected function setupModerateRoutes($segment, $routeName, $controller) {
+ Route::get($segment.'/{id}/moderate', [
+ 'as' => $routeName.'.moderate',
+ 'uses' => $controller.'@moderate',
+ 'operation' => 'moderate',
+ ]);
+
+ Route::post($segment.'/{id}/moderate', [
+ 'as' => $routeName.'.saveModeration',
+ 'uses' => $controller.'@saveModeration',
+ 'operation' => 'moderate',
+ ]);
+}
+```
+
+If you want the route to point to a different controller, you can add the route in ```routes/backpack/custom.php``` instead.
+
+
+### Publish a column / field / filter / button and modify it
+
+All Backpack packages allow you to easily overwrite and customize the views. If you want Backpack to pick up _your_ file, instead of the one in the package, you can do that by just placing a file with the same name in your views. So if you want to overwrite the select2 field (```vendor/backpack/crud/src/resources/views/fields/select2.blade.php```) to change some functionality, you need to create ```resources/views/vendor/backpack/crud/fields/select2.blade.php```. You can do that manually, or use this command:
+```shell
+php artisan backpack:publish crud/fields/select2
+```
+This will look for the blade file and copy it inside the folder, so you can edit it.
+
+>**Please note:** Once you place a file with the same name inside your project, Backpack will pick that one up instead of the one in the package. That means that even though the file in the package is updated, you won't be getting those updates, since you're not using that file. Blade modifications are almost never breaking changes, but it's a good thing to receive updates with zero effort. Even small ones. So please overwrite the files as little as possible. Best to create your own custom fields/column/filters/buttons, whenever you can.
+
+
+### Filter the options in a select field
+
+This also applies to: select2, select2_multiple, select2_from_ajax, select2_from_ajax_multiple.
+
+There are 3 possible solutions:
+1. If there will be few options (dozens), the easiest way would be to use ```select_from_array``` or ```select2_from_array``` instead. Since you tell it what the options are, you can do any filtering you want there.
+2. If there are a lot of options (100+), best to use ```select2_from_ajax``` instead. You'll be able to filter the results any way you want in the controller method (the one that responds with the results to the AJAX call).
+3. If you can't use ```select2_from_array``` for ```select2_from_ajax```, you can create another model and add a global scope to it. For example, say you only want to show the users that belong to the user's company. You can create ```App\Models\CompanyUser``` and use that in your ```select2``` field instead of ```App\Models\User```:
+
+```php
+company_id) {
+ $companyId = Auth::user()->company->id;
+
+ static::addGlobalScope('company_id', function (Builder $builder) use ($companyId) {
+ $builder->where('company_id', $companyId);
+ });
+ }
+ }
+}
+```
+
+
+### Use the same column name multiple times in a CRUD
+
+If you try to add multiple columns with the same ```name```, by default Backpack will only show the last one. That's because ```name``` is also used as a key in the ```$column``` array. So when you ```addColumn()``` with the same name twice, it just overwrites the previous one.
+
+In order to insert two columns with the same name, use the ```key``` attribute on the second column (or both columns). If this attribute is present for a column, Backpack will use ```key``` instead of ```name```. Example:
+
+```diff
+ $this->crud->addColumn([
+ 'label' => "Location",
+ 'type' => 'select',
+ 'name' => 'location_id',
+ 'entity' => 'location',
+ 'attribute' => 'title',
+ 'model' => "App\Models\Location"
+ ]);
+
+ $this->crud->addColumn([
+ 'label' => "Location Type",
+ 'type' => 'radio_location_type',
+ 'options' => [
+ 1 => "Country",
+ 2 => "Region"
+ ],
+ 'name' => 'location_id',
++ 'key' => 'location_type',
+ 'entity' => 'location',
+ 'attribute' => 'type',
+ 'model' => "App\Models\Location"
+ ]);
+```
+
+
+### Use the Media Library (File Manager)
+
+The default Backpack installation doesn't come with a file management component. Because most projects don't need it. But we've created a first-party add-on that brings the power of [elFinder](http://elfinder.org/) to your Laravel projects. To install it, [follow the instructions on the add-ons page](https://github.com/Laravel-Backpack/FileManager). It's as easy as running:
+
+```bash
+# require the package
+composer require backpack/filemanager
+
+# then run the installation process
+php artisan backpack:filemanager:install
+```
+
+If you've chosen to install [backpack/filemanager](https://github.com/Laravel-Backpack/FileManager), you'll have elFinder integrated into:
+- TinyMCE (as "tinymce" field type)
+- CKEditor (as "ckeditor" field type)
+- CRUD (as "browse" and "browse_multiple" field types)
+- stand-alone, at the */admin/elfinder* route;
+
+For the integration, we use [barryvdh/laravel-elfinder](https://github.com/barryvdh/laravel-elfinder).
+
+
+
+
+### Manually install Backpack
+
+If the automatic installation doesn't work for you and you need to manually install CRUD, here are all the commands it is running:
+
+1) In your terminal:
+
+``` bash
+composer require backpack/crud:"4.1.x-dev as 4.0.99"
+```
+
+2) Instead of running ```php artisan backpack:install``` you can run:
+```bash
+php artisan vendor:publish --provider="Backpack\CRUD\BackpackServiceProvider" --tag="minimum"
+php artisan migrate
+php artisan backpack:publish-middleware
+```
+
+
+### Load fields from a different folder
+
+If you're developing a package, you might need Backpack to pick up fields from your package folder, instead of having to publish them upon installation.
+
+Fields, Columns and Filters all have a ```view_namespace``` parameter you can use. Type your folder there, and Backpack will check that folder first, then where the views are published, then Backpack's package folder. Example:
+
+```php
+$this->crud->addFilter([ // add a "simple" filter called Draft
+ 'type' => 'complex',
+ 'name' => 'checkbox',
+ 'label' => 'Checked',
+ 'view_namespace' => 'custom_filters'
+],
+false, // the simple filter has no values, just the "Draft" label specified above
+function () { // if the filter is active (the GET parameter "draft" exits)
+ $this->crud->addClause('where', 'checkbox', '1');
+});
+```
+This will make Backpack look for the ```resources/views/custom_filters/complex.blade.php```, and pick that up before anything else.
+
+
+### Add a select2 field that depends on another field
+
+The ```select2_from_ajax``` and ```select2_from_ajax_multiple``` fields allow you to filter the results of a select2, depending on what has already been selected in a form. Say you have to select2 fields. When the AJAX call is made to the second field, all other variables in the page also get passed - that means you can filter the results of the second select2.
+
+Say you want to show two selects:
+- the first one shows Categories
+- the second one shows Articles, but only from the category above
+
+1. In your CrudController you would do:
+
+```php
+$this->crud->addField([ // SELECT2
+ 'label' => 'Category',
+ 'type' => 'select',
+ 'name' => 'category',
+ 'entity' => 'category',
+ 'attribute' => 'name',
+]);
+
+$this->crud->addField([ // select2_from_ajax: 1-n relationship
+ 'label' => "Article", // Table column heading
+ 'type' => 'select2_from_ajax_multiple',
+ 'name' => 'articles', // the column that contains the ID of that connected entity;
+ 'entity' => 'article', // the method that defines the relationship in your Model
+ 'attribute' => 'title', // foreign key attribute that is shown to user
+ 'data_source' => url('http://github.com/api/article'), // url to controller search function (with /{id} should return model)
+ 'placeholder' => 'Select an article', // placeholder for the select
+ 'include_all_form_fields' => true, //sends the other form fields along with the request so it can be filtered.
+ 'minimum_input_length' => 0, // minimum characters to type before querying results
+ 'dependencies' => ['category'], // when a dependency changes, this select2 is reset to null
+ // 'method' => 'GET', // optional - HTTP method to use for the AJAX call (GET, POST)
+]);
+```
+
+**DIFFERENT HERE**: ```minimum_input_length```, ```dependencies``` and ```include_all_form_fields```.
+
+2. That second select points to routes that need to be registered:
+
+```php
+Route::get('api/article', 'App\Http\Controllers\Api\ArticleController@index');
+Route::get('api/article/{id}', 'App\Http\Controllers\Api\ArticleController@show');
+```
+
+**DIFFERENT HERE**: Nothing.
+
+3. Then that controller would look something like this:
+
+```php
+input('q');
+
+ // NOTE: this is a Backpack helper that parses your form input into an usable array.
+ // you still have the original request as `request('form')`
+ $form = backpack_form_input();
+
+ $options = Article::query();
+
+ // if no category has been selected, show no options
+ if (! $form['category']) {
+ return [];
+ }
+
+ // if a category has been selected, only show articles in that category
+ if ($form['category']) {
+ $options = $options->where('category_id', $form['category']);
+ }
+
+ if ($search_term) {
+ $results = $options->where('title', 'LIKE', '%'.$search_term.'%')->paginate(10);
+ } else {
+ $results = $options->paginate(10);
+ }
+
+ return $results;
+ }
+
+ public function show($id)
+ {
+ return Article::find($id);
+ }
+}
+```
+
+**DIFFERENT HERE**: We use ```$form``` to determine what other variables have been selected in the form, and modify the result accordingly.
+
+
+
+### Change the content class for an operation
+
+If you want to make the contents of an operation take more / less space from the window, you can do that:
+
+(A) for all CRUDs by specifying the custom content class in your ```config/backpack/crud.php```:
+
+```php
+ // Here you may override the css-classes for the content section of the create view globally
+ // To override per view use $this->crud->setCreateContentClass('class-string')
+ 'create_content_class' => 'col-md-8 col-md-offset-2',
+
+ // Here you may override the css-classes for the content section of the edit view globally
+ // To override per view use $this->crud->setEditContentClass('class-string')
+ 'edit_content_class' => 'col-md-8 col-md-offset-2',
+
+ // Here you may override the css-classes for the content section of the revisions timeline view globally
+ // To override per view use $this->crud->setRevisionsTimelineContentClass('class-string')
+ 'revisions_timeline_content_class' => 'col-md-10 col-md-offset-1',
+
+ // Here you may override the css-class for the content section of the list view globally
+ // To override per view use $this->crud->setListContentClass('class-string')
+ 'list_content_class' => 'col-md-12',
+
+ // Here you may override the css-classes for the content section of the show view globally
+ // To override per view use $this->crud->setShowContentClass('class-string')
+ 'show_content_class' => 'col-md-8 col-md-offset-2',
+
+ // Here you may override the css-classes for the content section of the reorder view globally
+ // To override per view use $this->crud->setReorderContentClass('class-string')
+ 'reorder_content_class' => 'col-md-8 col-md-offset-2',
+```
+
+(B) for a single CRUD, by using:
+
+```php
+$this->crud->setCreateContentClass('col-md-8 col-md-offset-2');
+$this->crud->setUpdateContentClass('col-md-8 col-md-offset-2');
+$this->crud->setListContentClass('col-md-8 col-md-offset-2');
+$this->crud->setShowContentClass('col-md-8 col-md-offset-2');
+$this->crud->setReorderContentClass('col-md-8 col-md-offset-2');
+$this->crud->setRevisionsTimelineContentClass('col-md-8 col-md-offset-2');
+```
+
+
+
+### Overwrite a Method on the CrudPanel Object
+
+Starting with Backpack v4, you can use a custom CrudPanel object instead of the one in the package. In your custom CrudPanel object, you can overwrite any method you want, but please note that this means that you're overwriting core components, and will be making it more difficult to upgrade to newer versions of Backpack.
+
+You can do this in any of your service providers (ex: ```app/Providers/AppServiceProvider.php```) to load your class instead of the one in the package:
+
+```php
+$this->app->extend('crud', function () {
+ return new \App\MyExtendedCrudPanel;
+});
+```
+
+Details and implementation [here](https://github.com/Laravel-Backpack/CRUD/pull/1990).
diff --git a/4.1/crud-operation-clone.md b/4.1/crud-operation-clone.md
new file mode 100644
index 00000000..96d8a8c6
--- /dev/null
+++ b/4.1/crud-operation-clone.md
@@ -0,0 +1,127 @@
+# Clone Operation
+
+--
+
+
+## About
+
+This CRUD operation allows your admins to duplicate one or more entries from the database.
+
+>**IMPORTANT:** The clone operation does NOT duplicate related entries. So n-n relationships will be unaffected. However, this also means that n-n relationships are ignored. So when you clone an entry, the new entry:
+>- will NOT have the same 1-1 relationships
+>- will have the same 1-n relationships
+>- will NOT have the same n-1 relationships
+>- will NOT have the same n-n relationships
+>
+>This might be somewhat counterintuitive for end users - though it should make perfect sense for us developers. This is why the Clone operation is NOT enabled by default.
+
+
+## Clone a Single Item
+
+
+### How it Works
+
+Using AJAX, a POST request is performed towards ```/entity-name/{id}/clone```, which points to the ```clone()``` method in your EntityCrudController.
+
+
+### How to Use
+
+To enable it, you need to ```use \Backpack\CRUD\app\Http\Controllers\Operations\CloneOperation;``` on your EntityCrudController. For example:
+
+```php
+crud->setModel(\App\Models\Product::class);
+ $this->crud->setRoute(backpack_url('http://github.com/product'));
+ $this->crud->setEntityNameStrings('product', 'products');
+ }
+}
+```
+
+This will make the Clone button appear in the table view, and will allow access to the controller method if manually accessed.
+
+
+### How to Overwrite
+
+In case you need to change how this operation works, overwrite the ```clone()``` trait method in your EntityCrudController; make sure you give the method in the trait a different name, so that there are no conflicts:
+
+```php
+use \Backpack\CRUD\app\Http\Controllers\Operations\CloneOperation { clone as traitClone; }
+
+public function clone($id)
+{
+ $this->crud->hasAccessOrFail('clone');
+ $this->crud->setOperation('clone');
+
+ // whatever you want
+
+ // if you still want to call the old clone method
+ $this->traitClone($id);
+}
+```
+
+You can also overwrite the clone button by creating a file with the same name inside your ```resources/views/vendor/backpack/crud/buttons/```. You can easily publish the clone button there to make changes using:
+
+```zsh
+php artisan backpack:publish crud/buttons/clone
+```
+
+
+## Clone Multiple Items (Bulk Clone)
+
+In addition to the button for each entry, you can show checkboxes next to each element, and allow your admin to clone multiple entries at once.
+
+
+
+### How it Works
+
+Using AJAX, a POST request is performed towards ```/entity-name/bulk-clone```, which points to the ```bulkClone()``` method in your EntityCrudController.
+
+
+### How to Use
+
+To enable it, you need to ```use \Backpack\CRUD\app\Http\Controllers\Operations\BulkCloneOperation;``` on your EntityCrudController.
+
+
+### How to Overwrite
+
+In case you need to change how this operation works, just create a ```bulkClone()``` method in your EntityCrudController:
+
+```php
+use \Backpack\CRUD\app\Http\Controllers\Operations\BulkCloneOperation { bulkClone as traitBulkClone; }
+
+public function bulkClone($id)
+{
+ // your custom code here
+ //
+ // then you can call the old bulk clone if you want
+ $this->traitBulkClone($id);
+}
+```
+
+You can also overwrite the bulk clone button by creating a file with the same name inside your ```resources/views/vendor/backpack/crud/buttons/```. You can easily publish the clone button there to make changes using:
+
+```zsh
+php artisan backpack:publish crud/buttons/bulk_clone
+```
+
+
+## Exempt attributes when cloning
+If you have attributes that should not be cloned (eg. a SKU with an unique constraint), you can overwrite the replicate method on your model:
+
+```php
+ public function replicate(array $except = null) {
+
+ return parent::replicate(['sku']);
+ }
+```
diff --git a/4.1/crud-operation-create.md b/4.1/crud-operation-create.md
new file mode 100644
index 00000000..29dfa829
--- /dev/null
+++ b/4.1/crud-operation-create.md
@@ -0,0 +1,135 @@
+# Create Operation
+
+---
+
+
+## About
+
+This operation allows your admins to add new entries to a database table.
+
+
+
+
+## Requirements
+
+All editable attributes should be ```$fillable``` on your Model.
+
+
+## How to Use
+
+To use the Create operation, you must:
+
+**Step 0. Use the operation trait on your EntityCrudController**. This should be as simple as this:
+
+```php
+crud->setValidation(StoreRequest::class);
+ // $this->crud->addField($field_definition_array);
+ }
+}
+```
+
+**Step 1. Specify what field types** you'd like to show for each editable attribute, in your EntityCrudController's ```setupCreateOperation()``` method. You can do that using the [Fields API](/docs/{{version}}/crud-fields#fields-api). In short you can:
+
+```php
+protected function setupCreateOperation()
+{
+ $this->crud->addField($field_definition_array);
+}
+```
+
+**Step 2. Specify validation rules, in your the EntityCrudRequest file**. Then make sure that file is used for validation, by telling the CRUD to validate that request file in ```setupCreateOperation()```:
+```php
+$this->crud->setValidation(StoreRequest::class);
+```
+
+For more on how to manipulate fields, please read the [Fields documentation page](/docs/{{version}}/crud-fields). For more on validation rules, check out [Laravel's validation docs](https://laravel.com/docs/master/validation#available-validation-rules).
+
+
+## How It Works
+
+CrudController is a RESTful controller, so the ```Create``` operation uses two routes:
+- GET to ```/entity-name/create``` - points to ```create()``` which shows the Add New Entry form (```create.blade.php```);
+- POST to ```/entity-name``` - points to ```store()``` which does the actual storing operation;
+
+The ```create()``` method will show all the fields you've defined for this operation using the [Fields API](/docs/{{version}}/crud-fields#fields-api), then upon Save the ```store()``` method will first check the validation from the FormRequest you've specified, then create the entry using the Eloquent model. Only attributes that are specified as fields, and are ```$fillable``` on the model will actually be stored in the database.
+
+
+## Callbacks
+
+Developers coming from GroceryCRUD or other CRUD systems will be looking for callbacks to run before_insert, before_update, after_insert, after_update. **There are no callbacks in Backpack**. The store code is inside a trait, so you can easily overwrite it:
+
+```php
+crud->addField(['type' => 'hidden', 'name' => 'author_id']);
+ // $this->crud->removeField('password_confirmation');
+
+ // Note: By default Backpack ONLY saves the inputs that were added on page using Backpack fields.
+ // This is done by stripping the request of all inputs that do NOT match Backpack fields for this
+ // particular operation. This is an added security layer, to protect your database from malicious
+ // users who could theoretically add inputs using DeveloperTools or JavaScript. If you're not properly
+ // using $guarded or $fillable on your model, malicious inputs could get you into trouble.
+
+ // However, if you know you have proper $guarded or $fillable on your model, and you want to manipulate
+ // the request directly to add or remove request parameters, you can also do that.
+ // We have a config value you can set, either inside your operation in `config/backpack/crud.php` if
+ // you want it to apply to all CRUDs, or inside a particular CrudController:
+ // $this->crud->setOperationSetting('saveAllInputsExcept', ['_token', '_method', 'http_referrer', 'current_tab', 'save_action']);
+ // The above will make Backpack store all inputs EXCEPT for the ones it uses for various features.
+ // So you can manipulate the request and add any request variable you'd like.
+ // $this->crud->getRequest()->request->add(['author_id'=> backpack_user()->id]);
+ // $this->crud->getRequest()->request->remove('password_confirmation');
+
+ $response = $this->traitStore();
+ // do something after save
+ return $response;
+ }
+}
+```
+
+>But before you do that, ask yourself - **_is this something that should be done when an entry is added/updated/deleted from the application, too_**? Not just the admin panel? If so, a better place for it would be the Model. Remember your Model is a pure Eloquent Model, so the cleanest way might be to use [Eloquent Event Observers](https://laravel.com/docs/5.5/eloquent#events) or [accessors and mutators](https://laravel.com/docs/master/eloquent-mutators#accessors-and-mutators).
+
+
+## Translatable models and multi-language CRUDs
+
+For UX purposes, when creating multi-language entries, the Create form will only allow the admin to add an entry in one language, the default one. The admin can then edit that entry in all available languages, to translate it. Check out [this same section in the Update operation](/docs/{{version}}/crud-operation-update#translatable-models) for how to enable multi-language functionality.
+
+
+## Separate Validation Rules for Create and Update
+
+**Differences between the Create and Update validations?** If your Update operation requires a different validation than the Create operation, just:
+- create a separate request file for each operation;
+- instruct your EntityCrudController to use separate files, in the "use" section;
+
+For example, we could create ```UpdateTagRequest.php``` and ```CreateTagRequest.php```, with different validations, then in TagCrudController just do:
+```diff
+- use App\Http\Requests\TagRequest as StoreRequest;
++ use App\Http\Requests\CreateTagRequest as StoreRequest;
+- use App\Http\Requests\TagRequest as UpdateRequest;
++ use App\Http\Requests\UpdateTagRequest as UpdateRequest;
+```
diff --git a/4.1/crud-operation-delete.md b/4.1/crud-operation-delete.md
new file mode 100644
index 00000000..36e4a90c
--- /dev/null
+++ b/4.1/crud-operation-delete.md
@@ -0,0 +1,96 @@
+# Delete Operation
+
+--
+
+
+## About
+
+This CRUD operation allows your admins to remove one or more entries from the table.
+
+>In case your entity has SoftDeletes, it will perform a soft delete. The admin will _not_ know that his entry has been hard or soft deleted, since it will no longer show up in the ListEntries view.
+
+
+## Delete a Single Item
+
+
+### How it Works
+
+Using AJAX, a DELETE request is performed towards ```/entity-name/{id}```, which points to the ```destroy()``` method in your EntityCrudController.
+
+
+### How to Use
+
+To enable it, you need to ```use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;``` on your EntityCrudController. For example:
+
+```php
+
+### How to Overwrite
+
+In case you need to change how this operation works, just create a ```destroy()``` method in your EntityCrudController:
+
+```php
+use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation { destroy as traitDestroy; }
+
+public function destroy($id)
+{
+ $this->crud->hasAccessOrFail('delete');
+
+ return $this->crud->delete($id);
+}
+```
+
+You can also overwrite the delete button by creating a file with the same name inside your ```resources/views/vendor/backpack/crud/buttons/```. You can easily publish the delete button there to make changes using:
+
+```zsh
+php artisan backpack:publish crud/buttons/delete
+```
+
+
+## Delete Multiple Items (Bulk Delete)
+
+In addition to the button for each entry, you can show checkboxes next to each element, and allow your admin to delete multiple entries at once.
+
+
+
+### How it Works
+
+Using AJAX, a DELETE request is performed towards ```/entity-name/bulk-delete```, which points to the ```bulkDelete()``` method in your EntityCrudController.
+
+
+### How to Use
+
+You need to ```use \Backpack\CRUD\app\Http\Controllers\Operations\BulkDeleteOperation;``` on your EntityCrudController.
+
+
+### How to Overwrite
+
+In case you need to change how this operation works, just create a ```bulkDelete()``` method in your EntityCrudController:
+
+```php
+use \Backpack\CRUD\app\Http\Controllers\Operations\BulkDeleteOperation { bulkDelete as traitBulkDelete; }
+
+public function bulkDelete($id)
+{
+ // your custom code here
+}
+```
+
+You can also overwrite the bulk delete button by creating a file with the same name inside your ```resources/views/vendor/backpack/crud/buttons/```. You can easily publish the delete button there to make changes using:
+
+```zsh
+php artisan backpack:publish crud/buttons/bulk_delete
+```
diff --git a/4.1/crud-operation-fetch.md b/4.1/crud-operation-fetch.md
new file mode 100644
index 00000000..3f4a8f3e
--- /dev/null
+++ b/4.1/crud-operation-fetch.md
@@ -0,0 +1,157 @@
+# Fetch Operation
+
+---
+
+
+## About
+
+This operation allows an EntityCrudController to respond to AJAX requests with entries in the database for _a different entity_, in a format that can be used by the ```relationship```, ```select2_from_ajax``` and ```select2_from_ajax_multiple``` fields.
+
+
+
+## Requirements
+
+None.
+
+
+## How to Use
+
+In order to enable this operation in your CrudController, you need to:
+1. Use the ```FetchOperation``` trait;
+2. Add a ```fetchEntityName()``` method, that will respond to the AJAX requests (following this naming convention);
+
+```php
+ use \Backpack\CRUD\app\Http\Controllers\Operations\FetchOperation;
+
+ protected function fetchTag()
+ {
+ return $this->fetch(\App\Models\Tag::class);
+ }
+```
+
+To customize the FetchOperation, pass an array to the ```fetch()``` call, rather than a class name. For example:
+
+```php
+fetch([
+ 'model' => \App\Models\Tag::class, // required
+ 'searchable_attributes' => ['name', 'description'],
+ 'paginate' => 10, // items to show per page
+ 'query' => function($model) {
+ return $model->active();
+ } // to filter the results that are returned
+ ]);
+ }
+}
+```
+
+3. A route following has been created automatically to point to the ```fetchTag``` method you created. You now point your AJAX select to this route, using ```backpack_url('http://github.com/your-main-entity/fetch/tag')``` .
+
+
+
+## How It Works
+
+Based on the fact that the ```fetchTag()``` method exist, the Fetch operation will create a ```/product/fetch/tag``` POST route, which points to ```fetchTag()```. Inside ```fetchTag()``` we call ```fetch()```, that responds with entries in the format ```select2``` needs.
+
+**Preventing FetchOperation of guessing the searchable attributes**
+
+If not specified `searchable_attributes` will be automatically infered from model dabatase columns. To prevent this behaviour you can setup an empty `searchable_attributes` array.
+
+That said, you can use something like below:
+
+```php
+public function fetchUser() {
+ return $this->fetch([
+ 'model' => User::class,
+ 'query' => function($model) {
+ $search = request()->input('q') ?? false;
+ if ($search) {
+ return $model->whereRaw('CONCAT(`first_name`," ",`last_name`) LIKE "%' . $search . '%"');
+ }else{
+ return $model;
+ }
+ },
+ 'searchable_attributes' => []
+ ]);
+ }
+```
+
+
+## Using FetchOperation with `select2_ajax` filter
+
+The FetchOperation can also be used as the source URL for the `select2_ajax` filter. To do that, we need to:
+- change the AJAX method from `GET` (the default for this filter) to `POST` (the default for the Fetch operation);
+- tell the filter what attribute we want to show to the user;
+
+```
+$this->crud->addFilter([
+ 'name' => 'category_id',
+ 'type' => 'select2_ajax',
+ 'label' => 'Category',
+ 'placeholder' => 'Pick a category',
+ 'method' => 'POST', // mandatory change
+ // 'select_attribute' => 'name' // the attribute that will be shown to the user by default 'name'
+ // 'select_key' => 'id' // by default is ID, change it if your model uses some other key
+],
+backpack_url('http://github.com/product/fetch/category'), // the fetch route on the ProductCrudController
+function($value) { // if the filter is active
+ // $this->crud->addClause('where', 'category_id', $value);
+});
+
+```
+
+
+
+## How to Overwrite
+
+In case you need to change how this operation works, it's best to take a look at the ```FetchOperation.php``` trait to understand how it works. It's a pretty simple operation. Most common ways to overwrite the Fetch operation are documented below:
+
+**Custom behaviour for one fetch method**
+
+To make a ```fetchCategory()``` method behave differently, you can copy-paste the logic inside the ```FetchOperation::fetch()``` and change it to do whatever you need. Instead of returning ```$this->fetch()``` you can return your own results.
+
+**Custom behaviour for multiple fetch methods inside a Controller**
+
+To make all calls to ```fetch()``` inside an EntityCrudController behave differently, you can easily overwrite the ```fetch()``` method in that controller:
+
+```php
+use \Backpack\CRUD\app\Http\Controllers\Operations\FetchOperation;
+
+public function fetch($arg)
+{
+ // your custom code here
+}
+```
+
+Then all ```$this->fetch()``` calls from that Controller will be using your custom code.
+
+In case you need to call the original ```fetch()``` method (from the trait) inside your custom ```fetch()``` method (inside the controller), you can do:
+
+```php
+use \Backpack\CRUD\app\Http\Controllers\Operations\FetchOperation { fetch as traitFetch; }
+
+public function fetch($arg)
+{
+ // your custom code here
+
+ // call the method in the trait
+ return $this->traitFetch();
+}
+```
+
+**Custom behaviour for all fetch calls, in all Controllers**
+
+If you want all your ```fetch()``` calls to behave differently, no matter what Controller they are in, you can:
+- duplicate the ```FetchOperation``` trait inside your application;
+- instead of using ```\Backpack\CRUD\app\Http\Controllers\Operations\FetchOperation``` inside your controllers, use your custom operation trait;
diff --git a/4.1/crud-operation-inline-create.md b/4.1/crud-operation-inline-create.md
new file mode 100644
index 00000000..1f5e83c7
--- /dev/null
+++ b/4.1/crud-operation-inline-create.md
@@ -0,0 +1,112 @@
+# InlineCreate Operation
+
+---
+
+
+## About
+
+This operation allows your admins to add new entries to a database table on-the-fly, from a modal.
+
+For example:
+- if you have an ```ArticleCrudController``` where your user can also select ```Categories```;
+- this operation adds the ability to create ```Categories``` right inside the ```ArticleCrudController```'s Create form;
+ - the admin needs to click an Add button
+ - a modal will show the form from ```CategoryCrudController```'s Create operation;
+
+
+
+
+
+## Requirements
+
+- a working Create operation;
+- correctly defined Eloquent relationships on both the primary Model, and the secondary Model;
+- a working Fetch operation to retrieve the secondary Model from the primary Model;
+- an understanding of what we call "_main_" and "_secondary_" in this case; using the same example as above, where you want to be able to add ```Categories``` in a modal, inside ```ArticleCrudController```'s create&update forms:
+ - the _main entity_ would be Article (big form);
+ - the _secondary entity_ would be Category (small form, in a modal);
+
+
+## How to Use
+
+> If your field name is comprised of multiple words (eg. `contact_number` or `contactNumber`) you will need to also define the `data_source` attribute for this field; keep in mind that by to generate a route, your field name will be parsed run through `Str::kebab()` - that means `_` (underscore) or `camelCase` will be converted to `-` (hyphens), so in `fetch` your route will be `contact-number` instead of the expected `contactNumber`. To fix this, you need to define: `data_source => backpack_url('http://github.com/monster/fetch/contact-number')` (replace with your strings)
+
+To use the Create operation, you must:
+
+**Step 1. Use the operation trait on your secondary entity's CrudController** (aka. the entity that will gain the ability to be created inline, in our example CategoryCrudController). Make sure you use `InlineCreateOperation` *after* `CreateOperation`:
+
+```php
+crud->setValidation(StoreRequest::class);
+ // $this->crud->addField($field_definition_array);
+ // }
+}
+```
+
+**Step 2. Use [the relationship field](/docs/{{version}}/crud-fields#relationship) inside the ```setupCreateOperation()``` or ```setupUpdateOperation()``` of the main entity** (where you'd like to be able to click a button and a modal shows up, in our example ArticleCrudController), and define ```inline_create``` on it:
+
+```php
+// for 1-n relationships (ex: category) - inside ArticleCrudController
+[
+ 'type' => "relationship",
+ 'name' => 'category', // the method on your model that defines the relationship
+ 'ajax' => true,
+ 'inline_create' => true, // assumes the URL will be "/admin/category/inline/create"
+]
+
+// for n-n relationships (ex: tags) - inside ArticleCrudController
+[
+ 'type' => "relationship",
+ 'name' => 'tags', // the method on your model that defines the relationship
+ 'ajax' => true,
+ 'inline_create' => [ 'entity' => 'tag' ] // specify the entity in singular
+ // that way the assumed URL will be "/admin/tag/inline/create"
+]
+
+// OPTIONALS - to customize behaviour
+[
+ 'type' => "relationship",
+ 'name' => 'tags', // the method on your model that defines the relationship
+ 'ajax' => true,
+ 'inline_create' => [ // specify the entity in singular
+ 'entity' => 'tag', // the entity in singular
+ // OPTIONALS
+ 'force_select' => true, // should the inline-created entry be immediately selected?
+ 'modal_class' => 'modal-dialog modal-xl', // use modal-sm, modal-lg to change width
+ 'modal_route' => route('tag-inline-create'), // InlineCreate::getInlineCreateModal()
+ 'create_route' => route('tag-inline-create-save'), // InlineCreate::storeInlineCreate()
+ 'include_main_form_fields' => ['field1', 'field2'], // pass certain fields from the main form to the modal
+ ]
+```
+
+
+**Step 3. OPTIONAL - You can create a ```setupInlineCreateOperation()``` method in the EntityCrudController**, to make the InlineCreateOperation different to the CreateOperation, for example have more/less fields, or different fields. Check out the [Fields API](/docs/{{version}}/crud-fields#fields-api) for a reference of all you can do with them.
+
+
+## How It Works
+
+The ```CreateInline``` operation uses two routes:
+- POST to ```/entity-name/inline/create/modal``` - ```getInlineCreateModal()``` which returns the contents of the Create form, according to how it's been defined by the CreateOperation (in ```setupCreateOperation()```, then overwritten by the InlineCreateOperation (in ```setupInlineCreateOperation()```);
+- POST to ```/entity-name/inline/create``` - points to ```storeInlineCreate()``` which does the actual saving in the database by calling the ```store()``` method from the CreateOperation;
+
+Since this operation is just a way to allow access to the Create operation from a modal, the ```getInlineCreateModal()``` method will show all the fields you've defined for this operation using the [Fields API](/docs/{{version}}/crud-fields#fields-api), then upon Save the ```store()``` method will first check the validation from the FormRequest you've specified, then create the entry using the Eloquent model. Only attributes that are specified as fields, and are ```$fillable``` on the model will actually be stored in the database.
diff --git a/4.1/crud-operation-list-entries.md b/4.1/crud-operation-list-entries.md
new file mode 100644
index 00000000..07575546
--- /dev/null
+++ b/4.1/crud-operation-list-entries.md
@@ -0,0 +1,237 @@
+# List Operation
+
+---
+
+
+## About
+
+This operation shows a table with all database entries. It's the first page the admin lands on (for an entity), and it's usually the gateway to all other operations, because it holds all the buttons.
+
+A simple List view might look like this:
+
+
+
+But a complex implementation of the ListEntries operation, using Columns, Filters, custom Buttons, custom Operations, responsive table, Details Row, Export Buttons will still look pretty good:
+
+
+
+You can easily customize [columns](#columns), [buttons](#buttons), [filters](#filters), [enable/disable additional features we've built](#other-features), or [overwrite the view and build your own features](#how-to-overwrite).
+
+
+## How It Works
+
+The main route leads to ```EntityCrudController::index()```, which shows the table view (```list.blade.php```. Inside that table view, we're using AJAX to fetch the entries and place them inside DataTables. That AJAX points to the same controller, ```EntityCrudController::search()```.
+
+Actions:
+- ```index()```
+- ```search()```
+
+For views, it uses:
+- ```list.blade.php```
+- ```columns/```
+- ```buttons/```
+
+
+## How to Use
+
+Use the operation trait on your controller:
+```php
+crud->addColumn();
+ }
+}
+```
+
+Configuration for this operation should be done inside your ```setupListOperation()``` method. **For a minimum setup, you only need to define the columns you need to show in the table.**
+
+
+### Columns
+
+The List operation uses "columns" to determine how to show the attributes of an entry to the user. All column types must have their ```name```, ```label``` and ```type``` specified, but some could require some additional attributes.
+
+```php
+$this->crud->addColumn([
+ 'name' => 'name', // The db column name
+ 'label' => "Tag Name", // Table column heading
+ 'type' => 'Text'
+]);
+```
+
+Backpack has 22+ [column types](/docs/{{version}}/crud-columns) you can use. Plus, you can easily [create your own type of column](/docs/{{version}}/crud-columns##creating-a-custom-column-type). **Check out the [Columns](/docs/{{version}}/crud-columns##creating-a-custom-column-type) documentation page** for a detailed look at column types, API and usage.
+
+
+### Buttons
+
+Buttons are used to trigger other operations. Some point to entirely new routes (```create```, ```update```, ```show```), others perform the operation on the current page using AJAX (```delete```).
+
+The ShowList operation has 3 places where buttons can be placed:
+ - ```top``` (where the Add button is)
+ - ```line``` (where the Edit and Delete buttons are)
+ - ```bottom``` (after the table)
+
+Backpack adds a few buttons by default:
+- ```add``` to the ```top``` stack;
+- ```edit``` and ```delete``` to the ```line``` stack;
+
+To learn more about buttons, **check out the [Buttons](/docs/{{version}}/crud-buttons) documentation page**.
+
+
+### Filters
+
+Filters show up right before the actual table, and provide a way for the admin to filter the results in the ListEntries table. To learn more about filters, **check out the [Filters](/docs/{{version}}/crud-filters) documentation page**.
+
+
+### Other Features
+
+
+#### Details Row
+
+The details row functionality allows you to present more information in the table view of a CRUD. When enabled, a "+" button will show up next to every row, which on click will expand a "details row" below it, showing additional information.
+
+
+
+On click, an AJAX request is sent to the ```entity/{id}/details``` route, which calls the ```showDetailsRow()``` method on your EntityCrudController. Everything returned by that method is then shown in the details row. You'll want to overwrite that method to show anything you'd like in the details row.
+
+To use, inside your ```EntityCrudController```:
+1. Enable the functionality: ```$this->crud->enableDetailsRow();```
+2. Overwrite the ```showDetailsRow($id)``` method;
+
+Alternative for the 2nd step: overwrite ```views/backpack/crud/details_row.blade.php``` which is called by the default ```showDetailsRow($id)``` functionality.
+
+```php
+class EntityCrudController extends CrudController
+{
+ use \Backpack\CRUD\app\Http\Operations\ListOperation;
+
+ protected $setupDetailsRowRoutes = false;
+}
+```
+
+#### Export Buttons
+
+Exporting the DataTable to PDF, CSV, XLS is as easy as typing ```$this->crud->enableExportButtons();``` in your constructor.
+
+
+
+**Please note that when clicked, the button will export**
+- **the _currently visible_ table columns** (except columns marked as ```visibleInExport => false```);
+- **the columns that are forced to export** (with ```visibleInExport => true``` or ```exportOnlyField => true```);
+
+**In the UI, the admin can use the "Visibility" button, and the "Items per page" dropdown to manipulate what is visible in the table - and consequently what will be exported.**
+
+**Export Buttons Rules**
+
+Available customization:
+```
+'visibleInExport' => true/false
+'visibleInTable' => true/false
+'exportOnlyField' => true
+```
+
+By default, the field will start visible in the table. Users can hide it toggling visibility. Will be exported if visible in the table.
+
+If you force `visibleInExport => true` you are saying that independent of field visibility in table it will **always** be exported.
+
+Contrary is `visibleInExport => false`, even if visible in table, field will not be exported as per developer instructions.
+
+Setting `visibleInTable => true` will force the field to stay in the table no matter what. User can't hide it. (By default all fields visible in the table will be exported. If you don't want to export this field use with combination with `visibleInExport => false`)
+
+Using `'visibleInTable' => false` will make the field start hidden in the table. But users can toggle it's visibility.
+
+If you want a field that is not on table, user can't show it, but will **ALWAYS** be exported use the `exportOnlyField => true`. If used will ignore any other custom visibility you defined.
+
+
+#### Custom Query
+
+By default, all entries are shown in the ListEntries table, before filtering. If you want to restrict the entries to a subset, you can use the methods below in your EntityCrudController's ```setupListOperation()``` method:
+
+```php
+// Change what entries are shown in the table view.
+// This changes all queries on the table view,
+// as opposed to filters, who only change it when that filter is applied.
+$this->crud->addClause('active'); // apply a local scope
+$this->crud->addClause('type', 'car'); // apply local dynamic scope
+$this->crud->addClause('where', 'name', '=', 'car');
+$this->crud->addClause('whereName', 'car');
+$this->crud->addClause('whereHas', 'posts', function($query) {
+ $query->activePosts();
+ });
+$this->crud->groupBy();
+$this->crud->limit();
+
+$this->crud->orderBy();
+// please note it's generally a good idea to use crud->orderBy() inside "if (!$this->crud->getRequest()->has('order')) {}"; that way, your custom order is applied ONLY IF the user hasn't forced another order (by clicking a column heading)
+```
+
+
+#### Responsive Table
+
+If your CRUD table has more columns than can fit inside the viewport (on mobile / tablet or smaller desktop screens), unimportant columns will start hiding and an expansion icon (three dots) will appear to the left of each row. We call this behaviour "_responsive table_", and consider this to be the best UX. By behaviour we consider the 1st column the most important, then 2nd, then 3rd, etc; the "actions" column is considered as important as the 1st column. You can of course [change the importance of columns](/docs/{{version}}/crud-columns#define-which-columns-to-hide-in-responsive-table).
+
+If you do not like this, you can **toggle off the responsive behaviour for all CRUD tables** by changing this config value in your ```config/backpack/crud.php``` to ```false```:
+```php
+ // enable the datatables-responsive plugin, which hides columns if they don't fit?
+ // if not, a horizontal scrollbar will be shown instead
+ 'responsive_table' => true
+```
+
+To turn off the responsive table behaviour for _just one CRUD panel_, you can use ```$this->crud->disableResponsiveTable()``` in your ```setupListOperation()``` method.
+
+
+#### Persistent Table
+
+By default, ListEntries will NOT remember your filtering, search and pagination when you leave the page. If you want ListEntries to do that, you can enable a ListEntries feature we call ```persistent_table```.
+
+**This will take the user back to the _filtered table_ after adding an item, previewing an item, creating an item or just browsing around**, preserving the table just like he/she left it - with the same filtering, pagination and search applied. It does so by saving the pagination, search and filtering for an arbitrary amount of time (by default: forever).
+
+To use ```persistent_table``` you can:
+- enable it for all CRUDs with the config option ```'persistent_table' => true``` in your ```config/backpack/crud.php```;
+- enable it inside a particular crud controller with ```$this->crud->enablePersistentTable();```
+- disable it inside a particular crud controller with ```$this->crud->disablePersistentTable();```
+
+> You can configure the persistent table duration in ``` config/backpack/crud.php ``` under `operations > list > persistentTableDuration`. False is forever. Set any amount of time you want in minutes. Note: you can configure it's expiring time on a per-crud basis using `$this->crud->setOperationSetting('persistentTableDuration', 120); in your setupListOperation()` for 2 hours persistency. The default is `false` which means forever.
+
+
+## How to Overwrite
+
+The main route leads to ```EntityCrudController::index()```, which loads ```list.blade.php```. Inside that table view, we're using AJAX to fetch the entries and place them inside a DataTables. The AJAX points to the same controller, ```EntityCrudController::search()```.
+
+
+### The View
+
+You can change how the ```list.blade.php``` file looks and works, by just placing a file with the same name in your ```resources/views/vendor/backpack/crud/list.blade.php```. To quickly do that, run:
+
+```zsh
+php artisan backpack:publish crud/list
+```
+
+Keep in mind that by publishing this file, you won't be getting any updates we'll be pushing to it.
+
+
+### The Operation Logic
+
+Getting and showing the information is done inside the ```index()``` method. Take a look at the ```CrudController::index()``` method (your EntityCrudController is extending this CrudController) to see how it works.
+
+To overwrite it, just create an ```index()``` method in your ```EntityCrudController```.
+
+
+### The Search Logic
+
+An AJAX call is made to the ```search()``` method:
+- when entries are shown in the table;
+- when entries are filtered in the table;
+- when search is performed on the table;
+- when pagination is performed on the table;
+
+You can of course overwrite this ```search()``` method by just creating one with the same name in your ```EntityCrudController```. In addition, you can overwrite what a specific column is searching through (and how), by [using the searchLogic attribute](/docs/{{version}}/crud-columns#custom-search-logic) on columns.
diff --git a/4.1/crud-operation-reorder.md b/4.1/crud-operation-reorder.md
new file mode 100644
index 00000000..4f2de640
--- /dev/null
+++ b/4.1/crud-operation-reorder.md
@@ -0,0 +1,82 @@
+# Reorder Operation
+
+---
+
+
+## About
+
+This operation allows your admins to reorder & nest entries.
+
+
+
+
+## Requirements
+
+Your model should have the following integer fields, with a default value of 0: ```parent_id```, ```lft```, ```rgt```, ```depth```.
+
+Additionally, the `parent_id` field has to be nullable.
+
+
+## How to Use
+
+In order to enable this operation in your CrudController, you need to use the ```ReorderOperation``` trait, and have a ```setupReorderOperation()``` method that defines the ```label``` and ```max_level``` of allowed depth.
+
+```php
+crud->set('reorder.label', 'name');
+ // define how deep the admin is allowed to nest the items
+ // for infinite levels, set it to 0
+ $this->crud->set('reorder.max_level', 2);
+ }
+}
+```
+
+This will:
+- allow access to the Reorder operation;
+- make a "Reorder" button appear next to "Add entry" in the List view, if the List operation is enabled;
+- enable the routes needed by the Reorder operation;
+
+Where:
+- ```attribute_name``` should be the attribute you want shown on the draggable elements (ex: ```name```);
+- ```ALLOWED_DEPTH``` should be an integer, how many levels deep would you allow your admin to go when nesting; for infinite levels, you should set it to ```0```;
+
+
+## How It Works
+
+The ```/reorder``` route points to a ```reorder()``` method in your ```EntityCrudController```.
+
+
+
+## How to Overwrite
+
+In case you need to change how this operation works, take a look at the ```ReorderOperation.php``` trait to understand how it works. You can easily overwrite the ```reorder()``` or the ```saveReorder()``` methods:
+
+```php
+use \Backpack\CRUD\app\Http\Controllers\Operations\ReorderOperation { reorder as traitReorder; }
+
+public function reorder()
+{
+ // your custom code here
+
+ // call the method in the trait
+ return $this->traitReorder();
+}
+```
+
+You can also overwrite the reorder button by creating a file with the same name inside your ```resources/views/vendor/backpack/crud/buttons/```. You can easily publish the reorder button there to make changes using:
+
+```zsh
+php artisan backpack:publish crud/buttons/reorder
+```
diff --git a/4.1/crud-operation-revisions.md b/4.1/crud-operation-revisions.md
new file mode 100644
index 00000000..8f841408
--- /dev/null
+++ b/4.1/crud-operation-revisions.md
@@ -0,0 +1,71 @@
+# Revise Operation
+
+---
+
+
+## About
+
+Revise allows your admins to store, see and undo changes to entries on an Eloquent model.
+
+The operation provides you with a simple interface to work with [venturecraft/revisionable](https://github.com/VentureCraft/revisionable#implementation), which is a great package that stores all changes in a separate table. It can work as an audit trail, a backup system and an accountability system for the admins.
+
+When enabled, ```Revise``` will show another button in the table view, between _Edit_ and _Delete_. On click, that button opens another page which will allow an admin to see all changes and who made them:
+
+
+
+
+
+
+## How to Use
+
+In order to enable this operation for a CrudController, you need to:
+
+**Step 1.** Install [the package](https://github.com/laravel-backpack/revise-operation) that provides this operation. This will also install venturecraft/revisionable if it's not already installed in your project.
+
+```bash
+composer require backpack/revise-operation
+```
+
+**Step 2.** Create the revisions table:
+
+```bash
+cp vendor/venturecraft/revisionable/src/migrations/2013_04_09_062329_create_revisions_table.php database/migrations/ && php artisan migrate
+```
+
+**Step 3.** Use [venturecraft/revisionable](https://github.com/VentureCraft/revisionable#implementation)'s trait on your model, and an ```identifiableName()``` method that returns an attribute on the model that the admin can use to distinguish between entries (ex: name, title, etc). If you are using another bootable trait be sure to override the boot method in your model.
+
+```php
+namespace App\Models;
+
+class Article extends Eloquent {
+ use \Backpack\CRUD\app\Models\Traits\CrudTrait, \Venturecraft\Revisionable\RevisionableTrait;
+
+ public function identifiableName()
+ {
+ return $this->name;
+ }
+
+ // If you are using another bootable trait
+ // be sure to override the boot method in your model
+ public static function boot()
+ {
+ parent::boot();
+ }
+}
+```
+
+**Step 4.** In your CrudController, use the operation trait:
+
+```php
+
+## About
+
+This CRUD operation allows your admins to preview an entry. When enabled, it will add a "Preview" button in the ListEntries view, that points to a show page:
+
+
+
+In case your entity is translatable, it will show a multi-language dropdown, just like Edit.
+
+
+## How it Works
+
+The ```/entity-name/{id}/show``` route points to the ```show()``` method in your EntityCrudController. Inside this method, it uses ```setFromDb()``` to try to magically figure out all attributes you would like shown for this Model, and shows them using [Column types](/docs/{{version}}/crud-columns) inside ```show.blade.php```.
+
+
+## How to Use
+
+To enable this operation, you need to use the ```ShowOperation``` trait on your CrudController:
+
+```php
+crud->set('show.setFromDb', false);
+
+ // example logic
+ $this->crud->addColumn([
+ 'name' => 'table',
+ 'label' => 'Table',
+ 'type' => 'table',
+ 'columns' => [
+ 'name' => 'Name',
+ 'desc' => 'Description',
+ 'price' => 'Price',
+ ]
+ ]);
+ $this->crud->addColumn([
+ 'name' => 'fake_table',
+ 'label' => 'Fake Table',
+ 'type' => 'table',
+ 'columns' => [
+ 'name' => 'Name',
+ 'desc' => 'Description',
+ 'price' => 'Price',
+ ],
+ ]);
+ $this->crud->addColumn('text');
+ // $this->crud->removeColumn('date');
+ // $this->crud->removeColumn('extras');
+
+ // Note: if you HAVEN'T set show.setFromDb to false, the removeColumn() calls won't work
+ // because setFromDb() is called AFTER setupShowOperation(); we know this is not intuitive at all
+ // and we plan to change behaviour in the next version; see this Github issue for more details
+ // https://github.com/Laravel-Backpack/CRUD/issues/3108
+ }
+```
+
+
+## How to Overwrite
+
+In case you need to modify the show logic in a meaningful way, you can create a ```show()``` method in your EntityCrudController. The route will then point to your method, instead of the one in the trait. For example:
+
+```php
+use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation { show as traitShow; }
+
+public function show($id)
+{
+ // custom logic before
+ $content = $this->traitShow($id);
+ // cutom logic after
+ return $content;
+}
+```
diff --git a/4.1/crud-operation-update.md b/4.1/crud-operation-update.md
new file mode 100644
index 00000000..3e4aa3f0
--- /dev/null
+++ b/4.1/crud-operation-update.md
@@ -0,0 +1,239 @@
+# Update Operation
+
+---
+
+
+## About
+
+This operation allows your admins to edit entries from the database.
+
+
+
+
+## Requirements
+
+All editable attributes should be ```$fillable``` on your Model.
+
+
+## How to Use
+
+**Step 0. Use the operation trait on your controller**:
+
+```php
+crud->setValidation(StoreRequest::class);
+ // $this->crud->addField()
+
+ // or just do everything you've done for the Create Operation
+ // $this->crud->setupCreateOperation();
+
+ // You can also do things depending on the current entry
+ // (the database item being edited or updated)
+ // if ($this->crud->getCurrentEntry()->smth == true) {}
+ }
+}
+```
+
+This will:
+- allow access to this operation;
+- make an Edit button appear in the ```line``` stack, next to each entry, in the List operation view;
+
+To use the Update operation, you must:
+
+**Step 1. Specify what field types** you'd like to show for each attribute, in your controller's ```setupUpdateOperation()``` method. You can do that using the [Fields API](/docs/{{version}}/crud-fields#fields-api). In short you can:
+
+```php
+// add a field only to the Update operation
+$this->crud->addField($field_definition_array);
+// add a field to both the Update and Update operations
+$this->crud->addField($field_definition_array);
+```
+
+**Step 2. Specify which FormRequest file to use for validation and authorization**, inside your ```setupUpdateOperation()``` method. You can pass the same FormRequest as you did for the Create operation if there are no differences. If you need separate validation for Create and Update [look here](#separate-validation).
+```php
+$this->crud->setValidation(StoreRequest::class);
+```
+
+For more on how to manipulate fields, please read the [Fields documentation page](/docs/{{version}}/crud-fields). For more on validation rules, check out [Laravel's validation docs](https://laravel.com/docs/master/validation#available-validation-rules).
+
+
+## How It Works
+
+CrudController is a RESTful controller, so the ```Update``` operation uses two routes:
+- GET to ```/entity-name/{id}/edit``` - points to ```edit()``` which shows the Edit form (```edit.blade.php```);
+- POST to ```/entity-name/{id}/edit``` - points to ```update()``` which uses Eloquent to update the entry in the database;
+
+The ```edit()``` method will show all the fields you've defined for this operation using the [Fields API](/docs/{{version}}/crud-fields#fields-api), then upon Save the ```update()``` method will first check the validation from the typehinted FormRequest, then create the entry using the Eloquent model. Only attributes that have a field type added and are ```$fillable``` on the model will actually be updated in the database.
+
+
+## Callbacks
+
+Developers coming from GroceryCRUD or other CRUD systems will be looking for callbacks to run before_insert, before_update, after_insert, after_update. **There are no callbacks in Backpack**. The store code is inside a trait, so you can easily overwrite it:
+
+```php
+crud->addField(['type' => 'hidden', 'name' => 'author_id']);
+ // $this->crud->removeField('password_confirmation');
+
+ // Note: By default Backpack ONLY saves the inputs that were added on page using Backpack fields.
+ // This is done by stripping the request of all inputs that do NOT match Backpack fields for this
+ // particular operation. This is an added security layer, to protect your database from malicious
+ // users who could theoretically add inputs using DeveloperTools or JavaScript. If you're not properly
+ // using $guarded or $fillable on your model, malicious inputs could get you into trouble.
+
+ // However, if you know you have proper $guarded or $fillable on your model, and you want to manipulate
+ // the request directly to add or remove request parameters, you can also do that.
+ // We have a config value you can set, either inside your operation in `config/backpack/crud.php` if
+ // you want it to apply to all CRUDs, or inside a particular CrudController:
+ // $this->crud->setOperationSetting('saveAllInputsExcept', ['_token', '_method', 'http_referrer', 'current_tab', 'save_action']);
+ // The above will make Backpack store all inputs EXCEPT for the ones it uses for various features.
+ // So you can manipulate the request and add any request variable you'd like.
+ // $this->crud->getRequest()->request->add(['author_id'=> backpack_user()->id]);
+ // $this->crud->getRequest()->request->remove('password_confirmation');
+ // $this->crud->getRequest()->request->add(['author_id'=> backpack_user()->id]);
+ // $this->crud->getRequest()->request->remove('password_confirmation');
+
+ $response = $this->traitUpdate();
+ // do something after save
+ return $response;
+ }
+}
+```
+
+>But before you do that, ask yourself - **_is this something that should be done when an entry is added/updated/deleted from the application, too_**? Not just the admin admin? If so, a better place for it would be the Model. Remember your Model is a pure Eloquent Model, so the cleanest way might be to use [Eloquent Event Observers](https://laravel.com/docs/5.5/eloquent#events) or [accessors and mutators](https://laravel.com/docs/master/eloquent-mutators#accessors-and-mutators).
+
+
+## Translatable models and multi-language CRUDs
+
+
+
+For localized apps, you can let your admins edit multi-lingual entries. Translations are stored using [spatie/laravel-translatable](https://github.com/spatie/laravel-translatable).
+
+In order to make one of your Models translatable (localization), you need to:
+0. Be running MySQL 5.7+ (or a PostgreSQL with JSON column support);
+1. [Install spatie/laravel-translatable](https://github.com/spatie/laravel-translatable#installation);
+2. In your database, make all translatable columns either JSON or TEXT.
+3. Use Backpack's ```HasTranslations``` trait on your model (instead of using spatie's ```HasTranslations```) and define what fields are translatable, inside the ```$translatable``` property. For example:
+
+```php
+ You DO NOT need to cast translatable string columns as array/json/object in the Eloquent model. From Eloquent's perspective they're strings. So:
+> - you _should NOT_ cast ```name```; it's a string in Eloquent, even though it's stored as JSON in the db by SpatieTranslatable;
+> - you _should_ cast ```extras``` to ```array```, if each translation stores an array of some sort;
+
+Change the languages available to translate to/from, in your crud config file (```config/backpack/crud.php```). By default there are quite a few enabled (English, French, German, Italian, Romanian).
+
+Additionally, if you have slugs (but only if you need translatable slugs), you'll need to use backpack's classes instead of the ones provided by cviebrock/eloquent-sluggable:
+
+```php
+ [
+ 'source' => 'slug_or_name',
+ ],
+ ];
+ }
+}
+```
+> If your slugs are not translatable, use the ```cviebrock/eloquent-sluggable``` traits. The Backpack's ```Sluggable``` trait saves your slug as a JSON object, regardless of the ```slug``` field being defined inside the ```$translatable``` property.
+
+
+## Separate Validation Rules for Create and Update
+
+**Differences between the Create and Update validations?** If your Update operation requires a different validation than the Create operation, just:
+- create a separate request file for each operation;
+- instruct your EntityCrudController to use separate files, in the "use" section;
+
+For example, we could create ```UpdateTagRequest.php``` and ```CreateTagRequest.php```, with different validations, then in TagCrudController just do:
+```diff
+- use App\Http\Requests\TagRequest as StoreRequest;
++ use App\Http\Requests\CreateTagRequest as StoreRequest;
+- use App\Http\Requests\TagRequest as UpdateRequest;
++ use App\Http\Requests\UpdateTagRequest as UpdateRequest;
+```
diff --git a/4.1/crud-operations.md b/4.1/crud-operations.md
new file mode 100644
index 00000000..c4a60df6
--- /dev/null
+++ b/4.1/crud-operations.md
@@ -0,0 +1,966 @@
+# Operations
+
+---
+
+When creating a CRUD Panel, your ```EntityCrudController``` (where Entity = your model name) is extending ```CrudController```. **By default, no operations are enabled.** No routes are registered.
+
+To use an operation, you need to use the operation trait on your controller. For example, to enable the List operation:
+
+```php
+
+## Standard Operations
+
+No operations are enabled by default.
+
+But Backpack does provide the logic for the most common operations admins perform on Eloquent model. You just need to use it (and maybe configure it) in your controller.
+
+Operations provided by Backpack:
+- [List](/docs/{{version}}/crud-operation-list-entries) - allows the admin to see all entries for an Eloquent model, with pagination, search, filters;
+- [Create](/docs/{{version}}/crud-operation-create) - allows the admin to add a new entry;
+- [Update](/docs/{{version}}/crud-operation-update) - allows the admin to edit an existing entry;
+- [Show](/docs/{{version}}/crud-operation-show) - allows the admin to preview an entry;
+- [Delete](/docs/{{version}}/crud-operation-delete) - allows the admin to remove and entry;
+- [BulkDelete](/docs/{{version}}/crud-operation-delete) - allows the admin to remove multiple entries in one go;
+- [Clone](/docs/{{version}}/crud-operation-clone) - allows the admin to make a copy of a database entry;
+- [BulkClone](/docs/{{version}}/crud-operation-clone) - allows the admin to make a copy of multiple database entries in one go;
+- [Reorder](/docs/{{version}}/crud-operation-reorder) - allows the admin to reorder & nest all entries of a model, in a hierarchy tree;
+- [Revisions](/docs/{{version}}/crud-operation-revisions) - shows an audit log of all changes to an entry, and allows the admin to undo modifications;
+
+
+
+### Operation Actions
+
+Each Operation is actually _a trait_, which can be used on CrudControllers. This trait can contain one or more methods (or functions). Since Laravel calls each Controller method an _action_, that means each _Operation_ can have one or many _actions_. For example, we have the ```create``` operation and two actions: ```create()``` and ```store()```.
+
+```php
+trait CreateOperation
+{
+ public function create()
+ {
+ // ...
+ }
+
+ public function store()
+ {
+ // ...
+ }
+}
+```
+
+An action can do something with AJAX and return true/false, it can return a view, or whatever else you can do inside a controller method. Notice that it's a ```public``` method - which is a Laravel requirement, in order to point a route to it.
+
+You can check which action is currently being performed using the [standard Laravel Route API](https://laravel.com/api/8.x/Illuminate/Routing/Route.html):
+
+- ```\Route::getCurrentRoute()->getAction()``` or ```$this->crud->getRequest()->route()->getAction()```:
+```
+array:8 [▼
+ "middleware" => array:2 [▼
+ 0 => "web"
+ 1 => "admin"
+ ]
+ "as" => "crud.monster.index"
+ "uses" => "App\Http\Controllers\Admin\MonsterCrudController@index"
+ "operation" => "list"
+ "controller" => "App\Http\Controllers\Admin\MonsterCrudController@index"
+ "namespace" => "App\Http\Controllers\Admin"
+ "prefix" => "admin"
+ "where" => []
+]
+```
+- ```\Route::getCurrentRoute()->getActionName()``` or ```$this->crud->getRequest()->route()->getActionName()```:
+```
+App\Http\Controllers\Admin\MonsterCrudController@index
+```
+- ```\Route::getCurrentRoute()->getActionMethod()``` or ```$this->crud->getRequest()->route()->getActionMethod()```:
+```
+index
+```
+
+You can also use the shortcuts on the CrudPanel object:
+```php
+$this->crud->getActionMethod(); // returns the method on the controller that was called by the route; ex: create(), update(), edit() etc;
+$this->crud->actionIs('create'); // checks if the controller method given is the one called by the route
+```
+
+
+### Titles, Headings and Subheadings
+
+For standard CRUD operations, each _action_ that shows an interface uses some texts to show the user what page, operation or action he is currently performing:
+- **Title** - page title, shown in the browser's title bar;
+- **Heading** - biggest heading on page;
+- **Subheading** - short description of the current page, sits beside the heading;
+
+
+
+You can get and set the above using:
+```php
+// Getters
+$this->crud->getTitle('create'); // get the Title for the create action
+$this->crud->getHeading('create'); // get the Heading for the create action
+$this->crud->getSubheading('create'); // get the Subheading for the create action
+
+// Setters
+$this->crud->setTitle('some string', 'create'); // set the Title for the create action
+$this->crud->setHeading('some string', 'create'); // set the Heading for the create action
+$this->crud->setSubheading('some string', 'create'); // set the Subheading for the create action
+```
+
+These methods are usually useful inside actions, not in ```setup()```. Since action methods are called _after_ ```setup()```, any call to these getters and setters in ```setup()``` would get overwritten by the call in the action.
+
+
+### Handling Access to Operations
+
+Admins are allowed to do an operation or not using a very simple system: ```$crud->settings['operation_name']['access']``` will either be ```true``` or ```false```. When you enable a stock Backpack operation by doing ```use SomeOperation;``` on your controller, all operations will run ```$this->crud->allowAccess('operation_name');```, which will toggle that variable to ```true```.
+
+You can easily add or remove elements to this access array in your ```setup()``` method, or your custom methods, using:
+```php
+$this->crud->allowAccess('operation_name');
+$this->crud->allowAccess(['list', 'update', 'delete']);
+$this->crud->denyAccess('operation');
+$this->crud->denyAccess(['update', 'create', 'delete']);
+
+$this->crud->hasAccess('operation_name'); // returns true/false
+$this->crud->hasAccessOrFail('create'); // throws 403 error
+$this->crud->hasAccessToAll(['create', 'update']); // returns true/false
+$this->crud->hasAccessToAny(['create', 'update']); // returns true/false
+```
+
+
+### Operation Routes
+
+Starting with Backpack 4.0, routes can be defined in the CrudController. Your ```routes/backpack/custom.php``` file will have calls like ```Route::crud('product', 'ProductCrudController');```. This ```Route::crud()``` is a macro that will go to that controller and run all the methods that look like ```setupXxxRoutes()```. That means each operation can have its own method to define the routes it needs. And they do - if you check out the code of any operation, you'll see every one of them has a ```setupOperationNameRoutes()``` method.
+
+If you want to add a new route to your controller, there are two ways to do it:
+1. Add a route in your ```routes/backpack/custom.php```;
+2. Add a method following the ```setupXxxRoutes()``` convention to your controller;
+
+Inside a ```setupOperationNameRoutes()```, you'll notice that's also where we define the operation name:
+
+```php
+ protected function setupShowRoutes($segment, $routeName, $controller)
+ {
+ Route::get($segment.'/{id}/show', [
+ 'as' => $routeName.'.show',
+ 'uses' => $controller.'@show',
+ 'operation' => 'show',
+ ]);
+ }
+```
+
+
+### Getting an Operation Name
+
+Once an operation name has been set using that route, you can do ```$crud->getOperation()``` inside your views and do things according to this.
+
+
+
+## Creating a Custom Operation
+
+
+### Command-line Tool
+
+If you've installed ```backpack/generators```, you can do ```php artisan backpack:crud-operation {OperationName}``` to generate an empty operation trait, that you can edit and use on your CrudControllers. For example:
+
+```bash
+php artisan backpack:crud-operation Comment
+```
+
+Will generate ```app/Http/Controllers/Admin/Operations/CommentOperation``` with the following contents:
+
+```php
+ $routeName.'.comment',
+ 'uses' => $controller.'@comment',
+ 'operation' => 'comment',
+ ]);
+ }
+
+ /**
+ * Add the default settings, buttons, etc that this operation needs.
+ */
+ protected function setupCommentDefaults()
+ {
+ $this->crud->allowAccess('comment');
+
+ $this->crud->operation('comment', function () {
+ $this->crud->loadDefaultOperationSettingsFromConfig();
+ });
+
+ $this->crud->operation('list', function () {
+ // $this->crud->addButton('top', 'comment', 'view', 'crud::buttons.comment');
+ // $this->crud->addButton('line', 'comment', 'view', 'crud::buttons.comment');
+ });
+ }
+
+ /**
+ * Show the view for performing the operation.
+ *
+ * @return Response
+ */
+ public function comment()
+ {
+ $this->crud->hasAccessOrFail('comment');
+
+ // prepare the fields you need to show
+ $this->data['crud'] = $this->crud;
+ $this->data['title'] = $this->crud->getTitle() ?? 'comment '.$this->crud->entity_name;
+
+ // load the view
+ return view("crud::operations.comment", $this->data);
+ }
+}
+```
+
+You'll notice the generated operation has:
+- a GET route (inside ```setupCommentRoutes()```);
+- a method that sets the defaults for this operation (```setupCommentDefaults()```);
+- a method to perform the operation, or show an interface (```comment()```);
+
+You can customize these to fit the operation you have in mind, then ```use \App\Http\Controllers\Admin\Operations\CommentOperation;``` inside the CrudControllers where you want the operation.
+
+
+### Contents of a Custom Operation
+
+Thanks to [Backpack's simple architecture](/docs/{{version}}/crud-basics#architecture), each CRUD panel uses a controller and a route, that are placed inside your project. That means you hold the keys to how this controller works.
+
+To add an operation to an ```EntityCrudController```, you can:
+- decide on your operation name; for example... "publish";
+- create a method that loads the routes inside your controller:
+```php
+ protected function setupPublishRoutes($segment, $routeName, $controller)
+ {
+ Route::get($segment.'/{id}/publish', [
+ 'as' => $routeName.'.publish',
+ 'uses' => $controller.'@publish',
+ 'operation' => 'publish',
+ ]);
+ }
+```
+- create a method that performs the operation you want:
+```php
+ public function publish()
+ {
+ // do something
+ // return something
+ }
+```
+- [add a new button for this operation to the List view](/docs/{{version}}/crud-buttons#creating-a-custom-button), or enable access to it, inside a ```setupPublishDefaults()``` method:
+```php
+ protected function setupPublishDefaults()
+ {
+ $this->crud->allowAccess('publish');
+
+ $this->crud->operation('list', function () {
+ $this->crud->addButton('line', 'publish', 'view', 'buttons.publish', 'beginning');
+ });
+ }
+```
+
+Take a look at the examples below for a better picture and code examples.
+
+If you intend to reuse this operation across multiple controllers, you can group all the methods above in a trait, say ```PublishOperation.php``` and then just use that trait on the controllers where you need the operation:
+
+```php
+ $routeName.'.publish',
+ 'uses' => $controller.'@publish',
+ 'operation' => 'publish',
+ ]);
+ }
+
+ protected function setupPublishDefaults()
+ {
+ $this->crud->allowAccess('publish');
+
+ $this->crud->operation('list', function () {
+ $this->crud->addButton('line', 'publish', 'view', 'buttons.publish', 'beginning');
+ });
+ }
+
+ public function publish()
+ {
+ // do something
+ // return something
+ }
+}
+```
+
+In the example above, you could just do ```use \App\Http\Controllers\Admin\CustomOperations\PublishOperation;``` on any EntityCrudController, and your operation will be added - complete with routes, buttons, access, actions, everything.
+
+
+### Access to Custom Operations
+
+Since you're creating a new operation, in terms of restricting access you can:
+1. allow access to this new operation depending on access to a default operation (usually if the admin can ```update```, he's ok to perform custom operations);
+2. customize access to this particular operation, by just using a different key than the default ones; for example, you can allow access by using ```$this->crud->allowAccess('publish')``` in your ```setup()``` method, then check for access to that operation using ```$this->crud->hasAccess('publish')```;
+
+
+### Adding Settings to the CrudPanel object
+
+#### Using the Settings API
+
+Anything an operation does to configure itself, or process information, should be stored inside ```$this->crud->settings``` . It's an associative array, and you can add/change things using the Settings API:
+
+```php
+// for the operation that is currently being performed
+$this->crud->setOperationSetting('show_title', true);
+$this->crud->getOperationSetting('show_title');
+$this->crud->hasOperationSetting('show_title');
+
+// for a particular operation, pass the operation name as a last parameter
+$this->crud->setOperationSetting('show_title', true, 'create');
+$this->crud->getOperationSetting('show_title', 'create');
+$this->crud->hasOperationSetting('show_title', 'create');
+
+// alternatively, you could use the direct methods with no fallback to the current operation
+$this->crud->set('create.show_title', false);
+$this->crud->get('create.show_title');
+$this->crud->has('create.show_title');
+```
+
+#### Using the crud config file
+
+Additionally, operations can load default settings from the config file. You'll notice the ```config/backpack/crud.php``` file contains an array of operations, each with various settings. Those settings there are loaded by the operation as defaults, to allow users to change one setting in the config, and have that default changed across ALL of their CRUDs. If you take a look at the List operation you'll notice this:
+
+```php
+ /**
+ * Add the default settings, buttons, etc that this operation needs.
+ */
+ protected function setupListDefaults()
+ {
+ $this->crud->allowAccess('list');
+
+ $this->crud->operation('list', function () {
+ $this->crud->loadDefaultOperationSettingsFromConfig();
+ });
+ }
+```
+
+You can do the same in custom operations. Because this call happens in setupListDefaults(), inside an operation closure, the settings will only be added when that operation is being performed.
+
+
+
+### Adding Methods to the CrudPanel Object
+
+You can add static methods to this ```$this->crud``` (which is a CrudPanel object) object with ```$this->crud->macro()```, because the object is [macroable](https://unnikked.ga/understanding-the-laravel-macroable-trait-dab051f09172). So you can do:
+
+```php
+class MonsterCrudController extends CrudController
+{
+ public function setup()
+ {
+ $this->crud->macro('doStuff', function($something) {
+ echo '
'; var_dump($something); echo '
';
+ dd($this);
+ });
+ $this->crud->macro('getColumnsInTheFormatIWant', function() {
+ $columns = $this->columns();
+ // ... do something to $columns;
+ return $columns;
+ });
+
+ // bla-bla-bla the actual setup code
+ }
+ public function sendEmail()
+ {
+ // ...
+ $this->crud->doStuff();
+ dd($this->crud->getColumnsInTheFormatIWant());
+ // ...
+ }
+ public function markPending()
+ {
+ // ...
+ $this->crud->doStuff();
+ dd($this->crud->getColumnsInTheFormatIWant());
+ // ...
+ }
+}
+```
+
+So if you define a custom operation that needs some static methods added to the ```CrudPanel``` object, you can add them. The best place to register your macros in a custom operation would probably be inside your ```setupXxxDefaults()``` method, inside an operation closure. That way, the static methods you add are only added when that operation is being performed. For example:
+
+```php
+protected function setupPrintDefaults()
+{
+ $this->crud->allowAccess('print');
+
+ $this->crud->operation('print', function() {
+ $this->crud->macro('getColumnsInTheFormatIWant', function() {
+ $columns = $this->columns();
+ // ... do something to $columns;
+ return $columns;
+ });
+ });
+}
+```
+
+With the example above, you'll be able to use ```$this->crud->getColumnsInTheFormatIWant()``` inside your operation actions.
+
+
+### Using a feature from another operation
+
+Anything an operation does to configure itself, or process information, is stored on the ```$this->crud->settings``` property. Operation features (ex: fields, columns, buttons, filters, etc) are created in such a way that all they do is add an entry in settings, for an operation, and manipulate it. That means there is nothing stopping you from using a feature from one operation in a different operation.
+
+If you create a Print operation, and want to use the ```columns``` feature that List and Show use, you can just go ahead and do ```$this->crud->addColumn()``` calls inside your operation. You'll notice the columns are stored inside ```$this->crud->settings['print.columns']```, so they're completely different from the ones in the List or Show operation. You'll need to actually do something with the columns you added, inside your operation methods or views - of course.
+
+
+
+### Examples
+
+
+#### Creating a New Operation With No Interface
+
+Let's say we have a ```UserCrudController``` and we want to create a simple ```Clone``` operation, which would create another entry with the same info. So very similar to ```Delete```. What we need to do is:
+
+1. Create a route for this operation - as we've learned above we can do that in a ```setupXxxRoutes()``` method:
+
+```php
+ protected function setupPublishRoutes($segment, $routeName, $controller)
+ {
+ Route::get($segment.'/{id}/clone', [
+ 'as' => $routeName.'.clone',
+ 'uses' => $controller.'@clone',
+ 'operation' => 'clone',
+ ]);
+ }
+```
+
+2. Add the method inside ```UserCrudController```:
+
+```php
+public function clone($id)
+{
+ $this->crud->hasAccessOrFail('create');
+ $this->crud->setOperation('Clone');
+
+ $clonedEntry = $this->crud->model->findOrFail($id)->replicate();
+
+ return (string) $clonedEntry->push();
+}
+```
+
+3. Create a button for this method. Since our operation is similar to "Delete", lets start from that one and customize what we need. The button should clone the entry using an AJAX call. No need to load another page for an operation this simple. We'll create a ```resources\views\vendor\backpack\crud\buttons\clone.blade.php``` file:
+
+```php
+@if ($crud->hasAccess('create'))
+ Clone
+@endif
+
+{{-- Button Javascript --}}
+{{-- - used right away in AJAX operations (ex: List) --}}
+{{-- - pushed to the end of the page, after jQuery is loaded, for non-AJAX operations (ex: Show) --}}
+@push('after_scripts') @if (request()->ajax()) @endpush @endif
+
+@if (!request()->ajax()) @endpush @endif
+```
+
+4. We can now actually add this button to our ```UserCrudController::setupCloneOperation()``` method, or our ```setupCloneDefaults()``` method:
+
+```php
+protected function setupCloneDefaults() {
+ $this->crud->allowAccess('clone');
+
+ $this->crud->operation(['list', 'show'], function () {
+ $this->crud->addButtonFromView('line', 'clone', 'clone', 'beginning');
+ });
+}
+```
+
+>Of course, **if you plan to re-use this operation on another EntityCrudController**, it's a good idea to isolate the method inside a trait, then use that trait on each EntityCrudController where you want the operation to work.
+
+
+#### Creating a New Operation With An Interface
+
+Let's say we have a ```UserCrudController``` and we want to create a simple ```Moderate``` operation, where we show a form where the admin can add his observations and what not. In this respect, it should be similar to ```Update``` - the button should lead to a separate form, then that form will probably have a Save button. So when creating the methods, we should look at ```CrudController::edit()``` and ```CrudController::updateCrud()``` for working examples.
+
+What we need to do is:
+
+1. Create routes for this operation - we can do that using the ```setupOperationNameRoutes()``` convention inside a ```UserCrudController```:
+
+```php
+ protected function setupModerateRoutes($segment, $routeName, $controller)
+ {
+ Route::get($segment.'/{id}/moderate', [
+ 'as' => $routeName.'.getModerate',
+ 'uses' => $controller.'@getModerateForm',
+ 'operation' => 'moderate',
+ ]);
+ Route::post($segment.'/{id}/moderate', [
+ 'as' => $routeName.'.postModerate',
+ 'uses' => $controller.'@postModerateForm',
+ 'operation' => 'moderate',
+ ]);
+ }
+```
+
+2. Add the methods inside ```UserCrudController```:
+
+```php
+public function getModerateForm($id)
+{
+ $this->crud->hasAccessOrFail('update');
+ $this->crud->setOperation('Moderate');
+
+ // get the info for that entry
+ $this->data['entry'] = $this->crud->getEntry($id);
+ $this->data['crud'] = $this->crud;
+ $this->data['title'] = 'Moderate '.$this->crud->entity_name;
+
+ return view('vendor.backpack.crud.moderate', $this->data);
+}
+
+public function postModerateForm(Request $request = null)
+{
+ $this->crud->hasAccessOrFail('update');
+
+ // TODO: do whatever logic you need here
+ // ...
+ // You can use
+ // - $this->crud
+ // - $this->crud->getEntry($id)
+ // - $request
+ // ...
+
+ // show a success message
+ \Alert::success('Moderation saved for this entry.')->flash();
+
+ return \Redirect::to($this->crud->route);
+}
+```
+
+3. Create the ```/resources/views/vendor/backpack/crud/moderate.php``` blade file, which shows the moderate form and what not. Best to start from the ```edit.blade.php``` file and customize:
+
+```html
+@extends(backpack_view('layouts.top_left'))
+
+@php
+ $defaultBreadcrumbs = [
+ trans('backpack::crud.admin') => backpack_url('http://github.com/dashboard'),
+ $crud->entity_name_plural => url(http://github.com/$crud-%3Eroute),
+ 'Moderate' => false,
+ ];
+
+ // if breadcrumbs aren't defined in the CrudController, use the default breadcrumbs
+ $breadcrumbs = $breadcrumbs ?? $defaultBreadcrumbs;
+@endphp
+
+@section('header')
+
+
+@endsection
+
+```
+
+4. Create a button for this operation. Since our operation is similar to "Update", lets start from that one and customize what we need. The button should just take the admin to the route that shows the Moderate form. Nothing fancy. We'll create a ```resources\views\vendor\backpack\crud\buttons\moderate.blade.php``` file:
+
+```php
+@if ($crud->hasAccess('moderate'))
+ Moderate
+@endif
+```
+
+4. We can now actually add this button to our ```UserCrudController::setup()```, to register that button inside the List operation:
+
+```php
+$this->crud->operation('list', function() {
+ $this->crud->addButtonFromView('line', 'moderate', 'moderate', 'beginning');
+});
+```
+
+Or better yet, we can do this inside a ```setupModerateDefaults()``` method, which gets called automatically by CrudController when the ```moderate``` operation is being performed (thanks to the operation name set on the routes):
+
+```php
+protected function setupModerateDefaults()
+{
+ $this->crud->allowAccess('moderate');
+
+ $this->crud->operation('list', function() {
+ $this->crud->addButtonFromView('line', 'moderate', 'moderate', 'beginning');
+ });
+}
+```
+
+>Of course, **if you plan to re-use this operation on another EntityCrudController**, it's a good idea to isolate the method inside a trait, then use that trait on each EntityCrudController where you want the operation to be enabled.
+
+```php
+ $routeName.'.getModerate',
+ 'uses' => $controller.'@getModerateForm',
+ 'operation' => 'moderate',
+ ]);
+ Route::post($segment.'/{id}/moderate', [
+ 'as' => $routeName.'.postModerate',
+ 'uses' => $controller.'@postModerateForm',
+ 'operation' => 'moderate',
+ ]);
+ }
+
+ protected function setupmoderateDefaults()
+ {
+ $this->crud->allowAccess('moderate');
+
+ $this->crud->operation('list', function() {
+ $this->crud->addButtonFromView('line', 'moderate', 'moderate', 'beginning');
+ });
+ }
+
+ public function getModerateForm($id)
+ {
+ $this->crud->hasAccessOrFail('update');
+ $this->crud->setOperation('Moderate');
+
+ // get the info for that entry
+ $this->data['entry'] = $this->crud->getEntry($id);
+ $this->data['crud'] = $this->crud;
+ $this->data['title'] = 'Moderate '.$this->crud->entity_name;
+
+ return view('vendor.backpack.crud.moderate', $this->data);
+ }
+
+ public function postModerateForm(Request $request = null)
+ {
+ $this->crud->hasAccessOrFail('update');
+
+ // TODO: do whatever logic you need here
+ // ...
+ // You can use
+ // - $this->crud
+ // - $this->crud->getEntry($id)
+ // - $request
+ // ...
+
+ // show a success message
+ \Alert::success('Moderation saved for this entry.')->flash();
+
+ return \Redirect::to($this->crud->route);
+ }
+}
+```
+
+
+#### Creating a New Operation With a Bulk Action (No Interface)
+
+Say we want to create a ```BulkClone``` operation, with a button which clones multiple entries at the same time. So very similar to our ```BulkDelete```. What we need to do is:
+
+1. Create a new button:
+
+```html
+@if ($crud->hasAccess('bulkClone') && $crud->get('list.bulkActions'))
+ Clone
+@endif
+
+@push('after_scripts')
+
+@endpush
+```
+
+2. Create a method in your EntityCrudController (or in a trait, if you want to re-use it for multiple CRUDs):
+
+```php
+ public function bulkClone()
+ {
+ $this->crud->hasAccessOrFail('create');
+
+ $entries = $this->crud->getRequest()->input('entries');
+ $clonedEntries = [];
+
+ foreach ($entries as $key => $id) {
+ if ($entry = $this->crud->model->find($id)) {
+ $clonedEntries[] = $entry->replicate()->push();
+ }
+ }
+
+ return $clonedEntries;
+ }
+```
+
+3. Add a route to point to this new method:
+
+```php
+protected function setupBulkCloneRoutes($segment, $routeName, $controller)
+{
+ Route::post($segment.'/bulk-clone', [
+ 'as' => $routeName.'.bulkClone',
+ 'uses' => $controller.'@bulkClone',
+ 'operation' => 'bulkClone',
+ ]);
+}
+```
+
+4. Setup the default features we need for the operation to work:
+
+```php
+protected function setupBulkCloneDefaults()
+{
+ $this->crud->allowAccess('bulkClone');
+
+ $this->crud->operation('list', function () {
+ $this->crud->enableBulkActions();
+ $this->crud->addButton('bottom', 'bulk_clone', 'view', 'crud::buttons.bulk_clone', 'beginning');
+ });
+}
+```
+
+
+Now there's a Clone button on our List bottom stack, that works as expected for multiple entries.
+
+The button makes one call for all entries, and only triggers one notification. If you would rather make a call for each entry, you can use something like below:
+
+```html
+@if ($crud->hasAccess('create') && $crud->bulk_actions)
+ Clone
+@endif
+
+@push('after_scripts')
+
+@endpush
+```
diff --git a/4.1/crud-save-actions.md b/4.1/crud-save-actions.md
new file mode 100644
index 00000000..deb0aa7a
--- /dev/null
+++ b/4.1/crud-save-actions.md
@@ -0,0 +1,132 @@
+# Save Actions
+
+---
+
+
+## About
+
+`Create` and `Update` forms end in a Save button with a drop menu. Every option in that dropdown is a SaveAction - they determine where the user is redirected after the saving is complete.
+
+
+## Default Save Actions
+
+There are four save actions registered by Backpack by default. They are:
+ - ```save_and_back``` (Save your entity and go back to previous URL)
+ - ```save_and_edit``` (Save and edit the current entry)
+ - ```save_and_new``` (Save and go to create new entity page)
+ - ```save_and_preview``` (Save and go to show the current entity)
+
+
+## Save Actions API
+
+Inside your CrudController, inside your ```setupCreateOperation()``` or ```setupUpdateOperation()``` methods, you can change what save buttons are shown for each operation by using the methods below:
+
+#### addSaveAction(array $saveAction)
+
+Adds a new SaveAction to the "Save" button/dropdown.
+
+```php
+$this->crud->addSaveAction([
+ 'name' => 'save_action_one',
+ 'redirect' => function($crud, $request, $itemId) {
+ return $crud->route;
+ }, // what's the redirect URL, where the user will be taken after saving?
+
+ // OPTIONAL:
+ 'button_text' => 'Custom save message', // override text appearing on the button
+ // You can also provide translatable texts, for example:
+ // 'button_text' => trans('backpack::crud.save_action_one'),
+ 'visible' => function($crud) {
+ return true;
+ }, // customize when this save action is visible for the current operation
+ 'referrer_url' => function($crud, $request, $itemId) {
+ return $crud->route;
+ }, // override http_referrer_url
+ 'order' => 1, // change the order save actions are in
+]);
+```
+
+#### addSaveActions(array $saveActions)
+
+The same principle of `addSaveAction([])` but for adding multiple actions with only one crud call.
+
+```php
+$this->crud->addSaveActions([
+ [
+ 'name' => 'save_action_one',
+ 'visible' => function($crud) {
+ return true;
+ },
+ 'redirect' => function($crud, $request, $itemId) {
+ return $crud->route;
+ },
+ ],
+ [
+ 'name' => 'save_action_two',
+ 'visible' => function($crud) {
+ return true;
+ },
+ 'redirect' => function($crud, $request, $itemId) {
+ return $crud->route;
+ },
+ ],
+]);
+```
+
+#### replaceSaveActions(array $saveActions)
+
+This allows you to replace the current save actions with the ones provided in an array.
+
+```php
+$this->crud->replaceSaveActions(
+ [
+ 'name' => 'save_action_one',
+ 'visible' => function($crud) {
+ return true;
+ },
+ 'redirect' => function($crud, $request, $itemId) {
+ return $crud->route;
+ },
+ ],
+);
+```
+
+
+#### removeSaveAction(string $saveAction)
+
+This allows you to remove a specific save action from the save actions array. Provide the name of the save action that you would like to remove.
+```php
+$this->crud->removeSaveAction('save_action_one');
+```
+
+#### removeSaveActions(array $saveActions)
+
+The same principle as `removeSaveAction()` but to remove multiple actions at same time. You should provide an array with save action names.
+```php
+$this->crud->removeSaveActions(['save_action_one','save_action_two']);
+```
+
+#### orderSaveAction(string $saveAction, int $wantedOrder)
+
+You can specify a certain order for a certain save action.
+
+```php
+$this->crud->orderSaveAction('save_action_one', 1);
+```
+
+We will setup the save action in the desired order and try to re-order the other save actions accordingly. If you want more granular control over all save actions order, you can define ```order``` when creating the save action, or use ```orderSaveActions()```
+
+#### orderSaveActions(array $saveActions)
+
+Allows you to reorder multiple save actions at same time. You can use it by either specifying only the names of the save actions, in the order you want, or by specifying their order number too:
+
+```php
+// make save actions show up in this order
+$this->crud->orderSaveActions(['save_action_one','save_action_two']);
+// or
+$this->crud->orderSaveActions(['save_action_one' => 3,'save_action_two' => 2]);
+```
+
+#### setSaveActions(array $saveActions)
+
+Alias for ```replaceSaveActions(array $saveActions)```.
diff --git a/4.1/crud-tutorial.md b/4.1/crud-tutorial.md
new file mode 100644
index 00000000..410741da
--- /dev/null
+++ b/4.1/crud-tutorial.md
@@ -0,0 +1,382 @@
+# CRUD Crash Course
+
+---
+
+What's the simplest entity you can think of? It will probably be something like ```Tag```, which only holds an ```id``` and a ```name```. Let's create this new entity in the database, the model for it, then create a CRUD Panel to let admins manage entries for this entity.
+
+We assume:
+- you've [installed Backpack](/docs/{{version}}/installation);
+- you don't already have a ```Tag``` model in your project;
+
+
+## Generate Files
+
+> **NEW!!!** Starting with Aug 2021, there's a much simpler way to generate everything 🎉 **Check out our new paid addon - [Backpack DevTools](https://backpackforlaravel.com/products/devtools).** It's a GUI that will help you generate Migrations, Models (complete with relationships), CRUDs from the browser 😱 It does cost extra, but it's well worth the price if you use Backpack regularly or your models are not dead-simple.
+
+Since we don't have an Eloquent model for it already, we're going to use [Jeffrey Way's Generators](https://github.com/laracasts/Laravel-5-Generators-Extended) package, which you've most likely installed along with Backpack, to generate the migration.
+
+```zsh
+# install a 3rd party tool to generate migrations from the command line
+composer require --dev laracasts/generators
+
+# generate a migration and run it
+php artisan make:migration:schema create_tags_table --schema="name:string:unique"
+php artisan migrate
+```
+
+Now that we have the ```tags``` table in the database, let's generate the actual files we'll be using:
+
+```zsh
+php artisan backpack:crud tag #use singular, not plural
+```
+
+The code above will have generated:
+- a migration (```database/migrations/yyyy_mm_dd_xyz_create_tags_table.php```);
+- a database table (```tags``` with just two columns: ```id``` and ```name```);
+- a model (```app/Models/Tag.php```);
+- a controller (```app/Http/Controllers/Admin/TagCrudController.php```);
+- a request (```app/Http/Requests/TagCrudRequest.php```);
+- a resource route, as a line inside ```routes/backpack/custom.php```;
+- a new item in the sidebar menu, in ```resources/views/vendor/backpack/base/inc/sidebar_content.blade.php```;
+
+**Next up:** we'll need to go through the generated files, and customize for our needs.
+
+
+## Customize Generated Files
+
+We'll skip the migration and database table, since there's nothing there specific to Backpack, nothing to customize, and we've already run the migration.
+
+
+### The Model
+
+Let's take a look at the generated model:
+
+```php
+
+### The Controller
+
+Let's take a look at ```app/Http/Controllers/Admin/TagCrudController.php```. It should look something like this:
+
+```php
+crud->setModel("App\Models\Tag");
+ $this->crud->setRoute("admin/tag");
+ $this->crud->setEntityNameStrings('tag', 'tags');
+ }
+
+ protected function setupListOperation()
+ {
+ // TODO: remove setFromDb() and manually define Columns, maybe Filters
+ $this->crud->setFromDb();
+ }
+
+ protected function setupCreateOperation()
+ {
+ $this->crud->setValidation(TagRequest::class);
+
+ // TODO: remove setFromDb() and manually define Fields
+ $this->crud->setFromDb();
+ }
+
+ protected function setupUpdateOperation()
+ {
+ $this->setupCreateOperation();
+ }
+}
+```
+
+#### The Basics
+
+What we should notice inside this TagCrudController is that:
+- ```TagCrudController extends CrudController```;
+- ```TagCrudController``` has a ```setup()``` method, where can plug in the basics of our CRUD panel; everything we write here is applied on ALL operations;
+- All operations are enabled by using that operation's trait on the controller;
+- Each operation is set up inside a ```setupXxxOperation()``` method;
+
+As we can tell from the comments in our ```setupXxxOperation()``` methods, in most cases we _shouldn't_ use ```$this->crud->setFromDb()```, which automagically figures out which columns and fields to show. That's because for real models, in real projects, it would _never_ be able to 100% figure out which field types to use. Real projects are very custom - that's a fact. In real projects, models are complicated, use a bunch of field types and you'll want to customize things. Instead of using ```setFromDb()``` then gradually changing what you don't like, **we heavily recommend you manually define all fields and columns you need**.
+
+That being said, since our ```Tag``` model is so simple, we _can_ leave it like this - it will work perfectly, since we only need a ```text``` field and a ```text``` column. But let's not do that. Let's define our fields and columns manually, like big boys & girls.
+
+#### Option 1. SetupXxxOperation Methods
+
+We can either define each operations inside its ```setupXxxOperation()``` method:
+
+```php
+ protected function setupListOperation()
+ {
+ $this->crud->addColumn(['name' => 'name', 'type' => 'text', 'label' => 'Name']);
+ }
+
+ protected function setupCreateOperation()
+ {
+ $this->crud->setValidation(TagRequest::class);
+ $this->crud->addField(['name' => 'name', 'type' => 'text', 'label' => 'Name']);
+ }
+
+ protected function setupUpdateOperation()
+ {
+ $this->setupCreateOperation(); // since this calls the methods above, no need to do anything here
+ }
+```
+
+This will:
+- disable the ```setFromDb()``` functionality (since we deleted that line);
+- add a simple ```text``` column for our ```name``` attribute for the List operation (the table view);
+- add a simple ```text``` field for our ```name``` attribute to the Create and Update forms;
+
+It's the exact same thing ```setFromDb()``` would have figured out, but done manually. This way, if we want to add [other columns](/docs/{{version}}/crud-columns)) or [other fields](/docs/{{version}}/crud-fields), we can easily do that. If we want to change the label of the ```name``` field from ```Name``` to ```Tag name```, we just make that small change. The benefits of _not_ using ```setFromDb()``` will be more obvious once you use Backpack on real models, we promise.
+
+#### Option 2. Operation Closures
+
+An alternative to defining operation inside ```setupXxxOperation()``` methods is to do it inside the ```setup()``` method. However, as we've mentioned before, everything you run in your ```setup()``` method is run for ALL operations. So you can easily end up bloating your operation with unnecessary operations. If you don't like having a method to configure each operation, and would like to define everything in ```setup()```, you should do so inside an ```operation()``` closure. Whatever's inside that closure will only be run for that operation. For example, everything we've done above would look like this if done inside operation closures:
+
+```php
+ public function setup()
+ {
+ $this->crud->setModel('App\Models\Tag');
+ $this->crud->setRoute(config('backpack.base.route_prefix') . '/tag');
+ $this->crud->setEntityNameStrings('tag', 'tags');
+
+ $this->crud->operation('list', function() {
+ $this->crud->addColumn(['name' => 'name', 'type' => 'text', 'label' => 'Name']);
+ });
+
+ $this->crud->operation(['create', 'update'], function() {
+ $this->crud->addValidation(TagCrudRequest::class);
+ $this->crud->addField(['name' => 'name', 'type' => 'text', 'label' => 'Name']);
+ });
+ }
+
+
+}
+```
+
+#### Other Calls
+
+Here, inside your ```setup()``` or ```setupXxxOperation``` methods, you can also do a lot of other things, like adding buttons, adding filters, customizing your query, etc. For a full list of the things you can do inside ```setup()``` check out our [cheat sheet](/docs/{{version}}/crud-cheat-sheet).
+
+Next, let's continue to another generated file.
+
+
+### The Request
+
+Backpack will also generate a [standard FormRequest file](https://laravel.com/docs/master/validation#form-request-validation), that you can use for validation of the Create and Update forms. There is nothing Backpack-specific in here, but let's take a look at the generated ```app/Http/Requests/TagRequest.php``` file:
+
+```php
+check();
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules()
+ {
+ return [
+ // 'name' => 'required|min:5|max:255'
+ ];
+ }
+
+ /**
+ * Get the validation attributes that apply to the request.
+ *
+ * @return array
+ */
+ public function attributes()
+ {
+ return [
+ //
+ ];
+ }
+
+ /**
+ * Get the validation messages that apply to the request.
+ *
+ * @return array
+ */
+ public function messages()
+ {
+ return [
+ //
+ ];
+ }
+}
+
+```
+
+This file is a 100% pure FormRequest file - all Laravel, nothing particular to Backpack. In generated FormRequest files, no validation rules are imposed by default. But we do want ```name``` to be ```required``` and ```unique```, so let's do that, using the [standard Laravel validation rules](https://laravel.com/docs/master/validation#available-validation-rules):
+
+```diff
+ /**
+ * Get the validation rules that apply to the request.
+ *
+ * @return array
+ */
+ public function rules()
+ {
+ return [
+- // 'name' => 'required|min:5|max:255'
++ 'name' => 'required|min:5|max:255|unique:tags,name'
+ ];
+ }
+```
+
+> If your validation needs to be different between the Create and Update operations, [you can easily do that too](/docs/{{version}}/crud-operation-create#separate-requests-for-create-and-update), by specifying different FormRequest files for each operation.
+
+
+### The Route
+
+We have already generated our CRUD route, and we don't need to do anything about it, but let's check our ```routes/backpack/custom.php```. It should look like this:
+
+```php
+ config('backpack.base.route_prefix', 'admin'),
+ 'middleware' => ['web', config('backpack.base.middleware_key', 'admin')],
+ 'namespace' => 'App\Http\Controllers\Admin',
+], function () { // custom admin routes
+ // CRUD resources and other admin routes
+ Route::crud('tag', 'TagCrudController');
+}); // this should be the absolute last line of this file
+```
+
+Here, we can see that our routes have been placed:
+- under a prefix that we can change in ```config/backpack/base.php```;
+- under a middleware we can change in ```config/backpack/base.php```;
+- inside the ```App\Http\Controllers\Admin``` namespace, because that's where our custom CrudControllers will be generated;
+
+**It's generally a good idea to have the all admin routes in this separate file.** If you edit this file in the future, make sure you leave the last line intact, so that other routes can be automatically generated inside this file. And of course, add your routes inside this route group, so that:
+- you have a single prefix for your admin routes (ex: ```admin/tag```, ```admin/product```, ```admin/dashboard```);
+- all your admin panel functionality is protected by the same middleware;
+- all your admin panel controllers live in one place (```App\Http\Controllers\Admin```);
+
+
+### The Menu Item
+
+We've previously generated a menu item in the ```views/vendor/backpack/base/inc/sidebar_content.php``` file. You'll see this file is pure HTML. This will allow you to customize the menu as much as you want. The "active" state of the menu is done with JavaScript, based on the ```href``` attribute.
+
+This is the bit that has been generated for you:
+
+```php
+
+```
+
+You can of course change anything here, if you want.
+
+
+## The result
+
+You are now ready to go to ```your-app-name.domain/admin/tag``` and see your fully functional admin panel for ```Tags```.
+
+**Congratulations, you should now have a good understanding of how Backpack\CRUD works!** This is a very very basic example, but the process will be identical for Models with 50+ attributes, complicated logic, etc.
+
+If you do have complex models, we _heavily_ recommend you go purchase [Backpack DevTools](https://backpackforlaravel.com/products/devtools) right now. It's the official paid GUI for generating all of the above. And while you're at it, you can [purchase a Backpack license](https://backpackforlaravel.com/pricing) too 😉
diff --git a/4.1/demo.md b/4.1/demo.md
new file mode 100644
index 00000000..ec1e9328
--- /dev/null
+++ b/4.1/demo.md
@@ -0,0 +1,68 @@
+# Demo
+
+---
+
+We've put together a working Laravel app (backend-only), that you can install on your machine. This should make it easier to:
+- see how it looks & feels;
+- see how it works;
+- change stuff in code, to see how easy it is to customize Backpack;
+
+In this [Demo repository](https://github.com/laravel-backpack/demo), we've:
+- installed Laravel 6;
+- installed Backpack\CRUD on top;
+- created a few demo models (Monsters, Icons, Products) and admin panels for them, using dozens of field types, column types, filters, etc - to show off most of Backpack's default features;
+- installed a few Backpack extensions: PermissionManager, PageManager, LogManager, BackupManager, Settings, MenuCRUD, NewsCRUD;
+
+
+>**Don't use this demo to start your real projects.** Please use [the recommended installation procedure](/docs/{{version}}/installation). You don't want all the bogus entities we've created. You don't want all the packages we've used. And you _definitely_ don't want the default admin user. Start from scratch.
+
+
+## Demo Preview
+
+
+
+If you just want to take a look at the Backpack interface and click around, you don't need to install the Demo. **Take a look at [demo.backpackforlaravel.com](https://demo.backpackforlaravel.com/admin) - we've installed for you.** The online demo is wiped and reinstalled every hour, on the hour.
+
+
+## Demo Installation
+
+1) In your ```Projects``` or ```www``` directory, wherever you host your apps:
+
+```zsh
+git clone https://github.com/Laravel-Backpack/demo.git backpack-demo
+```
+
+2) Set your database information in your ```.env``` file (use ```.env.example``` as an example);
+
+3) Install all the requirements:
+``` zsh
+cd backpack-demo
+composer install
+```
+
+4) Populate the database and stuff:
+```zsh
+php artisan key:generate
+php artisan migrate
+php artisan db:seed --class="Backpack\Settings\database\seeds\SettingsTableSeeder"
+php artisan db:seed
+```
+
+
+## Demo Usage
+
+Once everything's installed, and your database has been set up:
+
+- Your admin panel is available at http://localhost/backpack-demo/admin
+- Login with email ```admin@example.com```, password ```admin```
+- You can register a different account, to check out the process and see your gravatar inside the admin panel.
+- By default, registration is open only in your local environment. Check out ```config/backpack/base.php``` to change this and other preferences.
+- Check out the Monsters admin panel - it features over 40 field types.
+- The magic of Backpack is not in its standard functionality, but in how easy it is to code your own, or customize every little bit of it. Our recommendation:
+ - Go through the [CRUD Tutorial](/docs/{{version}}/crud-tutorial) to understand it;
+ - Create a new CRUD panel for an entity, using the faster procedure outlined at the end of that page; say... ```car```;
+
+
+>**vhost configurations**
+>
+>Depending on your vhost configuration you might need to access the application via a different url, for example if you're using ```artisan serve``` you can access it on http://127.0.0.1:8000/admin - if you're using Laravel Valet, then it may look like http://backpack-demo.test/admin - you will need to access the url which matches your systems configuration. If you do not understand how to configure your virtual hosts, we suggest [watching Laracasts Episode #1](https://laracasts.com/series/laravel-from-scratch/episodes/1) to quickly get started.
diff --git a/4.1/faq.md b/4.1/faq.md
new file mode 100644
index 00000000..5724c731
--- /dev/null
+++ b/4.1/faq.md
@@ -0,0 +1,100 @@
+# Frequently Asked Questions
+
+---
+
+
+
+## Licensing
+
+
+### Do I need a license to test Backpack?
+
+You don't need a license code AT ALL, if you're just installing Backpack on localhost. Just go ahead and install Backpack, you'll have zero limitations until you go to production.
+
+
+
+### Do I need a license to put a project on a testing domain?
+
+Yes, you do need a license code. But not a _separate_ license code. If you've already purchased a license code, you should use the same code for both your staging and production instances - even if the domains are different.
+
+If you're interested in a license code to test your project online, _before_ you purchase a Backpack license - take note that we don't do that. We do not issue licenses for testing an already built app on a staging domain. If you've reached a point where you put your project on a staging server, that should mean Backpack has already helped you or your company save dozens or hundreds of hours of work - so that qualifies as commercial use. We recommend you purchase a license code - you can use the same license code on both your staging and production domain.
+
+An alternative to be able to test a project online, without paying anything, would be to put your project online and bear the annoying notification bubbles. If you don't mind the notification bubbles, you can get a general idea of what's working and what's not. It's not ideal, but it's free.
+
+
+
+### Do I need a license to create an open-source project?
+
+No, you do not. But there's a huge catch.
+
+Because Backpack requires a license code to work in production, all users of _your open-source project_ will require a Backpack license code for their apps to work in production. So yes, your project will be open-source, but developers _will_ need to pay for a Backpack license if their project is commercial, or apply for a free non-commercial license on our website. This makes it a bit inconvenient to use Backpack for open-source work, we know that.
+
+To rephrase and clarify - _you_ don't need a license code to develop an open-source project that uses Backpack. But _your users_ will. And no, if you purchase a Backpack license, your open-source users are not covered by your license, only you are. Even if you do have a Backpack license code, that is for you alone, and you should never _ever_ make that code public, or share it with anybody outside your company.
+
+We plan to address this inconvenience in Backpack v5, by having a "Backpack Lite" package under MIT License, with limited features. Then you could easily build things on top of that, instead of the main Backpack package. But until then, I'm afraid the problem remains - and the only solution is to clearly state in your README file that your package is open-source, but one of your dependencies requires payment for commercial use. Feel free to email hello@tabacitu.ro with details about your project, for more information.
+
+
+
+
+### How do I use the Backpack license key I purchased/received?
+
+There are two places where you can put your Backpack license code:
+
+- (A) inside your .ENV file, ona a new line, as `BACKPACK_LICENSE=xxx`
+- (B) inside your `config/backpack/base.php`, at the bottom, you'll find `'license_code' => env('BACKPACK_LICENSE', false)` - you can replace `false` with your license code (wrapped by single quotes)
+
+Option (A) is the recommended one, because there's no point in saving the license code within the code base (in git), and exposing it to whoever has access to the source code. The Backpack license code is only needed in production, so the best way is to add an environment variable there, in on your production server.
+
+
+
+## Miscellaneous
+
+
+
+### How do I update Backpack to the latest non-breaking version?
+
+First of all, **run `composer update` on your project**. That will pull in the latest supported version of all your Backpack packages.
+
+Then you should **re-publish the JS and CSS assets**. There are two ways to do that:
+
+(A) Run `php artisan vendor:publish --provider="Backpack\CRUD\BackpackServiceProvider" --tag=public --force`. Please note this will overwrite anything that's already there. This B solution has a downside: _unused files are not removed_. A few files Backpack no longer uses will still be in your public/packages folder, even though they're no longer used.
+
+(B) If you have NOT touched you `public/packages` folder, or placed anything custom inside it:
+- delete the public/packages directory and all its contents;
+- run `php artisan vendor:publish --provider="Backpack\CRUD\BackpackServiceProvider" --tag=public`
+- if you use elFinder, also delete `resources/views/vendor/elfinder` and run `php artisan backpack:filemanager:install`
+
+
+
+### How do I uninstall Backpack from my project?
+
+You can remove Backpack from your project pretty easily, if you decide to stop using it. You just have to do the opposite of the installation process:
+
+```bash
+# delete the files Backpack has placed inside your application
+rm -rf app/Http/Middleware/CheckIfAdmin.php
+rm -rf config/backpack
+rm -rf config/gravatar.php
+rm -rf public/packages
+rm -rf resources/views/errors
+rm -rf resources/views/vendor/backpack
+rm -rf routes/backpack
+
+# delete any CrudControllers you've created, so MAYBE:
+rm -rf app/Http/Controllers/Admin
+
+# delete any Requests you've created for your CrudControllers.
+# MAKE SURE YOU DON'T NEED ANYTHING IN THIS DIRECTORY ANYMORE.
+# You might have OTHER requests that are not Backpack-related.
+rm -rf app/Http/Requests
+
+# (maybe) remove other Backpack dev tools you've used
+composer remove --dev laracasts/generators
+
+# remove Backpack from your composer.json requirements
+composer remove --dev backpack/generators
+composer remove backpack/crud
+
+```
+
+That's it! If you've decided NOT to use Backpack, we'd be super-grateful if you could send us an email telling us WHY you didn't like Backpack, or it didn't fit your project. It might help us take Backpack in a different direction, one where you might want to use it. Thank you 🙏
diff --git a/4.1/getting-started-advanced-features.md b/4.1/getting-started-advanced-features.md
new file mode 100644
index 00000000..525cd4d2
--- /dev/null
+++ b/4.1/getting-started-advanced-features.md
@@ -0,0 +1,49 @@
+# 3. Advanced Features
+
+---
+
+**Duration:** 5 min
+
+Here are some other cool things Backpack makes easy for you. We recommend going through them one by one, just browsing. You might not need the feature _right now_, but when _you do_, you'll know how to find it.
+
+---
+
+
+## Other Operations
+- [Show](/docs/{{version}}/crud-operation-show) Operation - you can let your admins preview an entry
+- [Reorder](/docs/{{version}}/crud-operation-reorder) Operation - you can reorder and nesting entries (hierarchy tree)
+- [Revisions](/docs/{{version}}/crud-operation-revisions) Operation - you can keep a record of all modifications to an entry, and let your admin revert changes
+- [Clone](/docs/{{version}}/crud-operation-clone) Operation - you can make a copy of an entry;
+- [BulkDelete](/docs/{{version}}/crud-operation-delete) Operation - you can delete multiple items in one go;
+- [BulkClone](/docs/{{version}}/crud-operation-clone) Operation - you can clone multiple items in one go;
+
+---
+
+
+## Other Features
+- **Create & Update**
+ - [Manage files on disk](/docs/{{version}}/crud-how-to#use-the-media-library-file-manager) (media library)
+ - [Fake fields](/docs/{{version}}/crud-fields#optional-fake-field-attributes-stores-fake-attributes-as-json-in)
+ - Translatable models and [multi-language CRUDs](/docs/{{version}}/crud-operation-update#translatable-models)
+ - [Tabs in create/update forms](/docs/{{version}}/crud-fields#split-fields-into-tabs)
+
+--
+
+- **ListEntries**
+ - you can add a "+" button next to each entry, to allow the admin to easily preview some quick information that was too big to fit inside a columns - we call it [details row](/docs/{{version}}/crud-operation-list-entries#details-row)
+ - export all visible items in the table by adding [export buttons](/docs/{{version}}/crud-operation-list-entries#export-buttons)
+ - [custom search logic](/docs/{{version}}/crud-columns#custom-search-logic) for the columns in the list view
+
+
+Additionally, here are a few more ways you can customize your CRUDs:
+- [Custom Views for each CRUD](/docs/{{version}}/crud-how-to#customize-views-for-each-crud-panel)
+- [Custom Content Class for each CRUD](/docs/{{version}}/crud-how-to#resize-the-content-wrapper-for-an-operation)
+- [Custom CSS or JS](/docs/{{version}}/crud-how-to#customize-css-and-js-for-default-crud-operations) for each CRUD Operation
+
+**That's it for today!** Told you we're done with long lessons :-) Hopefully some of the above have piqued your interest and you've clicked to see what Backpack can do. In the [next lesson](/docs/{{version}}/getting-started-license-and-support) we'll go through a few other Backpack packages that cover some recurring use cases.
+
+
+
+
+ Next →
+
diff --git a/4.1/getting-started-basics.md b/4.1/getting-started-basics.md
new file mode 100644
index 00000000..12016657
--- /dev/null
+++ b/4.1/getting-started-basics.md
@@ -0,0 +1,163 @@
+# 1. Basics
+
+---
+
+**Duration:** 5 minutes
+
+> **Are you already comfortable with Laravel?** In order to understand this series and make use of Backpack, you'll need to have a decent understanding of the Laravel framework. If you don't, please go ahead and [watch this excellent intro series on Laracasts](https://laracasts.com/series/laravel-from-scratch-2018) and accommodate yourself with Laravel first.
+
+
+
+## What is Backpack?
+A software that helps Laravel professionals build administration panels - secure areas where administrators login and create, read, update and delete application information. It is *not* a CMS, it is more a framework that lets you *build your own* CMS. You can install it in your existing project or in a totally new project.
+
+It's designed to be flexible enough to allow you to **build admin panels for everything from simple presentation websites to CRMs, ERPs, eCommerce, eLearning, etc**. We can vouch for that, because we have built all that stuff using Backpack already.
+
+
+## What's a CRUD?
+
+A **CRUD** is what we call a section of your admin panel that lets the admin _Create, Read, Update or Delete_ entries of a certain entity (or Model). So you can have a CRUD for Products, a CRUD for Articles, a CRUD for Categories, or whatever else you might want to create, read, update or delete.
+
+For the purpose of this series, we'll show examples on the ```Tag``` entity. This is what a Tag CRUD could look like:
+
+
+
+But Backpack is prepared for feature-packed CRUDs - since it's a good tool for very complex projects too. Here's what a CRUD that uses all of Backpack's features could look like:
+
+
+
+Mind that you will _almost never_ use all of Backpack's features in one CRUD. But if you do... it still looks good, and it'll be intuitive to use.
+
+
+## Main Features
+
+
+### Front-End Design
+
+Backpack installs the [CoreUI](https://coreui.io) HTML theme, and our own design on top - [Backstrap](https://backstrap.net). It uses Bootstrap 4, and has many HTML blocks ready for you to use. When you're building a custom page in your admin panel, it's easy to just copy-paste the HTML from our [Backstrap demo](https://backstrap.net), or from the [CoreUI documentation](https://coreui.io/docs/getting-started/introduction/) and it will look good, without you having to design anything.
+
+It also installs Noty for triggering JS notification bubbles, and SweetAlerts. So you can easily use these across your admin panel. You can [trigger alerts in PHP](/docs/{{version}}/base-alerts#triggering-alerts-in-php) or [trigger alerts in JavaScript](/docs/{{version}}/base-alerts#triggering-alerts-in-javascript).
+
+
+
+### Authentication
+
+Backpack comes with a basic authentication system that's separate from Laravel's. This way, you can have different login screens for users & admins, if you need. If not, you can choose to use only one authentication - either Laravel's, or Backpack's.
+
+
+
+After you [install Backpack](/docs/{{version}}/installation) (don't do it now), you'll be able to log into your admin panel at ```http://yourapp/admin```. You can change the URL prefix from ```admin``` to something else in your ```config/backpack/base.php``` file, along with a bunch of other configuration options. [Click here](https://github.com/Laravel-Backpack/CRUD/blob/master/src/config/backpack/base.php) to browse the configuration file and see what it can do for you.
+
+
+
+### CRUDs
+
+This is where it gets interesting. As soon as you [install Backpack](/docs/{{version}}/installation) in your project, you can create **CRUDs** for your admins to easily manipulate DB information. Let's browse through a simple example, of creating a CRUD administration panel for a Tag entity.
+
+You can generate everything a CRUD needs using one of the methods below:
+
+---
+
+**Option A) PAID - using our GUI, [Backpack DevTools](https://backpackforlaravel.com/products/devtools)**
+
+Just install DevTools, fill in a web form with the columns for your entity, and it'll generate all needed files. It's that simple. Check out [the images here](https://backpackforlaravel.com/products/devtools) for how it works. It's especially useful for more complex entities. It is a paid tool though, and you might not be ready to purchase yet, so let's explore a free option too.
+
+**Option B) FREE - using the command-line interface**
+
+You can use anything you want to generate the Migration and Model, so in this case we're going to use [laracasts/generators](https://github.com/laracasts/Laravel-5-Generators-Extended):
+
+```zsh
+# STEP 0. install a 3d party tool to generate migrations
+composer require --dev laracasts/generators
+
+# STEP 1. create a migration
+php artisan make:migration:schema create_tags_table --model=0 --schema="name:string:unique,slug:string:unique"
+php artisan migrate
+
+# STEP 2. create a CRUD for it
+php artisan backpack:crud tag #use singular, not plural
+```
+
+---
+
+In both cases, what we're getting is a simple CRUD panel, which you should now be able to see in the Sidebar.
+
+For a simple entry like this, the generated CRUD panel will even work "as is", no need for customizations. But don't expect this for more complex entities. They will usually have particularities and need customization. That's where Backpack shines - modifying anything in the CRUD Panel is easy and intuitive, once you understand how it works.
+
+The methods above will generate:
+- a **migration** file
+- a **model** (```app\Models\Tag.php```)
+- a **request** file, for form validation (```app\Http\Requests\TagCrudRequest.php```)
+- a **controller** file, where you can customize how the CrudPanel looks and feels (```app\Http\Controllers\Admin\TagCrudController.php```)
+- a **route**, as a line inside ```routes/backpack/custom.php```
+
+It will also add:
+- a route inside ```routes/backpack/custom.php```, pointing to that controller;
+- a sidebar item inside ```resources/views/vendor/backpack/base/inc/sidebar_content.blade.php```;
+
+You might have noticed that **no views** are generated. That's because in most cases you _don't need_ custom views with Backpack. All your custom code is in the controller, model or request, so the default views are loaded, from the package. If you do, however, need to customize a view, it is [ridiculously easy](/docs/{{version}}/crud-how-to#customize-views-for-each-crud-panel).
+
+Also, we won't be covering the **migration**, **model** and **request** files here, as they are in no way custom. The only thing you need to make sure is that the Model is properly configured (db table, relationships, ```$fillable``` or ```$guarded``` properties, etc) and that it uses our ```CrudTrait```. What we _will_ be covering is ```TagCrudController``` - which is where most of your logic will reside. Here's a copy of a simple one you might use to achieve the above:
+
+```php
+crud->setModel("App\Models\Tag");
+ $this->crud->setRoute("admin/tag");
+ $this->crud->setEntityNameStrings('tag', 'tags');
+ }
+
+ public function setupListOperation()
+ {
+ $this->crud->setColumns(['name', 'slug']);
+ }
+
+ public function setupCreateOperation()
+ {
+ $this->crud->setValidation(TagCrudRequest::class);
+
+ $this->crud->addField([
+ 'name' => 'name',
+ 'type' => 'text',
+ 'label' => "Tag name"
+ ]);
+ $this->crud->addField([
+ 'name' => 'slug',
+ 'type' => 'text',
+ 'label' => "URL Segment (slug)"
+ ]);
+ }
+
+ public function setupUpdateOperation()
+ {
+ $this->setupCreateOperation();
+ }
+}
+```
+
+You should notice:
+- It uses basic inheritance (```TagCrudController extends CrudController```); so if you want to modify a behaviour (save, update, reorder, etc), you can easily do that by overwriting the corresponding method in your ```TagCrudController```;
+- All operations are enabled by using that operation's trait on the controller;
+- The ```setup()``` method defines the basics of the CRUD panel;
+- Each operation is set up inside a ```setupXxxOperation()``` method;
+
+**That's all for today!** If you want to learn more, go ahead and [read the next lesson](/docs/{{version}}/getting-started-crud-operations) of this series.
+
+
+
+
+ Next →
+
diff --git a/4.1/getting-started-crud-operations.md b/4.1/getting-started-crud-operations.md
new file mode 100644
index 00000000..9fd25ce2
--- /dev/null
+++ b/4.1/getting-started-crud-operations.md
@@ -0,0 +1,254 @@
+# 2. CRUD Operations
+
+---
+
+**Duration:** 10 minutes
+
+Let's bring back the example in our first lesson. The Tags CRUD:
+
+
+
+With its ```TagCrudController```:
+
+```php
+crud->setModel("App\Models\Tag");
+ $this->crud->setRoute("admin/tag");
+ $this->crud->setEntityNameStrings('tag', 'tags');
+ }
+
+ public function setupListOperation()
+ {
+ $this->crud->setColumns(['name', 'slug']);
+ }
+
+ public function setupCreateOperation()
+ {
+ $this->crud->setValidation(TagCrudRequest::class);
+
+ $this->crud->addField([
+ 'name' => 'name',
+ 'type' => 'text',
+ 'label' => "Tag name"
+ ]);
+ $this->crud->addField([
+ 'name' => 'slug',
+ 'type' => 'text',
+ 'label' => "URL Segment (slug)"
+ ]);
+ }
+
+ public function setupUpdateOperation()
+ {
+ $this->setupCreateOperation();
+ }
+}
+```
+
+In the example above, we've enabled the most common operations:
+- **Create** - using a create form (aka "*add form*")
+- **List** - using AJAX DataTables (aka "*list view*", aka "*table view*")
+- **Update** - using an update form (aka "*edit form*")
+- **Delete** - using a *button* in the *list view*
+- **Show** - using a *button* in the *list view*
+
+These are the basic operations an admin can execute on an Eloquent model, thanks to Backpack. We do have additional operations (Reorder, Revisions, Clone, BulkDelete, BulkClone), and you can easily _create a custom operation_, but let's not get ahead of ourselves. Baby steps. **Let's go through the most important features of the operations you'll be using _all the time_: ListEntries, Create and Update**.
+
+
+## Create & Update Operations
+
+
+
+
+### Fields
+
+Inside your Controller's ```setupCreateOperation()``` or ```setupUpdateOperation()``` method, you'll be able to define what fields you want the admin to see, when creating/updating entries. In the example above, we only have two fields, both using the ```text``` field type. So that's what's shown to the admin. When the admin presses _Save_, assuming your model has those two attributes as ```$fillable```, Backpack will save the entry and take you back to the ListEntries view. Keep in mind we're using a _pure_ Eloquent model. So of course, inside the model you could use accessors, mutators, events, etc.
+
+
+But a lot of times, you won't just need text inputs. You'll need datepickers, upload buttons, 1-n relationship, n-n relationships, textareas, etc. For each field, you only need to define it properly in the Controller. Here are the most used methods to manipulate fields:
+
+```php
+$this->crud->addField($field_definition_array);
+$this->crud->addFields([$field_definition_array_1, $field_definition_array_2]);
+$this->crud->removeField('name');
+$this->crud->removeFields(['name_1', 'name_2']);
+
+// pro tip:
+// a quick way to add simple fields: let the CRUD decide what field type it is
+$this->crud->addField('db_column_name');
+```
+
+A typical *field definition array* will need at least three things:
+- ```name``` - the attribute (column in the database), which will also become the name of the input;
+- ```type``` - the kind of field we'd like to use (text, number, select2, etc);
+- ```label``` - the human-readable label for the input (will be generated from ```name``` if not given);
+
+
+You can use [one of the 44+ field types we've provided](/docs/{{version}}/crud-fields#default-field-types), or easily [create a custom field type](/docs/{{version}}/crud-fields#creating-a-custom-field-type) if you have some super-specific need that we haven't covered yet, or even [overwrite how a field type works](#overwriting-default-field-types). Take a few minutes and [browse the 44+ field types](/docs/{{version}}/crud-fields#default-field-types), to understand how the definition array differs from one to another and how many use cases you have already covered.
+
+Let's take another example, slightly more complicated than the ```text``` fields we used above. Something you'll encounter all the time is relationship fields. So let's say the ```Tag``` model has an **n-n relationship** with an Article model:
+
+```php
+ public function articles()
+ {
+ return $this->belongsToMany('App\Models\Article', 'article_tag');
+ }
+```
+
+We could use the code below to add a ```select2_multiple``` field to the Tag update forms:
+
+```php
+$this->crud->addField([
+ 'type' => 'select2_multiple',
+ 'name' => 'articles', // the relationship name in your Model
+ 'entity' => 'articles', // the relationship name in your Model
+ 'attribute' => 'title', // attribute on Article that is shown to admin
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
+]);
+```
+
+**Notes:**
+- If we call this inside ```setupUpdateOperation()``` it will only be added on that operation;
+- Because we haven't specified a ```label```, Backpack will take the "_articles_" name and turn it into a label: "_Articles_";
+
+If we had an Articles CRUD, and the reverse relationship defined on the ```Article``` model too, we could also add a ```select2_multiple``` field in the Article CRUD, to allow the admin to choose which tags apply to each article. This actually makes more sense than the above :-)
+
+```php
+$this->crud->addField([
+ 'label' => "Tags",
+ 'type' => 'select2_multiple',
+ 'name' => 'tags', // the method that defines the relationship in your Model
+ 'entity' => 'tags', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
+]);
+```
+
+> When generating a CrudController, you might be using the ```$this->crud->setFromDb();``` method by default, which tries to figure out what fields you might need in your create/update forms and what columns in your list view, but - as you'd expect - it only works for the simple field types. You can:
+>
+> (1) choose to keep using ```setFromDb()``` and add/remove/change additional fields
+>
+> or
+>
+> (2) delete ```setFromDb()``` and manually define each field and column;
+>
+> **Our recommendation**, for anything but the simplest CRUDs, **is to manually define each field** - much easier to understand and customize, for your future self and any other developer that comes after you.
+
+
+### Callbacks
+
+Developers coming from GroceryCRUD on CodeIgniter or other CRUD systems will be looking for callbacks to run ```before_insert```, ```before_update```, ```after_insert```, ```after_update```. **There are no callbacks in Backpack**. The ```store()``` and ```update()``` code is inside a trait, so you can easily overwrite that method, and call it inside your new method. For example, here's how we can do things before/after an item is saved in the Create operation:
+
+```php
+traitStore();
+ // do something after save
+ return $response;
+ }
+}
+```
+
+>But before you do that, ask yourself - **_is this something that should be done when an entry is added/updated/deleted from the application, too_**? Not just the admin panel? If so, a better place for it would be the Model. Remember your Model is a pure Eloquent Model, so the cleanest way might be to use [Eloquent Event Observers](https://laravel.com/docs/6.0/eloquent#events) or [accessors and mutators](https://laravel.com/docs/master/eloquent-mutators#accessors-and-mutators).
+
+
+## List Operation
+
+List shows the admin a table with all entries. On the front-end, the information is pulled using AJAX calls, and shown using DataTables. It's the most feature-packed operation in Backpack, but right now we're just going through the most important features you need to know about: columns, filters and buttons.
+
+You should configure the List operation inside the ```setupListOperation()``` method.
+
+
+### Columns
+
+Columns help you specify *which* attributes are shown in the table and *in which order*. **Their syntax is super-similar to fields**:
+
+```php
+$this->crud->addColumn($column_definition_array); // add a single column, at the end of the table
+$this->crud->addColumns([$column_definition_array_1, $column_definition_array_2]); // add multiple columns, at the end of the table
+$this->crud->removeColumn('column_name'); // remove a column from the table
+$this->crud->removeColumns(['column_name_1', 'column_name_2']); // remove an array of columns from the table
+$this->crud->setColumnDetails('column_name', ['attribute' => 'value']);
+$this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
+
+$this->crud->setColumns([$column_definition_array_1, $column_definition_array_2]); // make these the only columns in the table
+```
+
+You can use one of the [14+ column types](/docs/{{version}}/crud-columns#default-column-types) to show information to the user in the table, or easily [create a custom column type](/docs/{{version}}/crud-columns#creating-a-custom-column-type), if you have a super-specific need. Here's an example of using the methods above:
+
+```php
+$this->crud->addColumn([
+ 'name' => 'published_at',
+ 'type' => 'date',
+ 'label' => 'Publish_date',
+]);
+
+// PRO TIP: to quickly add a text column, just pass the name string instead of an array
+$this->crud->addColumn('text'); // adds a text column, at the end of the stack
+```
+
+
+### Filters
+
+
+
+Filters provide an easy way for the admin to well… _filter_ the ListEntries table. The syntax is very similar to Fields and Columns and you can use one of the [existing 8 filter types](/docs/{{version}}/crud-filters) or easily [create a custom filter](/docs/{{version}}/crud-filters#creating-custom-filters).
+
+```php
+$this->crud->addFilter($options, $values, $filter_logic);
+$this->crud->removeFilter($name);
+$this->crud->removeAllFilters();
+```
+
+For more on this, check out the [filters documentation page](/docs/{{version}}/crud-filters), when you need them.
+
+
+### Buttons
+
+
+
+If you want to add a custom button to an entry, you can do that. If you want to remove a button, you can also do that. Look for the [buttons documentation](/docs/{{version}}/crud-buttons) when you need it.
+
+```php
+// positions: 'beginning' and 'end'
+// stacks: 'line', 'top', 'bottom'
+// types: view, model_function
+$this->crud->addButton($stack, $name, $type, $content, $position);
+$this->crud->removeButton($name);
+$this->crud->removeButtonFromStack($name, $stack);
+```
+
+**That's it for today!** Thanks for sticking with us this long. This has been the most important and longest lesson. You can go ahead and [install Backpack](/docs/{{version}}/installation) now, as you've already gone through the most important features. Or [read the next lesson](/docs/{{version}}/getting-started-advanced-features), about advanced features.
+
+
+
+
+ Next →
+
\ No newline at end of file
diff --git a/4.1/getting-started-license-and-support.md b/4.1/getting-started-license-and-support.md
new file mode 100644
index 00000000..e455e857
--- /dev/null
+++ b/4.1/getting-started-license-and-support.md
@@ -0,0 +1,56 @@
+# 4. Add-ons, License & Support
+
+---
+
+**Duration:** 3 minutes
+
+
+## Add-ons
+
+In addition to our core packages (Base and CRUD), we have quite a few packages you can install or download, that treat common use cases. Some have been developed by our core team, some by our wonderful community. For example, we have plug&play interfaces to manage [site-wide settings](https://github.com/Laravel-Backpack/Settings), [the default Laravel users table](https://github.com/eduardoarandah/UserManager), [users, groups & permissions](https://github.com/Laravel-Backpack/PermissionManager), [content for custom pages, using page templates](https://github.com/Laravel-Backpack/PageManager), [news articles, categories and tags](https://github.com/Laravel-Backpack/NewsCRUD), etc.
+
+Take a look at:
+- [all official add-ons](/docs/{{version}}/add-ons-official)
+- [all community add-ons](/docs/{{version}}/add-ons-community)
+
+
+## License
+
+Backpack is **free for non-commercial use**, but needs a license code in order to prevent "_unlicensed use_" notification bubbles and interruption of service. You can get a license code for your project:
+- ```free```, if you're using it for non-commercial purposes; [apply here](https://backpackforlaravel.com/pricing);
+- ```free```, if you've contributed to Backpack on Github; [apply here](https://backpackforlaravel.com/pricing);
+- ```€69 EUR/project```, if you're making money using it for a project; [buy here](https://backpackforlaravel.com/pricing);
+- ```€399 EUR for unlimited projects```, if you use Backpack a lot; [buy here](https://backpackforlaravel.com/pricing);
+
+**Freelancers** or companies **who make money using Backpack** - for themselves, their employers or their clients, **should [purchase a commercial license here](https://backpackforlaravel.com/pricing)**.
+
+
+>**You don't need a license code on LOCALHOST.** If you're just trying Backpack on your own machine, you don't need a license code. You only need a license code when you take your application to production.
+
+
+## Support
+
+With thousands of developers using Backpack, a lot of them non-commercial, and such a small price, **we can't offer official support for the packages**. We've been doing this since 2016, we actively maintain the packages, we try to squash any bugs ASAP and add new features all the time, but we unfortunately can't spend time on back-and-forth on implementation issues in your project. But. We do have good documentation and have been blessed with a **great community**, where people help each other out. If Backpack becomes your tool of preference, I highly recommend you join our gang. Help others get started, create cool stuff, or even influence the direction of Backpack:
+
+- **[StackOverflow tag](https://stackoverflow.com/questions/tagged/backpack-for-laravel) for support requests** (If you need help creating something using Backpack, post your question on StackOverflow using the ```backpack-for-laravel``` tag. We've been blessed with a great community that is happy to help. Who doesn't like getting StackOverflow points?)
+- **[Gitter Chatroom](https://gitter.im/BackpackForLaravel/Lobby) for quick questions** (If you have an urgent matter that won't take much time to answer, use our 24/7 Gitter chatroom. Be considerate, everyone's probably working on their own project right now.)
+- **[Github Issues](https://github.com/laravel-backpack/) for bugs** (Found a bug? Great! Please search for it on Github first - someone might have already found it. If not, open an issue, we're happy to learn about it and make Backpack better. )
+- **[/r/BackpackForLaravel subreddit](https://www.reddit.com/r/BackpackForLaravel/) for showing off your work, asking for opinions on implementation, sharing tips, packages, etc.**
+
+Thank you for sticking up with us for so long. This is the last Backpack lesson we can give you. **Now you have absolutely no excuse not to start your first Backpack project :-)** Here are a few links for if you still don't think you're ready:
+
+- [Go through the demo](/docs/{{version}}/demo) and play around
+- Read this [CRUD Crash Course](/docs/{{version}}/crud-tutorial) and do the steps yourself
+- Take a look at the [CrudController API Cheat Sheet](/docs/{{version}}/crud-cheat-sheet)
+
+
+
+
+ CRUD Crash Course
+
+
+ Demo
+
+
+ Cheat Sheet
+
\ No newline at end of file
diff --git a/4.1/getting-started-videos.md b/4.1/getting-started-videos.md
new file mode 100644
index 00000000..4d76b0bf
--- /dev/null
+++ b/4.1/getting-started-videos.md
@@ -0,0 +1,118 @@
+# Getting Started Videos
+
+---
+
+**Total Duration:** 31 minutes
+
+
+
+
Intro
+
+
+Meet your teacher, [Cristian Tabacitu](https://twitter.com/tabacitu), the founder of Backpack for Laravel.
+
+
+
+
+Mentioned in this video:
+- [Laravel](https://laravel.com)
+- ["Laravel from Scratch" series on Laracasts](https://laravelfromscratch.com/)
+- [Backpack's docs repo on Github](https://github.com/laravel-backpack/docs)
+
+----
+
+
+
The Admin Interface
+
+Before we go deep into the PHP features offered by Backpack, it's important to understand the HTML & CSS it uses, and how that can make your life easier when building admin panels. This is often an afterthought in admin panels, but Backpack makes it really really easy to create admin pages that are 100% custom.
+
+
+
+
+Mentioned in this video:
+- [Laravel docs - installation](https://laravel.com/docs/7.x)
+- [Backpack docs - installation](/docs/{{version}}/installation)
+- [Backpack docs - how to customize the user interface](/docs/{{version}}/base-how-to#customizing-the-design-of-the-menu-sidebar-footer)
+- [Backpack docs - widgets](/docs/{{version}}/base-widgets)
+- [Backpack docs - add-ons](/addons)
+- [Bootstrap 4 docs](https://getbootstrap.com/)
+- [Backstrap.net - the default HTML template & UI blocks](https://backstrap.net/)
+
+----
+
+
+
Generating and Understanding CRUDs
+
+Let's generate a few Backpack CRUDs - places where the admin can Create, Read, Update or Delete entries. CRUDs will make it easy for you to build admin panels, 10x faster than before.
+
+
+
+
+> **NEW!!!** Starting with Aug 2021, there's a much simpler way to generate everything 🎉 Instead of using Blueprint,
+ **check out our new paid addon - [Backpack DevTools](https://backpackforlaravel.com/products/devtools).** It's a GUI that will help you generate Migrations, Models (complete with relationships), CRUDs from the browser 😱 It does cost extra, but it's well worth the price if you use Backpack regularly or your models are not dead-simple.
+
+
+Mentioned in this video:
+- [Backpack's online demo](https://demo.backpackforlaravel.com/admin/login)
+- [laravel-shift/blueprint](https://blueprint.laravelshift.com/) - CLI tool to generate Eloquent models
+- [Laravel docs - migrations](https://laravel.com/docs/7.x/migrations#introduction)
+- [backpack/generators - CLI tool to generate CRUDs](https://github.com/laravel-backpack/generators)
+- [Fork - Git client for Mac OS & Windows](https://git-fork.com/)
+- [Backpack's List Operation](/docs/{{version}}/crud-operation-list-entries) - features [columns](/docs/{{version}}/crud-columns), [filters](/docs/{{version}}/crud-filters), [buttons](/docs/{{version}}/crud-buttons), [widgets](/docs/{{version}}/base-widgets), [other features](/docs/{{version}}/crud-operation-list-entries#other-features)
+- [Backpack's Create Operation](/docs/{{version}}/crud-operation-create) - features [fields](/docs/{{version}}/crud-fields), [widgets](/docs/{{version}}/base-widgets), [save actions](/docs/{{version}}/crud-save-actions), [split fields into tabs](/docs/{{version}}/crud-fields#split-fields-into-tabs), [add custom HTML between the fields](/docs/{{version}}/crud-fields#custom-html)
+- [Backpack's Update Operation](/docs/{{version}}/crud-operation-update)
+- [Backpack's Delete Operation](/docs/{{version}}/crud-operation-delete)
+
+Not mentioned in this video, but heavily recommended:
+- [Backpack DevTools](https://backpackforlaravel.com/products/devtools)
+
+----
+
+
+
Using Operations and Features in CRUDs
+
+I'd argue the best part of Backpack is not how easy it is to generate CRUDs, but how easy it is to customize them. In this video, we'll be taking a look at the default Operations that Backpack offers, and changing things around to fit our purpose. In the process, you'll understand how they work, and just how easy it is to use, customize or overwrite Operations like Create, Update, List, Delete, Reorder, Clone, BulkClone and BulkDelete.
+
+
+
+
+Mentioned in this video:
+- [Backpack operations](/docs/{{version}}/crud-operations)
+- Laravel docs - [validation using Laravel Form Requests](https://laravel.com/docs/7.x/validation#form-request-validation)
+- Laravel docs - [validation rules](https://laravel.com/docs/7.x/validation#available-validation-rules)
+- [Reorder Operation](/docs/{{version}}/crud-operation-reorder)
+- [Clone & BulkClone Operations](/docs/{{version}}/crud-operation-clone)
+- Columns - [the 20+ column types](/docs/{{version}}/crud-columns#default-column-types), [columns API](/docs/{{version}}/crud-columns#columns-api), [fluent syntax](/docs/{{version}}/crud-fluent-syntax#fluent-columns), [array syntax](/docs/{{version}}/crud-columns#about), [overwriting a column type](/docs/{{version}}/crud-columns#overwriting-default-column-types), [creating a custom column type](/docs/{{version}}/crud-columns#creating-a-custom-column-type)
+- Fields - [the 50+ field types](/docs/{{version}}/crud-fields#default-field-types), [fluent syntax](/docs/{{version}}/crud-fluent-syntax#fluent-fields-api), [array syntax](/docs/{{version}}/crud-fields#about), [overwriting a field type](/docs/{{version}}/crud-fields#overwriting-default-field-types), [custom field types](/docs/{{version}}/crud-fields#creating-a-custom-field-type)
+- [the contents of an Operation - sidebar item, routes, controller](/docs/{{version}}/crud-operations#contents-of-a-custom-operation)
+
+----
+
+
+Thank you for dedicating these 31 minutes to learning Backpack. **You should now be able to build your first admin panel.** But if you feel like you're _not quite ready yet_, here are a few more things you can do:
+
+- [Go through the demo](/docs/{{version}}/demo) and play around, browse the features (pay special attention to the Monsters CRUD)
+- Read this [CRUD Crash Course](/docs/{{version}}/crud-tutorial) and do the steps yourself
+- Take a look at the [CrudController API Cheat Sheet](/docs/{{version}}/crud-cheat-sheet)
+- Read our [Getting Started Text Course](/docs/{{version}}/getting-started-basics)
+- Purchase and install [Backpack DevTools](https://backpackforlaravel.com/products/devtools) which will generate the minimum stuff for you
+
+
+
diff --git a/4.1/index.md b/4.1/index.md
new file mode 100644
index 00000000..e73f725f
--- /dev/null
+++ b/4.1/index.md
@@ -0,0 +1,58 @@
+#### About
+
+- [Introduction](/docs/{{version}}/introduction)
+- [Demo](/docs/{{version}}/demo)
+- [Installation](/docs/{{version}}/installation)
+- [Release Notes](/docs/{{version}}/release-notes)
+- [Upgrade Guide](/docs/{{version}}/upgrade-guide)
+- [FAQ](/docs/{{version}}/faq)
+
+#### Getting Started
+- [Video Course](/docs/{{version}}/getting-started-videos)
+- [Text Course](/docs/{{version}}/getting-started-basics)
+ - [1. Basics](/docs/{{version}}/getting-started-basics)
+ - [2. CRUD Operations](/docs/{{version}}/getting-started-crud-operations)
+ - [3. Advanced Features](/docs/{{version}}/getting-started-advanced-features)
+ - [4. Add-ons, License & Support](/docs/{{version}}/getting-started-license-and-support)
+
+#### Admin UI
+
+- [About](/docs/{{version}}/base-about)
+- [Alerts](/docs/{{version}}/base-alerts)
+- [Breadcrumbs](/docs/{{version}}/base-breadcrumbs)
+- [Widgets](/docs/{{version}}/base-widgets)
+- [FAQ](/docs/{{version}}/base-how-to)
+
+#### CRUD Panels
+
+- [Basics](/docs/{{version}}/crud-basics)
+- [Crash Course](/docs/{{version}}/crud-tutorial)
+- [Operations](/docs/{{version}}/crud-operations)
+ + [List](/docs/{{version}}/crud-operation-list-entries)
+ + [Columns](/docs/{{version}}/crud-columns)
+ + [Buttons](/docs/{{version}}/crud-buttons)
+ + [Filters](/docs/{{version}}/crud-filters)
+ + [Create](/docs/{{version}}/crud-operation-create) & [Update](/docs/{{version}}/crud-operation-update)
+ + [Fields](/docs/{{version}}/crud-fields)
+ + [Save Actions](/docs/{{version}}/crud-save-actions)
+ + [Delete](/docs/{{version}}/crud-operation-delete)
+ + [Show](/docs/{{version}}/crud-operation-show)
+ + [Columns](/docs/{{version}}/crud-columns)
+- [Additional Operations](/docs/{{version}}/crud-operations)
+ + [Clone](/docs/{{version}}/crud-operation-clone)
+ + [Reorder](/docs/{{version}}/crud-operation-reorder)
+ + [Revise](/docs/{{version}}/crud-operation-revisions)
+ + [Fetch](/docs/{{version}}/crud-operation-fetch)
+ + [InlineCreate](/docs/{{version}}/crud-operation-inline-create)
+- [API](/docs/{{version}}/crud-cheat-sheet)
+ + [Cheat Sheet](/docs/{{version}}/crud-cheat-sheet)
+ + [Crud API](/docs/{{version}}/crud-api)
+ + [Fluent API](/docs/{{version}}/crud-fluent-syntax)
+- [FAQ](/docs/{{version}}/crud-how-to)
+
+
+#### Add-ons
+
+- [Official Add-ons](/docs/{{version}}/add-ons-official)
+- [Community Add-ons](https://backpackforlaravel.com/addons)
+- [How to Create an Add-on](/docs/{{version}}/add-ons-tutorial-using-the-addon-skeleton)
diff --git a/4.1/install-optionals.md b/4.1/install-optionals.md
new file mode 100644
index 00000000..8ef1b9db
--- /dev/null
+++ b/4.1/install-optionals.md
@@ -0,0 +1,167 @@
+# Install Optional Packages
+
+---
+
+Each Backpack package has its own installation instructions in its readme file. We duplicate them here for easy access.
+
+Everything else is optional. Your project might use them or it might not. Only do each of the following steps if you need the functionality that package provides.
+
+
+## BackupManager
+
+[>> See screenshots and installation](https://github.com/Laravel-Backpack/BackupManager)
+
+1) In your terminal
+
+```bash
+# Install the package
+composer require backpack/backupmanager
+
+# Publish the config file and lang files:
+php artisan vendor:publish --provider="Backpack\BackupManager\BackupManagerServiceProvider"
+
+# [optional] Add a sidebar_content item for it
+php artisan backpack:add-sidebar-content "
"
+```
+
+2) Add a new "disk" to config/filesystems.php:
+
+```php
+// used for Backpack/BackupManager
+'backups' => [
+ 'driver' => 'local',
+ 'root' => storage_path('backups'), // that's where your backups are stored by default: storage/backups
+],
+```
+This is where you choose a different driver if you want your backups to be stored somewhere else (S3, Dropbox, Google Drive, Box, etc).
+
+3) [optional] Modify your backup options in config/backup.php
+
+4) [optional] Instruct Laravel to run the backups automatically in your console kernel:
+
+```php
+// app/Console/Kernel.php
+
+protected function schedule(Schedule $schedule)
+{
+ $schedule->command('backup:clean')->daily()->at('04:00');
+ $schedule->command('backup:run')->daily()->at('05:00');
+}
+```
+
+5) [optional] If you need to change the path to the mysql_dump command, you can do that in your config/database.php file. For MAMP on Mac OS, add these to your mysql connection:
+```php
+'dump' => [
+ 'dump_binary_path' => '/Applications/MAMP/Library/bin/', // only the path, so without `mysqldump` or `pg_dump`
+ 'use_single_transaction',
+ 'timeout' => 60 * 5, // 5 minute timeout
+]
+```
+
+
+## LogManager
+
+[>> See screenshots and installation](https://github.com/Laravel-Backpack/logmanager)
+
+
+1) Install via composer:
+
+```bash
+composer require backpack/logmanager
+```
+
+2) Add a "storage" filesystem disk in config/filesystems.php:
+
+```php
+// used for Backpack/LogManager
+'storage' => [
+ 'driver' => 'local',
+ 'root' => storage_path(),
+],
+```
+
+3) Configure Laravel to create a new log file for every day, in your .ENV file, if it's not already. Otherwise there will only be one file at all times.
+
+```
+APP_LOG=daily
+```
+
+or directly in your config/app.php file:
+```php
+'log' => env('APP_LOG', 'daily'),
+```
+
+4) [optional] Add a menu item for it in resources/views/vendor/backpack/base/inc/sidebar_content.blade.php or menu.blade.php:
+
+```bash
+php artisan backpack:add-sidebar-content "
"
+```
+
+## Settings
+
+An interface for the administrator to easily change application settings. Uses Laravel Backpack.
+
+[>> See screenshots and installation](https://github.com/Laravel-Backpack/settings)
+
+Installation:
+
+```bash
+# install the package
+composer require backpack/settings
+
+# run the migration
+php artisan vendor:publish --provider="Backpack\Settings\SettingsServiceProvider"
+php artisan migrate
+
+# [optional] add a menu item for it to the sidebar_content file
+php artisan backpack:add-sidebar-content "
"
+
+# [optional] insert some example dummy data to the database
+php artisan db:seed --class="Backpack\Settings\database\seeds\SettingsTableSeeder"
+```
+
+
+## PageManager
+
+An admin panel where you, as a developer, can define templates with different fields, and the admin can choose between those templates to create/edit pages with content.
+
+[>> See screenshots and installation](https://github.com/Laravel-Backpack/pagemanager)
+
+
+## PermissionManager
+
+An admin panel for user authentication on Laravel 5, using Backpack\CRUD. Add, edit, delete users, roles and permission.
+
+[>> See screenshots and installation](https://github.com/Laravel-Backpack/PermissionManager)
+
+
+## MenuCrud
+
+An admin panel for menu items on Laravel 5, using Backpack\CRUD. Add, edit, reorder, nest, rename menu items and link them to Backpack\PageManager pages, external link or custom internal link.
+
+[>> Github](https://github.com/Laravel-Backpack/MenuCRUD)
+
+
+## NewsCrud
+
+Since NewsCRUD does not provide any extra functionality other than Backpack\CRUD, it is not a package. It's just a tutorial to show you how this can be achieved. In the future, CRUD examples like this one will be easily installed from the command line, from a central repository. Until then, you will need to manually create the files.
+
+[>> Github](https://github.com/Laravel-Backpack/NewsCRUD)
+
+
+
+## FileManager
+
+Backpack admin interface for files and folders, using [barryvdh/laravel-elfinder](https://github.com/barryvdh/laravel-elfinder).
+
+[>> See screenshots and installation](https://github.com/Laravel-Backpack/FileManager)
+
+Installation:
+
+```bash
+composer require backpack/filemanager
+```
+
+```bash
+php artisan backpack:filemanager:install
+```
diff --git a/4.1/installation.md b/4.1/installation.md
new file mode 100644
index 00000000..b1375db2
--- /dev/null
+++ b/4.1/installation.md
@@ -0,0 +1,73 @@
+# Installation
+
+---
+
+
+## Requirements
+
+If you can run Laravel 8, 7 or 6, you can install Backpack. Backpack does _not_ have additional requirements. For the following process, we assume:
+
+- you have a [working installation of Laravel](https://laravel.com/docs/8.x#installation) (an existing project is fine, you don't need a *fresh* Laravel install);
+
+- you have configured your .ENV file with your database and mail information;
+
+- you can run the ```composer``` command from any directory (you have ```composer``` registered as a global command); if you need to run ```php composer.phar``` or reference another directory, please remember to adapt the commands below to your configuration;
+
+
+## Installation
+
+
+### Install Core Packages
+
+0) Open your project folder in your terminal:
+
+```bash
+cd your-laravel-project-name
+```
+
+1) In your project's main directory:
+
+``` bash
+# require Backpack using Composer
+composer require backpack/crud:"4.1.*"
+composer require --dev backpack/generators
+
+# run the installation command
+php artisan backpack:install
+```
+
+> Backpack install is interactive and will ask questions during installation, if you don't want that add the `--no-interaction` argument to the install command.
+
+2) [optional] Backpack assumes you already have your Eloquent Models properly set up. If you don't, **consider using something to quickly generate Migrations & Models**. You can use anything you want, but here are the options we recommend:
+
+- a) Generate from a **web interface** - [Backpack Devtools](https://backpackforlaravel.com/products/devtools) - premium product, paid separately. A simple GUI to quickly generate Migrations, Models, Factories, Seeders and CRUDs, right from your browser. Works well for entities of all sizes.
+
+- b) Generate from the **command-line** - [Laracasts Generators](https://github.com/laracasts/Laravel-5-Generators-Extended) - free & open-source. Adds a new artisan command so that you can do `php artisan make:migration:schema create_users_table --schema="username:string, email:string:unique"`. Works well for smaller entities.
+
+- c) Generate from a **YAML file** - [LaravelShift's Blueprint](https://blueprint.laravelshift.com/) - free & open-source. Enables you to create a `draft.yml` file in your repo, where you can specify the column using their custom YAML syntax. Works well for small & medium entities.
+
+3) Take note that:
+- By default all users are considered admins; If that's not what you want in your application (you have both users and admins), please:
+ - Change ```app/Http/Middleware/CheckIfAdmin.php```, particularly ```checkIfUserIsAdmin($user)```, to make sure you only allow admins to access the admin panel;
+ - Change ```app/Providers/RouteServiceProvider::HOME```, which will send logged in (but not admin) users to `/home`, to something that works for your app; This is only needed in Laravel 7+;
+- Change configuration values in ```config/backpack/base.php``` to make the admin panel your own. Backpack is white label, so you can change everything: menu color, project name, developer name etc.
+- If your User model has been moved (it is not ```App\User.php```), please change ```config/backpack/base.php``` to use the correct user model using the ```user_model_fqn``` config key. If you are using Laravel 8 and up, you need to change this. Because by default Laravel 8 and up save the ```User``` model inside the ```Models``` directory.
+
+That's it. If you already know how to use Backpack, next up you'll probably want to [create CRUD Panels](/docs/{{version}}/crud-tutorial#generate-files).
+
+> If it's your first time installing Backpack, it is **highly recommended** that you go through our [Getting Started series](/docs/{{version}}/getting-started-basics), to understand how Backpack works. That's why we created it - to help you learn how to use this admin panel framework. In ~23 minutes we'll teach you 80% of what you can do, and how.
+
+
+
+### Install Add-ons
+
+In case you want to add extra functionality that's already been built, check out [the installation steps for the add-ons we've developed](/docs/{{version}}/install-optionals).
+
+
+## Frequently Asked Questions
+
+- **Error: The process X exceeded the timeout of 60 seconds.** It might mean Github or Packagist is unavailable at the moment. This usually doesn't last for more than a few minutes, so you can run ```php artisan backpack:install --timeout=600``` to increase the timeout to 10 minutes. If this doesn't work either, take a look behind the scenes with ```php artisan backpack:install --timeout=600 --debug```;
+
+- **Error: SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long**. Your MySQL version might be a bit old. Please [apply this quick fix](https://laravel-news.com/laravel-5-4-key-too-long-error), then run ```php artisan migrate:fresh```.
+
+- **Any other installation error?** If you can't install Backpack because of a different error, you can [try the manual installation process](/docs/{{version}}/crud-how-to#manually-install-backpack), which you can tweak to your needs.
diff --git a/4.1/introduction.md b/4.1/introduction.md
new file mode 100644
index 00000000..37722481
--- /dev/null
+++ b/4.1/introduction.md
@@ -0,0 +1,93 @@
+# Introduction
+
+---
+
+Backpack is a collection of Laravel packages that help you **build custom administration panels**, for anything from presentation websites to complex web applications. You can install them on top of existing Laravel installations _or_ fresh projects.
+
+In a nutshell:
+
+- Backpack will provide you with a _visual interface_ for the admin panel (the HTML, the CSS, the JS); it pulls in the excellent [CoreUI](https://coreui.io/) theme, with our own design called [Backstrap](https://backstrap.net), adds authentication functionality & bubble notifications; when you decide to build a custom feature for your admin panel, you already have the HTML blocks for the UI, and it will look good;
+- Backpack will help you build _sections where your admins can manipulate entries for Eloquent models_; we call them _CRUD Panels_ after the most basic operations: Create/Read/Update/Delete; after [understanding Backpack](/docs/{{version}}/getting-started-basics), you'll be able to create a CRUD panel for each entity in about 10 minutes / model:
+
+```bash
+# STEP 0. create migration (in case you're starting from scratch)
+composer require --dev laracasts/generators
+php artisan make:migration:schema create_tags_table --model=0 --schema="name:string:unique"
+php artisan migrate
+
+# STEP 1. create a Model, Request, Controller, Route and sidebar item for the admin panel
+php artisan backpack:crud tag #use singular, not plural
+
+# STEP 2. go through the generated files, customize according to your needs
+```
+
+Better yet, if you purchase our brand-new [Backpack DevTools](https://backpackforlaravel.com/products/devtools) (premium addon, paid extra) you can generate better Migrations, Models, Seeders, Factories and CRUDs... from the comfort of your browser window 🤯 It's never been this easy:
+
+
+
+---
+
+
+## How to Start
+
+We heavily recommend you spend a little time to understand Backpack, and only afterwards install and use it. Fortunately it's super-simple to get started. Using any of the options below will get you to a point where you can use Backpack in your projects:
+- **[Video Course](/docs/{{version}}/getting-started-videos)** - 31 minutes
+- **[Text Course](/docs/{{version}}/getting-started-basics)** - 20 minutes
+- **[Email Course](https://backpackforlaravel.com/getting-started-emails)** - 1 email per day, for 4 days, 5 minutes each
+
+
+
+ Video Course
+ Text Course
+ Email Course
+
+---
+
+
+## Need to Know
+
+
+### Requirements
+
+ - Laravel 8.x, 7.x or 6.x
+ - MySQL (recommended) / PostgreSQL / SQLite / SQL Server
+
+
+### How does it look?
+
+- Take a look at [our homepage](https://backpackforlaravel.com/).
+- Play around in our [live demo](https://demo.backpackforlaravel.com/admin/login).
+- [Install the demo](/docs/{{version}}/demo) and fiddle with the code.
+
+
+### Security
+
+Backpack has never had a critical vulnerability/hack. But there _have_ been important security updates for dependencies (including Laravel). Please [login with Github](/auth/github) or [subscribe to our security newsletter](https://backpackforlaravel.com/newsletter), so we can reach you in case anything bad happens. No spam, no marketing emails, we promise. We only send about 2 emails per year, when we introduce major Backpack updates or there's a problem you should know about.
+
+
+### Maintenance
+
+Backpack 4.1 is the current version, and is being actively maintained by the Backpack team, with the help of a wonderful community of Backpack veterans. [See all contributors](https://github.com/Laravel-Backpack/CRUD/graphs/contributors).
+
+
+### License
+
+Backpack is under a license we call "_You make money, I make money_" (YummY). Backpack's source is public, and you can use it for free for non-commercial purposes (testing, non-profits, personal use, etc), but if you make money using it, you need to purchase a commercial license. Please see [the pricing section](https://backpackforlaravel.com/pricing) for more details. In production, you need a license code for both commercial and non-commercial use, to prevent nagging notification bubbles. **On localhost, you don't need a license code at all.**
+
+
+### Versioning
+
+When installing Backpack, require its minor version (currently ```4.1.*```). Backpack follows the same versioning system as did prior to Laravel 6 - minor Backpack versions _will_ include breaking changes. This allows us to push new features without charging our users again. For us, this is what ```major.minor.patch``` means:
+
+- ```major``` - **PAID upgrade; MAJOR breaking changes;** historically every 2-3 years; upgrading may take even 2-3 hours; includes MAJOR new features, MAJOR changes in how the whole system works, and complete rewrites; it allows us to _considerably_ improve how we build admin panels and add features that were previously impossible;
+- ```minor``` - **FREE upgrade; SOME breaking changes**; historically every 6 months; upgrading takes 15-60 minutes; offers big new features, for free;
+- ```patch``` - **FREE upgrade; NO breaking changes**; historically every week; upgrading can be done automatically with composer; includes bug fixes and non-breaking new features;
+
+
+### Add-ons
+
+In addition to our core CRUD package, there are a few additional packages you might want to take a look at, that treat common use cases. Some have been developed by our core team, some by our wonderful community. You can just install interfaces to manage [site-wide settings](https://github.com/Laravel-Backpack/Settings), [the default Laravel users table](https://github.com/eduardoarandah/UserManager), [users, groups & permissions](https://github.com/Laravel-Backpack/PermissionManager), [content for custom pages, using page templates](https://github.com/Laravel-Backpack/PageManager), [news articles, categories and tags](https://github.com/Laravel-Backpack/NewsCRUD), etc.
+
+For more information, please see:
+- [all official add-ons](/docs/{{version}}/add-ons-official)
+- [all community add-ons](/docs/{{version}}/add-ons-community)
diff --git a/4.1/release-notes.md b/4.1/release-notes.md
new file mode 100644
index 00000000..1a690293
--- /dev/null
+++ b/4.1/release-notes.md
@@ -0,0 +1,174 @@
+# Release Notes
+
+---
+
+**Launch date:** May 5th, 2020
+
+Anybody with a 4.0 license can install and use 4.1, but in order to get the new features in a project that currently runs 4.0, you need to [follow the upgrade guide](/docs/{{version}}/upgrade-guide). Don't get fooled by the fact that we kept the 4.x.x prefix - that's just to show that **Backpack 4.1 is a FREE upgrade from 4.0**. But **Backpack 4.1 is a MAJOR new version**, with over 6 months of work put into it, and major improvements under-the-hood too. It is the current and recommended version of Backpack and it's got so many cool new things that we couldn't fit them all inside this page.
+
+But here's the big stuff Backpack 4.1 brings to the table, and why you should upgrade from [Backpack 4.0](/docs/4.0) to 4.1.
+
+
+
+## Added
+
+### Operations
+
+#### **New operation: ```InlineCreate```**
+
+- allows admins to create related items on-the-fly, without leaving the current form;
+- shows a new button next to your relationship fields; when you click [+ Add], a modal is shown with all the fields needed to create a related item on-the-fly; it basically brings that entry's Create form on this page;
+- it works well for entities with a few inputs, but it also works well for huge entities with dozens of inputs, tabs, etc;
+- see [docs](https://backpackforlaravel.com/docs/4.1/crud-operation-inline-create), [PR](https://github.com/Laravel-Backpack/CRUD/pull/2311), [demo](https://demo.backpackforlaravel.com/admin/monster)
+
+
+
+
+
+#### **New operation: ```Fetch```**
+
+- responds to AJAX requests and returns the results in a format the Select2 likes;
+- this operation makes adding AJAX selects much MUCH easier; you don't even have to leave the controller;
+- see [docs](/docs/4.1/crud-operation-fetch), [PR](https://github.com/Laravel-Backpack/CRUD/pull/2308)
+
+
+
+
+
+### Fields
+
+#### **New field type: ```relationship```**
+
+- **one relationship field to rule them all**; instead of thinking whether you need ```select2```, ```select2_multiple```, ```select2_from_ajax``` or ```select2_from_ajax_multiple``` you can now just use the ```relationship``` field, that includes the functionality of all of them... and more;
+- **intelligent defaults**; it automatically figures out the ```entity```, ```model```, ```attribute```, ```multiple```, ```pivot``` and ```label```, so most of the time you'll just need to define two things for it to work - ```name``` and ```type```;
+- **supports both non-AJAX and AJAX**; for the dropdown options, it defaults to immediate querying; if you want to load the options using AJAX, you just have to point it to the correct route, using ```data_source```; which is super-easy to do using the new Fetch operation detailed above;
+- see [docs](/docs/4.1/crud-fields#relationship), [PR](https://github.com/Laravel-Backpack/CRUD/pull/2311), [demo](https://demo.backpackforlaravel.com/admin/monster)
+
+
+
+
+
+#### **New field type: ```repeatable```** (aka ```matrix```, aka ```groups```, aka ```multiply```)
+
+- **lets your admin define one or multiple "_somethings_" right inside their create/update form**, when a "_something_" includes more than one input (ex: Testimonial can require ```name```, ```position```, ```company``` and ```quote```);
+- the end result is stored as JSON by default, but you can intercept the saving and store it any way you like;
+- makes it dead-simple to allow your admins to add/edit/delete multiple "things" inside an entry, when that "thing" is not important enough to have its own database table and Model;
+- see [docs](/docs/4.1/crud-fields#repeatable), [PR](https://github.com/Laravel-Backpack/CRUD/pull/2266)
+
+
+
+
+
+#### **New field type: ```easymde```** (alternative to ```simplemde```)
+
+- SimpleMDE (the JS library) still works, but has not received any updates in 4 years; that's why we recommend using a different markdown editor - one that is maintained;
+- fortunately, EasyMDE is a SimpleMDE fork that looks and works the same, and it is well looked after;
+- we recommend replacing all your SimpleMDE fields with EasyMDE - the change couldn't be simpler;
+- see [docs](/docs/4.1/crud-fields#easymde), [PR](https://github.com/Laravel-Backpack/CRUD/pull/2737)
+
+
+
+
+
+### Columns
+
+#### **New columns feature: ```wrapper```**
+
+- allows you to **change how columns look and feel, by wrapping the text into a custom HTML element**; similarly to how we've been able to do for years with Fields, you can now specify a wrapper for columns, and change that wrapper's ```class```, ```style```, etc.
+- you can now **easily add links to your columns**; make it easy for admins to jump from one CRUD to another, by making relationship columns point to that Model's CRUD; but they can also point to whatever else you want;
+- you can now **easily make your column text a different color depending on its content**, just by adding a Bootstrap class (ex: add ```badge badge-warning``` or ```text-success```);
+- see [docs](/docs/{{version}}/crud-columns#wrap-column-text-in-an-html-element), [PR](https://github.com/Laravel-Backpack/CRUD/pull/2448), [demo](https://demo.backpackforlaravel.com/admin/article)
+
+
+
+
+
+
+#### **New column: ```relationship```**
+
+- the perfect companion to the new ```relationship``` field;
+- **intelligent defaults**; it automatically figures out the ```entity```, ```model```, ```attribute```, ```multiple```, ```pivot``` and ```label```, so most of the time you'll just need to define two things for it to work - ```name``` and ```type```;
+- see [docs](/docs/{{version}}/crud-columns#relationship), [PR](https://github.com/Laravel-Backpack/CRUD/pull/2615), [demo](https://demo.backpackforlaravel.com/admin/monster)
+
+
+
+
+#### **New column: ```relationship_count```**
+
+- shows the number of items related to the current entry, on that relationship, for example "413 items";
+- perfect for when your entity points to A LOT of other entries;
+- if you have a CRUD with Filters for that related Model, you can add the `wrapper` attribute mentioned above to this column, to turn it into a link that points to a filtered view of that related CRUD; that way the admin can click this column and see those 413 items;
+- see [docs](/docs/{{version}}/crud-columns#relationship_count), [PR](https://github.com/Laravel-Backpack/CRUD/pull/2615), [demo](https://demo.backpackforlaravel.com/admin/monster)
+
+
+
+
+### Widgets
+
+#### **New widget: ```chart```**
+
+- easily add a widget with a chart, on any admin panel page, directly from your Controller or blade file;
+- the same/similar syntax for multiple chart libraries: ChartJS, Highcharts, Fusioncharts, Echarts, Frappe, C3, thanks to [Laravel Charts](https://charts.erik.cat/); easily switch between charting libraries;
+- easily defer DB queries to an AJAX call (recommended) or make them upon page load;
+- see [docs](/docs/4.1/base-widgets#chart), [PR](https://github.com/Laravel-Backpack/CRUD/pull/2596), [demo](https://demo.backpackforlaravel.com/admin/)
+
+
+
+
+
+
+#### **New ```Widgets``` class**
+
+- a global object that allows you to more easily add/edit Widgets to your admin panel pages;
+- you can still manipulate the ```$data['widgets']``` directly, but you can also use this new class;
+- you can pass the entire widget definition array to ```Widget::add()``` or you can use the new fluent syntax;
+- see [docs](/docs/4.1/base-widgets#widgets-api), [PR](https://github.com/Laravel-Backpack/CRUD/pull/2599), [demo](https://demo.backpackforlaravel.com/admin/)
+
+
+
+
+
+
+### One more thing
+
+#### **Alternative fluent syntax for fields, columns, filters, buttons**
+
+- An optional new way of interacting with Fields, Columns, Filters, Buttons;
+- **Add or modify. It's the same method.** Create or modify a field/column/filter/button/widget with one call - think of ```CRUD::field()``` as a new ```$this->crud->addOrModifyField()```;
+- **Reduce your CrudController length by 20-60%.** Most field&column definitions will fit on just one line.
+- **Better syntax highlighting. Better auto-completion.** For most IDEs at least.
+- **Intelligent defaults.** Most fields only actually need the `name` from you - Backpack will try to guess everything else. Even the `type`. Even the relationship.
+- see [docs](/docs/4.1/crud-fluent-syntax), [PR](https://github.com/Laravel-Backpack/CRUD/pull/2513)
+
+
+
+
+
+
+
+
+## Changed
+
+- For the ```List Operation```, you can now easily:
+ - **hide/show the search bar** - see docs, [PR](https://github.com/Laravel-Backpack/CRUD/pull/2479);
+ - **hide/show a "Reset" button** that resets the DataTable to its default search, filtering, pagination - see docs, [PR](https://github.com/Laravel-Backpack/CRUD/pull/2509);
+- You can now easily **customize the buttons at the end of the Create/Update forms** - see docs, [PR](https://github.com/Laravel-Backpack/CRUD/pull/2356);
+- You can now make all Backpack routes **use a different web middleware** than ```web``` - see docs, [PR](https://github.com/Laravel-Backpack/CRUD/pull/2408);
+- Field ```wrapperAttributes``` was renamed to ```wrapper```;
+
+
+
+## Removed
+
+- Support for Laravel 5.8;
+- Support for PHP lower than 7.2.5;
+- ```laravel/helpers``` dependency, but you can still install it yourself, if you want to use the array and string helpers;
+- ```venturecraft/revisionable``` dependency; in order to use the Revisions operation you now have to install [the backpack/revise-operation add-on](https://github.com/laravel-backpack/revise-operation);
+- ```barryvdh/laravel-elfinder``` dependency; in order to use the File Manager screen, the ```browse``` or ```browse_multiple``` field types, you now need to install the [backpack/filemanager add-on](https://github.com/Laravel-Backpack/FileManager) that we created;
+- ```intervention/image``` dependency; in order to use the ```image``` field type you might need to [install the package](http://image.intervention.io/getting_started/installation), if you've copy-pasted our example mutator in your Model;
+- ```App\Models\BackpackUser``` is no longer needed, recommended or published when installing Backpack; authentication now works with your default ```App\User``` model (or whatever it is); this eliminates a bit of unneeded complexity, and fixes a bunch of problems when there are morph relationships towards the User model; but you can still keep it if you like to have a separate model for you admins;
+
+
+---
+
+In order to get all of the features above (and a few more hidden gems), please [follow the upgrade guide](/docs/{{version}}/upgrade-guide), to get from Backpack 4.0 to Backpack 4.1.
diff --git a/4.1/upgrade-guide.md b/4.1/upgrade-guide.md
new file mode 100644
index 00000000..67bdb70e
--- /dev/null
+++ b/4.1/upgrade-guide.md
@@ -0,0 +1,273 @@
+# Upgrade Guide
+
+---
+
+This will guide you to upgrade from Backpack 4.0 to 4.1. The steps are color-coded by the probability that you will need it for your application: High, Medium and Low.
+
+
+## Requirements
+
+Please make sure your project respects the requirements below, before you start the upgrade process. You can check with ```php artisan backpack:version```:
+
+- PHP 7.4.x, 7.3.x or 7.2.5+
+- Laravel 7.x or 6.x
+- Backpack\CRUD 4.0.x
+- 10-30 minutes for most projects, on top of the Laravel upgrade
+
+**If you're running Backpack version 3.x, please follow ALL the minor upgrade guides first, to incrementally get to use Backpack 4.0**. Test that your app works well with each version, after each upgrade. Only _afterwards_ can you follow this guide, to upgrade from 4.0 to 4.1. Previous upgrade guides:
+- [upgrade from 3.6 to 4.0](https://backpackforlaravel.com/docs/4.0/upgrade-guide); this is a major upgrade, and requires a v4 license code; if you've purchased a Backpack v3 license, but don't have a Backpack v4 license yet, [read the 4.0 Release Notes here](/docs/4.0/release-notes#backpack-v3-buyers).
+- [upgrade from 3.5 to 3.6](https://backpackforlaravel.com/docs/3.6/upgrade-guide);
+- [upgrade from 3.4 to 3.5](https://backpackforlaravel.com/docs/3.5/upgrade-guide);
+- [upgrade from 3.3 to 3.4](https://backpackforlaravel.com/docs/3.4/upgrade-guide);
+
+
+## Upgrade Steps
+
+
+Step 0. **[Upgrade to Laravel 6](https://laravel.com/docs/6.x/upgrade). Then [upgrade to Laravel 7](https://laravel.com/docs/7.x/upgrade), if you can.** This is not _required_, but it's _recommended_. You need to do this _one day_ anyway - might as well do it now. Backpack 4.0 (that your project is already running) supports Laravel 5.8, 6 and 7. So you should:
+- **upgrade your project to use Laravel v6 or v7**
+- test your app is working fine with them
+- continue with "Step 1" below, to also upgrade Backpack to 4.1
+
+Our recommendation is to _not_ stick to Laravel 6.0 just because it's a [LTS version](https://en.wikipedia.org/wiki/Laravel#Release_history), but to upgrade to the latest Laravel. All upgrades after Laravel 5.6 have been very _very_ easy, and it's expected for this to continue, since Laravel has reached stability for some years now. If you're scared or lazy, for just $9 you can purchase a [Laravel Shift](https://laravelshift.com/), to automatically upgrade, and make sure you haven't missed a step.
+
+
+### Composer
+
+Step 1. Update your ```composer.json``` file to require ```"backpack/crud": "4.1.*"```
+
+Step 2. If you have a lot of Backpack add-ons installed (and their dependencies), here are their latest versions, that support Backpack 4.1, you can copy-paste the versions of the packages you're using:
+```
+ "backpack/logmanager": "^4.0.0",
+ "backpack/settings": "^3.0.0",
+ "backpack/pagemanager": "^3.0.0",
+ "backpack/menucrud": "^2.0.0",
+ "backpack/newscrud": "^4.0.0",
+ "backpack/permissionmanager": "^6.0.0",
+ "backpack/backupmanager": "^2.0.0",
+ "spatie/laravel-translatable": "^4.0",
+ "backpack/langfilemanager": "^3.0.0",
+
+ /* and in require-dev */
+
+ "backpack/generators": "^3.0",
+ "laracasts/generators": "^1.0"
+```
+
+Step 3. If you're using the Revisions operation, it has now been split into a separate package. So please add ```"backpack/revise-operation": "^1.0",``` to your composer's require section.
+
+Step 4. Backpack itself is no longer using ```laravel/helpers```. Instead of using helpers like ```str_slug()``` we're now doing ```Str::slug()``` everywhere. We recommend you do the same. But if you want to keep using string and array helpers, please add ```"laravel/helpers": "^1.1",``` to your composer's require section.
+
+Step 5. Since we're no longer using ```laravel/helpers```, we need the ```Str``` and ```Arr``` classes to be aliased. You should have already done this when upgrading to Laravel 5.8/6.x/7.x. But please make sure that in your ```config/app.php``` you have these aliases:
+```php
+ 'aliases' => [
+ // ...
+ 'Arr' => Illuminate\Support\Arr::class,
+ // ..
+ 'Str' => Illuminate\Support\Str::class,
+ // ..
+ ],
+```
+
+Step 6. Backpack no longer installs the FileManager by default (elFinder), since most projects don't need it. If you did use the FileManager, or the ```browse``` or ```browse_multiple``` fields, make sure you require ```"backpack/filemanager": "^1.0",``` in your ```composer.json``` - we've separated it into an add-on.
+
+Step 7. Backpack no longer installs ```intervention/image``` by default. If you use the ```image``` field type and you've used our example Mutator in your Model, you might be using ```intervention/image``` - please check. If so, please add ```"intervention/image": "^2.3",``` to your ```composer.json```'s require section.
+
+Step 8. Run ```composer update``` in the command line.
+
+
+### Models
+
+No changes needed.
+
+
+### Routes
+
+No changes needed.
+
+
+### Config
+
+Step 9. Backpack no longer provides, needs or uses the ```App\Models\BackpackUser``` model for authentication. New installs default to using ```App\User```. Since that model was only used for authentication & forgotten-password functionality, we recommend you:
+- delete the ```App\Models\BackpackUser.php``` file;
+- change your ```config/backpack/base.php``` file to:
+
+```diff
+- 'user_model_fqn' => App\Models\BackpackUser::class,
++ 'user_model_fqn' => App\User::class,
+```
+- if you've used PermissionManager, change your ```config/backpack/permissionmanager.php``` file to:
+
+```diff
+ 'models' => [
+- 'user' => App\Models\BackpackUser::class,
++ 'user' => App\User::class,
+ 'permission' => Backpack\PermissionManager\app\Models\Permission::class,
+ 'role' => Backpack\PermissionManager\app\Models\Role::class,
+ ],
+```
+
+- your ```App\User``` will need some changes for backpack to use it properly. It must use ```CrudTrait``` and ```HasRoles``` traits:
+
+```diff
+ **IMPORTANT:** If you use polymorphic relationships, you might have mentions of the ```App\Models\BackpackUser``` model in your BD. You will need to replace all those mentions in the DB with the standard ```App\User``` model.
+
+**If you've used ```PermissionManager``` or ```spatie/laravel-permission```, please note that you DO use polymorphic relationships.** All permissions and roles that pointed to ```App\Models\BackpackUser``` in the database need to be pointed to ```App\User``` model now:
+
+```bash
+# -------------------
+# ONLY if you've used PermissionManager and/or spatie/laravel=permission
+# -------------------
+
+# Step 9.1.
+# Create a database backup. Please. Pretty please.
+
+# Step 9.2.
+# Publish the migration for the standard configuration.
+# This should work as-is if you haven't changed table names.
+php artisan vendor:publish --provider="Backpack\PermissionManager\PermissionManagerServiceProvider" --tag="migrations"
+
+# Step 9.3.
+# Take a look at the migration and change whatever you need:
+# - are the table names the same in the DB & in the migration?
+# - are the column names the same?
+# - are there entries in the DB with App\Models\BackpackUser?
+# - did you notice there's no down() method for the migration? maybe you'll create a DB backup now, if you haven't?
+
+# Step 9.4.
+# Run the migration.
+php artisan migrate
+
+# Step 9.5.
+# Take another look at your model_has_roles and model_has_permissions tables.
+# Are there any more entries that point to App\Models\BackpackUser?
+```
+
+Another example of polymorphic relationships is the ```revisions``` table, if you've used it you may have references to ```App\Models\BackpackUser``` there too, please replace it with ```App\User```.
+
+
+### CrudControllers
+
+The steps below should apply for each of your CrudControllers. For each Step, go through every one of your CrudControllers (usually stored in ```app\Http\Controllers\Admin```:
+
+Step 10. If you're using the ```RevisionsOperation``` inside your CrudControllers, that operation has been moved to a separate package (that you've already installed in steps 3 & 8). Now you need to:
+- inside your CrudControllers, search for ```Backpack\CRUD\app\Http\Controllers\Operations\RevisionsOperation``` and replace with ```Backpack\ReviseOperation\ReviseOperation```
+- if you've customized the Revisions operation, take note that the specialty methods to set a Revisions view no longer exist; inside your CrudController, please use the normal ```get()```/```set()```, but please note that the operation is now called "_revise_" (verb) not "_revisions_" (noun), so your changes should be:
+ - from ```$this->crud->setRevisionsView()``` to ```$this->crud->set('revise.view')```
+ - from ```$this->crud->getRevisionsView()``` to ```$this->crud->get('revise.view')```
+ - from ```$this->crud->setRevisionsTimelineView()``` to ```$this->crud->set('revise.timelineView')```
+ - from ```$this->crud->getRevisionsTimelineView()``` to ```$this->crud->set('revise.timelineView')```
+ - from ```$this->crud->setRevisionsTimelineContentClass()``` to ```$this->crud->set('revise.timelineContentClass')```
+ - from ```$this->crud->getRevisionsTimelineContentClass()``` to ```$this->crud->set('revise.timelineContentClass')```
+- if you've defined settings for the "_revisions_" operation for all CRUDs, inside your ```config/backpack/crud.php```, please note that the operation name has changed, so inside ```operations``` you should change ```revisions``` to ```revise```;
+
+Step 11. Inside CrudControllers, Backpack 4.1:
+- no longer defines ```$this->request```
+- still defines ```$this->crud->request``` (aka ```CRUD::request```) but uses getters and setters to work with it (```$this->crud->getRequest()``` and ```$this->crud->setRequest()```);
+
+Why? Since ```$this->request``` did nothing at all, we've removed it, to avoid any confusion between working with ```$this->request``` and ```$this->crud->request```. Make sure that:
+- **If you have ```$this->request``` anywhere in your CrudControllers custom logic**, please replace it with either Laravel's ```request()``` helper or with ```$this->crud->getRequest()```.
+- **If you have ```$this->crud->request``` anywhere inside your custom CrudController logic**, please replace it with either ```$this->crud->getRequest()``` or ```$this->crud->setRequest()``` depending on what your intention is.
+
+Step 12. Inside CrudControllers, if you've used ```wrapperAttributes``` on fields, please note that it's now called ```wrapper```. Please search & replace ```wrapperAttributes``` with ```wrapper``` in your CrudControllers.
+
+Additionally, for the `select2_from_ajax` and `select2_from_ajax_multiple` field types, the inputs on the main form are no longer sent through the AJAX request by default. If you're using [dependant selects](https://backpackforlaravel.com/docs/4.1/crud-how-to#add-a-select2-field-that-depends-on-another-field), please make sure that you add `'include_all_form_fields' => true` to your `select2_from_ajax` and `select2_from_ajax_multiple` field definition to keep the same behaviour as before.
+
+
+### CSS & JS Assets
+
+Step 13. We've updated most CSS & JS dependencies to their latest versions. There are two ways to publish the latest styles and scripts for these dependencies:
+- (A) If you have NOT touched you ```public/packages``` folder, or placed anything custom inside it:
+ - delete the ```public/packages``` directory and all its contents;
+ - run ```php artisan vendor:publish --provider="Backpack\CRUD\BackpackServiceProvider" --tag=public```
+ - if you use elFinder, also delete ```resources/views/vendor/elfinder``` and run ```php artisan backpack:filemanager:install```
+- (B) Run ```php artisan vendor:publish --provider="Backpack\CRUD\BackpackServiceProvider" --tag=public --force```. Please note this will overwrite anything that's already there. This B solution has a downside: unused files are not removed. A few files Backpack no longer uses will still be in your ```public/packages``` folder, even though they're no longer used.
+
+
+
+
+### Views
+
+
+Step 14. **If you've overwritten default Fields, or have custom Fields**, take note that ALL of them have suffered changes (for the better); as a minimum, if you have any files in ```resources/views/vendor/backpack/crud/fields``` you should:
+- find & replace ```crud::inc.field_attributes``` with ```crud::fields.inc.attributes```
+- find & replace ```crud::inc.field_translatable_icon``` with ```crud::fields.inc.translatable_icon```
+- change the wrapping element; take a look at the diff below or at [the diff for the text field](https://github.com/Laravel-Backpack/CRUD/pull/2601/files#diff-9b83997dcde20848b90e97048aca5485), and do the same for all the fields you've created or overwritten:
+
+```diff
+-
++ @include('crud::fields.inc.wrapper_start')
+
+// Your actual field HTML
+
+-
++ @include('crud::fields.inc.wrapper_end')
+```
+
+
+Step 15. **If you've overwritten Columns, or have custom Columns**, take note that ALL columns have suffered changes (for the better). Most notably:
+- ```wrapper``` allows you to add links to your columns;
+- ```escaped``` allows you to output HTML instead of text;
+
+If you want your custom/overwritten columns to have these cool new features, they're very easy to implement:
+- [take a look here](https://github.com/Laravel-Backpack/CRUD/pull/2508/files#diff-e82fc7ec56e0617fb83762cc2a9467d4) for a simple column (ex: ```text```);
+- [take a look here](https://github.com/Laravel-Backpack/CRUD/pull/2508/files#diff-ab965b3cd4720c4c2ec4a2423f3ea648) for a column that has multiple entries (ex: ```select```);
+
+
+If you need a difftool, we recommend [Kaleidoscope](https://www.kaleidoscopeapp.com) on Mac OS, [WinMerge](https://winmerge.org) on Windows, or [Fork](https://git-fork.com/) on both Mac OS and Windows.
+
+
+Step 16. Backpack 4.1 uses the same icon set, [Line Awesome](https://icons8.com/line-awesome), but we've upgraded to the latest version.
+- The good news - this new version brings a total of 1000+ icons, and complete icon-parity with Font Awesome 5.11.2. Any icon Font Awesome 5 has, Line Awesome has it too.
+- The bad news:
+ - it's not 100% backwards-compatible. The same icons are there, but a few of them have changed names. For example, there's no more ```newspaper-o``` it's now just ```newspaper```;
+ - additionally, we're no longer using the "_font awesome compatible syntax_" to load Line Awesome Icons (```fa fa-home```), we're now using the "_line awesome syntax_" (```la la-home```), to prevent conflicts when both fonts are used at the same time;
+
+In order to account for this icon font change please:
+- inside your ```resources/views/vendor/backpack``` folder, search & replace ```fa fa-``` with ```la la-```;
+- for each icon you fix above, double-check that it shows in the browser; if it doesn't, search for an alternative on the [Line Awesome website](https://icons8.com/line-awesome); usually the syntax change is very _very_ small; and there are a lot more icons now, so you'll definitely find something;
+
+Step 17. In order to be able to use the new fluent syntax for Widgets, you should make sure all main admin panel views (ex: dashboard, create, update, etc) extend the ```blank``` template:
+
+```diff
+//from
+- @extends('backpack::layouts.top_left')
+- @extends(backpack_view('layouts.top_left'))
+
+// to
++ @extends(backpack_view('blank'))
+// or
++ @extends('backpack::blank')
+
+```
+
+
+### Cache
+
+Step 18. Clear your app's cache:
+```
+php artisan config:clear
+php artisan cache:clear
+php artisan view:clear
+```
+
+---
+
+**You're done! Good job.** Thank you for taking the time to upgrade. Now you can:
+- thoroughly test your application and your admin panel;
+- start using the [new features in Backpack 4.1](/docs/4.1/release-notes);
diff --git a/5.x/add-ons-community.md b/5.x/add-ons-community.md
new file mode 100644
index 00000000..c0cde2e2
--- /dev/null
+++ b/5.x/add-ons-community.md
@@ -0,0 +1,19 @@
+# Community Add-ons
+
+---
+
+We've been blessed with a wonderful, supportive community, where developers help each other out. Some of them have even created add-ons, so that we can all reuse functionality across our projects:
+
+| Name | Description | License |
+| ------------- |:-------------:| --------:|
+| [BackpackBlog](https://github.com/AbbyJanke/BackpackBlog) | blog front-end and back-end | - |
+| [BackpackMeta](https://github.com/AbbyJanke/BackpackMeta) | helps create meta options for extending core functions | - |
+| [LogViewer](https://github.com/eduardoarandah/backpacklogviewer) | advanced logging interface - brings the ArcaneDev/LogViewer package to Backpack admin panels | [MIT](https://github.com/eduardoarandah/backpacklogviewer/blob/master/LICENSE.md) |
+| [UserManager](https://github.com/eduardoarandah/UserManager) | manage the default Laravel users table (no permissions, no groups) | [MIT](https://github.com/eduardoarandah/UserManager/blob/master/LICENSE) |
+| [laravel-backpack-redirection-manager](https://github.com/novius/laravel-backpack-redirection-manager) | manage missing page redirections | [AGPL-3](https://github.com/eduardoarandah/backpacklogviewer/blob/master/LICENSE.md) |
+| [laravel-backpack-translation-manager](https://github.com/novius/laravel-backpack-translation-manager) | manage translations stored in the database | - |
+| [estarter-ecommerce-for-laravel](https://github.com/updivision/estarter-ecommerce-for-laravel) | complete e-commerce back-end (products, categories, clients, orders) | [YUMMY](https://github.com/updivision/estarter-ecommerce-for-laravel/blob/master/LICENSE.md) |
+| [laravel-generators](https://github.com/webfactor/laravel-generators) | CLI to generate migrations, factories, seeders, CRUDs, lang files, route files | [MIT](https://github.com/webfactor/laravel-generators/blob/master/LICENSE.md) |
+| [laravel-backpack-gallery-crud](https://gitlab.com/seandowney/laravel-backpack-gallery-crud) | manage photo galleries | [MIT](https://gitlab.com/seandowney/laravel-backpack-gallery-crud/blob/master/LICENSE.md) |
+| [signature-field-for-backpack](https://github.com/iMokhles/signature-field-for-backpack) | field type that lets admins draw their signature | [MIT](https://github.com/iMokhles/signature-field-for-backpack/blob/master/license.md) |
+| [DynamicFieldHintsForBackpack](https://github.com/DoDSoftware/DynamicFieldHintsForBackpack) | automatically add db comments as field hints | [MIT](https://github.com/DoDSoftware/DynamicFieldHintsForBackpack/blob/master/license.md) |
diff --git a/5.x/add-ons-custom-operation.md b/5.x/add-ons-custom-operation.md
new file mode 100644
index 00000000..fa19ab02
--- /dev/null
+++ b/5.x/add-ons-custom-operation.md
@@ -0,0 +1,197 @@
+# Create an Add-On for a Custom Operation
+
+-----
+
+This tutorial will help you package a custom operation into a Composer package, so that you (or other people) can use it in multiple Laravel projects. If you haven't already, please [create your custom operation](/docs/{{version}}/crud-operations#creating-a-custom-operation) first, and make sure it's working well, before you move it to a package. It's just easier that way.
+
+
+
+## Part A. Create The Package
+
+
+
+### Step 1. Generate the package folder
+
+Install this excellent package that will create the boilerplate code for you:
+```sh
+composer require jeroen-g/laravel-packager --dev
+```
+
+Ask the package to generate the boilerplate code for your new package:
+
+```sh
+php artisan packager:new MyName SomeCustomOperation --i
+```
+
+Keep in mind:
+- the ```MyName``` should be your GitHub handle (or organisation), in studly case (```CompanyName```);
+- the ```SomeCustomOperation``` should be the package name you want, in studly case (```ModerateOperation```);
+- the ```website``` should be a valid URL, so include the protocol too: ```http://example.com```;
+- the ```description``` should be pretty short;
+- the ```license``` is just the license name, if it's a common one (ex: ```MIT```, ```GPLv2```);
+
+This will create a ```/packages/MyName/SomeCustomOperation``` folder in your root directory, which will hold all the code for your package. It has pulled a basic package template, that we need to customize.
+
+It will also modify your project's ```composer.json``` file to point to this new folder.
+
+
+### Step 2. Define dependencies
+
+Inside your ```/packages/MyName/SomeCustomOperation/composer.json``` file, make sure you require the version of Backpack your package will support. If unsure, copy-paste the requirement from your project's ```composer.json``` file.
+
+```diff
+ "require": {
++ "backpack/crud": "^4.0.0"
+- "illuminate/support": "~5|~6"
+ },
+```
+
+Note:
+- you can also remove the ```illuminate/support``` requirement in most cases - if Backpack is installed, so is that;
+- feel free to add any other requirements your package might have;
+
+Notice that this ```composer.json``` will also:
+- define your package namespace (in ```autoload/psr-4```);
+- set up Laravel package autoloading (in ```extra/laravel/providers```);
+
+
+### Step 3. Instruct your Laravel Project to use your package
+
+```sh
+composer require myname/somecustomoperation
+```
+
+Congratulations! Now you have a basic package, installed in ```packages/MyName/SomeCustomOperation```, that is loaded in your current Laravel project. Note that:
+- The command above added a requirement to your **project's ```composer.json``` file**, to require the package; Because previously Packager has pointed to the packages folder, it will pick it up from there, instead of the Internet;
+- Then your **package's ```composer.json```** file will point to the ```ServiceProvider``` inside your package's ```src``` folder;
+- The ServiceProvider is the class that ties your package to Laravel's inner workings.
+
+> If you want to test that your package is being loaded, you can do a ```dd('got here')``` inside your package's ```ServiceProvider::boot``` method. If you refresh the page, you should see that ```dd()``` statement executed.
+
+
+
+### Step 4. Move the files needed for the operation
+
+You can choose whatever folder structure you want for your package. But within Backpack add-ons, we follow the convention that the package folder should look as much as possible like a Laravel project folder. That way, when someone looks at the addon's source code, they instantly understand where everything is.
+
+**Operation Trait**
+
+Notice a file has already been created, with the operation name, inside your package's ```src``` folder. You can **move your operation trait code** from ```app/Http/Controllers/Admin/Operations``` to this ```src/SomeCustomOperation``` file, but make sure:
+- you use the proper namespace (```MyName\SomeCustomOperation```);
+- you define it as a Trait, not a Class;
+
+**Views**
+
+If your operation has a user interface, consider moving all the views this operation needs inside your package folder, inside a ```resources/views``` folder.
+
+Then in your package's ServiceProvider, make sure inside ```boot()``` that you load the views:
+```php
+ $this->loadViewsFrom(__DIR__.'/../resources/views', 'somecustomoperation');
+```
+
+**Config**
+
+For most custom Operations, there's really no need to define your own config file. You can just instruct people to use the ```config/backpack/crud.php``` file, and define stuff inside ```operations```, inside an array with your operation's name. If this works for you, then:
+- delete the ```config``` folder entirely;
+- inside your ServiceProvider's ```register()``` method, delete the line with ```mergeConfigFrom()```;
+- inside your ServiceProvider's ```bootForConsole()``` method, delete the line that publishes the config file;
+- inside your ServiceProvider's ```bootFromConsole()``` method, include:
+```bash
+ $this->publishes([
+ __DIR__.'/../resources/views' => base_path('resources/views/vendor/backpack'),
+ ], 'somecustomoperation.views');
+```
+
+That way, developers define config values for your custom operation the same way they define them for a default Backpack operation.
+
+**Translations**
+
+If your Operation has an interface, it most likely also needs a translation file, so that strings are translatable. To add a translation file:
+- inside your ServiceProvider's ```boot()``` method, include:
+```bash
+$this->loadTranslationsFrom(__DIR__.'/../resources/lang', 'backpack');
+```
+- inside your ServiceProvider's ```bootFromConsole()``` method, include:
+```bash
+ $this->publishes([
+ __DIR__.'/../resources/lang' => resource_path('lang/vendor/backpack'),
+ ], 'somecustomoperation');
+```
+- create the ```resources/lang/en``` folder;
+- create a PHP file with a shorter representative name inside that folder, for example ```somecustom.php```, with the translation lines there;
+- you'll be able to use ```trans('somecustomoperation::somecustom.line_key')``` throughout your operation's controller/views;
+
+
+
+### Step 5. Delete the package files you don't need
+
+- in most cases you won't need a Facade for the operation, so you can delete the ```src/Facades``` folder; if you do that, also remove the alias to that Facade, at the bottom of your package's ```composer.json``` file;
+- in most cases you won't need the ```register()```, ```provides()``` methods in your ServiceProvider; it's best to remove them;
+
+
+
+### Step 6. Customize Markdown Files
+
+Inside your package folder, go through all markdown files and make them your own. At the very least, go through:
+- LICENSE.md - use the [MIT license](https://opensource.org/licenses/MIT) if unsure;
+- README.md - write a clear description and instructions for how to use your operation; if you include clear documentation and screenshots, more people will use your package, guaranteed;
+
+
+
+### Step 7. Make your first git commit
+
+Inside your package folder, run:
+```bash
+cd packages/myname/somecustomoperation
+git init
+git add .
+git commit -m "first commit"
+```
+
+
+
+## Part B. Put The Package Online
+
+
+
+### Put it on GitHub
+
+First, [create a new GitHub Repository](https://github.com/new) for it. Remember to use the same name you defined in your package's ```composer.json```. If in doubt, double-check.
+
+Second, add that new GitHub Repo as a remote, and push your code to your new GitHub repo.
+
+```bash
+git remote add origin git@github.com:yourusername/yourrepository.git
+git push -u origin master
+git tag -a 1.0.0 -m 'First version'
+git push --tags
+```
+
+The tags are the way you will version your package, so it's important you do it.
+
+
+### Put it on Packagist
+
+In order for people to be able to install your package using composer, your package needs to be registered with Packagist, Composer's free package registry.
+
+On [Packagist.org](https://packagist.org/), submit a new package. Enter your package's GitHub URL and click Check. If any errors occur, follow the onscreen instructions. When you're done, you're taken to your package's packagist page.
+
+**Congrats, you have a working package online**, you can now install it using Composer.
+
+Note: On the package page, you might get a notice like this: _This package is not auto-updated. Please set up the [GitHub Service Hook](https://packagist.org/profile/) for Packagist so that it gets updated whenever you push!_ Let's take care of that. Click that link, get your API token and go to your package's GitHub page, in Settings / Webhooks & Services / Add a new service. Search for Packagist. Enter your username and the token and hit Submit. Your error in Packagist should disappear in 5–10 minutes.
+
+
+### Feedback and Promotion
+
+Congratulations on your new Backpack addon!
+
+To get feedback, ask people to try it on:
+- [our subreddit](https://www.reddit.com/r/BackpackForLaravel/)
+- [our Gitter chatroom](https://gitter.im/BackpackForLaravel/Lobby)
+
+Make sure you write something nice, so people are interested to click.
+
+After you've got some feedback, and a few users have installed your package and everything seems fine, time to promote it big time:
+- post it to [laravel-news.com/links](https://laravel-news.com/links)
+- show it off in the [Laracasts forum](https://laracasts.com/discuss)
+- ask people to try it in [laravel.io](https://laravel.io/forum)
diff --git a/5.x/add-ons-how-to-create-a-backpack-addon.md b/5.x/add-ons-how-to-create-a-backpack-addon.md
new file mode 100644
index 00000000..41a8e7d7
--- /dev/null
+++ b/5.x/add-ons-how-to-create-a-backpack-addon.md
@@ -0,0 +1,216 @@
+# How to Create an Add-on
+
+---
+
+
+### Intro
+
+There's nothing special about add-ons. They are simple Composer packages.
+
+But for consistency, we recommend you follow our simple folder structure. Our rule of thumb: **organize your ```src``` folder like it were a Laravel application**. We do this because it's easier for users to understand how the package works, and it makes it easy to copy-paste the code inside their apps and modify, for complicated use cases. That way, add-ons can be kept super-simple, with everybody adding functionality _in their own apps_. Example folder structure:
+- [src]
+ - [app]
+ - [Http]
+ - [Models]
+ - [Requests]
+ - [database]
+ - [migrations]
+ - [seeds]
+ - [routes]
+ - YourPackageNameServiceProvider.php
+- [tests]
+- composer.json
+- CHANGELOG.md
+- LICENSE.md
+- README.md
+
+Requirements:
+- a working installation of the [Backpack demo](https://github.com/laravel-backpack/demo)
+- 1-2 hours
+
+
+## Step 1. Create a package
+
+### Install Backpack Demo
+
+We're going to use [the Backpack demo project](https://github.com/laravel-backpack/demo) to create a new package. Follow the instructions in [the Installation chapter](https://github.com/laravel-backpack/demo#install).
+
+Any Laravel & Backpack app would work. But since you're going to require packages that you only need during package development, and make various changes to app files, we recommended you _create_ the package using a Backpack demo. After the package is online (with zero functionality), you will _install_ it in a real application, and _modify_ it right there, in the ```vendor``` folder. You will then delete this Backpack demo project.
+
+
+### Install CLI tool
+
+We're going to use [Jeroen-G/laravel-packager](https://github.com/Jeroen-G/laravel-packager) to generate a new package. Follow the instructions in the Installation chapter.
+
+### Generate Package Files
+
+Next up, decide what your vendor name will be. This is NOT the package name, it's the name all your packages will reside under. For example, Laravel uses "laravel". Backpack for Laravel uses "backpack". Jeffrey Way uses "way". If unsure, use your GitHub username for the vendor name. That's what people usually do, if they don't run a company / brand.
+
+Then decide what your package name will be. Ex: ```newscrud```, ```usermanager```, etc.
+
+Then run:
+```
+php artisan packager:new myvendor mypackage
+```
+
+This will create a ```/packages/``` folder in your root directory, where your package will be stored, so you can build it. It will also pull [a very basic package template](https://github.com/thephpleague/skeleton), created by thephpleague. Everything you have right now is in ```packages/myvendor/mypackage``` - check it out.
+
+### Customize Generated Files
+
+Now let's customise it and add some boilerplate code, everything that most Laravel Packages will need. Replace everything you need in ```composer.json```, ```CHANGELOG.md```, ```CONTRIBUTING.md```, ```LICENSE.md```, ```README.md```. Make it yours.
+
+If you want to use Laravel package auto-discovery (and why wouldn't you), make sure to include the Laravel providers section in your ```composer.json```'s ```extra``` section, like so:
+```
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ },
+ "laravel": {
+ "providers": [
+ "Backpack\\NewsCRUD\\NewsCRUDServiceProvider"
+ ]
+ }
+ }
+```
+
+In ```/src/``` you'll find your service provider. That's where your package's logic is, but it's empty. Use this Service Provider template and replace ```League``` with your ```myvendor``` and ```Skeleton``` with your ```mypackage```. Your package will probably need some Controllers, routes and config files.
+
+### Create The Files Your Package Needs
+
+Here are a few commands that could help you do that:
+
+```bash
+# make sure everything is inside your src folder
+cd src/
+
+# to create a controller
+echo "app/Http/Controllers/ControllerName.php
+
+# to create a request file
+echo "app/Http/Requests/EntityRequest.php
+
+# to create a route file
+echo "routes/mypackage.php
+
+# to create a config file
+echo "config/mypackage.php
+
+# to create a views folder
+mkdir resources/views/
+```
+
+You use the routes, config and controller files just like you use the ones in your application. Nothing changes there. But remember that all classes should have the package's namespace:
+
+```php
+namespace MyVendor\MyPackage\Http\Controllers;
+```
+
+### Make Sure Your Laravel App Loads The Package
+
+Add your service provider to your app's ```/config/app.php```
+
+If not, add it:
+```
+"MyVendor\MyPackage\MyPackageServiceProvider",
+```
+
+Check that you autoload your package in composer.json:
+```
+"autoload" : {
+ "psr-4": {
+ "Domain\\PackageName\\": "packages/Domain/PackageName/src"
+ }
+},
+```
+
+Let's recreate the autoload
+```
+cd ../../../..
+composer dump-autoload
+```
+
+If you have a config file to publish, do:
+```
+php artisan vendor:publish
+```
+
+Now test it. Start by doing a ```dd('testing)``` in your service provider's ```boot()``` method. If your package is working fine, I recommend you put it online first, even before it does _anything useful_. You'll get the setup out of the way, and be able to focus on code. Plus, you'll be able to install it in a _real_ Backpack application, and edit it from the ```vendor/myvendor/mypackage``` folder (and push to your git remote).
+
+---
+
+
+## Step 2. Put it on GitHub
+
+```
+cd packages/domain/packagename/
+git init
+git add .
+git commit -m "first commit"
+```
+
+Create [a new GitHub repository](https://github.com/new).
+
+```
+git remote add origin git@github.com:yourusername/yourrepository.git
+git push -u origin master
+git tag -a 1.0.0 -m 'First version'
+git push --tags
+```
+
+Tags are the way you will version your package, so it's important you do it. People will only be able to get updates if you tag them.
+
+---
+
+
+## Step 3. Put it on Packagist
+
+On [Packagist.org](https://packagist.org), submit a new package. Enter your package's GitHub URL and click Check. If any errors occur, follow the onscreen instructions.
+
+When you're done, you'll be taken to your packagist page, where you'll probably get a notice like this:
+
+>This package is not auto-updated. Please set up the [GitHub Service Hook](https://packagist.org/profile/) for Packagist so that it gets updated whenever you push!
+
+Let's take care of that. Click that link, get your API token and go to your package's GitHub page, in ```Settings / Webhooks & Services / Add a new service```. Search for Packagist. Enter your username and the token and hit Submit. Your error in Packagist should disappear in 5–10 minutes.
+
+Congrats! You now have a working package online. You can now require it with composer.
+
+
+---
+
+
+## Step 4. Install in a Real Project
+
+We've instructed you to create the package in a disposable backpack-demo install. If you've done so, you can now install your package **in your _real_ project**:
+
+```bash
+composer require myvendor/mypackage --prefer-source
+```
+
+Using the ```prefer-source``` flag will actually _clone the git repo_ inside your ```vendor/myvendor/mypackage``` directory. So you can do:
+
+```bash
+cd /vendor/myvendor/mypackage
+git checkout master
+```
+
+Then after each change you want to publish, you would mark that change in your ```CHANGELOG.md``` file and do:
+```bash
+git pull origin master
+git add .
+git commit -am "fixes #14189 - some problem or feature with an id"
+git tag 1.0.3
+git push origin master --tags
+```
+
+---
+
+**That's it. Go build your package!** If you end up with something you like, please share it with the community in the [Gitter Chatroom](https://gitter.im/BackpackForLaravel/Lobby), and add it to [the Community Add-Ons page](/docs/{{version}}/add-ons-community), so other people know about it (_login, then click Edit in the top-right corner of the page_).
+
+You can now delete the Backpack project, and the database you've created for it (if any).
+
+For extra reading credits, these are the resources we've used to create this guide:
+- https://laravel.com/docs/packages
+- https://laracasts.com/discuss/channels/tips/developing-your-packages-in-laravel-5
+- https://github.com/jaiwalker/setup-laravel5-package
+- https://github.com/Jeroen-G/laravel-packager
+- https://laracasts.com/lessons/package-development-101
diff --git a/5.x/add-ons-official.md b/5.x/add-ons-official.md
new file mode 100644
index 00000000..6d892966
--- /dev/null
+++ b/5.x/add-ons-official.md
@@ -0,0 +1,22 @@
+# Official Add-ons
+
+In addition to our core packages (CRUD and PRO), we've developed a few packages you can install or download, that treat common use cases.
+
+Premium add-ons (paid separately):
+- [Backpack PRO](https://backpackforlaravel.com/products/pro-for-unlimited-projects) - adds 5 more operations, 10 filters, 28 more fields, 6 more columns and 1 more widget to your toolbelt; we believe it's everything you need to build admin panels... of any complexity PAID EXTRA
+- [Backpack DevTools](https://backpackforlaravel.com/products/devtools) - a GUI to easily generate Migrations, Models, Seeders, Factories and CRUDs, right from your browser window; a power user's dream come true! PAID EXTRA
+- [Backpack Figma Template](https://backpackforlaravel.com/products/figma-template) - quickly create designs and mockups, using Backpack's design, screens and components; empower your designers to design admin panels that are easy-to-code; PAID EXTRA
+- [Backpack EditableColumns](https://backpackforlaravel.com/products/editable-columns) - let admins make quick edits, right from the table view; PAID EXTRA
+
+
+Free add-ons:
+ - [PermissionManager](https://github.com/Laravel-Backpack/PermissionManager) - interface to manage users & permissions, using [spatie/laravel-permission](https://github.com/spatie/laravel-permission); FREE
+ - [Settings](https://github.com/Laravel-Backpack/Settings) - interface to edit site-wide settings; FREE
+ - [PageManager](https://github.com/Laravel-Backpack/PageManager) - interface to manage content for custom pages, using page templates; FREE
+ - [MenuCRUD](https://github.com/Laravel-Backpack/MenuCRUD) - interface to create/update/reorder menu items; FREE
+ - [NewsCRUD](https://github.com/Laravel-Backpack/NewsCRUD) - interface to manage news articles, categories and tags; FREE
+ - [LogManager](https://github.com/Laravel-Backpack/LogManager) - interface to preview Laravel log files; FREE
+ - [BackupManager](https://github.com/Laravel-Backpack/BackupManager) - interface to backup your files & db using [spatie/laravel-backup](https://github.com/spatie/laravel-backup); FREE
+
+
+>**The free add-ons only provide basic functionality.** What will be enough for _most_ projects. They do not intend to be a complete solution for all use cases. If you need to customize a package for your specific use case, you can easily do that, by copy-pasting their code in your project and modifying it. Every official package has been created with this in mind, has a very simple architecture, uses Backpack best practices. Find the "extend" section in each of their docs for more about this.
diff --git a/5.x/add-ons-tutorial-using-the-addon-skeleton.md b/5.x/add-ons-tutorial-using-the-addon-skeleton.md
new file mode 100644
index 00000000..06e09c15
--- /dev/null
+++ b/5.x/add-ons-tutorial-using-the-addon-skeleton.md
@@ -0,0 +1,302 @@
+# Create an Add-On using our Addon Skeleton
+
+-----
+
+This tutorial will help you package a Backpack operation or entire CRUD into a Composer package, so that you can use it in multiple Laravel projects. And if you open-source it, others can do the same.
+
+
+
+## Part A. Build the Functionality in Your Project
+
+Make sure you have working code in your project. Code everything the package will need, the same way you normally do. Before even _thinking_ about turning it into a package, you should have working code. This is easier because:
+- you don't have to do anything new while working on functionality
+- you don't have to think about package namespaces
+- you don't have to think about what to make configurable or translatable
+- you can test the functionality alone (without the package wiring and stuff)
+
+**(optional) Hot tip:** Don't commit the code to your package yet. Or, if you've already done a commit (and it's the last commit), run `git reset HEAD^` to undo the commit (but keep the changes). This is _not necessary_ but we find it super-helpful. If you changes are inside your project, but uncommitted, you can easily see the files that have changed using `git status`, hence... the files that contain the functionality you should move to the package. It's like a progress screen - everything here should disappear - that's how you know you're done.
+
+**(optional) Bonus points:** You can use a Git client (like [Git Fork](https://git-fork.com/)) instead of `git status`, because that'll also show the atomic changes you've made to route files, sidebar etc... not only the file names:
+
+
+
+As you move things to your new package, they'll disappear from here. You know you're done when you only have the changes the users of your package need to make, to use it. Normally that's just a change to the `composer.json` and (maybe) a configuration file.
+
+
+
+## Part B. Create The Package
+
+
+
+### Step 1. Generate the package folder
+
+Let's install this excellent package that will make everything a lot faster:
+```sh
+composer require jeroen-g/laravel-packager --dev
+```
+
+Let's create our package. Instead of using their skeleton, we're going to use the Backpack [addon-skeleton](https://github.com/Laravel-Backpack/addon-skeleton):
+
+```sh
+php artisan packager:new --i --skeleton="https://github.com/Laravel-Backpack/addon-skeleton/archive/master.zip"
+```
+
+It will then ask you some basic information about the package. Keep in mind:
+- the ```vendor-name``` should probably be your GitHub handle (or organisation), in kebab-case (ex: `company-name`); it will be used for folder names, but also for GitHub and Packagist links;
+- the ```package-name``` should be in `kebab-case` too (ex: ```moderate-operation```);
+- the `skeleton`, if you haven't copied the entire command above, should probably be the one we provide: `https://github.com/Laravel-Backpack/addon-skeleton/archive/master.zip`, which has everything you need to quickly create a Backpack add-on, including an innovative `AddonServiceProvider` that "_just works_";
+- the ```website``` should be a valid URL, so include the protocol too: ```http://example.com```;
+- the ```description``` should be pretty short; you can change it later in `composer.json`;
+- the ```license``` is just the license name, if it's a common one (ex: ```MIT```, ```GPLv2```); our skeleton assumes you want `MIT` but you can easily change it;
+
+OK great. The command has:
+- created a ```/packages/vendor-name/package-name``` folder in your root directory;
+- modified your project's ```composer.json``` file to load the files in this new folder;
+
+This new folder should hold all your package files. You're off to a great start, because you're using our package skeleton (aka template), so it's already a _working package_. And it's already got a good file structure.
+
+Let's take a look at the generated files inside ```/packages/vendor-name/package-name```:
+
+
+
+
+You'll notice that it looks _exactly_ like a Laravel project, with a few exceptions:
+- PHP classes live in `src` instead of `app`;
+- inside that `src` folder you also have an `AddonServiceProvider`; so let's take a moment to explain why it's there, and what it does:
+ - normally a package needs a ServiceProvider to tell Laravel "load the views from here", "load the migrations from here", "load configs from here", things like that; because a Composer package can also be a general PHP package (non-Laravel), normally you have to code a ServiceProvider for your package, that tells Laravel how to use your package - you have to write all that wiring logic;
+ - but thanks to `AddonServiceProvicer`, you don't have to do any of that; it's all done _automatically_ if the files are in the right directories, just like Laravel does itself, in your project's folders;
+ - the only thing you should worry about is placing your route files in `routes`, your migrations in `database/migrations` etc. and the `AddonServiceProvider` will understand and tell Laravel to load them; easy-peasy;
+
+Excited by how easy it'll be to make it work? Excellent, let's do it.
+
+> If you want to test that your package is being loaded, you can do a ```dd('got here')``` inside your package's ```AddonServiceProvider::boot``` method. If you refresh the page, you should see that ```dd()``` statement executed.
+
+
+### Step 1. Initialize a git repo and make your first package commit
+
+Let's save what we have so far - the generated files:
+```bash
+# go to the package folder (of course - use your names here)
+cd packages/vendor-name/package-name
+
+# create a new git repo
+git init
+
+# (optional, but recommended)
+# by default the skeleton includes folders for most of the stuff you need
+# so that it's easier to just drag&drop files there; but you really
+# shouldn't have folders that you don't use in your package;
+# so an optional but recommended step here would be to
+# delete all .gitkeep files, so that you leave the
+# empty folders empty; that way, you can still
+# drag&drop stuff into them, but Git will
+# ignore the empty folders
+find . -name ".gitkeep" -print # shows all .gitkeep files, to double-check
+find . -name ".gitkeep" -exec rm -rf {} \; # deletes all .gitkeep files
+
+# commit the initially generated files
+git add .
+git commit -am "generated package code using laravel-packager and the backpack addon-skeleton"
+```
+
+Excellent. Now we have _two_ git repos, that we can use as a progress indicator:
+- the _project_ repo, where the files are uncommitted;
+- the _package_ repo, where we'll be moving the functionality;
+
+If you've used a git client you can even place them side-by-side, and see the progress as you move files from the project (left) to the package (right). But you don't _have to_ do that, it's just a nice visual indicator if it's your first package:
+
+
+
+
+### Step 2. Define any extra dependencies
+
+Your ```/packages/vendor-name/package-name/composer.json``` file already requires the latest version of Backpack (thanks to the addon skeleton). If your package needs any third-party packages apart from Backpack and Laravel, make sure to add them to the `require` section. Normally this just means cutting&pasting the line from your project's `composer.json` to your package's `composer.json`.
+
+
+
+### Step 3. Move the functionality from your project to your package
+
+Time to move files from your _project_ to your _package_. You can use whatever you want for that - drag&drop, the command line, your IDE or editor, whatever you want.
+
+
+
+
+As you do that, your `git status` or git client should show fewer and fewer files in your _project_, and more and more files in your _package_.
+
+Below we'll take each project directory, one by one, and explain where its files should go. But this should all pretty intuitive:
+
+#### Files inside your project's ```app``` directory
+
+Move from the subdirectory there to the same subdirectory inside your package's `src`; that means:
+ - controllers go inside `src/Http/Controllers`;
+ - requests go inside `src/Http/Requests`;
+ - models go inside `src/Models`;
+ - commands go inside `src/Commands`;
+ - etc.
+
+IMPORTANT: Since you're moving PHP classes, **after moving them you must also change their namespaces**. Your class is no longer `App\Http\Controllers\Admin\ExampleCrudController` but `VendorName\PackageName\Http\Controllers\ExampleCrudController`.
+
+I'd love to tell you you can it using a search&replace, but... no. In this case search&replace is not worth it, because it might also replace other stuff you don't want replaced. So it's best to just go ahead:
+- open all the files you've moved;
+- manually replace stuff like `App\Http` with `VendorName\PackageName\Http`;
+
+#### Files inside your project's `config` directory
+
+If you _won't_ be using config files, just delete the entire `config` package directory.
+
+If you _will_ be using config files, to let the users of your package publish it and change how stuff works that way, it's super-simple to use:
+- you already have a file generated in `/packages/vendor-name/package-name/config/package-name.php`;
+- cut&paste any config values you want over here; if you add for example `config_key`, it'll be available in your classes using `config('vendor-name.package-name.config_key')`;
+
+If you don't have any configs right now, but will want to add later, that's OK too. Do it later.
+
+#### Files inside your project's `database` directory
+
+You have the same directory in your package, just move them there.
+
+That means:
+- `database/migrations`
+- `database/seeds` or `database/seeders`
+- `database/factories`
+
+
+#### Files inside your project's `resources\views` directory
+
+You have the same directory in your package, just move them there. Views moved in your package folder will be automatically available in the `vendor-name.package-name` namespace, so you can load them using `view('vendor-name.package-name::path.to.file')`.
+
+For views that need to be changed by the user upon installation, and cannot be moved to the package (for example, menu items inside `sidebar_content.blade.php`), add the changes the user needs to do inside your package's `readme.md` file, under Installation.
+
+#### Files inside your project's `resources\lang` directory
+
+If your package won't support translations yet, just skip this.
+
+If it will, notice you already have a lang file created for English, in your package - `/packages/vendor-name/package-name/resources/lang/en/package-name.php`. Populate that file with the language lines you need, by cutting&pasting from your project. They'll be available as `lang('vendor-name.package-name::package-name.line_key')` so you need to also find&replace your old keys with the new ones.
+
+#### Files inside your project's `routes` directory
+
+If your package only adds a view (ex: a field, a column, a filter, a widget) then it probably won't need a route, you can just delete the entire `routes` directory in your package.
+
+If you package _does_ need routes (like when it provides an entire CRUD), you'll find there's already a file in your `/packages/vendor-name/package-name/route/package-name.php`, waiting for your routes, with a few helpful comments. Just cut&paste the routes from your project inside that file.
+
+#### Helper functions inside your project's `bootstrap\helpers.php` file
+
+If you've added any functions there that you need inside the package, you'll notice there's already a `/packages/vendor-name/package-name/bootstrap/helpers.php` file waiting for you. Cut&paste them there.
+
+If your package does not any extra need helper functions, just delete the entire `bootstrap` directory in the package.
+
+
+### Step 4. Test that the package works
+
+That's pretty much it. You've created your package! 🥳 All the files your package need are inside your package, and the only remaining changes in your project (as reflected by `git status`) should be the minimal changes that users need to do to install your package.
+
+Go ahead and test it in the browser. Make sure the functionality that was working inside your _project_ is still working now that it's inside a _package_. You might have forgotten something - we all do sometimes.
+
+
+### Step 5. Delete the package files you don't need
+
+Now that you know your package is working, go through the package folder and delete whatever your package isn't actually using: empty directories, empty files, placeholder files. Clean it up a little bit.
+
+
+
+### Step 6. Customize Markdown Files
+
+Inside your package folder, go through all markdown files and make them your own. At the very least, open the `README.md` file and spend a little time on it, give it some love:
+- write a clear description;
+- add a screenshot if appropriate;
+- write clear installation instructions (step-by-step) for how to use your package;
+- answer any questions users might have about what the package does;
+- link to whatever dependencies or resources your add-on uses, so that they check out their docs instead of bugging you about it;
+
+If you plan to make this package public, take the `README.md` seriously, because it's a HUGE factor in how popular your package can become. If you include clear documentation and screenshots, more people will use your package - guaranteed.
+
+
+
+## Part C. Put The Package Online
+
+
+First, [create a new GitHub Repository](https://github.com/new) for it. Remember to use the same name you defined in your package's ```composer.json```. If in doubt, double-check.
+
+Second, add that new GitHub Repo as a remote, and push your code to your new GitHub repo.
+
+```bash
+# save your working files to Git
+git add .
+git commit -am "working code for v1.0.0"
+
+# add the remote to Github
+git remote add origin git@github.com:yourusername/yourrepository.git
+git branch -M main
+git push -u origin main
+git tag -a 1.0.0 -m 'First version'
+git push --tags
+```
+
+The tags are the way you will version your package, so it's important you do it.
+
+
+
+## Part D. Make the package public (on Packagist)
+
+In order for people to be able to install your package using Composer, your package needs to be registered with [Packagist.org](https://packagist.org/), Composer's free package registry.
+
+On [Packagist.org](https://packagist.org/), submit a new package. Enter your package's GitHub URL and click Check. If any errors occur, follow the onscreen instructions. When you're done, you're taken to your package's Packagist page.
+
+**Congrats, you have a working package online**, you can now install it using Composer.
+
+Note: On the package page, you might get a notice like this: _This package is not auto-updated. Please set up the [GitHub Service Hook](https://packagist.org/profile/) for Packagist so that it gets updated whenever you push!_ Let's take care of that. Click that link, get your API token and go to your package's GitHub page, in Settings / Webhooks & Services / Add a new service. Search for Packagist. Enter your username and the token and hit Submit. Your error in Packagist should disappear in 5–10 minutes.
+
+
+
+## Part E. Install the repo from GitHub
+
+If you look close to your project's `composer.json` file, you'll notice your project is loading the package from `packages/vendor-name/package-name`. Which is fine, it's worked fine until now. But it's now time to install the package like your users will, and have it in `vendor/vendor-name/package-name`. That way:
+- you test that your users are able to install the package;
+- you don't commit anything extra inside your project;
+- you can _easily_ make changes to your package, from whatever project you're using it in;
+
+To do that, go ahead and do this to uninstall your package from your project:
+```bash
+cd ../../.. # so that you're inside your project, not package
+
+# discard the changes in your composer files
+# and delete the files from packages/vendor-name/package-name
+php artisan packager:remove vendor-name package-name
+```
+
+And now install it exactly the same as your users will:
+- if it's closed-source, add the GitHub repo to your `composer.json` then move on to the next step; do NOT do this if your package is open-source:
+
+```json
+ "repositories": {
+ "vendor-name/package-name": {
+ "type": "vcs",
+ "url": "https://github.com/vendor-name/package-name"
+ }
+ }
+```
+
+- both for closed-source and open-source (on Packagist), install it using Composer's `--prefer-source` flag, so that it pulls the actual GitHub repo:
+
+```bash
+composer require vendor-name/package-name --prefer-source
+```
+
+That's it. It should be working fine now, but from the `vendor/vendor-name/package-name` directory. You can `cd vendor/vendor-name/package-name` and you'll see that you can `git checkout master`, make changes, tag releases, push to GitHub, everything.
+
+
+
+### Feedback and Promotion
+
+Congratulations on your new Backpack addon!
+
+To get feedback, ask people to try it on:
+- [our addons repo](https://github.com/laravel-backpack/addons)
+- [our subreddit](https://www.reddit.com/r/BackpackForLaravel/)
+- [our Gitter chatroom](https://gitter.im/BackpackForLaravel/Lobby)
+
+Make sure you write something nice, so people are interested to click.
+
+After you've got some feedback, and a few users have installed your package and everything seems fine, time to promote it big time:
+- post it to [laravel-news.com/links](https://laravel-news.com/links)
+- show it off in the [Laracasts forum](https://laracasts.com/discuss)
+- ask people to try it in [laravel.io](https://laravel.io/forum)
diff --git a/5.x/add-ons-tutorial.md b/5.x/add-ons-tutorial.md
new file mode 100644
index 00000000..01da4d66
--- /dev/null
+++ b/5.x/add-ons-tutorial.md
@@ -0,0 +1,232 @@
+# How to Create a Backpack Add-on
+
+---
+
+
+### Intro
+
+So you've created a custom field, column, filter, or an entire CRUD. Great! If you want to re-use it across projects, or you think _other people_ would like to use it too, there's a good way to do that.
+
+The process below will involve creating a new package on GitHub, Composer & Packagist - which is a little challenging to wrap your head around, the first time you do it. But if you were able to create a custom field, you will be able to do that too. And in doing this, you'll learn the basics of creating and maintaining a PHP package. That's something that not all PHP developers can do, so it's pretty cool, I think.
+
+> If you already know how to create & maintain a PHP package, this tutorial might be too easy for you. Try to skim it, because we give useful tips. But you can also just go to [:DigitallyHappy/toggle-field-for-backpack](https://github.com/DigitallyHappy/toggle-field-for-backpack), clone the repo and make the changes you see fit.
+
+Requirements:
+- a working installation of Laravel & Backpack 4 (alternative: you can install the [Backpack demo](https://github.com/laravel-backpack/demo));
+- a GitHub account (free or paid);
+- 15-30 minutes;
+
+
+
+## Step 0. Scope and Constants
+
+**Decide what your package is going to do.** Try to keep the package as small as possible. If you're trying to share multiple fields/columns/etc, we recommend you create a different package for each field type. This will make it:
+- easier for you to communicate what the package does;
+- easier for you to maintain a field type (or abandon it);
+- more likely for people to install & use your package;
+
+In the tutorial below, we'll assume you're trying to share one custom field - ```dummy.blade.php```. But the process will be the same no matter what you're building, starting from the skeletons packages below.
+
+Once you know what you're building, there are a few constants which you need to decide upon. Names that once you've chosen, it will be _possible_, but _very difficult_ to change:
+
+**Package Name.** Try to find a name that is as explicit as possible. So that users, just by reading the name, will pretty much understand what the package does. Also, try to include "_for Backpack_" - that way it will stand out to developers who use Backpack (your target audience).
+- Good Examples: ```json-editor-field-for-backpack```, ```user-column-for-backpack```, ```users-crud-for-backpack```;
+- Bad Examples: ```custom-field``` (too general), ```cbf``` (too cryptic), ```aurora``` (this is not the place to be creative :smile: );
+Since in this example we're trying to build a package for the new ```dummy``` field type, we'll choose ```dummy-field-for-backpack``` as the package name.
+
+**Vendor Name.** You noticed how every time you install a composer package, it's ```composer install something/package-name```? Well that's what that "something" is - the _vendor name_. It's usually the name of the company or person behind the project. The easiest to remember would be your GitHub username, or your company's GitHub username. But, if you're not happy with those, you _can_ choose a different vendor name - basically a brand name, under which you build packages. This could be the place to be creative :smile:, if you don't have a company name already. In the example below we'll use ```company-name```.
+
+**Class Namespace.** When people reference your package's classes, this is what they see first. It's a good practice to use VendorName/PackageName as the namespace for your package. But notice it's no longer kebab-case (using dashes - ```my-company/dummy-field-for-backpack```), it is PascalCase (```MyCompany/DummyFieldForBackpack```).
+
+
+
+## Step 1. Clone the skeleton package
+
+To get your package online ASAP, we've prepared a few "skeleton" packages, that you can fork and modify:
+- [:DigitallyHappy/toggle-field-for-backpack](https://github.com/DigitallyHappy/toggle-field-for-backpack) - field add-on example;
+- TODO - column add-on example;
+- TODO - filter add-on example;
+- TODO - button add-on example;
+- TODO - CRUD add-on example;
+- TODO - multiple CRUD add-on example;
+- TODO - CRUD with dependencies add-on example;
+
+Pick the skeleton package that's as similar as possible to what you want to build. On its GitHub page, under if you click the green **Clone or Download** button, you'll get the path to that repo. In your project, let's clone that repo:
+```bash
+# git clone {REPO URL} packages/{VENDOR NAME}/{PACKAGE NAME}
+git clone git@github.com:DigitallyHappy/toggle-field-for-backpack.git packages/my-company/dummy-field-for-backpack
+```
+
+
+## Step 2. Make it your own
+
+Take a look at the files you've copied - it's a very simple package. In you package's root folder we have:
+- ```README.md``` - your package's "home page" on Github; this should hold all the information needed to use your package;
+- ```composer.json``` - configuration file that tells Composer (the PHP package installer) more about your package;
+- ```CHANGELOG.md``` - where you should write every time you make changes to the field;
+- ```LICENSE.md``` - so that people know how they're allowed to use your package (MIT is the default);
+
+Take a look at all of them and modify to fit your needs. It should be faster to modify by hand, and pretty intuitive. But, if it's the first time you create a PHP package, you can use the process below, to make sure you don't mess up anything, since making a casing mistake somewhere (```my-vendor``` instead of ```MyVendor```) could take you very long to debug:
+- **namespace** - find ```DigitallyHappy\ToggleFieldForBackpack``` and replace with your _VendorName\PackageName_ (ex: ```MyCompany\DummyFieldForBackpack```);
+- **escaped namespace** - find ```DigitallyHappy\\ToggleFieldForBackpack``` and replace with your _VendorName\\PackageName_ (ex: ```MyCompany\\DummyFieldForBackpack```);
+- **vendor and package name** - find ```digitallyhappy/toggle-field-for-backpack``` and replace with your _vendor-name/package-name_ (ex: ```my-company/dummy-field-for-backpack```);
+- **package name** - find ```toggle-field-for-backpack``` and replace with your _package-name_ (ex: ```dummy-field-for-backpack```);
+- **vendor name** - find ```digitallyhappy``` and replace with your _vendor-name_ (ex: ```my-company```);
+- **author name** - find ```Cristian Tabacitu``` and replace with your name (ex: ```John Doe```);
+- **author email** - find ```hello@tabacitu.ro``` and replace with your email (ex: ```john@example.com```);
+- **author website** - find ```https://tabacitu.ro``` and replace with your website or GitHub page (ex: ```http://example.com```);
+- open ```changelog.md``` and keep only the 1.0.0 version; put today's date;
+- open ```composer.json``` and change the description of your package;
+- open ```readme.md``` and change the text to better describe _your_ package; don't worry about the screenshot, we'll change that one in a future step;
+
+In ```/src/``` you'll find your service provider, which does one thing: it loads the views in your ```src/resources/views``` under the ```dummy-field-for-backpack``` view namespace. So that anybody who installs your package can use a view that your package includes, by referencing ```dummy-field-for-backpack::path.to.view```.
+
+Also in ```/src/``` you'll notice ```src/resources/views/fields/toggle.blade.php```. This is the example field, which you can rename and use to start coding you field. Or if you already have your field ready, you can just delete this file, and copy-paste the finished blade file from your project
+
+
+## Step 3. Put it on GitHub
+
+```
+# make sure you replace the below with your actual vendor name and package name
+cd packages/my-company/dummy-field-for-backpack/
+git add .
+git commit -m "turned the skeleton package into dummy-field package"
+```
+
+Create [a new GitHub repository](https://github.com/new). Then get the Git URL the same way you did for the Toggle package, from the green "Clone or Download" button. With that Git URL:
+
+```
+# remove the old origin (pointing to the toggle package)
+git remote rm origin
+
+# add a remote pointing to YOUR github repo
+git remote add origin git@github.com:yourusername/yourrepository.git
+
+# refresh the new origin remote everywhere
+git config master.remote origin
+git config master.merge refs/heads/master
+
+# push your code to your github repo
+git push -u origin master
+
+# tag your release as 1.0.0
+git tag -a 1.0.0 -m 'First version'
+
+# push your tags to the Repo - this is very important to Packagist;
+git push --tags
+```
+
+You might not have used git tags until now. Tags are the way you will version your package, so it's important you do it. For every new version, you need to:
+- write your changes inside the ```changelog.md``` file, so people can easily see what's new;
+- tag your release with the proper tag, so that Packagist will know you've pushed a new version;
+
+---
+
+
+## Step 4. Put it on Packagist
+
+On [Packagist.org](http://packagist.org), create an account if you don't have one already, then click "Submit package" in the top-right corner. Enter your package's GitHub URL and click Check. If any errors occur, follow the onscreen instructions.
+
+When you're done, you'll be taken to your Packagist page, where you'll probably get a notice like this:
+
+>This package is not auto-updated. Please set up the [GitHub Service Hook](https://packagist.org/profile/) for Packagist so that it gets updated whenever you push!
+
+Let's take care of that. Click [that link](https://packagist.org/profile/), click "Show API Token", copy it and go to _your package's GitHub page_, in ```Settings / Webhooks & Services / Add a new service```. Search for Packagist. Enter your username and the token and hit Submit. Your error in Packagist should disappear in 5–10 minutes.
+
+Congrats! You now have a working package online. You can now require it with composer.
+
+
+---
+
+
+## Step 5. Install it
+
+Since your package is now online, you can now install it using composer.
+
+```bash
+# go to the root of you Laravel app
+cd ../../..
+
+# delete the folder from packages
+rm -r packages
+
+composer require my-company/dummy-field-for-backpack --prefer-source
+```
+
+Notice we've installed it using the ```prefer-source``` flag. This will actually _clone the git repo_ inside your ```vendor/myvendor/mypackage``` directory. So you can do:
+
+```bash
+cd /vendor/my-company/dummy-field-for-backpack
+git checkout master
+```
+
+**That's it. Your package is online and installable!** You have most of the knowledge needed to build and maintain a PHP package.
+
+
+
+## Step 6. Double-check, then triple-check
+
+### Are you sure it's working?
+After your package is online and ready to use, double-check that it's working well. Then triple-check.
+
+### Your README is your home page
+Afterwards go to your README file again, and make sure it's the best it can be. Remember, your README file is the first thing people see when they find your package. If it's not appealing, they won't use it. If it doesn't do a good job of explaining how to use it, they won't use it. Take this seriously. This is where A LOT of packages go wrong - the authors do not spend the right amount of time on their README page.
+
+IMPORTANT. Make sure your README has a nice screenshot of the functionality you're offering. The easier it is for a developer to see the benefit of using your package, the more likely it is for them to install it. There's a trick in uploading images to GitHub, then using them in your README file. Go to your package's GitHub page, and add an issue. In that issue's body, drag&drop the screenshot image. GitHub will upload it, and give it an URL. Copy-paste that URL, submit the issue (you can also already close the issue), then use that image URL inside your README file. Boom! Free image hosting.
+
+By now you should have made some changes to your files, inside your ```vendor/my-company/dummy-field-for-backpack``` directory.
+
+After each change you want to publish, you should:
+1. Write about that change in your ```CHANGELOG.md``` file. Increment the version sticking to SEMVER.
+
+2. Commit and push your changes, remembering to also create a new tag with the version.
+```bash
+git pull origin master
+git add .
+git commit -am "fixes #14189 - some problem or feature with an id from Github"
+git tag 1.0.1
+git push origin master --tags
+```
+
+
+## Step 7. Feedback and Promotion
+
+Congratulations on your new Backpack addon!
+
+To get feedback, ask people to try it on:
+- [our subreddit](https://www.reddit.com/r/BackpackForLaravel/)
+- [our Gitter chatroom](https://gitter.im/BackpackForLaravel/Lobby)
+
+Make sure you write something nice, so people are interested to click.
+
+After you've got some feedback, and a few users have installed your package and everything seems fine, time to promote it big time:
+- post it to [laravel-news.com/links](https://laravel-news.com/links)
+- show it off in the [Laracasts forum](https://laracasts.com/discuss)
+- ask people to try it in [laravel.io](https://laravel.io/forum)
+
+
+## Extra Credits
+
+If you're building a bigger package, with one CRUD or more, we recommend you follow the simple folder structure we use across all Backpack packages. Our rule of thumb: **organize your ```src``` folder like it were a Laravel application**. We do this because it's easier for developers to understand how the package works, and it makes it easy to copy-paste the code inside their apps and modify, for complicated use cases. That way, add-ons can be kept super-simple, with everybody adding functionality _in their own apps_. Example folder structure:
+- [src]
+ - [app]
+ - [Http]
+ - [Models]
+ - [Requests]
+ - [database]
+ - [migrations]
+ - [seeds]
+ - [routes]
+ - AddonServiceProvider.php
+- [tests]
+- composer.json
+- CHANGELOG.md
+- LICENSE.md
+- README.md
+
+For extra reading credits, these are the resources we've used to create this guide:
+- https://laravel.com/docs/packages
+- https://laracasts.com/discuss/channels/tips/developing-your-packages-in-laravel-5
+- https://github.com/jaiwalker/setup-laravel5-package
+- https://github.com/Jeroen-G/laravel-packager
+- https://laracasts.com/lessons/package-development-101
diff --git a/5.x/base-about.md b/5.x/base-about.md
new file mode 100644
index 00000000..1cc67367
--- /dev/null
+++ b/5.x/base-about.md
@@ -0,0 +1,219 @@
+# About Backpack's User Interface
+
+---
+
+Backpack helps you build admin panels faster by:
+- installing our custom HTML theme, [Backstrap](https://backstrap.net), based on Bootstrap 4 and [CoreUI](https://coreui.io);
+- installing [sweetalert](https://sweetalert.js.org/) for triggering pretty Confirm modals;
+- installing [noty](https://ned.im/noty/#/) to show notification bubbles upon error/success/warning/info - triggered from JavaScript;
+- installing [prologue/alerts](https://github.com/prologuephp/alerts) for triggering notification bubbles from PHP (both on the same page and using flashdata);
+- providing a separate authentication system for your admins;
+- providing pretty error pages for most common errors;
+- providing a horizontal menu and a side menu you can customize;
+- providing a place for your admin to to change his email/name/password;
+- providing a few helpers you can use throughout your admin panel;
+
+For the simplest projects, you will never need to know how it works, never need to customize anything but the ```config/backpack/base.php``` file. But here's how everything works, below.
+
+
+## Layout & Design
+
+
+### General
+
+Backpack pulls in our custom HTML template, [Backstrap](https://www.npmjs.com/package/@digitallyhappy/backstrap), and adds our own CSS file on top, for a few cosmetic improvements. We've chosen to base Backstrap on [CoreUI](https://coreui.io), because it provides design blocks for all common features of an administration panel. When you decide to build custom pages for your Admin Panel, you can just use Backstrap's HTML blocks - no designer needed. You can see all the HTML components Backstrap provides on [backstrap.net](https://backstrap.net), and copy-paste HTML from there, or use [CoreUI](https://coreui.io)'s documentation for details.
+
+
+### New Files in Your App
+
+After installation, you'll notice Backpack has added a few files:
+
+**1) View to ```resources/views/vendor/backpack/base/inc/sidebar_content.blade.php```**
+
+This file is used to show the contents of the menu to the left (sidebar). It's been published there so that you can easily modify its contents, by editing its HTML.
+
+**2) Middleware to ```app/Http/Middleware/CheckIfAdmin.php```**
+
+This middleware is used to test if users have access to admin panel pages. You can (and should customize it) if you have both users and admins in your app.
+
+**3) Route file to ```routes/backpack/custom.php```**
+
+This route file is for convenience and convention. We recommend you place all your admin panel routes here.
+
+
+
+### Published Views
+
+After installation, you'll notice Backpack has added a new blade file in ```resources/views/vendor/backpack/base/```:
+ - ```inc/sidebar_content.blade.php```;
+
+That file is used to show the contents of the menu to the left (sidebar). It's been published there so that you can easily modify its contents, by editing its HTML or adding dynamic content through [widgets](/docs/{{version}}/base-widgets).
+
+
+### Unpublished Views
+
+You can change any blade file to your own needs. Determine what file you'd need to modify if you were to edit directly in the project's vendor folder, then go to ```resources/views/vendor/backpack/base``` and create a file with the exact same name. Backpack\Base will use this new file, instead of the one in the package.
+
+For example:
+- if you want to add an item to the top menu, you could just create a file called ```resources/views/vendor/backpack/base/inc/topbar_left_content.blade.php```; Backpack will now use this file's contents, instead of ```vendor/backpack/base/src/resources/views/inc/topbar_left_content.php```;
+- if you want to change the contents of the dashboard page, you can just create a file called `resources/views/vendor/backpack/base/dashboard.blade.php` and Backpack will use that one, instead of the one in the package;
+
+You can create blade views from scratch, or you can use our command to publish the view from the package and edit it to your liking:
+```
+php artisan backpack:publish base/dashboard
+```
+
+Then inside the blade files, you can use either plain-old HTML or add dynamic content through [Backpack widgets](/docs/{{version}}/base-widgets).
+
+
+### Folder Structure
+
+If you'll take a look inside any Backpack package, you'll notice the ```src``` directory is organised like a standard Laravel app. This is intentional. It should help you easily understand how the package works, and how you can overwrite/customize its functionality.
+
+- ```app```
+ - ```Console```
+ - ```Commands```
+ - ```Http```
+ - ```Controllers```
+ - ```Middleware```
+ - ```Requests```
+ - ```Notifications```
+- ```config```
+- ```resources```
+ - ```lang```
+ - ```views```
+- ```routes```
+
+
+## Authentication
+
+When installed, Backpack provides a way for admins to login, recover password and register (don't worry, register is only enabled on ```localhost```). It does so with its own authentication controllers, models and middleware. If you have regular end-users (not admins), you can keep the _user_ authentication completely separate from _admin_ authentication. You can change which model, middleware classes Backpack uses, inside the ```config/backpack/base.php``` config file.
+
+> **Backpack uses Laravel's default ```App\User``` model**. This assumes you weren't already using this model, or the ```users``` table, for anything else. Or that you plan to use it for both users & admins. Otherwise, please read below.
+
+
+### Using a Different User Model
+
+If you want to use a different User model than ```App\User``` or you've changed its location, please, you can tell Backpack to use _a different_ model in ```config/backpack/base.php``` instead of the ```App\User``` model that Laravel apps usually have. Look for ```user_model_fqn```.
+
+
+
+### Having Both Regular Users and Admins
+
+If you already use the ```users``` table to store end-users (not admins), you will need a way to differentiate admins from regular users. Backpack does not force one method on you. Here are two methods we recommend, below:
+- (A) adding an ```is_admin``` column to your ```users``` table, then changing the ```app/Http/Middleware/CheckIfAdmin::checkIfUserIsAdmin()``` method to test that attribute exists, and is true;
+- (B) using the [PermissionManager](https://github.com/Laravel-Backpack/PermissionManager) extension - this will also add groups and permissions; Then tell Backpack to use _your new permission middleware_ to check if a logged in user is an admin, inside ```config/backpack/base.php```;
+
+
+### Routes
+
+By default, all administration panel routes will be behind an ```/admin/``` prefix, and under an ```CheckIfAdmin``` middleware. You can change that inside ```config/backpack/base.php```.
+
+Inside your _admin controllers or views_, please:
+- use ```backpack_auth()``` instead of ```auth()```;
+- use ```backpack_user()``` instead of ```auth()->user```;
+- use ```backpack_url()``` instead of ```url()```;
+
+This will make sure you're using the model, prefix & middleware that you've defined in ```config/backpack/base.php```. In case you decide to make changes there later, you won't need to change anything else. There are also [other backpack helpers you can use](#helpers).
+
+
+## Admin Account
+
+When logged in, the admin can click his/her name to go to his "account" page. There, they will be able to do a few basic operations: change name, email or password.
+
+
+### Change Name and Email
+
+Changing name and email is done inside ```Backpack\Base\app\Http\Controllers\Auth\MyAccountController```, using the ```getAccountInfoForm()``` and ```postAccountInfoForm()``` methods. If you want to change how this works, we recommend you create a ```routes/backpack/base.php``` file, copy-paste all Backpack\Base routes there and change whatever routes you need, to point to _your own controller_, where you can do whatever you want.
+
+If you only want to add a few new inputs, you can do that by creating a file in ```resources/views/vendor/backpack/base/my_account.blade.php``` that uses code from the same file in the Backpack package, but adds the inputs you need. Remember to also make these fields ```$fillable``` in your User model.
+
+
+### Change Password
+
+Password changing is done inside ```Backpack\Base\app\Http\Controllers\Auth\MyAccountController```. If you want to change how this works, we recommend you create a ```routes/backpack/base.php``` file, copy-paste all Backpack\Base routes there and change whatever you need. You can then point the route to your own controller, where you can do whatever you want.
+
+
+
+## Helpers
+
+You can use these helpers anywhere in your app (models, views, controllers, requests, etc), except the config files, since the config files are loaded _before_ the helpers.
+
+- **```backpack_url(http://github.com/$path)```** - Use this helper instead of ```url()``` to generate paths with the admin prefix prepended.
+- **```backpack_auth()```** - Returns the Auth facade, using the current Backpack guard. Basically a shorthand for ```\Auth::guard(backpack_guard_name())```. Use this instead of ```auth()``` inside your admin panel pages.
+- **```backpack_middleware()```** - Returns the key for the admin middleware. Default is ```admin```.
+- ```backpack_authentication_column()``` - Returns the username column. The Laravel and Backpack default is ```email```.
+- ```backpack_users_have_email()``` - Tests that the ```email``` column exists on the users table and returns true/false.
+- ```backpack_avatar($user)``` - Receives a user object and returns a path to an avatar image, according to the preferences in the config file (gravatar, placeholder or custom).
+- ```backpack_guard_name()``` - Returns the guard used for Backpack authentication.
+- ```backpack_user()``` - Returns the current Backpack user, if logged in. Basically a shorthand for ```\Auth::guard(backpack_guard_name())->user()```. Use this instead of ```auth()->user()``` inside your admin pages.
+
+
+## Error Pages
+
+When installing Backpack, a few error views are published into ```resources/views/errors```, if you don't already have other files there. This is because Laravel does not provide error pages for all HTTP error codes. Having these files in your project will make sure that, if a user gets an HTTP error, at least it will look decent. Error pages are provided for the following error codes: ```400```, ```401```, ```403```, ```404```, ```405```, ```408```, ```429```, ```500```, ```503```.
+
+
+
+## Custom Pages
+
+To create a new page for your admin panel, you can follow the same process you would if you created a normal Laravel page (a Route, View and maybe a Controller). Just make sure that:
+- the route file is under the `admin` middleware;
+- the view extends one of our layout files (so that you get the design and the topbar+sidebar layout;
+
+### Add a custom page to your admin panel (dynamic page)
+
+```php
+
+# Step 1. Create the controller (we recommend you place it in your `app/Http/Controllers/Admin`)
+
+Example page
+@endsection
+```
+
+### Add a custom page to your admin panel (static page)
+
+Alternatively, if you are not getting any information from the database, and are just creating a quick static page, here's a quicker way:
+
+
+```php
+
+# Step 1. Create a route for it (we recommend you place it in your `routes/backpack/custom.php` for simplicity)
+
+Route::get('example-page', function () { return view('admin.example_page'); });
+
+# Step 2. Create that view (we recommend you place it in your `resources/views/admin`:
+
+@extends(backpack_view('blank'))
+
+@section('content')
+
Example page
+@endsection
+
+```
+
diff --git a/5.x/base-alerts.md b/5.x/base-alerts.md
new file mode 100644
index 00000000..d2c91701
--- /dev/null
+++ b/5.x/base-alerts.md
@@ -0,0 +1,63 @@
+# Alerts
+
+---
+
+
+## About
+
+When building custom functionality, you'll probably need to give feedback to the admin for something that happened in the background. You can easily do that in Backpack by triggering alerts (aka notification bubbles, aka notifications). You can do that both from JavaScript and from PHP - and they will look exactly the same. In fact, Backpack operations use this same API. By using Alerts in your custom pages too, you make sure your alerts look the same across your admin panel - and your UI will be consistent.
+
+
+
+### Triggering Alerts in PHP
+
+We use [prologue/alerts](https://github.com/prologuephp/alerts#adding-alerts-through-alert-levels) to trigger notifications. Check out its documentation for the entire syntax.
+
+Most of the time, all you need to do is trigger a notification of a certain type, or trigger a notification using flash data, so that it shows after a redirect:
+
+```php
+public function foo()
+{
+ \Alert::add('info', 'This is a blue bubble.');
+ \Alert::add('warning', 'This is a yellow/orange bubble.');
+ \Alert::add('error', 'This is a red bubble.');
+ \Alert::add('success', 'Got it This is HTML in a green bubble.');
+ \Alert::add('primary', 'This is a dark blue bubble.');
+ \Alert::add('secondary', 'This is a grey bubble.');
+ \Alert::add('light', 'This is a light grey bubble.');
+ \Alert::add('dark', 'This is a black bubble.');
+
+ // the layout will make sure to show your notifications
+ return view('some_view');
+}
+
+public function bar()
+{
+ \Alert::add('success', 'You have successfully logged in')->flash();
+
+ // please note the above flash() method; this will store your notification in a session variable, so that you can redirect to another page, but the notification will still be shown (on the page you redirect to)
+ return Redirect::to('some-url');
+}
+```
+
+
+### Triggering Alerts in JavaScript
+
+We use [Noty](https://ned.im/noty/#/) to show notifications from JavaScript, on the same page. Check out its docs for detailed use. Most of the time you'll only need to do:
+
+```php
+new Noty({
+ type: "success",
+ text: 'Some notification text',
+}).show();
+
+// available types:
+// - success
+// - info
+// - warning/notice
+// - error/danger
+// - primary
+// - secondary
+// - dark
+// - light
+```
\ No newline at end of file
diff --git a/5.x/base-breadcrumbs.md b/5.x/base-breadcrumbs.md
new file mode 100644
index 00000000..a3a7d5ad
--- /dev/null
+++ b/5.x/base-breadcrumbs.md
@@ -0,0 +1,89 @@
+# Breadcrumbs
+
+---
+
+
+## About
+
+Breadcrumbs show a path to the current page in the top-right corner of the screen, and can be a useful part of the UI for deeply nested admin panels.
+
+Breadcrumbs are loaded in the default layout _before_ the ```header``` section.
+
+
+## Enable / Disable Breadcrumbs
+
+You can hide or show breadcrumbs on ALL of your admin panel pages by changing a boolean variable in your ```config/backpack/base.php```:
+
+```php
+ // Show / hide breadcrumbs on admin panel pages.
+ 'breadcrumbs' => true,
+```
+
+
+## How Breadcrumbs Work
+
+The ```inc.breadcrumbs``` view will show all breadcrumbs from the ```$breadcrumbs``` variable, if it's present on the page. The ```$breadcrumbs``` variable should be a simple associative array ```[ $label1 => $link1, $label2 => $link2 ]```. Examples:
+
+```php
+ $breadcrumbs = [
+ trans('backpack::crud.admin') => backpack_url('http://github.com/dashboard'),
+ trans('backpack::base.dashboard') => false,
+ ];
+
+ $breadcrumbs = [
+ trans('backpack::crud.admin') => backpack_url('http://github.com/dashboard'),
+ trans('backpack::base.dashboard') => false,
+ ];
+
+ $breadcrumbs = [
+ 'Admin' => route('dashboard'),
+ 'Dashboard' => false,
+ ];
+```
+
+Notice the last item should NOT have a link, it should be ```false```.
+
+
+## How to Define Breadcrumbs
+
+
+### Define Breadcrumbs Inside the Controller
+
+Make sure a ```$breadcrumbs``` variable is present inside your views:
+```php
+ /**
+ * Show the admin dashboard.
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function dashboard()
+ {
+ $this->data['title'] = trans('backpack::base.dashboard'); // set the page title
+ $this->data['breadcrumbs'] = [
+ trans('backpack::crud.admin') => backpack_url('http://github.com/dashboard'),
+ trans('backpack::base.dashboard') => false,
+ ];
+
+ return view('backpack::dashboard', $this->data);
+ }
+```
+
+
+### Define Breadcrumbs Inside the View
+
+Make sure a ```$breadcrumbs``` variable is present:
+
+```php
+@extends('backpack::layout')
+
+@php
+ $breadcrumbs = [
+ 'Admin' => backpack_url('http://github.com/dashboard'),
+ 'Dashboard' => false,
+ ];
+@endphp
+
+@section('content')
+ some other content here
+@endsection
+```
\ No newline at end of file
diff --git a/5.x/base-how-to.md b/5.x/base-how-to.md
new file mode 100644
index 00000000..43003379
--- /dev/null
+++ b/5.x/base-how-to.md
@@ -0,0 +1,638 @@
+# FAQs for the admin UI
+
+---
+
+
+
+## Look and feel
+
+
+### Customize the menu or sidebar
+
+During installation, Backpack publishes a few files in you ```resources/views/vendor/backpack/base/inc``` folder. In there, you'll also find:
+- ```sidebar_content.php```
+- ```topbar_left_content.php```
+- ```topbar_right_content.php```
+
+Change those files as you please.
+
+
+### Customize the dashboard
+
+The dashboard is shown from ```Backpack\Base\app\Http\Controller\AdminController.php::dashboard()```. If you take a look at that method, you'll see that the only thing it does is to set a title, breadcrumbs, and return a view: ```backpack::dashboard```.
+
+In order to place something else inside that view, like [widgets](/docs/{{version}}/base-widgets), simply publish that view in your project, and Backpack will pick it up, instead of the one in the package. Create a ```resources/views/vendor/backpack/base/dashboard.blade.php``` file:
+
+```html
+@extends(backpack_view('blank'))
+
+@php
+ $widgets['before_content'][] = [
+ 'type' => 'jumbotron',
+ 'heading' => trans('backpack::base.welcome'),
+ 'content' => trans('backpack::base.use_sidebar'),
+ 'button_link' => backpack_url('http://github.com/logout'),
+ 'button_text' => trans('backpack::base.logout'),
+ ];
+@endphp
+
+@section('content')
+
Your custom HTML can live here
+@endsection
+```
+
+To use information from the database, you can:
+- [use view composers](https://laravel.com/docs/5.7/views#view-composers) to push variables inside this view, when it's loaded;
+- load all your dashboard information using AJAX calls, if you're loading charts, reports, etc, and the DB queries might take a long time;
+- use the full namespace for your models, like ```\App\Models\Product::count()```;
+
+Take a look at the [widgets](/docs/{{version}}/base-widgets) we have - you can easily use those in your dashboard. You can also add whatever HTML you want inside the content block - check the [Backstrap HTML Template](https://backstrap.net/widgets.html) for design components you can copy-paste to speed up your custom HTML.
+
+
+### Customizing the design of the menu / sidebar / footer
+
+In ```config/backpack/base.php``` you'll notice there are variables where you can change exactly what CSS classes are placed on the HTML elements that represent the header, body, sidebar and footer:
+
+```php
+ // Horizontal navbar classes. Helps make the admin panel look similar to your project's design.
+ 'header_class' => 'app-header bg-light border-0 navbar',
+ // Try adding bg-dark, bg-primary, bg-secondary, bg-danger, bg-warning, bg-success, bg-info, bg-blue, bg-light-blue, bg-indigo, bg-purple, bg-pink, bg-red, bg-orange, bg-yellow, bg-green, bg-teal, bg-cyan
+ // You might need to add "navbar-dark" too if the background color is a dark one.
+ // Add header-fixed if you want the header menu to be sticky
+
+ // Body element classes.
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ // Try sidebar-hidden, sidebar-fixed, sidebar-compact, sidebar-lg-show
+
+
+ // Sidebar element classes.
+ 'sidebar_class' => 'sidebar sidebar-pills bg-light',
+ // Remove "sidebar-transparent" for standard sidebar look
+ // Try "sidebar-light" or "sidebar-dark" for dark/light links
+ // You can also add a background class like bg-dark, bg-primary, bg-secondary, bg-danger, bg-warning, bg-success, bg-info, bg-blue, bg-light-blue, bg-indigo, bg-purple, bg-pink, bg-red, bg-orange, bg-yellow, bg-green, bg-teal, bg-cyan
+
+ // Footer element classes.
+ 'footer_class' => 'app-footer',
+```
+
+Our default design might not be pleasant for your, or you might need to make the UI integrate better into your project. We totally understand. You can use the classes above to make it look considerably different.
+
+You'll find a few examples below - but you should use which classes you want to get the result you need.
+
+
+#### Backstrap
+
+Transparent top menu, transparent sidebar, transparent footer. This is the default. This is what _we_ think is best for most users, from our 8+ years of experience building admin panels. Prioritising _content_ over _menus_.
+
+
+
+```php
+ 'header_class' => 'app-header bg-light border-0 navbar',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar sidebar-pills bg-light',
+ 'footer_class' => 'app-footer',
+```
+
+
+#### Inspired by CoreUI
+
+White top menu, dark sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar',
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+#### Inspired by GitHub
+
+Black top menu, white sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header bg-dark navbar',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar bg-white sidebar-pills',
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+#### Blue Top Menu
+
+Blue top menu, dark sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar navbar-color bg-primary border-0',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar', // add "bg-white sidebar-pills" for light sidebar
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+
+#### Construction / Warning
+
+Yellow top menu, dark sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar navbar-light bg-warning',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar', // add "bg-white sidebar-pills" for light sidebar
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+#### Red Top Menu
+
+Red top menu, dark sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar navbar-color bg-error border-0',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar', // add "bg-white sidebar-pills" for light sidebar
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+#### Pink Top Menu
+
+Pink top menu, transparent sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar navbar-color bg-error border-0',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar sidebar-pills bg-light',
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+
+#### Green Top Menu
+
+Green top menu, white sidebar.
+
+
+
+```php
+ 'header_class' => 'app-header navbar navbar-color bg-green border-0',
+ 'body_class' => 'app aside-menu-fixed sidebar-lg-show',
+ 'sidebar_class' => 'sidebar sidebar-pills bg-white',
+ 'footer_class' => 'app-footer d-none',
+```
+
+
+
+### Change the colors
+
+#### Change primary color from purple to blue
+
+We thought you might want to do this. Purple isn't for everybody. That's why Backpack 4.1.57+ comes with two bundle CSS files: `bundle.css` and `blue-bundle.css`. That second file does exactly what you expect - changes the primary color from electric purple to blue. That's it. In order to use it, go to your `config/backpack/base.php` and use that file instead:
+
+```diff
+'styles' => [
+- 'packages/backpack/base/css/bundle.css',
++ 'packages/backpack/base/css/blue-bundle.css',
+```
+
+That's it. Now go to your browser and refresh, you should see blue buttons and text everywhere, instead of purple.
+
+#### Custom colors for primary, secondary, success, warning etc.
+
+This assumes you have:
+- Backpack 4.1.57+ (check with `php artisan backpack:version`) and its assets published (otherwise run `php artisan vendor:publish --provider="Backpack\CRUD\BackpackServiceProvider" --tag=public --force`);
+- a working Laravel install with NPM and Laravel Mix;
+
+Add Backstrap, Noty and Animate.css as dev-dependencies to your project:
+```
+npm install --dev
+npm i @digitallyhappy/backstrap --save-dev
+npm i noty --save-dev
+npm i animate.css@3.7.2 --save-dev
+```
+
+Then create a SCSS file for that custom bundle you want. We recommend doing it in `resources/scss/custom-backpack-bundle.scss`. Then customize this file to your liking:
+
+```scss
+// create a bundle CSS file for the an alternative Backstrap style (blue instead of purple for primary color)
+
+@import "http://github.com/node_modules/@digitallyhappy/backstrap/src/scss/_backstrap_colors";
+
+$primary: $black !default; // <--- For eg. This will make all buttons and texts black instead of purple
+$secondary: $gray-300 !default;
+$success: $green !default;
+$info: $blue !default;
+$warning: $yellow !default;
+$danger: $red !default;
+$light: $gray-200 !default;
+$dark: $black !default;
+
+$hover-color: rgba(105, 171, 239, 0.12);
+$border-color: rgba(0, 40, 100, 0.12);
+$muted-bg-color: rgba(0, 0, 0, 0.02);
+
+$theme-colors: () !default;
+$theme-colors: map-merge(
+ (
+ "primary": $primary,
+ "default": $secondary,
+ "secondary": $secondary,
+ "success": $success,
+ "info": $info,
+ "notice": $info,
+ "warning": $warning,
+ "danger": $danger,
+ "error": $danger,
+ "light": $light,
+ "dark": $dark
+ ),
+ $theme-colors
+);
+
+@import "http://github.com/node_modules/@digitallyhappy/backstrap/src/scss/_backstrap_miscellaneous";
+
+@import "http://github.com/node_modules/@coreui/coreui/scss/coreui";
+@import "http://github.com/node_modules/@digitallyhappy/backstrap/src/scss/_custom";
+@import "http://github.com/node_modules/@digitallyhappy/backstrap/src/scss/_noty";
+@import "http://github.com/node_modules/animate.css/source/_base";
+@import "http://github.com/node_modules/noty/src/noty";
+```
+
+Now add the command to your `webpack.mix.js` file to compile this new SASS file:
+
+```js
+// create a custom Backpack bundle CSS, with custom colors
+mix.sass('resources/scss/custom-backpack-bundle.scss', 'public/css/')
+ .options({
+ processCssUrls: false
+ });
+```
+
+And run `npm run dev`. If SASS is not a dev-requirement in your project already, Mix will add it automatically and ask you to run `npm run dev` again. Do that if necessary.
+
+Your result should say "_webpack compiled successfully_". If so, you can now use that new bundle file in all your Backpack pages by going to `config/backpack/base.php` and changing the main bundle CSS file that Backpack uses... with your own:
+
+```diff
+ 'styles' => [
+- 'packages/backpack/base/css/bundle.css',
++ 'css/custom-backpack-bundle.css',
+```
+
+
+
+### Create a new theme / child theme
+
+You can create a theme with your own HTML. Create a folder with all the views you want to overwrite, then change ```view_namespace``` inside your ```config/backpack/base.php``` to point to that folder. All views will be loaded from _that_ folder if they exist, then from ```resources/views/vendor/backpack/base```, then from the Base package.
+
+You can use child themes to:
+- create packages for your Backpack admin panels to look different (and re-use across projects)
+- use a different CSS framework (ex: Tailwind, Bulma)
+
+
+
+### Add custom JavaScript to all admin panel pages
+
+In ```config/backpack/base.php``` you'll notice this config option:
+
+```php
+ // JS files that are loaded in all pages, using Laravel's asset() helper
+ 'scripts' => [
+ // Backstrap includes jQuery, Bootstrap, CoreUI, Noty, Popper
+ 'packages/backpack/base/js/bundle.js?v='.\PackageVersions\Versions::getVersion('backpack/base'),
+
+ // examples (everything inside the bundle, loaded from CDN)
+ // 'https://code.jquery.com/jquery-3.4.1.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js',
+ // 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js',
+ // 'https://unpkg.com/@coreui/coreui/dist/js/coreui.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/pace/1.0.2/pace.min.js',
+ // 'https://unpkg.com/sweetalert/dist/sweetalert.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/noty/3.1.4/noty.min.js'
+
+ // examples (VueJS or React)
+ // 'https://unpkg.com/vue@2.4.4/dist/vue.min.js',
+ // 'https://unpkg.com/react@16/umd/react.production.min.js',
+ // 'https://unpkg.com/react-dom@16/umd/react-dom.production.min.js',
+ ],
+```
+
+You can add files to this array, and they'll be loaded in all admin panels pages.
+
+
+### Add custom CSS to all admin panel pages
+
+In ```config/backpack/base.php``` you'll notice this config option:
+
+```php
+ // CSS files that are loaded in all pages, using Laravel's asset() helper
+ 'styles' => [
+ 'packages/@digitallyhappy/backstrap/css/style.min.css',
+
+ // Examples (the fonts above, loaded from CDN instead)
+ // 'https://maxcdn.icons8.com/fonts/line-awesome/1.1/css/line-awesome-font-awesome.min.css',
+ // 'https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic',
+ ],
+```
+
+You can add files to this array, and they'll be loaded in all admin panels pages.
+
+
+### Customize the look and feel of the admin panel (using CSS)
+
+If you want to change the look and feel of the admin panel, you can create a custom CSS file wherever you want. We recommend you do it inside ```public/packages/myname/mycustomthemename/css/style.css``` folder so that it's easier to turn into a theme, if you decide later to share or re-use your CSS in other projects.
+
+In ```config/backpack/base.php``` add your file to this config option:
+
+```php
+ // CSS files that are loaded in all pages, using Laravel's asset() helper
+ 'styles' => [
+ 'packages/@digitallyhappy/backstrap/css/style.min.css',
+ // ...
+ 'packages/myname/mycustomthemename/css/style.css',
+ ],
+```
+
+This config option allows you to add CSS files that add style _on top_ of Backstrap, to make it look different. You can create a CSS file anywhere inside your ```public``` folder, and add it here.
+
+
+### How to add VueJS to all Backpack pages
+
+You can add any script you want inside all Backpack's pages by just adding it in your ```config/backpack/base.php``` file:
+
+```php
+
+ // JS files that are loaded in all pages, using Laravel's asset() helper
+ 'scripts' => [
+ // Backstrap includes jQuery, Bootstrap, CoreUI, Noty, Popper
+ 'packages/backpack/base/js/bundle.js',
+
+ // examples (everything inside the bundle, loaded from CDN)
+ // 'https://code.jquery.com/jquery-3.4.1.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js',
+ // 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js',
+ // 'https://unpkg.com/@coreui/coreui/dist/js/coreui.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/pace/1.0.2/pace.min.js',
+ // 'https://unpkg.com/sweetalert/dist/sweetalert.min.js',
+ // 'https://cdnjs.cloudflare.com/ajax/libs/noty/3.1.4/noty.min.js'
+
+ // examples (VueJS or React)
+ // 'https://unpkg.com/vue@2.4.4/dist/vue.min.js',
+ // 'https://unpkg.com/react@16/umd/react.production.min.js',
+ // 'https://unpkg.com/react-dom@16/umd/react-dom.production.min.js',
+ ],
+```
+
+You should be able to load Vue.JS by just uncommenting that one line. Or providing a link to a locally stored VueJS file.
+
+
+
+### Customize the translated strings (aka overwrite the language files)
+
+Backpack uses Laravel translations across the admin panel, to easily translate strings (ex: `{{ trans('backpack::base.already_have_an_account') }}`). If you don't like a translation, you're welcome to submit a PR to correct it for all users of your language. If you only want to correct it inside your app, or need to add a new translation string, you can *create a new file in your `resources/lang/vendor/backpack/en/base.php`* (similarly, `crud.php` or any other file). Any language strings that are inside your app, in the right folder, will be preferred over the ones in the package.
+
+Alternatively, if you need to customize A LOT of strings, you can use:
+```bash
+php artisan vendor:publish --provider="Backpack\CRUD\BackpackServiceProvider" --tag="lang"
+```
+which will publish ALL lang files, for ALL languages, inside `resources/lang/vendor/backpack`. But it's highly unlikely you need to modify all of them. In case you do publish all languages, please delete the ones you didn't change. That way, you only keep what's custom in your custom files, and it'll be easier to upgrade those files in the future.
+
+
+
+### Use the HTML & CSS for the front-end (Backstrap for front-facing website)
+
+If you like how Backpack looks and feels you can use the same interface to power your front-end, simply by making sure your blade view extend Backpack's layout file, instead of a layout file you'd create. Make sure your blade views extend `backpack_view('blank')` or create a layout file similar to our `layouts/top_left.blade.php` that better fits your needs. Then use it across your app:
+
+```php
+@extends(backpack_view('blank'))
+
+
Something
+```
+
+It's a good idea to go through our main layout file - [`layouts/top_left.blade.php`](https://github.com/Laravel-Backpack/CRUD/blob/master/src/resources/views/base/layouts/top_left.blade.php) - to understand how it works and how you can use it to your advantage. Most notably, you can:
+- use our `before_styles` and `after_styles` sections to easily _include_ CSS there - `@section('after_styles')`;
+- use our `before_styles` and `after_styles` stacks to easily _push_ CSS there - `@push('after_styles')`;
+- use our `before_scripts` and `after_scripts` sections to easily _include_ JS there - `@section('after_scripts')`;
+- use our `before_scripts` and `after_scripts` stacks to easily _push_ JS there - `@push('after_scripts')`;
+
+
+
+
+## Authentication
+
+
+### Customizing the Auth controllers
+
+In ```config/backpack/base.php``` you'll find these configuration options:
+
+```php
+ // Set this to false if you would like to use your own AuthController and PasswordController
+ // (you then need to setup your auth routes manually in your routes.php file)
+ 'setup_auth_routes' => true,
+```
+
+You can change both ```setup_auth_routes``` to ```false```. This means Backpack\Base won't register the Auth routes any more, so you'll have to manually register them in your route file, to point to the Auth controllers you want. If you're going to use the Auth controllers that Laravel generates, these are the routes you can use:
+```php
+Route::group(['middleware' => 'web', 'prefix' => config('backpack.base.route_prefix')], function () {
+ Route::auth();
+ Route::get('logout', 'Auth\LoginController@logout');
+});
+```
+
+
+### Customize the routes
+
+#### Custom routes - option 1
+
+You can place a new routes file in your ```app/routes/backpack/base.php```. If a file is present there, no default Backpack\Base routes will be loaded, only what's present in that file. You can use the routes file ```vendor/backpack/base/src/resources/views/base.php``` as an example, and customize whatever you want.
+
+#### Custom routes - option 2
+
+In ```config/backpack/base.php``` you'll find these configuration options:
+
+```php
+
+ /*
+ |--------------------------------------------------------------------------
+ | Routing
+ |--------------------------------------------------------------------------
+ */
+
+ // The prefix used in all base routes (the 'admin' in admin/dashboard)
+ 'route_prefix' => 'admin',
+
+ // Set this to false if you would like to use your own AuthController and PasswordController
+ // (you then need to setup your auth routes manually in your routes.php file)
+ 'setup_auth_routes' => true,
+
+ // Set this to false if you would like to skip adding the dashboard routes
+ // (you then need to overwrite the login route on your AuthController)
+ 'setup_dashboard_routes' => true,
+```
+
+In order to completely customize the auth routes, you can change both ```setup_auth_routes``` and ```setup_dashboard_routes``` to ```false```. This means Backpack\Base won't register any routes any more, so you'll have to manually register them in your route file. Here's what you can use to get started:
+```php
+Route::group(['middleware' => 'web', 'prefix' => config('backpack.base.route_prefix'), 'namespace' => 'Backpack\Base\app\Http\Controllers'], function () {
+ Route::auth();
+ Route::get('logout', 'Auth\LoginController@logout');
+ Route::get('dashboard', 'AdminController@dashboard');
+ Route::get('/', 'AdminController@redirect');
+});
+```
+
+
+### Use separate login/register forms for users and admins
+
+This is a default in Backpack v4.
+
+Backpack's authentication uses a completely separate authentication driver, provider, guard and password broker. They're all named ```backpack```, and registered in the vendor folder, invisible to you.
+
+If you need a separate login for user, just go ahead and create it. [Add the Laravel authentication, like instructed in the Laravel documentation](https://laravel.com/docs/5.7/authentication#authentication-quickstart): ```php artisan make:auth```. You'll then have:
+- the user login at ```/login``` -> using the AuthenticationController Laravel provides
+- the admin login at ```/admin/login``` -> using the AuthenticationControllers Backpack provides
+
+The user login will be using Laravel's default authentication driver, provider, guard and password broker, from ```config/auth.php```.
+
+Backpack's authentication driver, provider, guard and password broker can easily be overwritten by creating a driver/provider/guard/broker with the ```backpack``` name inside your ```config/auth.php```. If one named ```backpack``` exists there, Backpack will use that instead.
+
+
+### Overwrite Backpack authentication driver, provider, guard or password broker
+
+Backpack's authentication uses a completely separate authentication driver, provider, guard and password broker. Backpack adds them to what's defined in ```config/auth.php``` on runtime, and they're all named ```backpack```.
+
+To change a setting in how Backpack's driver/provider/guard or password broker works, create a driver/provider/guard/broker with the ```backpack``` name inside your ```config/auth.php```. If one named ```backpack``` exists there, Backpack will use that instead.
+
+
+### Use separate sessions for admin&user authentication
+
+This is a default in Backpack v4.
+
+
+### Login with username instead of email
+
+1. Create a ```username``` column in your users table and add it in ```$fillable``` on your ```User``` model. Best to do this with a migration.
+2. Remove the UNIQUE and NOT NULL constraints from ```email``` on your table. Best to do this with a migration. Alternatively, delete your ```email``` column and remove it from ```$fillable``` on your ```User``` model. If you already have a CRUD for users, you might also need to delete it from the Request, and from your UserCrudController.
+3. Change your ```config/backpack/base.php``` config options:
+```php
+ // Username column for authentication
+ // The Backpack default is the same as the Laravel default (email)
+ // If you need to switch to username, you also need to create that column in your db
+ 'authentication_column' => 'username',
+ 'authentication_column_name' => 'Username',
+```
+That's it. This will:
+- use ```username``` for login;
+- use ```username``` for registration;
+- use ```username``` in My Account, when a user wants to change his info;
+- completely disable the password recovery (if you've deleted the ```email``` db column);
+
+
+
+### Use your own User model instead of App\User
+
+By default, authentication and everything else inside Backpack is done using the ```App\User``` model. If you change the location of ```App\User```, or want to use a different User model for whatever other reason, you can do so by changing ```user_model_fqn``` in ```config/backpack/base.php``` to your new class.
+
+
+
+### Use your own profile image (avatar)
+
+By default, Backpack will use Gravatar to show the profile image for the currently logged in backpack user. In order to change this, you can use the option in ```config/backpack/base.php```:
+```php
+// What kind of avatar will you like to show to the user?
+// Default: gravatar (automatically use the gravatar for his email)
+//
+// Other options:
+// - placehold (generic image with his first letter)
+// - example_method_name (specify the method on the User model that returns the URL)
+'avatar_type' => 'gravatar',
+```
+
+Please note that this does not allow the user to change his profile image.
+
+
+
+### Add one or more fields to the Register form
+
+To add a new field to the Registration page, you should:
+
+**Step 1.** Overwrite the registration route, so it leads to _your_ controller, instead of the one in the package. We recommend you add it your ```routes/backpack/custom.php```, BEFORE the route group where you define your CRUDs:
+
+```php
+Route::get('admin/register', 'App\Http\Controllers\Admin\Auth\RegisterController')->name('backpack.auth.register');
+```
+
+**Step 2.** Create the new RegisterController somewhere in your project, that extends the RegisterController in the package, and overwrites the validation & user creation methods. For example:
+
+```php
+getTable();
+ $email_validation = backpack_authentication_column() == 'email' ? 'email|' : '';
+
+ return Validator::make($data, [
+ 'name' => 'required|max:255',
+ backpack_authentication_column() => 'required|'.$email_validation.'max:255|unique:'.$users_table,
+ 'password' => 'required|min:6|confirmed',
+ ]);
+ }
+
+ /**
+ * Create a new user instance after a valid registration.
+ *
+ * @param array $data
+ *
+ * @return User
+ */
+ protected function create(array $data)
+ {
+ $user_model_fqn = config('backpack.base.user_model_fqn');
+ $user = new $user_model_fqn();
+
+ return $user->create([
+ 'name' => $data['name'],
+ backpack_authentication_column() => $data[backpack_authentication_column()],
+ 'password' => bcrypt($data['password']),
+ ]);
+ }
+}
+```
+Add whatever validation rules & inputs you want, in addition to name and password.
+
+**Step 3.** Add the actual inputs to your HTML. You can easily overwrite the register view by adding this method to the same RegisterController:
+
+```php
+ public function showRegistrationForm()
+ {
+
+ return backpack_view('auth.register');
+ }
+```
+This will make the registration process pick up a view you can create, in ```resources/views/vendor/backpack/base/auth/register.blade.php```. You can copy-paste the original view, and modify as you please. Including adding your own custom inputs.
+
diff --git a/5.x/base-widgets.md b/5.x/base-widgets.md
new file mode 100644
index 00000000..f665bcc3
--- /dev/null
+++ b/5.x/base-widgets.md
@@ -0,0 +1,620 @@
+# Widgets
+
+---
+
+
+## About
+
+Widgets (aka cards, aka charts, aka graphs) provide a simple way to insert blade files into admin panel pages. You can use them to insert cards, charts, notices or custom content into pages.
+
+
+
+### Requirements
+
+In order to use the ```Widget``` class, you should make sure your main views (for new admin panel pages) extend the ```backpack::blank``` or ```backpack_view('blank')``` blade template. This template includes two sections where you can push widgets:
+- ```before_content```
+- ```after_content```
+
+
+
+### How to Use
+
+You can easily push widgets to these sections, by using the autoloaded ```Widget``` class. You can think of the ```Widget``` class as a global container for widgets, for the current page being rendered. That means you can call the ```Widget``` container inside a ```Controller```, inside a ```view```, or inside a service provider you create - wherever you want.
+
+```php
+use Backpack\CRUD\app\Library\Widget;
+
+Widget::add($widget_definition_array)->to('before_content');
+
+// alternatively, use a fluent syntax to define each widget attribute
+Widget::add()
+ ->to('before_content')
+ ->type('card')
+ ->content(null);
+```
+
+
+
+### Mandatory Attributes
+
+When passing a widget array, you need to specify at least these attributes:
+```php
+[
+ 'type' => 'card' // the kind of widget to show
+ 'content' => null // the content of that widget (some are string, some are array)
+],
+```
+
+
+### Optional Attributes
+
+Most widget types also have these attributes present, which you can use to tweak how the widget looks inside the page:
+```php
+'wrapper' => [
+ 'class' => 'col-sm-6 col-md-4', // customize the class on the parent element (wrapper)
+ 'style' => 'border-radius: 10px;',
+]
+```
+
+
+### Widgets API
+
+To manipulate widgets, you can use the methods below. The action will be performed on the page being constructed for the current request. And the ```Widget``` class is a global container, so you can add widgets to it both from the Controller, and from the view.
+
+```php
+// to add a widget to a different section than the default 'before_content' section:
+Widget::add($widget_definition_array)->to('after_content');
+Widget::add($widget_definition_array)->section('after_content');
+Widget::add($widget_definition_array)->group('after_content');
+
+// to create a widget, WITHOUT adding it to a section
+Widget::make($widget_definition_array);
+
+// to define the contents of a widget, pass the definition array to the make()/add() methods
+Widget::add($widget_definition_array);
+Widget::make($widget_definition_array);
+// alternatively, define each widget attribute one by one, using a fluent syntax
+Widget::add()
+ ->to('after_content')
+ ->type('card')
+ ->content('something');
+
+// to reference a widget later on, give it a unique 'name'
+Widget::add($widget_definition_array)->name('my_widget');
+
+// you can then easily modify it
+Widget::name('my_widget')->content('some other content'); // change the 'content' attribute
+Widget::name('my_widget')->forget('attribute_name'); // unset a widget attribute
+Widget::name('my_widget')->makeFirst(); // make a widget the first one in its section
+Widget::name('my_widget')->makeLast(); // to make a widget the last one in its section
+Widget::name('my_widget')->remove(); // remove the widget from its section
+```
+
+
+
+
+## Default Widget Types
+
+
+### Alert
+
+Shows a notification bubble, with the heading and text you specify:
+
+```php
+[
+ 'type' => 'alert',
+ 'class' => 'alert alert-danger mb-2',
+ 'heading' => 'Important information!',
+ 'content' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Corrupti nulla quas distinctio veritatis provident mollitia error fuga quis repellat, modi minima corporis similique, quaerat minus rerum dolorem asperiores, odit magnam.',
+ 'close_button' => true, // show close button or not
+]
+```
+
+For different colors, you can use the following classes: ```alert-success```, ```alert-warning```, ```alert-info```, ```alert-danger``` ```alert-primary```, ```alert-secondary```, ```alert-light```, ```alert-dark```.
+
+Widget Preview:
+
+
+
+
+
+
+### Card
+
+Shows a Bootstrap card, with the heading and body you specify. You can customize the class name to get cards of different color, size, etc.
+
+```php
+[
+ 'type' => 'card',
+ // 'wrapper' => ['class' => 'col-sm-6 col-md-4'], // optional
+ // 'class' => 'card bg-dark text-white', // optional
+ 'content' => [
+ 'header' => 'Some card title', // optional
+ 'body' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non mi nec orci euismod venenatis. Integer quis sapien et diam facilisis facilisis ultricies quis justo. Phasellus sem turpis, ornare quis aliquet ut, volutpat et lectus. Aliquam a egestas elit. Nulla posuere, sem et porttitor mollis, massa nibh sagittis nibh, id porttitor nibh turpis sed arcu.',
+ ]
+]
+```
+
+For different background colors, you can use the following classes: ```bg-success```, ```bg-warning```, ```bg-info```, ```bg-danger``` ```bg-primary```, ```bg-secondary```, ```bg-light```, ```bg-dark```.
+
+Other useful helper classes: ```text-center```, ```text-white```.
+
+Widget Preview:
+
+
+
+
+
+
+### Chart PRO
+
+Shows a pie chart / line chart / bar chart inside a Bootstrap card, with the heading and body you specify.
+
+
+
+To create and use a new widget chart, you need to:
+
+**Step 1.** Install laravel-charts, that offers a single PHP syntax for 6 different charting libraries:
+```
+composer require consoletvs/charts:"6.*"
+```
+
+**Step 2.** Create a new ChartController:
+
+```
+php artisan backpack:chart WeeklyUsers
+
+```
+
+This will create:
+- a new ChartController inside ```app\Http\Controllers\Admin\Charts\WeeklyUsersChartController```
+- a route towards that ChartController in your ```routes/backpack/custom.php```
+
+**Step 3.** Add the widget that points to that ChartController you just created:
+```php
+Widget::add([
+ 'type' => 'chart',
+ 'controller' => \App\Http\Controllers\Admin\Charts\WeeklyUsersChartController::class,
+
+ // OPTIONALS
+
+ // 'class' => 'card mb-2',
+ // 'wrapper' => ['class'=> 'col-md-6'] ,
+ // 'content' => [
+ // 'header' => 'New Users',
+ // 'body' => 'This chart should make it obvious how many new users have signed up in the past 7 days.
',
+ // ],
+]);
+```
+
+**Step 4.** Configure the ChartController you just created:
+- ```public function setup()``` (MANDATORY)
+ - initialize and configure ```$this->chart```, using the methods detailed in the [laravel-charts documentation](https://charts.erik.cat/getting_started.html);
+ - you _can_ define your dataset here, if you want your DB queries to be called upon page load;
+- ```public function data()``` (OPTIONAL, but recommended)
+ - use ```$this->chart->dataset()``` to configure what the chart should contain;
+ - if it's defined, the chart will loads its contents using AJAX;
+
+Optionally:
+- you can _easily_ switch the JavaScript library used, by changing the use statement at the top of this file:
+
+```diff
+-use ConsoleTVs\Charts\Classes\Chartjs\Chart;
++use ConsoleTVs\Charts\Classes\Echarts\Chart;
++use ConsoleTVs\Charts\Classes\Fusioncharts\Chart;
++use ConsoleTVs\Charts\Classes\Highcharts\Chart;
++use ConsoleTVs\Charts\Classes\C3\Chart;
++use ConsoleTVs\Charts\Classes\Frappe\Chart;
+```
+- you can change the path to the JS library; if you don't want it loaded from a CDN, you can define ```$library``` or ```getLibraryFilePath()``` on your ChartController:
+
+```php
+protected $library = 'http://path/to/file';
+
+// or
+
+public function getLibraryFilePath()
+{
+ return asset('path/to/your/js/file');
+
+ // or
+
+ return [
+ asset('path/to/first/js/file'),
+ asset('path/to/second/js/file'),
+ ];
+}
+```
+
+
+
+**That's it!** Refresh the page to see your new chart widget. Below, you'll find a few examples of how the ChartController can end up looking.
+
+
+
+**Example 1:** ChartController that loads results using AJAX:
+```php
+chart = new Chart();
+
+ // MANDATORY. Set the labels for the dataset points
+ $labels = [];
+ for ($days_backwards = 30; $days_backwards >= 0; $days_backwards--) {
+ if ($days_backwards == 1) {
+ }
+ $labels[] = $days_backwards.' days ago';
+ }
+ $this->chart->labels($labels);
+
+ // RECOMMENDED.
+ // Set URL that the ChartJS library should call, to get its data using AJAX.
+ $this->chart->load(backpack_url('http://github.com/charts/new-entries'));
+
+ // OPTIONAL.
+ $this->chart->minimalist(false);
+ $this->chart->displayLegend(true);
+ }
+
+ /**
+ * Respond to AJAX calls with all the chart data points.
+ *
+ * @return json
+ */
+ public function data()
+ {
+ for ($days_backwards = 30; $days_backwards >= 0; $days_backwards--) {
+ // Could also be an array_push if using an array rather than a collection.
+ $users[] = User::whereDate('created_at', today()
+ ->subDays($days_backwards))
+ ->count();
+ $articles[] = Article::whereDate('created_at', today()
+ ->subDays($days_backwards))
+ ->count();
+ $categories[] = Category::whereDate('created_at', today()
+ ->subDays($days_backwards))
+ ->count();
+ $tags[] = Tag::whereDate('created_at', today()
+ ->subDays($days_backwards))
+ ->count();
+ }
+
+ $this->chart->dataset('Users', 'line', $users)
+ ->color('rgb(77, 189, 116)')
+ ->backgroundColor('rgba(77, 189, 116, 0.4)');
+
+ $this->chart->dataset('Articles', 'line', $articles)
+ ->color('rgb(96, 92, 168)')
+ ->backgroundColor('rgba(96, 92, 168, 0.4)');
+
+ $this->chart->dataset('Categories', 'line', $categories)
+ ->color('rgb(255, 193, 7)')
+ ->backgroundColor('rgba(255, 193, 7, 0.4)');
+
+ $this->chart->dataset('Tags', 'line', $tags)
+ ->color('rgba(70, 127, 208, 1)')
+ ->backgroundColor('rgba(70, 127, 208, 0.4)');
+ }
+}
+
+```
+
+**Example 2.** Pie chart with both labels and dataset defined in the ```setup()``` method (no AJAX):
+
+```php
+chart = new Chart();
+
+ $this->chart->dataset('Red', 'pie', [10, 20, 80, 30])
+ ->backgroundColor([
+ 'rgb(70, 127, 208)',
+ 'rgb(77, 189, 116)',
+ 'rgb(96, 92, 168)',
+ 'rgb(255, 193, 7)',
+ ]);
+
+ // OPTIONAL
+ $this->chart->displayAxes(false);
+ $this->chart->displayLegend(true);
+
+ // MANDATORY. Set the labels for the dataset points
+ $this->chart->labels(['HTML', 'CSS', 'PHP', 'JS']);
+ }
+}
+
+```
+
+
+
+
+
+### Div
+
+Allows you to include multiple widgets in the div attributes of your choice. For example, you can include multiple widgets in a `````` with the code below:
+
+```php
+[
+ 'type' => 'div',
+ 'class' => 'row',
+ 'content' => [ // widgets
+ [ 'type' => 'card', 'content' => ['body' => 'One'] ],
+ [ 'type' => 'card', 'content' => ['body' => 'Two'] ],
+ [ 'type' => 'card', 'content' => ['body' => 'Three'] ],
+ ]
+]
+```
+
+Anything you specify on this widget, other than ```type``` and ```content```, has to be a string, and will be considered an attribute of the "div" element.
+
+
+
+
+### Jumbotron
+
+Shows a Bootstrap jumbotron component, with the heading and body you specify.
+
+```php
+[
+ 'type' => 'jumbotron',
+ 'heading' => 'Welcome!',
+ 'content' => 'Use the sidebar to the left to create, edit or delete content.',
+ 'button_link' => backpack_url('http://github.com/logout'),
+ 'button_text' => 'Logout',
+]
+```
+
+Widget Preview:
+
+
+
+
+
+
+### Progress
+
+Shows a colorful card to signify the progress towards a goal. You can customize the class name to get cards of different color, size, etc.
+
+```php
+[
+ 'type' => 'progress',
+ 'class' => 'card text-white bg-primary mb-2',
+ 'value' => '11.456',
+ 'description' => 'Registered users.',
+ 'progress' => 57, // integer
+ 'hint' => '8544 more until next milestone.',
+]
+```
+
+For different background colors, you can use the following classes: ```bg-success```, ```bg-warning```, ```bg-info```, ```bg-danger``` ```bg-primary```, ```bg-secondary```, ```bg-light```, ```bg-dark```.
+
+Other useful helper classes: ```text-center```, ```text-white```.
+
+Widget Preview:
+
+
+
+
+
+
+### Progress White
+
+Shows a white card to signify the progress towards a goal. You can customize the class name to get progress bars of different color.
+
+```php
+[
+ 'type' => 'progress_white',
+ 'class' => 'card mb-2',
+ 'value' => '11.456',
+ 'description' => 'Registered users.',
+ 'progress' => 57, // integer
+ 'progressClass' => 'progress-bar bg-primary',
+ 'hint' => '8544 more until next milestone.',
+]
+```
+
+For different progress bar colors, you can use the following classes: ```bg-success```, ```bg-warning```, ```bg-info```, ```bg-danger``` ```bg-primary```, ```bg-secondary```, ```bg-light```, ```bg-dark```.
+
+Widget Preview:
+
+
+
+
+
+
+### Script
+
+Loads a JavaScript file from a location you specify using a `
+
+@endpush
+```
+
+
+
+## Using a Widget Type from a Package
+
+You can choose the view namespace when loading a widget:
+
+```php
+
+// using the fluent syntax, use the 'from' alias
+Widget::add($widget_definition_array)->from('package::widgets');
+
+// using the widget definition array, specify its 'viewNamespace'
+Widget::add([
+ 'type' => 'card',
+ 'viewNamespace' => 'package::widgets',
+ 'wrapper' => ['class' => 'col-sm-6 col-md-4'],
+ 'class' => 'card text-white bg-primary text-center',
+ 'content' => [
+ // 'header' => 'Another card title',
+ 'body' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non mi nec orci euismod venenatis. Integer quis sapien et diam facilisis facilisis ultricies quis justo. Phasellus sem turpis, ornare quis aliquet ut, volutpat et lectus. Aliquam a egestas elit.',
+ ],
+]);
+
+```
+
+Similarly, if you want to create widgets somewhere else than in ```resources/views/vendor/backpack/base/widgets```, you can pass that directory as the namespace of your widget. For example, ```resources/views/admin/widgets``` would have ```admin.widgets``` as the namespace.
diff --git a/5.x/crud-api.md b/5.x/crud-api.md
new file mode 100644
index 00000000..04857b66
--- /dev/null
+++ b/5.x/crud-api.md
@@ -0,0 +1,530 @@
+# CRUD API
+
+---
+
+Here are all the features you will be using **inside your EntityCrudController**, grouped by the operation you will most likely use them for.
+
+## Operations
+
+- **operation()** - allows you to add a set of instructions inside ```setup()```, that only gets called when a certain operation is being performed;
+```php
+public function setup() {
+ // ...
+ $this->crud->operation('list', function() {
+ $this->crud->addColumn('name');
+ });
+}
+```
+
+
+### List Operation
+
+
+#### Columns
+
+Manipulate what columns are shown in the table view.
+
+- **addColumn()** - add a column, at the end of the stack
+```php
+$this->crud->addColumn($column_definition_array);
+```
+
+- **addColumns()** - add multiple columns, at the end of the stack
+```php
+$this->crud->addColumns([$column_definition_array, $another_column_definition_array]);
+```
+
+- **modifyColumn()** - change column attributes
+```php
+$this->crud->modifyColumn($name, $modifs_array);
+```
+
+- **removeColumn()** - remove one column from all operations
+```php
+$this->crud->removeColumn('column_name');
+```
+
+- **removeColumns()** - remove multiple columns from all operations
+```php
+$this->crud->removeColumns(['column_name_1', 'column_name_2']); // remove an array of columns from the stack
+```
+
+- **setColumnDetails()** - change the attributes of one column; alias of ```modifyColumn()```;
+```php
+$this->crud->setColumnDetails('column_name', ['attribute' => 'value']);
+```
+
+- **setColumnsDetails()** - change the attributes of multiple columns; alias of ```modifyColumn()```;
+```php
+$this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
+```
+
+- **setColumns()** - remove previously set columns and only use the ones give now;
+```php
+$this->crud->setColumns();
+// sets the columns you want in the table view, either as array of column names, or multidimensional array with all columns detailed with their types
+```
+
+- **Chained - beforeColumn()** - insert current column _before_ the given column
+```php
+// ------ REORDER COLUMNS
+$this->crud->addColumn()->beforeColumn('name');
+```
+
+- **Chained - afterColumn()** - insert current column _after_ the given column
+```php
+$this->crud->addColumn()->afterColumn('name');
+```
+
+- **Chained - makeFirstColumn()** - make this column the first one in the list
+```php
+$this->crud->addColumn()->makeFirstColumn();
+// Please note: you need to also specify priority 1 in your addColumn statement for details_row or responsive expand buttons to show
+```
+
+
+#### Buttons
+
+- **addButton()** - add a button in the given stack
+```php
+$this->crud->addButton($stack, $name, $type, $content, $position);
+// stacks: top, line, bottom
+// types: view, model_function
+// positions: beginning, end (defaults to 'beginning' for the 'line' stack, 'end' for the others);
+```
+
+- **addButtonFromModelFunction()** - add a button whose HTML is returned by a method in the CRUD model
+```php
+$this->crud->addButtonFromModelFunction($stack, $name, $model_function_name, $position);
+```
+
+- **addButtonFromView()** - add a button whose HTML is in a view placed at ```resources\views\vendor\backpack\crud\buttons```
+```php
+$this->crud->addButtonFromView($stack, $name, $view, $position);
+```
+
+- **modifyButton()** - modify the attributes of a button
+```php
+$this->crud->modifyButton($name, $modifications);
+```
+
+- **removeButton()** - remove a button from whatever stack it's in
+```php
+$this->crud->removeButton($name); // remove a single button
+$this->crud->removeButtons($names); // or multiple
+```
+
+- **removeButtonFromStack()** - remove a button from a particular stack
+```php
+$this->crud->removeButtonFromStack($name, $stack);
+```
+
+- **removeAllButtons()** - remove all buttons from any stack
+```php
+$this->crud->removeAllButtons();
+```
+
+- **removeAllButtonsFromStack()** - remove all buttons from a particular stack
+```php
+$this->crud->removeAllButtonsFromStack($stack);
+```
+
+
+#### Filters
+
+Manipulate what filters are shown in the table view. Check out [CRUD > Operations > ListEntries > Filters](/docs/{{version}}/crud-filters) to see examples of ```$filter_definition_array```
+
+- **addFilter()** - add a filter to the list view
+```php
+$this->crud->addFilter($filter_definition_array, $values, $filter_logic);
+```
+
+- **modifyFilter()** - change the attributes of a filter
+```php
+$this->crud->modifyFilter($name, $modifs_array);
+```
+
+- **removeFilter()** - remove a certain filter from the list view
+```php
+$this->crud->removeFilter($name);
+```
+
+- **removeAllFilters()** - remove all filters from the list view
+```php
+$this->crud->removeAllFilters();
+```
+
+- **filters()** - get all the registered filters for the list view
+```php
+$this->crud->filters();
+```
+
+
+#### Details Row
+
+Shows a ```+``` (plus sign) next to each table row, so that the user can expand that row and reveal details. You are responsible for creating the view with those details.
+
+- **enableDetailsRow()** - show the + sign in the table view
+```php
+$this->crud->enableDetailsRow();
+// NOTE: you also need to do allow access to the right users:
+$this->crud->allowAccess('details_row');
+// NOTE: you also need to do overwrite the showDetailsRow($id) method in your EntityCrudController to show whatever you'd like in the details row OR overwrite the views/backpack/crud/details_row.blade.php
+$this->crud->setDetailsRowView('your-view');
+```
+
+- **disableDetailsRow()** - hide the + sign in the table view
+```php
+$this->crud->disableDetailsRow();
+```
+
+
+#### Export Buttons
+
+Please note it will only export the current _page_ of results. So in order to export all entries the user needs to make the current page show "All" entries from the top-left picker.
+
+- **enableExportButtons()** - Show export to PDF, CSV, XLS and Print buttons on the table view
+```php
+$this->crud->enableExportButtons();
+```
+
+
+#### Responsive Table
+
+- **disableResponsiveTable()** - stop the listEntries view from showing/hiding columns depending on viewport width
+```php
+$this->crud->disableResponsiveTable();
+```
+
+- **enableResponsiveTable()** - make the listEntries view show/hide columns depending on viewport width
+```php
+$this->crud->enableResponsiveTable();
+```
+
+
+#### Persistent Table
+
+- **enablePersistentTable()** - make the listEntries remember the filters, search and pagination for a user, even if he leaves the page, for 2 hours
+```php
+$this->crud->enablePersistentTable();
+```
+
+- **disablePersistentTable()** - stop the listEntries from remembering the filters, search and pagination for a user, even if he leaves the page
+```php
+$this->crud->disablePersistentTable();
+```
+
+
+#### Page Length
+
+- **setDefaultPageLength()** - change the number of items per page in the list view
+```php
+$this->crud->setDefaultPageLength(10);
+```
+
+- **setPageLengthMenu()** - change the entire page length menu in the list view
+```php
+$this->crud->setPageLengthMenu([100, 200, 300]);
+```
+
+
+#### Actions Column
+
+- **setActionsColumnPriority()** - make the actions column (in the table view) hide when not enough space is available, by giving it an unreasonable priority
+```php
+$this->crud->setActionsColumnPriority(10000);
+```
+
+
+#### Custom / Advanced Queries
+
+- **addClause()** - change what entries are shown in the table view; this allows _developers_ to forcibly change the query used by the table view, as opposed to filters, that allow _users_ to change the query with new inputs;
+```php
+$this->crud->addClause('active'); // apply local scope
+$this->crud->addClause('type', 'car'); // apply local dynamic scope
+$this->crud->addClause('where', 'name', '=', 'car');
+$this->crud->addClause('whereName', 'car');
+$this->crud->addClause('whereHas', 'posts', function($query) {
+ $query->activePosts();
+ });
+```
+
+- **groupBy()** - shorthand to add a **groupBy** clause to the query
+```php
+$this->crud->groupBy();
+```
+
+- **limit()** - shorthand to add a **limit** clause to the query
+```php
+$this->crud->limit();
+```
+
+- **orderBy()** - shorthand to add an **orderBy** clause to the query
+```php
+$this->crud->orderBy();
+```
+
+
+### Show Operation
+
+Use [the same Columns API as for the ListEntries operation](#columns-api), but inside your ```show()``` method.
+
+
+### Create & Update Operations
+
+Manipulate what fields are shown in the create / update forms. Check out [CRUD > Operations > Create & Update > Fields](/docs/{{version}}/crud-fields) in the docs to see examples of ```$field_definition_array```.
+
+**Note:** The call is being performed for the current operation. So it's important to pay attention _where_ you're calling fields. Most likely, you'll want to do this inside ```setupCreateOperation()``` or ```setupUpdateOperation()```.
+
+- **addField()** - add one field
+```php
+$this->crud->addField($field_definition_array);
+$this->crud->addField('db_column_name'); // a lazy way to add fields: let the CRUD decide what field type it is and set it automatically, along with the field label
+```
+
+- **addFields()** - add multiple fields
+```php
+$this->crud->addFields($array_of_fields_definition_arrays);
+```
+
+- **modifyField()** - change the attributes of an existing field
+```php
+$this->crud->modifyField($name, $modifs_array);
+```
+
+- **removeField()** - remove a given field from the current operation
+```php
+$this->crud->removeField('name');
+```
+
+- **removeFields()** - remove multiple fields from the current operation
+```php
+$this->crud->removeFields($array_of_names);
+```
+
+- **removeAllFields()** - remove all registered fields
+```php
+$this->crud->removeAllFields();
+```
+- **Chained - beforeField()** - add a field _before_ a given field
+```php
+$this->crud->addField()->beforeField('name');
+```
+
+- **Chained - afterField()** - add a field _after_ a given field
+```php
+$this->crud->addField()->afterField('name');
+```
+
+- **setRequiredFields()** - check the FormRequests used in this EntityCrudController for required fields, and add an asterisk to them in the create or edit forms
+```php
+$this->crud->setRequiredFields(StoreRequest::class);
+```
+
+- **setValidation()** - makes sure validation and authorization in the FormRequest you've passed is being performed; also uses that file to figure out asterisk to show in the forms (calls ```setRequiredFields()``` above):
+```php
+$this->crud->setValidation(ArticleRequest::class);
+```
+
+
+### Reorder Operation
+
+Show a reorder button in the table view, next to Add. Provides an interface to reorder & nest elements, provided the ```parent_id```, ```lft```, ```rgt```, ```depth``` columns are in the database, and ```$fillable``` on the model.
+
+```php
+$this->crud->set('reorder.label', 'name'); // which model attribute to use for labels
+$this->crud->set('reorder.max_level', 3); // maximum nesting depth; this example will prevent the user from creating trees deeper than 3 levels;
+```
+
+- **disableReorder()** - disable the Reorder functionality
+```php
+$this->crud->disableReorder();
+```
+
+- **isReorderEnabled()** - returns ```true```/```false``` if the Reorder operation is enabled or not
+```php
+$this->crud->isReorderEnabled();
+```
+
+
+### Revise Operation
+
+A.k.a. Audit Trail. Tracks all changes to an entry and provides an interface to revert to a previous state. This operation is not installed by default - please check out [Revise Operation](/docs/{{version}}/crud-operation-revisions) for the installation & usage steps.
+
+
+## All Operations
+
+### Access
+
+Prevent or allow users from accessing different CRUD operations.
+
+- **allowAccess()** - give users access to one or multiple operations
+```php
+$this->crud->allowAccess('list');
+$this->crud->allowAccess(['list', 'create', 'delete']);
+```
+
+- **denyAccess()** - prevent users from accessing one or multiple operations
+```php
+$this->crud->denyAccess('list');
+$this->crud->denyAccess(['list', 'create', 'delete']);
+```
+
+- **hasAccess()** - check if the current user has access to one or multiple operations
+```php
+$this->crud->hasAccess('something'); // returns true/false
+$this->crud->hasAccessOrFail('something'); // throws 403 error
+$this->crud->hasAccessToAll(['create', 'update']); // returns true/false
+$this->crud->hasAccessToAny(['create', 'update']); // returns true/false
+```
+
+### Eager Loading Relationships
+
+- **with()** - when the current entry is loaded (in any operation) also get its relationships, so that only one query is made to the database per entry
+```php
+$this->crud->with('relationship_name');
+```
+
+### Custom Views
+
+- **setShowView()**, **setEditView()**, **setCreateView()**, **setListView()**, **setReorderView()**, **setRevisionsView()**, **setRevisionsTimelineView()**, **setDetailsRowView()** - set the view for a certain CRUD operation or feature
+
+```php
+// use a custom view for a CRUD operation
+$this->crud->setShowView('path.to.your.view');
+$this->crud->setEditView('path.to.your.view');
+$this->crud->setCreateView('path.to.your.view');
+$this->crud->setListView('path.to.your.view');
+$this->crud->setReorderView('path.to.your.view');
+$this->crud->setRevisionsView('path.to.your.view');
+$this->crud->setRevisionsTimelineView('path.to.your.view');
+$this->crud->setDetailsRowView('path.to.your.view');
+
+// more generally, you can use the Settings API:
+$this->crud->set('create.view', 'path.to.your.view');
+
+// if you want to load something from the /resources/vendor/backpack/crud directory, you can do
+$this->crud->set('create.view', 'crud::yourfolder.yourview');
+// or
+$this->crud->set('create.view', 'resources.vendor.backpack.crud.yourfolder.yourview');
+```
+
+### Content Class
+
+- **setShowContentClass()**, **setEditContentClass()**, **setCreateContentClass()**, **setListContentClass()**, **setReorderContentClass()**, **setRevisionsContentClass()**, **setRevisionsTimelineContentClass()** - set the CSS class for an operation view, to make the main area bigger or smaller:
+
+```php
+// use a custom view for a CRUD operation
+$this->crud->setShowContentClass('col-md-8');
+$this->crud->setEditContentClass('col-md-8');
+$this->crud->setCreateContentClass('col-md-8');
+$this->crud->setListContentClass('col-md-8');
+$this->crud->setReorderContentClass('col-md-8');
+$this->crud->setRevisionsContentClass('col-md-8');
+$this->crud->setRevisionsTimelineContentClass('col-md-8');
+
+// more generally, you can use the Settings API:
+$this->crud->set('create.contentClass', 'col-md-12');
+```
+
+### Getters
+
+- **getEntry()** - get a certain entry of the current model type
+```php
+$this->crud->getEntry($entry_id);
+```
+- **getEntries()** - get all entries using the current CRUD query
+```php
+$this->crud->getEntries();
+```
+
+- **getFields()** - get all fields for a certain operation, or for both
+```php
+$this->crud->getFields('create/update/both');
+```
+
+- **getCurrentEntry()** - get the current entry, for operations that work on a single entry
+```php
+$this->crud->getCurrentEntry();
+// ex: in your update() method, after calling parent::updateCrud()
+```
+
+### Operations
+
+- **getOperation()** - get the name of the operation that is currently being performed
+```php
+$this->crud->getOperation();
+```
+
+- **setOperation()** - set the name of the operation that is currently being performed
+```php
+$this->crud->setOperation('ListEntries');
+```
+
+### Actions
+
+An action is the controller method that is currently being run.
+
+- **getActionMethod()** - returns the method on the controller that was called by the route; ex: ```create()```, ```update()```, ```edit()``` etc;
+```php
+$this->crud->getActionMethod();
+```
+
+- **actionIs()** - checks if the given controller method is the one called by the route
+```php
+$this->crud->actionIs('create');
+```
+
+### Title, Heading, Subheading
+
+Legend:
+- _operation_ - a collection of functions in a CrudController, that together allow the admin to perform something on the current model;
+- _action_ - a method (aka function) of an operation; it is the actual PHP function's name;
+
+- **getTitle()** - get the Title for the create action
+```php
+$this->crud->getTitle('create');
+```
+
+- **getHeading()** - get the Heading for the create action
+```php
+$this->crud->getHeading('create');
+```
+
+- **getSubheading()** - get the Subheading for the create action
+```php
+$this->crud->getSubheading('create');
+```
+
+- **setTitle()** - set the Title for the create action
+```php
+$this->crud->setTitle('some string', 'create');
+```
+
+- **setHeading()** - set the Heading for the create action
+```php
+$this->crud->setHeading('some string', 'create');
+```
+
+- **setSubheading()** - set the Subheading for the create action
+```php
+$this->crud->setSubheading('some string', 'create');
+```
+
+### CrudPanel Basic Info
+
+- **setModel()** - set the Eloquent object that should be used for all operations
+```php
+$this->crud->setModel("App\Models\Example");
+```
+
+- **setRoute()** - set the main route to this CRUD
+```php
+$this->crud->setRoute("admin/example");
+// OR $this->crud->setRouteName("admin.example");
+```
+
+- **setEntityNameStrings()** - set how the entity name should be shown to the user, in singular and in plural
+```php
+$this->crud->setEntityNameStrings("example", "examples");
+```
diff --git a/5.x/crud-basics.md b/5.x/crud-basics.md
new file mode 100644
index 00000000..cd734260
--- /dev/null
+++ b/5.x/crud-basics.md
@@ -0,0 +1,46 @@
+# Basics
+
+---
+
+Backpack\CRUD provides a fast way to build administration panels - places where your administrators can Create, Read, Update, Delete entries for a specific Eloquent model. **One CRUD Panel provides functionality for one Eloquent Model.**
+
+
+## Requirements
+
+In order to create a CRUD Panel, you'll need:
+- **a table in the database** (and maybe connection tables for relationships);
+- **an Eloquent Model** that points to that db table;
+
+If you don't already have the models, don't worry, Backpack also includes a faster way to generate database migrations and models.
+
+
+## Architecture
+
+A Backpack CRUD Panel uses _the same elements_ you would have created for an administration panel, if you were doing it from scratch:
+- a **controller** - holds the logic for the all operations an admin can perform on that Eloquent model; will be generated in ```app/Http/Controllers/Admin```;
+- a **request** file - used to validate Create and Update forms; will be generated in ```app/Http/Requests```;
+- a resource **route** - points to the controller above; will be generated in ```routes/backpack/custom.php```;
+
+**The only difference** between building it from scratch and using Backpack\CRUD** is that:
+- your controller will be extending ```Backpack\CRUD\app\Http\Controllers\CrudController```**, which allow you to easily add traits that handle the most common operations: Create, Update, Delete, List, Show, Reorder, Revisions.
+- your model will ```use \Backpack\CRUD\CrudTrait```;
+
+This simple architecture (```ProductCrudController extends CrudController```) means:
+- **your CRUD Panel will not be a _black box_**; you can easily see the logic for each operation, by checking the methods on this controller, or the traits you'll be using;
+- **you can _easily_ overwrite what happens inside each operation**;
+- **you can _easily_ add custom operations**;
+
+For example:
+- want to change how a single ```Product``` is shown to the admin? just create a method called ```show()``` in your ```ProductCrudController```; simple OOP dictates that your method will be picked up, instead of the one in CrudController; some goes for ```create()```, ```store()```, etc - you have complete control;
+- want to create a new "Publish" operation on a ```Product```? your ```ProductCrudController``` is a great place for that logic; just create a custom ```publish()``` method and a route that points to it;
+
+
+## Files
+
+For a ```Tag``` entity, your CRUD Panel would consist of:
+- a controller (```app/Http/Controllers/Admin/TagCrudController.php```);
+- a request (```app/Http/Requests/TagCrudRequest.php```);
+- a route inside ```routes/backpack/custom.php```;
+- your existing model (```app/Models/Tag.php```);
+
+To further your understanding of how a CRUD Panel works, [read more about this example in the tutorial](/docs/{{version}}/crud-tutorial).
diff --git a/5.x/crud-buttons.md b/5.x/crud-buttons.md
new file mode 100644
index 00000000..6e669bd9
--- /dev/null
+++ b/5.x/crud-buttons.md
@@ -0,0 +1,237 @@
+# Buttons
+
+---
+
+
+## About
+
+Buttons are used inside the ListEdit operation, to allow the admin to trigger other operations. Some point to entirely new routes (```create```, ```update```, ```show```), others perform the operation on the current page using AJAX (```delete```).
+
+
+### Button Stacks
+
+The ShowList operation has 3 places where buttons can be placed:
+ - ```top``` (where the Add button is)
+ - ```line``` (where the Edit and Delete buttons are)
+ - ```bottom``` (after the table)
+
+When adding a button to the stack, you can choose whether to insert it at the ```beginning``` or ```end``` of the stack by specifying that as a last parameter.
+
+
+### Default Buttons
+
+Backpack adds a few buttons by default:
+- ```create``` to the ```top``` stack;
+- ```update``` and ```delete``` to the ```line``` stack;
+
+Default buttons are invisible if an operation has been disabled. For example, you can:
+- hide the "delete" button using ```$this->crud->denyAccess('delete')```;
+- show a "preview" button by using ```$this->crud->allowAccess('show')```;
+
+
+### Buttons API
+
+Here are a few things you can call in your EntityCrudController's ```setupListOperation()``` method, to manipulate buttons:
+
+```php
+// possible stacks: 'top', 'line', 'bottom';
+// possible positions: 'beginning' and 'end'; defaults to 'beginning' for the 'line' stack, 'end' for the others;
+
+// collection of all buttons
+$this->crud->buttons();
+
+// add a button; possible types are: view, model_function
+$this->crud->addButton($stack, $name, $type, $content, $position);
+
+// add a button whose HTML is returned by a method in the CRUD model
+$this->crud->addButtonFromModelFunction($stack, $name, $model_function_name, $position);
+
+// add a button whose HTML is in a view placed at resources\views\vendor\backpack\crud\buttons
+$this->crud->addButtonFromView($stack, $name, $view, $position);
+
+// remove a button
+$this->crud->removeButton($name);
+
+// remove a button for a certain stack
+$this->crud->removeButtonFromStack($name, $stack);
+
+// remove multiple buttons
+$this->crud->removeButtons($names, $stack);
+
+// remove all buttons
+$this->crud->removeAllButtons();
+
+// remove all buttons for a certain stack
+$this->crud->removeAllButtonsFromStack($stack);
+
+// order buttons in a stack, order is an array with the ordered names of the buttons
+$this->crud->orderButtons($stack, $order);
+
+// modify button, modifications are the attributes and their new values.
+$this->crud->modifyButton($name, $modifications);
+
+// Move the target button to the destination position, target and destion are the button names, where is 'before' or 'after'
+$this->crud->moveButton($target, $where, $destination);
+```
+
+
+### Overwriting a Default Button
+
+Before showing any buttons, Backpack will check your ```resources\views\vendor\backpack\crud\buttons``` directory, to see if you've overwritten any default buttons. If it finds a blade file with the same name there as the default buttons, it will use your blade file, instead of the default.
+
+That means **you can overwrite an existing button simply by creating a blade file with the same name inside this directory**.
+
+
+### Creating a Custom Button
+
+To create a custom button:
+- run `php artisan backpack:button new-button-name` to create a new blade file in `resources\views\vendor\backpack\crud\buttons`
+- add that button using the ```addButton()``` syntax above, in the EntityCrudControllers you want, inside the ```setupListOperation()``` method;
+
+In this blade file, you can use:
+- ```$entry``` - the database entry you're showing (only inside the ```line``` stack);
+- ```$crud``` - the entire CrudPanel object;
+- ```$button``` - the button you're currently showing;
+
+Note: If you've opted to add a button from a model function (not a blade file), inside your model function you can use `$this` to get the current entry (so for example, you can do `$this->id`.
+
+
+## Examples
+
+
+### Adding a Custom Button with a Blade File
+
+Let's say we want to create a simple ```moderate.blade.php``` button. This button would just open a ```user/{id}/moderate/``` route, which would point to ```UserCrudController::moderate()```. The steps would be:
+
+- Create the ```resources\views\vendor\backpack\crud\buttons\moderate.blade.php``` file:
+```php
+@if ($crud->hasAccess('update'))
+ Moderate
+@endif
+```
+- Add the new route, next to ```UserCrudController```'s route (most likely inside ```routes/backpack/custom.php```):
+```php
+Route::get('user/{id}/moderate', 'UserCrudController@moderate');
+```
+
+- We can now add a ```moderate()``` method to our ```UserCrudController```, which would moderate the user, and redirect back.
+```php
+public function moderate()
+{
+ // show a form that does something
+}
+```
+
+- Now we can actually add this button to any of ```UserCrudController::setupListOperation()```:
+```php
+$this->crud->addButtonFromView('line', 'moderate', 'moderate', 'beginning');
+```
+
+
+### Adding a Custom Button without a Blade File
+
+Instead of creating a blade file for your button, you can use a function on your model to output the button's HTML.
+
+In your ```ArticleCrudController::setupListOperation()```:
+```php
+// add a button whose HTML is returned by a method in the CRUD model
+$this->crud->addButtonFromModelFunction('line', 'open_google', 'openGoogle', 'beginning');
+```
+
+In your ```Article``` model:
+
+```php
+public function openGoogle($crud = false)
+{
+ return ' Google it';
+}
+```
+
+
+
+### Adding a Custom Button with JavaScript to the "top" stack
+
+Let's say we want to create an ```import.blade.php``` button. For simplicity, this button would just run an AJAX call which handles everything, and shows a status report to the user through notification bubbles.
+
+The "top" buttons are not bound to any certain entry, like buttons from the "list" stack. They can only do general things. And if they do general things, it's _generally_ recommended that you move their JavaScript to the bottom of the page. You can easily do that with ```@push('after_scripts')```, because the Backpack default layout has an ```after_scripts``` stack. This way, you can make sure your JavaScript is moved at the bottom of the page, after all other JavaScript has been loaded (jQuery, DataTables, etc). Check out the example below.
+
+The steps would be:
+
+- Create the ```resources\views\vendor\backpack\crud\buttons\import.blade.php``` file:
+
+```php
+@if ($crud->hasAccess('create'))
+
+ Import {{ $crud->entity_name }}
+
+@endif
+
+@push('after_scripts')
+
+@endpush
+```
+- Add the new route, next to ```UserCrudController```'s route (most likely inside ```routes/backpack/custom.php```):
+```php
+Route::get('user/import', 'UserCrudController@import');
+```
+
+- We can now add a ```import()``` method to our ```UserCrudController```, which would import the users.
+```php
+public function import()
+{
+ // whatever you decide to do
+}
+```
+
+- Now we can actually add this button to any of ```UserCrudController::setupListOperation()```:
+```php
+$this->crud->addButtonFromView('top', 'import', 'import', 'end');
+```
+
+### Reorder buttons
+
+The default order of line stack buttons is 'edit', 'delete'. Let's say you are using the `ShowOperation`, by default the preview button gets placed in the beggining of that stack, if you want to move it to the end of the stack you may use `orderButtons` or `moveButton`.
+
+```php
+CRUD::orderButtons('line', ['update', 'delete', 'show']);
+```
+
+```php
+CRUD::moveButton('show', 'after', 'delete');
+```
diff --git a/5.x/crud-cheat-sheet.md b/5.x/crud-cheat-sheet.md
new file mode 100644
index 00000000..8ce3d0bd
--- /dev/null
+++ b/5.x/crud-cheat-sheet.md
@@ -0,0 +1,344 @@
+# CRUD API Cheat Sheet
+
+---
+
+Here are all the functions you will be using **inside your EntityCrudController's ```setup()``` method**, grouped by the operation you will most likely use them for.
+
+## Operations
+
+
+### ListEntries
+
+
+#### Columns
+
+Methods: addColumn(), addColumns(), modifyColumn(), removeColumn(), removeColumns(), setColumnDetails(), setColumnsDetails(), setColumns(), beforeColumn(), afterColumn(), makeFirstColumn()
+
+```php
+// Manipulate what columns are shown in the table view.
+$this->crud->addColumn($column_definition_array); // add a column, at the end of the stack
+$this->crud->addColumns([$column_definition_array, $another_column_definition_array]); // add multiple columns, at the end of the stack
+$this->crud->modifyColumn($name, $modifs_array);
+$this->crud->removeColumn('column_name'); // remove a column from the stack
+$this->crud->removeColumns(['column_name_1', 'column_name_2']); // remove an array of columns from the stack
+$this->crud->setColumnDetails('column_name', ['attribute' => 'value']);
+$this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
+
+$this->crud->setColumns(); // set the columns you want in the table view, either as array of column names, or multidimensional array with all columns detailed with their types
+
+// ------ REORDER COLUMNS
+$this->crud->addColumn()->beforeColumn('name'); // will show this before the given column
+$this->crud->addColumn()->afterColumn('name'); // will show this after the given column
+
+$this->crud->addColumn()->makeFirstColumn();
+ // will make this column the first one in the list
+ // you need to also specify priority 1 in your addColumn statement for details_row or responsive expand buttons to show
+```
+
+
+#### Buttons
+
+Methods: buttons(), addButton(), addButtonFromModelFunction(), addButtonFromView(), removeButton(), removeButtonFromStack(), removeButtons(), removeAllButtons(), removeAllButtonsFromStack(), modifyButton(), moveButton()
+
+```php
+// possible stacks: 'top', 'line', 'bottom';
+// possible positions: 'beginning' and 'end'; defaults to 'beginning' for the 'line' stack, 'end' for the others;
+$this->crud->buttons(); // collection of all buttons
+$this->crud->addButton($stack, $name, $type, $content, $position); // possible types are: 'view', 'model_function'
+$this->crud->addButtonFromModelFunction($stack, $name, $model_function_name, $position); // add a button whose HTML is returned by a method in the CRUD model
+$this->crud->addButtonFromView($stack, $name, $view, $position); // add a button whose HTML is in a view placed at resources\views\vendor\backpack\crud\buttons
+$this->crud->removeButton($name);
+$this->crud->removeButtonFromStack($name, $stack);
+$this->crud->removeButtons($names, $stack);
+$this->crud->removeAllButtons();
+$this->crud->removeAllButtonsFromStack($stack);
+$this->crud->orderButtons($stack, $order); // order is an array with button names in the new order
+$this->crud->modifyButton($name, $modifications); // modifications are the attributes and their new values
+$this->crud->moveButton($target, $where, $destination); // move the target button to the destination position, target and destion are the button names, where is 'before' or 'after'
+```
+
+
+#### Filters
+
+Methods: addFilter(), modifyFilter(), removeFilter(), removeAllFilters(), filters()
+
+```php
+// Manipulate what filters are shown in the table view.
+//
+// Note: check out CRUD > Features > Filters in the docs to see examples of $filter_definition_array
+$this->crud->addFilter($filter_definition_array, $values, $filter_logic);
+$this->crud->modifyFilter($name, $modifs_array);
+$this->crud->removeFilter($name);
+$this->crud->removeAllFilters();
+$this->crud->filters(); // gets all the filters
+```
+
+
+#### Details Row
+
+Methods: enableDetailsRow(), disableDetailsRow()
+
+```php
+// Shows a + sign next to each table row, so that the user can expand that row and reveal details. You are responsible for creating the view with those details.
+$this->crud->enableDetailsRow();
+// NOTE: you also need to do allow access to the right users: $this->crud->allowAccess('details_row');
+// NOTE: you also need to do overwrite the showDetailsRow($id) method in your EntityCrudController to show whatever you'd like in the details row OR overwrite the views/backpack/crud/details_row.blade.php
+
+$this->crud->disableDetailsRow();
+```
+
+
+#### Export Buttons
+
+Methods: enableExportButtons()
+
+```php
+// Show export to PDF, CSV, XLS and Print buttons on the table view. Please note it will only export the current _page_ of results. So in order to export all entries the user needs to make the current page show "All" entries from the top-left picker.
+$this->crud->enableExportButtons();
+```
+
+
+#### Responsive Table
+
+Methods: enableResponsiveTable(), disableResponsiveTable()
+
+```php
+$this->crud->disableResponsiveTable();
+$this->crud->enableResponsiveTable();
+```
+
+
+#### Persistent Table
+
+Methods: enablePersistentTable(), disablePersistentTable()
+
+```php
+$this->crud->disablePersistentTable();
+$this->crud->enablePersistentTable();
+```
+
+
+#### Page Length
+
+Methods: setDefaultPageLength(), setPageLengthMenu()
+
+```php
+// you can define the default page length. If it does not exist we will add it to the pagination array.
+$this->crud->setDefaultPageLength(10);
+
+// you can configure the paginator shown to the user in various ways
+
+// values and labels, 1st array the values, 2nd array the labels:
+$this->crud->setPageLengthMenu([[100, 200, 300], ['one hundred', 'two hundred', 'three hundred']]);
+
+// values and labels in one array:
+$this->crud->setPageLengthMenu([100 => 'one hundred', 200 => 'two hundred', 300 => 'three hundred']);
+
+// only values, we will use the values as labels:
+$this->crud->setPageLengthMenu([100, 200, 300]); // OR
+$this->crud->setPageLengthMenu([[100, 200, 300]]);
+
+// only one option available:
+$this->crud->setPageLengthMenu(10);
+```
+
+NOTE: Do not use 0 as a key, if you want to represent "ALL" use -1 instead.
+
+
+#### Actions Column
+
+Methods: setActionsColumnPriority()
+
+```php
+// make the actions column (in the table view) hide when not enough space is available, by giving it an unreasonable priority
+$this->crud->setActionsColumnPriority(10000);
+```
+
+
+#### Custom / Advanced Queries
+
+Methods: addClause(), groupBy(), limit(), orderBy()
+
+```php
+// Change what entries are shown in the table view.
+// This changes all queries on the table view,
+// as opposed to filters, who only change it when that filter is applied.
+$this->crud->addClause('active'); // apply local scope
+$this->crud->addClause('type', 'car'); // apply local dynamic scope
+$this->crud->addClause('where', 'name', '=', 'car');
+$this->crud->addClause('whereName', 'car');
+$this->crud->addClause('whereHas', 'posts', function($query) {
+ $query->activePosts();
+ });
+$this->crud->groupBy();
+$this->crud->limit();
+
+$this->crud->orderBy();
+// please note it's generally a good idea to use crud->orderBy() inside "if (!$this->crud->getRequest()->has('order')) {}"; that way, your custom order is applied ONLY IF the user hasn't forced another order (by clicking a column heading)
+```
+
+
+### Show
+
+Use the same Columns API as for the ListEntries operation, but inside your ```show()``` method.
+
+
+### Create & Update Operations
+
+Methods: addField(), addFields(), modifyField(), modifyFields(), removeField(), removeFields(), removeAllFields(), beforeField(), afterField()
+
+```php
+// ------
+// FIELDS
+// ------
+// Manipulate what fields are shown in the create / update forms.
+//
+// Note: check out CRUD > Features > Field Types in the docs to see examples of $field_definition_array
+
+$this->crud->addField($field_definition_array);
+$this->crud->addField('db_column_name'); // a lazy way to add fields: let the CRUD decide what field type it is and set it automatically, along with the field label
+$this->crud->addFields($array_of_fields_definition_arrays);
+$this->crud->modifyField($name, $modifs_array);
+$this->crud->removeField('name');
+$this->crud->removeFields($array_of_names);
+$this->crud->removeAllFields();
+
+// ------ REORDER FIELDS
+$this->crud->addField()->beforeField('name'); // will show this before the given field
+$this->crud->addField()->afterField('name'); // will show this after the given field
+```
+
+
+### Reorder
+
+Methods: enableReorder(), disableReorder(), isReorderEnabled()
+
+```php
+ protected function setupReorderOperation()
+ {
+ // model attribute to be shown on draggable items
+ $this->crud->set('reorder.label', 'name');
+ // maximum number of nesting allowed
+ $this->crud->set('reorder.max_level', 2);
+
+ // extras:
+ // $this->crud->disableReorder();
+ // $this->crud->isReorderEnabled();
+ }
+```
+
+
+### Revisions
+
+```php
+// -------------------------
+// REVISIONS aka Audit Trail
+// -------------------------
+// Tracks all changes to an entry and provides an interface to revert to a previous state.
+//
+// IMPORTANT: You also need to use \Venturecraft\Revisionable\RevisionableTrait;
+// Please check out: https://backpackforlaravel.com/docs/crud-operation-revisions
+$this->crud->allowAccess('revisions');
+```
+
+
+## All Operations
+
+Methods: allowAccess(), denyAccess(), hasAccess(), hasAccessOrFail(), hasAccessToAll(), hasAccessToAny(), setShowView(), setEditView(), setCreateView(), setListView(), setReorderView(), setRevisionsView, setRevisionsTimelineView(), setDetailsRowView(), getEntry(), getFields(), getColumns(), getCurrentEntry(), getTitle(), setTitle(), getHeading(), setHeading(), getSubheading(), setSubheading(),
+
+```php
+// ------
+// ACCESS
+// ------
+// Prevent or allow users from accessing different CRUD operations.
+
+$this->crud->allowAccess('list');
+$this->crud->allowAccess(['list', 'create', 'delete']);
+$this->crud->denyAccess('list');
+$this->crud->denyAccess(['list', 'create', 'delete']);
+
+$this->crud->hasAccess('add'); // returns true/false
+$this->crud->hasAccessOrFail('add'); // throws 403 error
+$this->crud->hasAccessToAll(['create', 'update']); // returns true/false
+$this->crud->hasAccessToAny(['create', 'update']); // returns true/false
+
+// -------------
+// EAGER LOADING
+// -------------
+
+// eager load a relationship
+$this->crud->with('relationship_name');
+
+// ------------
+// CUSTOM VIEWS
+// ------------
+
+// use a custom view for a CRUD operation
+$this->crud->setShowView('your-view');
+$this->crud->setEditView('your-view');
+$this->crud->setCreateView('your-view');
+$this->crud->setListView('your-view');
+$this->crud->setReorderView('your-view');
+$this->crud->setRevisionsView('your-view');
+$this->crud->setRevisionsTimelineView('your-view');
+$this->crud->setDetailsRowView('your-view');
+
+// -------------
+// CONTENT CLASS
+// -------------
+
+// use a custom CSS class for the content of a CRUD operation
+$this->crud->setShowContentClass('col-md-12');
+$this->crud->setEditContentClass('col-md-12');
+$this->crud->setCreateContentClass('col-md-12');
+$this->crud->setListContentClass('col-md-12');
+$this->crud->setReorderContentClass('col-md-12');
+$this->crud->setRevisionsContentClass('col-md-12');
+$this->crud->setRevisionsTimelineContentClass('col-md-12');
+
+// -------
+// GETTERS
+// -------
+
+$this->crud->getEntry($entry_id);
+$this->crud->getEntries();
+
+$this->crud->getFields('create/update/both');
+
+// in your update() method, after calling parent::updateCrud()
+$this->crud->getCurrentEntry();
+
+// -------
+// OPERATIONS
+// -------
+
+$this->crud->setOperation('list');
+$this->crud->getOperation();
+
+// -------
+// ACTIONS
+// -------
+
+$this->crud->getActionMethod(); // returns the method on the controller that was called by the route; ex: create(), update(), edit() etc;
+$this->crud->actionIs('create'); // checks if the controller method given is the one called by the route
+
+$this->crud->getTitle('create'); // get the Title for the create action
+$this->crud->getHeading('create'); // get the Heading for the create action
+$this->crud->getSubheading('create'); // get the Subheading for the create action
+
+$this->crud->setTitle('some string', 'create'); // set the Title for the create action
+$this->crud->setHeading('some string', 'create'); // set the Heading for the create action
+$this->crud->setSubheading('some string', 'create'); // set the Subheading for the create action
+
+// ---------------------------
+// CrudPanel Basic Information
+// ---------------------------
+$this->crud->setModel("App\Models\Example");
+$this->crud->setRoute("admin/example");
+// OR $this->crud->setRouteName("admin.example");
+$this->crud->setEntityNameStrings("example", "examples");
+
+// check the FormRequests used in that EntityCrudController for required fields, and add an asterisk to them in the create/edit form
+$this->crud->setRequiredFields(StoreRequest::class, 'create');
+$this->crud->setRequiredFields(UpdateRequest::class, 'edit');
+```
diff --git a/5.x/crud-columns.md b/5.x/crud-columns.md
new file mode 100644
index 00000000..0d72296b
--- /dev/null
+++ b/5.x/crud-columns.md
@@ -0,0 +1,1020 @@
+# Columns
+
+---
+
+
+## About
+
+A column shows the information of an Eloquent attribute, in a user-friendly format.
+
+It's used inside default operations to:
+- show a table cell in **ListEntries**;
+- show an attribute value in **Show**;
+
+A column consists of only one file - a blade file with the same name as the column type (ex: ```text.blade.php```). Backpack provides you with [default column types](#default-column-types) for the common use cases, but you can easily [change how a default field type works](#overwriting-default-column-types), or [create an entirely new field type](#creating-a-custom-column-type).
+
+
+### Mandatory Attributes
+
+When passing a column array, you need to specify at least these attributes:
+```php
+[
+ 'name' => 'options', // the db column name (attribute name)
+ 'label' => "Options", // the human-readable label for it
+ 'type' => 'text' // the kind of column to show
+],
+```
+
+
+### Optional Attributes
+
+- [```searchLogic```](#custom-search-logic)
+- [```orderLogic```](#custom-order-logic)
+- [```orderable```](#custom-order-logic)
+- [```wrapper```](#custom-wrapper-for-columns)
+- [```visibleInTable```](#choose-where-columns-are-visible)
+- [```visibleInModal```](#choose-where-columns-are-visible)
+- [```visibleInExport```](#choose-where-columns-are-visible)
+- [```visibleInShow```](#choose-where-columns-are-visible)
+- [```priority```](#define-which-columns-to-hide-in-responsive-table)
+- [```escaped```](#escape-column-output)
+
+
+### Columns API
+
+Inside your ```setupListOperation()``` or ```setupShowOperation()``` method, there are a few calls you can make to configure or manipulate columns:
+
+```php
+// add a column, at the end of the stack
+$this->crud->addColumn($column_definition_array);
+
+// add multiple columns, at the end of the stack
+$this->crud->addColumns([$column_definition_array, $another_column_definition_array]);
+
+// remove a column from the stack
+$this->crud->removeColumn('column_name');
+
+// remove an array of columns from the stack
+$this->crud->removeColumns(['column_name_1', 'column_name_2']);
+
+// change the attributes of a column
+$this->crud->modifyColumn($name, $modifs_array);
+$this->crud->setColumnDetails('column_name', ['attribute' => 'value']);
+
+// change the attributes of multiple columns
+$this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
+
+// forget what columns have been previously defined, only use these columns
+$this->crud->setColumns([$column_definition_array, $another_column_definition_array]);
+
+// -------------------
+// New in Backpack 4.1
+// -------------------
+// add a column with this name
+$this->crud->column('price');
+
+// change the type and prefix attributes on the 'price' column
+$this->crud->column('price')->type('number')->prefix('$');
+```
+
+In addition, to manipulate the order columns are shown in, you can:
+
+```php
+// add this column before a given column
+$this->crud->addColumn('text')->beforeColumn('name');
+
+// add this column after a given column
+$this->crud->addColumn()->afterColumn('name');
+
+// make this column the first one in the list
+$this->crud->addColumn()->makeFirstColumn();
+```
+
+
+## FREE Column Types
+
+
+### boolean
+
+Show Yes/No (or custom text) instead of 1/0.
+
+```php
+[
+ 'name' => 'name',
+ 'label' => 'Status',
+ 'type' => 'boolean',
+ // optionally override the Yes/No texts
+ // 'options' => [0 => 'Active', 1 => 'Inactive']
+],
+```
+
+
+
+
+### check
+
+Show a favicon with a checked or unchecked box, depending on the given boolean.
+```php
+[
+ 'name' => 'featured', // The db column name
+ 'label' => 'Featured', // Table column heading
+ 'type' => 'check'
+],
+```
+
+
+
+
+### checkbox
+
+Shows a checkbox (the form element), and inserts the js logic needed to select/deselect multiple entries. It is mostly used for [the Bulk Delete action](/docs/{{version}}/crud-operation-delete#delete-multiple-items-bulk-delete), and [custom bulk actions](/docs/{{version}}/crud-operations#creating-a-new-operation-with-a-bulk-action-no-interface).
+
+Shorthand:
+```php
+$this->crud->enableBulkActions();
+```
+(will also add an empty custom_html column)
+
+Verbose:
+```php
+$this->crud->addColumn([
+ 'type' => 'checkbox',
+ 'name' => 'bulk_actions',
+ 'label' => ' ',
+ 'priority' => 1,
+ 'searchLogic' => false,
+ 'orderable' => false,
+ 'visibleInModal' => false,
+])->makeFirstColumn();
+```
+
+
+
+
+### closure
+
+Show custom HTML based on a closure you specify in your EntityCrudController.
+
+```php
+[
+ 'name' => 'created_at',
+ 'label' => 'Created At',
+ 'type' => 'closure',
+ 'function' => function($entry) {
+ return 'Created on '.$entry->created_at;
+ }
+],
+```
+
+> **DEPRECATED**: closure column will be removed in a future version of Backpack, since the same thing can now be achieved using any column (including the `text` column) and the `value` attribute - just pass the same closure to the `value` attribute of any column type.
+
+
+
+
+### custom_html
+
+Show the HTML that you provide in the page. You can optionally escape the text when displaying it on page, if you don't trust the value.
+
+```php
+[
+ 'name' => 'my_custom_html',
+ 'label' => 'Custom HTML',
+ 'type' => 'custom_html',
+ 'value' => 'Something',
+
+ // OPTIONALS
+ // 'escaped' => true // echo using {{ }} instead of {!! !!}
+],
+```
+
+> IMPORTANT As opposed to most other Backpack columns, the output of `custom_html` is **NOT escaped by default**. That means if the database value contains malicious JS, that JS might be run when the admin previews it. Make sure to purify the value of this column in an accessor on your Model. At a minimum, you can use `strip_tags()` (here's [an example](https://github.com/Laravel-Backpack/demo/commit/509c0bf0d8b9ee6a52c50f0d2caed65f1f986385)), but a lot better would be to use an [HTML Purifier package](https://github.com/mewebstudio/Purifier) (do that [manually](https://github.com/Laravel-Backpack/demo/commit/7342cffb418bb568b9e4ee279859685ddc0456c1) or by casting the attribute to `CleanHtmlOutput::class`).
+
+
+
+
+### date
+
+
+The date column will show a localized date in the default date format (as specified in the ```config/backpack/base.php``` file), whether the attribute is cast as date in the model or not.
+
+Note that the ```format``` attribute uses ISO date formatting parameters and not PHP ```date()``` formatters. See for more information.
+
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => 'Tag Name', // Table column heading
+ 'type' => 'date',
+ // 'format' => 'l j F Y', // use something else than the base.default_date_format config value
+],
+```
+
+
+
+
+### datetime
+
+
+The date column will show a localized datetime in the default datetime format (as specified in the ```config/backpack/base.php``` file), whether the attribute is cast as datetime in the model or not.
+
+Note that the ```format``` attribute uses ISO date formatting parameters and not PHP ```date()``` formatters. See for more information.
+
+
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => 'Tag Name', // Table column heading
+ 'type' => 'datetime',
+ // 'format' => 'l j F Y H:i:s', // use something else than the base.default_datetime_format config value
+],
+```
+
+
+
+
+### email
+
+The email column will output the email address in the database (truncated to 254 characters if needed), with a ```mailto:``` link towards the full email. Its definition is:
+```php
+[
+ 'name' => 'email', // The db column name
+ 'label' => 'Email Address', // Table column heading
+ 'type' => 'email',
+ // 'limit' => 500, // if you want to truncate the text to a different number of characters
+],
+```
+
+
+
+
+### enum
+
+The enum column will output the value of your database ENUM column or your PHP enum attribute.
+```php
+[
+ 'name' => 'status',
+ 'label' => 'Status',
+ 'type' => 'enum',
+],
+```
+
+By default, in case it's a `BackedEnum` it will show the `value` of the enum (when casted), in `database` or `UnitEnum` it will show the the enum value without parsing the value.
+
+If you want to output something different than what your enum stores you have two options:
+- For `database enums` you need to provide the `options` that translates the enums you store in database.
+- For PHP enums you can provide the same `options` or provide a `enum_function` from the enum to gather the final result.
+
+```php
+// for database enums
+[
+ 'name' => 'status',
+ 'label' => 'Status',
+ 'type' => 'enum',
+ 'options' => [
+ 'DRAFT' => 'Is draft',
+ 'PUBLISHED' => 'Is published'
+ ]
+],
+
+// for PHP enums, given the following enum example
+
+enum StatusEnum
+{
+ case DRAFT;
+ case PUBLISHED;
+
+ public function readableText(): string
+ {
+ return match ($this) {
+ StatusEnum::DRAFT => 'Is draft',
+ StatusEnum::PUBLISHED => 'Is published',
+ };
+ }
+}
+
+[
+ 'name' => 'status',
+ 'label' => 'Status',
+ 'type' => 'enum',
+ 'enum_function' => 'readableText',
+ 'enum_class' => 'App\Enums\StatusEnum'
+],
+```
+
+
+
+
+### image
+
+
+Show a thumbnail image.
+
+```php
+[
+ 'name' => 'profile_image', // The db column name
+ 'label' => 'Profile image', // Table column heading
+ 'type' => 'image',
+ // 'prefix' => 'folder/subfolder/',
+ // image from a different disk (like s3 bucket)
+ // 'disk' => 'disk-name',
+ // optional width/height if 25px is not ok with you
+ // 'height' => '30px',
+ // 'width' => '30px',
+],
+```
+
+
+
+
+### json
+
+
+Display database stored JSON in a prettier way to your users.
+
+```php
+[
+ 'name' => 'my_json_column_name',
+ 'label' => 'JSON',
+ 'type' => 'json',
+ // 'escaped' => false, // echo using {!! !!} instead of {{ }}, in order to render HTML
+],
+```
+
+
+
+
+### model_function
+
+
+The model_function column will output a function on your main model. Its definition is:
+```php
+[
+ // run a function on the CRUD model and show its return value
+ 'name' => 'url',
+ 'label' => 'URL', // Table column heading
+ 'type' => 'model_function',
+ 'function_name' => 'getSlugWithLink', // the method in your Model
+ // 'function_parameters' => [$one, $two], // pass one/more parameters to that method
+ // 'limit' => 100, // Limit the number of characters shown
+ // 'escaped' => false, // echo using {!! !!} instead of {{ }}, in order to render HTML
+],
+```
+For this example, if your model would feature this method, it would return the link to that entity:
+```php
+public function getSlugWithLink() {
+ return ''.$this->slug.'';
+}
+```
+
+
+
+
+### model_function_attribute
+
+
+If the function you're trying to use returns an object, not a string, you can use the model_function_attribute column, which will output the attribute on the function result. Its definition is:
+```php
+[
+ 'name' => 'url',
+ 'label' => 'URL', // Table column heading
+ 'type' => 'model_function_attribute',
+ 'function_name' => 'getSlugWithLink', // the method in your Model
+ // 'function_parameters' => [$one, $two], // pass one/more parameters to that method
+ 'attribute' => 'route',
+ // 'limit' => 100, // Limit the number of characters shown
+ // 'escaped' => false, // echo using {!! !!} instead of {{ }}, in order to render HTML
+],
+```
+
+
+
+
+### multidimensional_array
+
+
+Enumerate the values in a multidimensional array, stored in the db as JSON.
+
+```php
+[
+ 'name' => 'options', // The db column name
+ 'label' => 'Options', // Table column heading
+ 'type' => 'multidimensional_array',
+ 'visible_key' => 'name' // The key to the attribute you would like shown in the enumeration
+],
+```
+
+
+
+
+### number
+
+
+The text column will just output the number value of a db column (or model attribute). Its definition is:
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => 'Tag Name', // Table column heading
+ 'type' => 'number',
+ // 'prefix' => '$',
+ // 'suffix' => ' EUR',
+ // 'decimals' => 2,
+ // 'dec_point' => ',',
+ // 'thousands_sep' => '.',
+ // decimals, dec_point and thousands_sep are used to format the number;
+ // for details on how they work check out PHP's number_format() method, they're passed directly to it;
+ // https://www.php.net/manual/en/function.number-format.php
+],
+```
+
+
+
+
+### phone
+
+The phone column will output the phone number from the database (truncated to 254 characters if needed), with a ```tel:``` link so that users on mobile can click them to call (or with Skype or similar browser extensions). Its definition is:
+```php
+[
+ 'name' => 'phone', // The db column name
+ 'label' => 'Phone number', // Table column heading
+ 'type' => 'phone',
+ // 'limit' => 10, // if you want to truncate the phone number to a different number of characters
+],
+```
+
+
+
+
+### radio
+
+
+Show a pretty text instead of the database value, according to an associative array. Usually used as a column for the "radio" field type.
+
+```php
+[
+ 'name' => 'status',
+ 'label' => 'Status',
+ 'type' => 'radio',
+ 'options' => [
+ 0 => 'Draft',
+ 1 => 'Published'
+ ]
+],
+```
+
+This example will show:
+- "Draft" when the value stored in the db is 0;
+- "Published" when the value stored in the db is 1;
+
+
+
+
+### relationship_count
+
+Shows the number of items that are related to the current entry, for a particular relationship.
+
+```php
+[
+ // relationship count
+ 'name' => 'tags', // name of relationship method in the model
+ 'type' => 'relationship_count',
+ 'label' => 'Tags', // Table column heading
+ // OPTIONAL
+ // 'suffix' => ' tags', // to show "123 tags" instead of "123 items"
+
+ // if you need that column to be orderable in table, you need to manually provide the orderLogic
+ // 'orderable' => true,
+ // 'orderLogic' => function ($query, $column, $columnDirection) {
+ $query->orderBy('tags_count', $columnDirection);
+ },
+],
+```
+
+**Important Note:** This column will load ALL related items onto the page. Which is not a problem normally, for small tables. But if your related table has thousands or millions of entries, it will considerably slow down the page. For a much more performant option, with the same result, you can add a fake column to the results using Laravel's `withCount()` method, then use the `text` column to show that number. That will be a lot faster, and the end-result is identical from the user's perspective. For the same example above (number of tags) this is how it will look:
+```
+$this->crud->query->withCount('tags'); // this will add a tags_count column to the results
+$this->crud->addColumn([
+ 'name' => 'tags_count', // name of relationship method in the model
+ 'type' => 'text',
+ 'label' => 'Tags', // Table column heading
+ 'suffix' => ' tags', // to show "123 tags" instead of "123"
+]);
+```
+
+
+
+
+### row_number
+
+
+Show the row number (index). The number depends strictly on the result set (x records per page, pagination, search, filters, etc). It does not get any information from the database. It is not searchable. It is only useful to show the current row number.
+
+```php
+$this->crud->addColumn([
+ 'name' => 'row_number',
+ 'type' => 'row_number',
+ 'label' => '#',
+ 'orderable' => false,
+])->makeFirstColumn();
+```
+
+Notes:
+- you can have a different ```name```; just make sure your model doesn't have that attribute;
+- you can have a different label;
+- you can place the column as second / third / etc if you remove ```makeFirstColumn()```;
+- this column type allows the use of suffix/prefix just like the text column type;
+- if upon placement you notice it always shows ```false``` then please note there have been changes in the ```search()``` method - you need to add another parameter to your ```getEntriesAsJsonForDatatables()``` call;
+
+
+
+
+### select
+
+The select column will output its connected entity. Used for relationships like hasOne() and belongsTo(). Its name and definition is the same as for the select *field type*:
+```php
+[
+ // 1-n relationship
+ 'label' => 'Parent', // Table column heading
+ 'type' => 'select',
+ 'name' => 'parent_id', // the column that contains the ID of that connected entity;
+ 'entity' => 'parent', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'model' => "App\Models\Category", // foreign key model
+],
+```
+
+
+
+### select_from_array
+
+Show a particular text depending on the value of the attribute.
+
+```php
+[
+ // select_from_array
+ 'name' => 'status',
+ 'label' => 'Status',
+ 'type' => 'select_from_array',
+ 'options' => ['draft' => 'Draft (invisible)', 'published' => 'Published (visible)'],
+],
+```
+
+
+
+
+### select_multiple
+
+The select_multiple column will output a comma separated list of its connected entities. Used for relationships like hasMany() and belongsToMany(). Its name and definition is the same as the select_multiple field:
+```php
+[
+ // n-n relationship (with pivot table)
+ 'label' => 'Tags', // Table column heading
+ 'type' => 'select_multiple',
+ 'name' => 'tags', // the method that defines the relationship in your Model
+ 'entity' => 'tags', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'model' => 'App\Models\Tag', // foreign key model
+],
+```
+
+
+
+
+### text
+
+The text column will just output the text value of a db column (or model attribute). Its definition is:
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => 'Tag Name', // Table column heading
+ // 'prefix' => 'Name: ',
+ // 'suffix' => '(user)',
+ // 'limit' => 120, // character limit; default is 50,
+],
+```
+
+**Advanced use case:** The ```text``` column type can also show the attribute of a 1-1 relationship. If you have a relationship (like ```parent()```) set up in your Model, you can use relationship and attribute in the ```name```, using dot notation:
+```php
+[
+ 'name' => 'parent.title',
+ 'label' => 'Title',
+ 'type' => 'text'
+],
+```
+
+
+
+
+### textarea
+The text column will just output the text value of a db column (or model attribute) in a textarea field. Its definition is:
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => 'Tag Name', // Table column heading
+ // 'prefix' => 'Name: ',
+ // 'suffix' => '(user)',
+ // 'limit' => 120, // character limit; default is 50
+ // 'escaped' => false, // echo using {!! !!} instead of {{ }}, in order to render HTML
+],
+```
+
+
+### upload_multiple
+
+
+The ```table``` column will output a list of files and links, when used on an attribute that stores a JSON array of file paths. It is meant to be used inside the show functionality (not list, though it also works there), to preview files uploaded with the ```upload_multiple``` field type.
+
+Its definition is very similar to the [upload_multiple *field type*](/docs/{{version}}/crud-fields#upload_multiple).
+
+```php
+[
+ 'name' => 'photos',
+ 'label' => 'Photos',
+ 'type' => 'upload_multiple',
+ // 'disk' => 'public', // filesystem disk if you're using S3 or something custom
+],
+```
+
+
+
+
+### view
+
+Display any custom column type you want. Usually used by Backpack package developers, to use views from within their packages, instead of having to publish the views.
+
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => 'Tag Name', // Table column heading
+ 'type' => 'view',
+ 'view' => 'package::columns.column_type_name', // or path to blade file
+],
+```
+
+
+
+
+
+## PRO Column Types
+
+
+### array PRO
+
+Enumerate an array stored in the db column as JSON.
+```php
+[
+ 'name' => 'options', // The db column name
+ 'label' => 'Options', // Table column heading
+ 'type' => 'array'
+],
+```
+
+
+
+
+### array_count PRO
+
+Count the items in an array stored in the db column as JSON.
+
+```php
+[
+ 'name' => 'options', // The db column name
+ 'label' => 'Options', // Table column heading
+ 'type' => 'array_count',
+ // 'suffix' => 'options', // if you want it to show "2 options" instead of "2 items"
+],
+```
+
+
+
+
+### markdown PRO
+
+
+Convert a markdown string to HTML, using ```Illuminate\Mail\Markdown```. Since Markdown is usually used for long texts, this column is most helpful in the "Show" operation - not so much in the "ListEntries" operation, where only short snippets make sense.
+
+```php
+[
+ 'name' => 'text', // The db column name
+ 'label' => 'Text', // Table column heading
+ 'type' => 'markdown',
+],
+```
+
+> IMPORTANT As opposed to most other Backpack columns, the output of `markdown` is **NOT escaped by default**. That means if the database value contains malicious JS, that JS might be run when the admin previews it. Make sure to purify the value of this column in an accessor on your Model. At a minimum, you can use `strip_tags()` (here's [an example](https://github.com/Laravel-Backpack/demo/commit/509c0bf0d8b9ee6a52c50f0d2caed65f1f986385)), but a lot better would be to use an [HTML Purifier package](https://github.com/mewebstudio/Purifier) (do that [manually](https://github.com/Laravel-Backpack/demo/commit/7342cffb418bb568b9e4ee279859685ddc0456c1) or by casting the attribute to `CleanHtmlOutput::class`).
+
+
+
+
+### relationship PRO
+
+Output the related entries, no matter the relationship:
+- 1-n relationships - outputs the name of its one connected entity;
+- n-n relationships - enumerates the names of all its connected entities;
+
+Its name and definition is the same as for the relationship *field type*:
+```php
+[
+ // any type of relationship
+ 'name' => 'tags', // name of relationship method in the model
+ 'type' => 'relationship',
+ 'label' => 'Tags', // Table column heading
+ // OPTIONAL
+ // 'entity' => 'tags', // the method that defines the relationship in your Model
+ // 'attribute' => 'name', // foreign key attribute that is shown to user
+ // 'model' => App\Models\Category::class, // foreign key model
+],
+```
+
+Backpack tries to guess which attribute to show for the related item. Something that the end-user will recognize as unique. If it's something common like "name" or "title" it will guess it. If not, you can manually specify the ```attribute``` inside the column definition, or you can add ```public $identifiableAttribute = 'column_name';``` to your model, and Backpack will use that column as the one the user finds identifiable. It will use it here, and it will use it everywhere you haven't explicitly asked for a different attribute.
+
+
+
+
+### table PRO
+
+
+The ```table``` column will output a condensed table, when used on an attribute that stores a JSON array or object. It is meant to be used inside the show functionality (not list, though it also works there).
+
+Its definition is very similar to the [table *field type*](/docs/{{version}}/crud-fields#table).
+
+```php
+[
+ 'name' => 'features',
+ 'label' => 'Features',
+ 'type' => 'table',
+ 'columns' => [
+ 'name' => 'Name',
+ 'description' => 'Description',
+ 'price' => 'Price',
+ 'obs' => 'Observations'
+ ]
+],
+```
+
+
+
+
+### video PRO
+
+
+Display a small screenshot for a YouTube or Vimeo video, stored in the database as JSON using the "video" field type.
+
+```php
+[
+ 'name' => 'name', // The db column name
+ 'label' => 'Tag Name', // Table column heading
+ 'type' => 'video',
+],
+```
+
+
+
+
+## Overwriting Default Column Types
+
+You can overwrite a column type by placing a file with the same name in your ```resources\views\vendor\backpack\crud\columns``` directory. When a file is there, Backpack will pick that one up, instead of the one in the package. You can do that from command line using ```php artisan backpack:column --from=column-file-name```
+
+Examples:
+- creating a ```resources\views\vendor\backpack\crud\columns\number.blade.php``` file would overwrite the ```number``` column functionality;
+- ```php artisan backpack:column --from=text``` will take the view from the package and copy it to the directory above, so you can edit it;
+
+>Keep in mind that when you're overwriting a default column type, you're forfeiting any future updates for that column. We can't push updates to a file that you're no longer using.
+
+
+
+
+## Creating a Custom Column Type
+
+Columns consist of only one file - a blade file with the same name as the column type (ex: ```text.blade.php```). You can create one by placing a new blade file inside ```resources\views\vendor\backpack\crud\columns```. Be careful to choose a distinctive name, otherwise you might be overwriting a default column type (see above).
+
+For example, you can create a ```markdown.blade.php```:
+```php
+{!! \Markdown::convertToHtml($entry->{$column['name']}) !!}
+```
+
+The most useful variables you'll have in this file here are:
+- ```$entry``` - the database entry you're showing (Eloquent object);
+- ```$crud``` - the entire CrudPanel object, with settings, options and variables;
+
+By default, custom columns are not searchable. In order to make your column searchable you need to [specify a custom ```searchLogic``` in your declaration](#custom-search-logic).
+
+
+
+
+
+## Advanced Columns Use
+
+
+### Custom Search Logic for Columns
+
+If your column points to something atypical (not a value that is stored as plain text in the database column, maybe a model function, or a JSON, or something else), you might find that the search doesn't work for that column. You can choose which columns are searchable, and what those columns actually search, by using the column's ```searchLogic``` attribute:
+
+```php
+// column with custom search logic
+$this->crud->addColumn([
+ 'name' => 'slug_or_title',
+ 'label' => 'Title',
+ 'searchLogic' => function ($query, $column, $searchTerm) {
+ $query->orWhere('title', 'like', '%'.$searchTerm.'%');
+ }
+]);
+
+
+// 1-n relationship column with custom search logic
+$this->crud->addColumn([
+ 'label' => 'Cruise Ship',
+ 'type' => 'select',
+ 'name' => 'cruise_ship_id',
+ 'entity' => 'cruise_ship',
+ 'attribute' => 'cruise_ship_name_date', // combined name & date column
+ 'model' => 'App\Models\CruiseShip',
+ 'searchLogic' => function ($query, $column, $searchTerm) {
+ $query->orWhereHas('cruise_ship', function ($q) use ($column, $searchTerm) {
+ $q->where('name', 'like', '%'.$searchTerm.'%')
+ ->orWhereDate('depart_at', '=', date($searchTerm));
+ });
+ }
+]);
+
+
+// column that doesn't need to be searchable
+$this->crud->addColumn([
+ 'name' => 'slug_or_title',
+ 'label' => 'Title',
+ 'searchLogic' => false
+]);
+
+// column whose search logic should behave like it were a 'text' column type
+$this->crud->addColumn([
+ 'name' => 'slug_or_title',
+ 'label' => 'Title',
+ 'searchLogic' => 'text'
+]);
+```
+
+
+### Custom Order Logic for Columns
+
+If your column points to something atypical (not a value that is stored as plain text in the database column, maybe a model function, or a JSON, or something else), you might find that the ordering doesn't work for that column. You can choose which columns are orderable, and how those columns actually get ordered, by using the column's ```orderLogic``` attribute.
+
+For example, to order Articles not by its Category ID (as default, but by the Category Name), you can do:
+
+```php
+$this->crud->addColumn([
+ // Select
+ 'label' => 'Category',
+ 'type' => 'select',
+ 'name' => 'category_id', // the db column for the foreign key
+ 'entity' => 'category', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'orderable' => true,
+ 'orderLogic' => function ($query, $column, $columnDirection) {
+ return $query->leftJoin('categories', 'categories.id', '=', 'articles.select')
+ ->orderBy('categories.name', $columnDirection)->select('articles.*');
+ }
+]);
+```
+
+
+
+### Wrap Column Text in an HTML Element
+
+Sometimes the text that the column echoes is not enough. You want to add interactivity to it, by adding a link to that column. Or you want to show the value in a green/yellow/red badge so it stands out. You can do both of that - with the ```wrapper``` attribute, which most columns support.
+
+For example, you can wrap the text in an anchor element, to point to that Article's Show operation:
+
+```php
+$this->crud->addColumn([
+ // Select
+ 'label' => 'Category',
+ 'type' => 'select',
+ 'name' => 'category_id', // the db column for the foreign key
+ 'entity' => 'category', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'wrapper' => [
+ // 'element' => 'a', // the element will default to "a" so you can skip it here
+ 'href' => function ($crud, $column, $entry, $related_key) {
+ return backpack_url('http://github.com/article/'.$related_key.'/show');
+ },
+ // 'target' => '_blank',
+ // 'class' => 'some-class',
+ ],
+]);
+```
+
+If you specify ```wrapper``` to a column, the entries in that column will be wrapped in the element you specify. Note that:
+- To get an HTML anchor (a link), you can specify ```a``` for the element (but that's also the default); to get a paragraph you'd specify ```p``` for the element; to get an inline element you'd specify ```span``` for the element; etc;
+- Anything you declare in the ```wrapper``` array (other than ```element```) will be used as HTML attributes for that element (ex: ```class```, ```style```, ```target``` etc);
+- Each wrapper attribute, including the element itself, can be declared as a string OR as a callback;
+
+Let's take another example, and wrap a boolean column into a green/red span:
+
+```php
+$this->crud->addColumn([
+ 'name' => 'published',
+ 'label' => 'Published',
+ 'type' => 'boolean',
+ 'options' => [0 => 'No', 1 => 'Yes'], // optional
+ 'wrapper' => [
+ 'element' => 'span',
+ 'class' => function ($crud, $column, $entry, $related_key) {
+ if ($column['text'] == 'Yes') {
+ return 'badge badge-success';
+ }
+
+ return 'badge badge-default';
+ },
+ ],
+]);
+```
+
+
+
+### Choose Where Columns are Visible
+
+Starting with Backpack\CRUD 3.5.0, you can choose to show/hide columns in different contexts. You can pass ```true``` / ```false``` to the column attributes below, and Backpack will know to show the column or not, in different contexts:
+
+```php
+$this->crud->addColumn([
+ 'name' => 'description',
+ 'visibleInTable' => false, // no point, since it's a large text
+ 'visibleInModal' => false, // would make the modal too big
+ 'visibleInExport' => false, // not important enough
+ 'visibleInShow' => true, // boolean or closure - function($entry) { return $entry->isAdmin(); }
+]);
+```
+
+This also allows you to do tricky things like:
+- add a column that's hidden from the table view, but WILL get exported;
+- adding a column that's hidden everywhere, but searchable (even with a custom ```searchLogic```);
+
+
+### Multiple Columns With the Same Name
+
+Starting with Backpack\CRUD 3.3 (Nov 2017), you can have multiple columns with the same name, by specifying a unique ```key``` property. So if you want to use the same column name twice, you can do that. Notice below we have the same name for both columns, but one of them has a ```key```. This additional key will be used as an array key, if provided.
+
+```php
+// column that shows the parent's first name
+$this->crud->addColumn([
+ 'label' => 'Parent First Name', // Table column heading
+ 'type' => 'select',
+ 'name' => 'parent_id', // the column that contains the ID of that connected entity;
+ 'entity' => 'parent', // the method that defines the relationship in your Model
+ 'attribute' => 'first_name', // foreign key attribute that is shown to user
+ 'model' => 'App\Models\User', // foreign key model
+]);
+
+// column that shows the parent's last name
+$this->crud->addColumn([
+ 'label' => 'Parent Last Name', // Table column heading
+ 'type' => 'select',
+ 'name' => 'parent_id', // the column that contains the ID of that connected entity;
+ 'key' => 'parent_last_name', // the column that contains the ID of that connected entity;
+ 'entity' => 'parent', // the method that defines the relationship in your Model
+ 'attribute' => 'last_name', // foreign key attribute that is shown to user
+ 'model' => 'App\Models\User', // foreign key model
+]);
+```
+
+
+### Escape column output
+
+For security purposes, Backpack escapes the output of all column types except for `markdown` and `custom_html` (those columns would be useless escaped). That means it uses `{{ }}` to echo the output, not `{!! !!}`. If you have any HTML inside a db column, it will be shown as HTML instead of interpreted. It does that because, if the value was added by a malicious user (not admin), it could contain malicious JS code.
+
+However, if you trust that a certain column contains _safe_ HTML, you can disable this behaviour by setting the `escaped` attribute to `false`.
+
+Our recommendation, in order to trust the output of a column, is to either:
+- (a) only allow the admin to add/edit that column;
+- (b) purify the value in an accessor on the Model, so that every time you get it, it's cleaned; you can use an [HTML Purifier package](https://github.com/mewebstudio/Purifier) for that (do it [manually](https://github.com/Laravel-Backpack/demo/commit/7342cffb418bb568b9e4ee279859685ddc0456c1) or by casting the attribute to `CleanHtmlOutput::class`);
+
+
+### Define which columns to show or hide in the responsive table
+
+By default, DataTables-responsive will try his best to show:
+- **the first column** (since that usually is the most important for the user, plus it holds the modal button and the details_row button so it's crucial for usability);
+- **the last column** (the actions column, where the action buttons reside);
+
+When giving priorities, lower is better. So a column with priority 4 will be hidden BEFORE a column with priority 2. The first and last columns have a priority of 1. You can define a different priority for a column using the ```priority``` attribute. For example:
+
+```php
+$this->crud->addColumn([
+ 'name' => 'details',
+ 'type' => 'text',
+ 'label' => 'Details',
+ 'priority' => 2,
+]);
+$this->crud->addColumn([
+ 'name' => 'obs',
+ 'type' => 'text',
+ 'label' => 'Observations',
+ 'priority' => 3,
+]);
+```
+In the example above, depending on how much space it's got in the viewport, DataTables will first hide the ```obs``` column, then ```details```, then the last column, then the first column.
+
+You can make the last column be less important (and hide) by giving it an unreasonable priority:
+
+```php
+$this->crud->setActionsColumnPriority(10000);
+```
+
+>Note that responsive tables adopt special behavior if the table is not able to show all columns. This includes displaying a vertical ellipsis to the left of the row, and making the row clickable to reveal more detail. This behavior is automatic and is not manually controllable via a field property.
diff --git a/5.x/crud-fields-javascript-api.md b/5.x/crud-fields-javascript-api.md
new file mode 100644
index 00000000..fd7be1e5
--- /dev/null
+++ b/5.x/crud-fields-javascript-api.md
@@ -0,0 +1,293 @@
+# CrudField JavaScript Library
+
+---
+
+
+## About
+
+If you need to add custom interactions (if field is X then do Y), we have just the thing for you. You can easily add custom interactions, using our **CrudField JavaScript Library**. It's already loaded on our Create / Update pages, in the global `crud` object, and it makes it dead-simple to select a field - `crud.field('title')` - using a syntax that's very familiar to our PHP syntax, then do the most common things on it.
+
+
+## Syntax
+
+Here's everything our **CrudField JavaScript Library** provides:
+- selectors:
+ - `crud.field('title')` -> returns the `CrudField` object for a field with the name `title`;
+ - `crud.field('testimonials').subfield('text')` -> returns the `CrudField` for the `text` subfield within the `testimonials` repeatable field;
+- properties on `CrudField`:
+ - `.name` - returns the field name (eg. `title`);
+ - `.type` - returns the field type (eg. `text`);
+ - `.input` - returns the DOM element that actually holds the value (the input/textarea/select);
+ - `.value` - returns the value of that field (as a `string`);
+- events on `CrudField`:
+ - `.onChange(function(field) { do_someting(); })` - calls that function every time the field changes (which for most fields is upon each keytype);
+- methods on `CrudField`:
+ - `.hide()` - hides that field;
+ - `.show()` - shows that field, if it was previously hidden;
+ - `.disable()` - makes that field's input `disabled`;
+ - `.enable()` - removes `disabled` from that field's input;
+ - `.require()` - adds an asterisk next to that field's label;
+ - `.unrequire()` - removes any asterisk next to that field's label;
+ - `.change()` - trigger the change event (useful for a default state on pageload);
+- specialty methods on `CrudField`:
+ - `.check()` - if the field is a checkbox, checks it;
+ - `.uncheck()` - if the field is a checkbox, unchecks it;
+
+The beauty of this solution is that... it's flexibility. Since it's only a JS library that makes the most difficult things easy... there is _no limit_ to what you can do with it. Just write pure JS or jQuery on top of it, to achieve your business logic.
+
+
+## How to Use
+
+### Step by Step
+
+**Step 1.** Create a file to hold the custom JS. As a convention, we recommend you split up the JS by entity name. For example, for a Product we recommend creating `public/assets/js/admin/forms/product.js`.
+
+**Step 2.** Load that script file in your CrudController, within `setupCreateOperation()` or `setupUpdateOperation()`, depending on when you want it loaded:
+
+```php
+ Widget::add()->type('script')->content('assets/js/admin/forms/product.js');
+```
+
+or
+
+```php
+ Widget::add()->type('script')->content(asset('assets/js/admin/forms/product.js'));
+```
+
+**Step 3.** Inside that JS file, use the CrudField JS Library to manipulate fields, in any way you want. For example:
+
+```javascript
+ crud.field('agree_to_terms').onChange(function(field) {
+ if (field.value == 1) {
+ crud.field('agree_to_marketing_email').show();
+ } else {
+ crud.field('agree_to_marketing_email').hide();
+ }
+ }).change();
+```
+
+Alternatively, since all action methods also accept a `boolean` as a parameter, the above can also become:
+
+```javascript
+ crud.field('agree_to_terms').onChange(function(field) {
+ crud.field('agree_to_marketing_email').show(field.value == 1);
+ }).change();
+```
+
+Notice that we did three things here:
+- selected a field using `crud.field('agree_to_terms')`;
+- defined what happens when that field gets changed, using `.onChange()`;
+- triggered the change event using `.change()` - that way, the closure will get evaluated first thing when the pageloads, not only when the first field actually gets changed;
+
+
+
+### Examples
+
+We've identified the most common ways developers need to add interaction to their forms. Then we've documented them below. That way, it's easy for you to just copy-paste a solution, then customize to your needs. You can also see these examples fully working, in [our demo](https://demo.backpackforlaravel.com/admin/field-monster/create).
+
+
+#### (1) Show / hide a field
+
+When a checkbox is checked, show a second field:
+
+```javascript
+crud.field('visible').onChange(function(field) {
+ crud.field('visible_where').show(field.value == 1);
+}).change();
+```
+
+
+
+#### (2) Show/hide and enable/disable a field
+
+When a checkbox is checked, show a second field _and_ un-disable it, by chaining the action methods:
+
+```javascript
+crud.field('visible').onChange(function(field) {
+ crud.field('displayed_where').show(field.value == 1).enable(field.value == 1);
+}).change();
+```
+
+Alternatively, a more readable but verbose version:
+
+```javascript
+crud.field('visible').onChange(function(field) {
+ if (field.value == 1) {
+ crud.field('displayed_where').show().enable();
+ } else {
+ crud.field('displayed_where').hide().disable();
+ }
+}).change();
+```
+
+
+#### (3) When a radio option is selected, show a second field
+
+When a radio has something specific selected, show a second field:
+
+```javascript
+crud.field('type').onChange(function(field) {
+ crud.field('custom_type').show(field.value == 3);
+}).change();
+```
+
+
+
+
+#### (4) When a select has a specific value, show a second field
+
+When a select has something specific selected, show a second field:
+
+```javascript
+crud.field('parent').onChange(function(field) {
+ crud.field('custom_parent').show(field.value == 6);
+}).change();
+```
+
+
+
+
+#### (5) When a checkbox is checked and has a certain value, do something
+
+```javascript
+function do_something() {
+ console.log('Displayed AND custom parent.');
+}
+
+crud.field('parent').onChange(field => {
+ if (field.value === 6 && crud.field('displayed').value == 1) {
+ do_something();
+ }
+});
+```
+
+
+#### (6) When a checkbox is checked or a select has a certain value, show a third field
+
+```javascript
+let do_something_else = () => {
+ console.log('Displayed OR custom parent.');
+}
+
+crud.field('displayed').onChange(field => {
+ if (field.value === 1 || crud.field('parent').value == 6) {
+ do_something_else();
+ }
+});
+
+crud.field('parent').onChange(field => {
+ if (field.value === 6 || crud.field('displayed').value == 1) {
+ do_something_else();
+ }
+});
+```
+
+
+#### (7) When a select is a certain value, do something, otherwise do something else
+
+```javascript
+crud.field('parent').onChange(function(field) {
+ switch(field.value) {
+ case 2:
+ console.log('doing something');
+ break;
+ case 3:
+ console.log('doing something else');
+ break;
+ default:
+ console.log('not doing anything');
+ }
+});
+```
+
+
+#### (8) When a checkbox is checked, automatically check another one
+
+When a checkbox is checked, automatically check a different checkbox or radio:
+
+```javascript
+crud.field('visible').onChange(field => {
+ crud.field('displayed').check(field.value == 1);
+});
+```
+
+
+
+
+#### (9) When a text input is written into, write in a second input (eg. slug)
+
+Create a slugged version of an input and put it into a second input:
+
+```javascript
+let slugify = text =>
+ text.toString().toLowerCase().trim()
+ .normalize('NFD') // separate accent from letter
+ .replace(/[\u0300-\u036f]/g, '') // remove all separated accents
+ .replace(/\s+/g, '-') // replace spaces with -
+ .replace(/[^\w\-]+/g, '') // remove all non-word chars
+ .replace(/\-\-+/g, '-') // replace multiple '-' with single '-'
+
+crud.field('title').onChange(field => {
+ crud.field('slug').input.value = slugify(field.value);
+});
+```
+
+
+
+
+#### (10) Calculate a total of multiple fields
+
+When multiple inputs change, change a last input to calculate the total (or average, or difference):
+
+```javascript
+// Notice that we have to convert the input values from STRING to NUMBER
+function calculate_discount_percentage() {
+ let full_price = Number(crud.field('full_price').value);
+ let discounted_price = Number(crud.field('discounted_price').value);
+ let discount_percentage = (full_price - discounted_price) * 100 / full_price;
+
+ crud.field('discount_percentage').input.value = discount_percentage;
+}
+
+crud.fields(['full_price', 'discounted_price']).forEach(function(field) {
+ field.onChange(calculate_discount_percentage);
+});
+```
+
+
+
+
+#### (11) When a repeatable subfield changes, disable another subfield
+
+When a select subfield has been selected, enable a second subfield:
+
+```javascript
+crud.field('wish').subfield('country').onChange(function(field) {
+ crud.field('wish').subfield('body', field.rowNumber).enable(field.value == '');
+ });
+```
+
+
+
+
+
+#### (12) When a checkbox is checked, hide repeatable and disable all subfields
+
+When a checkbox is checked, disable all subfields in a repeatable and hide the repetable field entirely:
+
+```javascript
+crud.field('visible').onChange(field => {
+ var subfields = $(crud.field('wish').input).parent().find('[data-repeatable-holder]').data('subfield-names');
+
+ // disable/enable all subfields
+ subfields.forEach(element => {
+ crud.field('wish').subfield(element).enable(field.value == 1);
+ });
+
+ // hide/show the repeatable entirely
+ crud.field('wish').show(field.value == 1);
+}).change();
+// this last change() call makes the code above also run on pageload,
+// so that if the checkbox starts checked, it's visible,
+// if the checkbox starts unchecked, it's hidden
+```
diff --git a/5.x/crud-fields.md b/5.x/crud-fields.md
new file mode 100644
index 00000000..648053a7
--- /dev/null
+++ b/5.x/crud-fields.md
@@ -0,0 +1,2715 @@
+# Fields
+
+---
+
+
+## About
+
+Field types define how the admin can manipulate an entry's values. They're used by the Create and Update operations.
+
+Think of the field type as the type of input: ``````. But for most entities, you won't just need text inputs - you'll need datepickers, upload buttons, 1-n relationship, n-n relationships, textareas, etc.
+
+We have a lot of default field types, detailed below. If you don't find what you're looking for, you can [create a custom field type](/docs/{{version}}/crud-fields#creating-a-custom-field-type). Or if you just want to tweak a default field type a little bit, you can [overwrite default field types](/docs/{{version}}/crud-fields#overwriting-default-field-types).
+
+> NOTE: Starting with Backpack 4.1, if the _field name_ is the exact same as a relation method in the model, Backpack will assume you're adding a field for that relationship and infer relation attributes from it. To disable this behaviour, you can use `'entity' => false` in your field definition.
+
+
+### Fields API
+
+To manipulate fields, you can use the methods below. The action will be performed on the currently running operation. So make sure you run these methods inside ```setupCreateOperation()```, ```setupUpdateOperation()``` or in ```setup()``` inside operation blocks:
+
+```php
+// add a field
+$this->crud->addField($field_definition_array);
+
+// shorthand: add a text field
+$this->crud->addField('db_column_name');
+
+// add multiple fields
+$this->crud->addFields([$field_definition_array_1, $field_definition_array_2]);
+
+// change the attributes of a field
+$this->crud->modifyField($name, $modifs_array);
+
+// remove a field from both operations
+$this->crud->removeField('name');
+
+// remove multiple fields from both operations
+$this->crud->removeFields($array_of_names);
+
+// remove all fields from all operations
+$this->crud->removeAllFields();
+
+// FIELD ORDER
+
+// add a field before a given field
+$this->crud->addField($field_definition_array)->beforeField('name');
+
+// add a field after a given field
+$this->crud->addField($field_definition_array)->afterField('name');
+
+
+// -------------------
+// New in Backpack 4.1
+// -------------------
+// add a field with this name
+$this->crud->field('price');
+
+// change the type attribute on the 'price' field
+$this->crud->field('price')->type('number');
+```
+
+
+### Field Attributes
+
+
+#### Mandatory Field Attributes
+
+**The only attribute that's mandatory when you define a field is its `name`**, which will be used:
+- inside the inputs, as ``;
+- to store the information in the database, so your `name` should correspond to a database column (if the field type doesn't have different instructions);
+
+Every other field attribute other than `name`, Backpack 4.1+ will try to guess.
+
+
+#### Recommended Field Attributes
+
+Usually developers define the following attributes for all fields:
+- the ```name``` of the column in the database (ex: "title")
+- the human-readable ```label``` for the input (ex: "Title")
+- the ```type``` of the input (ex: "text")
+
+So at minimum, a field definition array usually looks like:
+```php
+[
+ 'name' => 'description',
+ 'label' => 'Article Description',
+ 'type' => 'textarea',
+]
+```
+
+Please note that `label` and `type` are not _mandatory_, just _recommended_:
+- `label` can be omitted, and Backpack will try to construct it from the `name`;
+- `type` can be omitted, and Backpack will try to guess it from the column type, or if there's a relationship on the Model with the same `name`;
+
+
+#### Optional - Field Attributes for Presentation Purposes
+
+There are a few optional attributes on most default field types, that you can use to easily achieve a few common customisations:
+
+```php
+[
+ 'prefix' => '',
+ 'suffix' => '',
+ 'default' => 'some value', // set a default value
+ 'hint' => 'Some hint text', // helpful text, shows up after the input
+ 'attributes' => [
+ 'placeholder' => 'Some text when empty',
+ 'class' => 'form-control some-class',
+ 'readonly' => 'readonly',
+ 'disabled' => 'disabled',
+ ], // change the HTML attributes of your input
+ 'wrapper' => [
+ 'class' => 'form-group col-md-12'
+ ], // change the HTML attributes for the field wrapper - mostly for resizing fields
+]
+```
+
+These will help you:
+
+- **prefix** - add a text or icon _before_ the actual input;
+- **suffix** - add a text or icon _after_ the actual input;
+- **default** - specify a default value for the input, on create;
+- **hint** - add descriptive text for this input;
+- **attributes** - change or add actual HTML attributes of the input (ex: readonly, disabled, class, placeholder, etc);
+- **wrapper** - change or add actual HTML attributes to the div that contains the input;
+
+
+#### Optional - Fake Field Attributes (stores fake attributes as JSON in the database)
+
+In case you want to store information for an entry that doesn't need a separate database column, you can add any number of Fake Fields, and their information will be stored inside a column in the db, as JSON. By default, an ```extras``` column is used and assumed on the database table, but you can change that.
+
+**Step 1.** Use the fake attribute on your field:
+```php
+[
+ 'name' => 'name', // JSON variable name
+ 'label' => "Tag Name", // human-readable label for the input
+
+ 'fake' => true, // show the field, but don't store it in the database column above
+ 'store_in' => 'extras' // [optional] the database column name where you want the fake fields to ACTUALLY be stored as a JSON array
+],
+```
+
+**Step 2.** On your model, make sure the db columns where you store the JSONs (by default only ```extras```):
+- are in your ```$fillable``` property;
+- are on a new ```$fakeColumns``` property (create it now);
+- are cast as array in ```$casts```;
+
+>If you need your fakes to also be translatable, remember to also place ```extras``` in your model's ```$translatable``` property and remove it from ```$casts```.
+
+Example:
+```php
+[
+ 'name' => 'meta_title',
+ 'label' => "Meta Title",
+ 'fake' => true,
+ 'store_in' => 'metas' // [optional]
+],
+[
+ 'name' => 'meta_description',
+ 'label' => "Meta Description",
+ 'fake' => true,
+ 'store_in' => 'metas' // [optional]
+],
+[
+ 'name' => 'meta_keywords',
+ 'label' => "Meta Keywords",
+ 'fake' => true,
+ 'store_in' => 'metas' // [optional]
+],
+```
+
+In this example, these 3 fields will show up in the create & update forms, the CRUD will process as usual, but in the database these values won't be stored in the ```meta_title```, ```meta_description``` and ```meta_keywords``` columns. They will be stored in the ```metas``` column as a JSON array:
+
+```php
+{"meta_title":"title","meta_description":"desc","meta_keywords":"keywords"}
+```
+
+If the ```store_in``` attribute wasn't used, they would have been stored in the ```extras``` column.
+
+If you need to perform any manipulation of the data before storing the fake fields, you should define a mutator for the column used to store the fake attributes, by default it's `extras`. It can be any other column you define in `store_in`.
+```php
+// in YourModel.php
+public function setExtrasAttribute($value)
+{
+ // Your code
+}
+
+#### Optional - Tab Attribute Splits Forms into Tabs
+
+You can now split your create/edit inputs into multiple tabs.
+
+
+
+In order to use this feature, you just need to specify the tab name for each of your fields. Example:
+
+```php
+// select_from_array
+$this->crud->addField([
+ 'name' => 'select_from_array',
+ 'label' => "Select from array",
+ 'type' => 'select_from_array',
+ 'options' => ['one' => 'One', 'two' => 'Two', 'three' => 'Three'],
+ 'allows_null' => false,
+ 'allows_multiple' => true,
+ 'tab' => 'Tab name here',
+]);
+```
+
+If you forget to specify a tab name for a field, Backpack will place it above all tabs.
+
+
+
+#### Optional - Attributes for Fields Containing Related Entries
+
+When a field works with related entities (relationships like `BelongsTo`, `HasOne`, `HasMany`, `BelongsToMany`, etc), Backpack needs to know how the current model (being create/edited) and the other model (that shows up in the field) are related. And it stores that information in a few additional field attributes, right after you add the field.
+
+*Normally, Backpack 4.1+ will guess all this relationship information for you.* If you have your relationships properly defined in your Models, you can just use a relationship field the same way you would a normal field. Pretend that _the method in your Model that defines your relationship_ is a real column, and Backpack will do all the work for you.
+
+But if you want to overwrite any of the relationship attributes Backpack guesses, here they are:
+- `entity` - points to the method on the model that contains the relationship; having this defined, Backpack will try to guess from it all other field attributes; ex: `category` or `tags`;
+- `model` - the classname (including namespace) of the related model (ex: `App\Models\Category`); usually deduced from the relationship function in the model;
+- `attribute` - the attribute on the related model (aka foreign attribute) that will be show to the user; for example, you wouldn't want a dropdown of categories showing IDs - no, you'd want to show the category names; in this case, the `attribute` will be `name`; usually deduced using the [identifiable attribute functionality explained below](#identifiable-attribute);
+- `multiple` - boolean, allows the user to pick one or multiple items; usually deduced depending on whether it's a 1-to-n or n-n relationship;
+- `pivot` - boolean, instructs Backpack to store the information inside a pivot table; usually deduced depending on whether it's a 1-to-n or n-n relationship;
+- `relation_type` - text, deduced from `entity`; not a good idea to overwrite;
+
+If you do need a field that contains relationships to behave a certain way, it's usually enough to just specify a different `entity`. However, you _can_ specify any of the attributes above, and Backpack will take your value for it, instead of trying to guess one.
+
+
+
+**Identifiable Attribute for Relationship Fields**
+
+Fields that work with relationships will allow you to select which ```attribute``` on the related entry you want to show to the user. All relationship fields (relationship, select, select2, select_multiple, select2_multiple, select2_from_ajax, select2_from_ajax_multiple) let you define the ```attribute``` for this specific purpose.
+
+For example, when the admin creates an ```Article``` they'll have to select a ```Category``` from a dropdown. It's important to show an attribute for ```Category``` that will help the admin easily identify the category, even if it's not the ID. In this example, it would probably be the category name - that's what you'd like the dropdown to show.
+
+In Backpack, you can explicitly define this, by giving the field an ```attribute```. But you can also NOT explicitly define this - Backpack will try to guess it. If you don't like what Backpack guessed would be a good identifiable attribute, you can either:
+- (A) explicitly define an ```attribute``` for that field
+
+>**Note**: If the attribute you want to show is an acessor in Model, you need to add it to the `$appends` property of the said Model. https://laravel.com/docs/9.x/eloquent-serialization#appending-values-to-json
+
+- (B) you can specify the identifiable attribute in your model, and all fields will pick this up:
+
+```php
+
+use Backpack\CRUD\app\Models\Traits\CrudTrait;
+
+class Category
+{
+ use CrudTrait;
+
+ // you can define this
+
+ /**
+ * Attribute shown on the element to identify this model.
+ *
+ * @var string
+ */
+ protected $identifiableAttribute = 'title';
+
+ // or for more complicated use cases you can do
+
+ /**
+ * Get the attribute shown on the element to identify this model.
+ *
+ * @return string
+ */
+ public function identifiableAttribute()
+ {
+ // process stuff here
+ return 'whatever_you_want_even_an_accessor';
+ }
+}
+```
+
+## FREE Field Types
+
+
+### checkbox
+
+Checkbox for true/false.
+
+```php
+[ // Checkbox
+ 'name' => 'active',
+ 'label' => 'Active',
+ 'type' => 'checkbox'
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### checklist
+
+Show a list of checkboxes, for the user to check one or more of them.
+
+```php
+[ // Checklist
+ 'label' => 'Roles',
+ 'type' => 'checklist',
+ 'name' => 'roles',
+ 'entity' => 'roles',
+ 'attribute' => 'name',
+ 'model' => "Backpack\PermissionManager\app\Models\Role",
+ 'pivot' => true,
+ // 'number_of_columns' => 3,
+],
+```
+
+**Note: If you don't use a pivot table (pivot = false), you need to cast your db column as `array` in your model,by adding your column to your model's `$casts`. **
+
+Input preview:
+
+
+
+
+
+
+### checklist_dependency
+
+```php
+[ // two interconnected entities
+ 'label' => 'User Role Permissions',
+ 'field_unique_name' => 'user_role_permission',
+ 'type' => 'checklist_dependency',
+ 'name' => ['roles', 'permissions'], // the methods that define the relationship in your Models
+ 'subfields' => [
+ 'primary' => [
+ 'label' => 'Roles',
+ 'name' => 'roles', // the method that defines the relationship in your Model
+ 'entity' => 'roles', // the method that defines the relationship in your Model
+ 'entity_secondary' => 'permissions', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'model' => "Backpack\PermissionManager\app\Models\Role", // foreign key model
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?]
+ 'number_columns' => 3, //can be 1,2,3,4,6
+ ],
+ 'secondary' => [
+ 'label' => 'Permission',
+ 'name' => 'permissions', // the method that defines the relationship in your Model
+ 'entity' => 'permissions', // the method that defines the relationship in your Model
+ 'entity_primary' => 'roles', // the method that defines the relationship in your Model
+ 'attribute' => 'name', // foreign key attribute that is shown to user
+ 'model' => "Backpack\PermissionManager\app\Models\Permission", // foreign key model
+ 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?]
+ 'number_columns' => 3, //can be 1,2,3,4,6
+ ],
+ ],
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### color
+
+```php
+[ // Color
+ 'name' => 'background_color',
+ 'label' => 'Background Color',
+ 'type' => 'color',
+ 'default' => '#000000',
+],
+```
+
+Input preview:
+
+
+
+
+
+
+### custom_html
+
+Allows you to insert custom HTML in the create/update forms. Usually used in forms with a lot of fields, to separate them using h1-h5, hr, etc, but can be used for any HTML.
+
+```php
+[ // CustomHTML
+ 'name' => 'separator',
+ 'type' => 'custom_html',
+ 'value' => ''
+],
+```
+**NOTE** If you would like to disable the `wrapper` on this field, eg. when using a `