This package adds a few editable columns for projects that use Siberfx for Laravel v6:
```
editable_text
editable_checkbox
editable_switch
editable_select
```
When edited, those columns will submit an AJAX request to the controller, so that attribute is updated in the database. The developer is in complete control of the saving process, to make these column as versatile as possible:

the saving process can succeed => will show green dot or green text (and/or notification bubble)
the saving process can fail => will show red dot or red text (and/or notification bubble)

![Editable Switch](https://user-images.githubusercontent.com/1032474/173112345-f98113e2-50da-4e09-85a0-8e9a31d951ee.gif)

For the editable_text column, as an admin, you'll notice that:

the columns that are editable are underlined (dotted)
you can click that value to edit it, then
Enter saves the value
Esc reverts the changes
↑ (up arrow) moves one row up (same editable column)
↓ (down arrow) moves one row down (same editable column)
Tab moves to the next editable input
Shift + Tab moves to the previous editable input
clicking out of the input keeps the changes, but does not submit them (text becomes greyed out)
For the editable_select:

the columns that are editable are underlined (dotted) and there is a dropdown arrow
you can click the dropdown to edit the value as you normally do with a select input
once the value is selected, it is saved immediately, but you can disable this by setting the save_on_change to false (it will save on only on focus out)
the navigation between the editable_select is the same as for the editable_text (Enter, Esc, ↑, ↓, Tab, Shift + Tab)
Space or Enter opens the dropdown
you can use options attribute to provide the options of the select input, you can directly pass an array or, you can use a closure, in the closure you'll have the entry as an argument (check the examples bellow).
Note: when using closures, if you want to have a similar behavior like "select_from_ajax" you can enable the forceReloadAfterUpdate that will redraw the table on update and update the select options given the current entry state. Eg. CRUD::setOperationSetting('forceReloadAfterUpdate', true) in your setupListOperation()
For the editable_checkbox and editable_switch columns, as an admin... you'll notice that it "just works".

Demo
Don't belive how simple it is to use? Go ahead, try it right now, in our online demo.

Installation
- Quick Installation
- Quick Installation
- In your Laravel + Siberfx project, run:
```
php artisan siberfx:require:editablecolumns
```

It will ask you for your token & password - which you get after you purchase this package. If you've purchased previously, you can see your token and password in your Siberfx account.

Manual Installation
Alternatively, if the quick installation above doesn't work, you can follow the steps below:

Step 1. Buy access to this package and you'll get an access token. With that token in hand, you should instruct your project to pull in missing packages from our private repository, instead of Packagist:

add your token to your project's auth.json file by running composer config http-basic.siberfx.com [your-token-username] [your-token-password]
add the Siberfx private repo to your composer.json:
```php

"repositories": [
    {
        "type": "composer",
        "url": "https://repo.siberfx.com/"
    }
],
```

Step 2. In your project, via command line:

```
composer require siberfx/editable-columns
```

Usage
Step 1. Inside your ProductCrudController (for example), use this new operation we've provided:
```php

class ProductCrudController extends CrudController
{
    use \Siberfx\CRUD\app\Http\Controllers\Operations\ListOperation;
    use \Siberfx\CRUD\app\Http\Controllers\Operations\CreateOperation;
    use \Siberfx\CRUD\app\Http\Controllers\Operations\UpdateOperation;
    use \Siberfx\CRUD\app\Http\Controllers\Operations\CloneOperation;
    use \Siberfx\CRUD\app\Http\Controllers\Operations\DeleteOperation;
+   use \Siberfx\EditableColumns\Http\Controllers\Operations\MinorUpdateOperation;

    public function setup()
    {
        CRUD::setModel(\App\Models\Product::class);
        CRUD::setRoute(config('siberfx.base.route_prefix').'/product');
        CRUD::setEntityNameStrings('product', 'products');
    }
```

Step 2. In your ListOperation, instead of using text, number, check, select_from_array columns, use the columns this package provides, if you want them editable:
```php
public function setupListOperation() 
{
    // editable_text
    CRUD::addColumn([
        'name'             => 'price',
        'type'             => 'editable_text',
        'label'            => 'Price',

        // Optionals
        'underlined'       => true, // show a dotted line under the editable column for differentiation? default: true
        'min_width'        => '120px', // how wide should the column be?
        'select_on_click'  => false, // select the entire text on click? default: false
        'save_on_focusout' => false, // if user clicks out, the value should be saved (instead of greyed out)
        'on_error' => [
            'text_color'          => '#df4759', // set a custom text color instead of the red
            'text_color_duration' => 0, // how long (in miliseconds) should the text stay that color (0 for infinite, aka until page refresh)
            'text_value_undo'     => false, // set text to the original value (user will lose the value that was recently input)
        ],
        'on_success' => [
            'text_color'          => '#42ba96', // set a custom text color instead of the green
            'text_color_duration' => 3000, // how long (in miliseconds) should the text stay that color (0 for infinite, aka until page refresh)
        ],
        'auto_update_row' => true, // update related columns in same row, after the AJAX call?
    ]);

    // editable_checkbox
    CRUD::addColumn([
        'name'  => 'agreed',
        'label' => 'Agreed',
        'type'  => 'editable_checkbox',

        // Optionals
        'underlined' => true, // show a dotted line under the editable column for differentiation? default: true
        'on_error' => [
            'status_color'          => '#df4759', // set a custom text color instead of the red
            'status_color_duration' => 0, // how long (in miliseconds) should the text stay that color (0 for infinite, aka until page refresh)
            'switch_value_undo'     => false, // set checkbox to the original value (user will lose the value that was recently input)
        ],
        'on_success' => [
            'status_color'          => '#42ba96', // set a custom text color instead of the green
            'status_color_duration' => 3000, // how long (in miliseconds) should the text stay that color (0 for infinite, aka until page refresh)
        ],
        'auto_update_row' => true, // update related columns in same row, after the AJAX call?
    ]);

    // editable_switch
    CRUD::addColumn([
        'name'  => 'agreed',
        'label' => 'Agreed',
        'type'  => 'editable_switch',

        // Optionals
        // All the options available on editable_checkbox are available here too, plus;
        'color'   => 'success',
        'onLabel' => '✓',
        'offLabel' => '✕',
    ]);

    // editable_select
    CRUD::addColumn([
        'name'    => 'categories',
        'label'   => 'Categories',
        'type'    => 'editable_select',
        'options' => \App\Models\Category::all()->pluck('name', 'id')->toArray(),
        // or
        'options' => (function ($entry) {
            return \App\Models\Category::whereDate('created_at', '<=', $entry->created_at)
                ->pluck('name', 'id')->toArray(),
        }),
        // or
        'options' => [
            '1' => 'One',
            '2' => 'Two',
            '3' => 'Three',
        ],

        // Optionals
        'underlined'       => true, // show a dotted line under the editable column for differentiation? default: true
        'save_on_focusout' => true, // if user clicks out, the value should be saved (instead of greyed out)
        'save_on_change'   => true,
        'on_error' => [
            'text_color'          => '#df4759', // set a custom text color instead of the red
            'text_color_duration' => 0, // how long (in miliseconds) should the text stay that color (0 for infinite, aka until page refresh)
            'text_value_undo'     => false, // set text to the original value (user will lose the value that was recently input)
        ],
        'on_success' => [
            'text_color'          => '#42ba96', // set a custom text color instead of the green
            'text_color_duration' => 3000, // how long (in miliseconds) should the text stay that color (0 for infinite, aka until page refresh)
        ],
        'auto_update_row' => true, // update related columns in same row, after the AJAX call?
    ]);
}
```

Step 3.A. Then inside setupMinorUpdateOperation(), define what FormRequest you want to use for validation. You can use the exact same FormRequest that you've used in your Create/Update operations, because MinorUpdate will only consider the validation rule for the currently edited attribute (and ignore everything else). So in most cases you just need to do:
```php
protected function setupMinorUpdateOperation()
{
    $this->crud->setValidation(StoreRequest::class);
}
```

Step 3.B. Alternatively, if you don't want to use a FormRequest for validation, but instead want to write some custom validation logic, or you need to modify the saving process, you can easily do that too. Just override the methods saveMinorUpdateFormValidation() (to override the validation), and saveMinorUpdateEntry() (to override the saving process). This methods are used by saveMinorUpdate() which you may also override although it's not really neccessary. The example below shows how to confirm/deny the edit. Modify it so it fits your project, it's in your control.
```php
public function saveMinorUpdateFormValidation()
{
    // validation example for the "price"
    // note that this is just an example, you may do this with the FormRequest
    if (request('attribute') === 'price' && !is_numeric(request('value'))) {
        throw ValidationException::withMessages([
            'price' => ['The price has to be a number.'],
        ]);
    }
}
public function saveMinorUpdateEntry()
{
    // Save the minor update
    $entry = $this->crud->getModel()->find(request('id'));
    $entry->{request('attribute')} = request('value');
    
    // Perform specific logic
    $entry->status = 'draft';

    return $entry->save();
}
```
Allowing null on the select column
If your column is nullable on database and you want to allow your users to send an empty selection you should add the "empty option" yourself when providing the select options.
```php
CRUD::addColumn([
        'name'    => 'categories',
        'label'   => 'Categories',
        'type'    => 'editable_select',
        'options' => array_merge(['' => 'No category'], \App\Models\Category::all()->pluck('name', 'id')->toArray()),
        // or
        'options' => [
            ''  => 'No Category',
            '1' => 'One',
            '2' => 'Two',
            '3' => 'Three',
        ],
    ]);
```
Search Logic for Editable Columns
Editable columns need to know what search logic to use. We are working on a way to avoid this step, but as of now, you should manually define the searchLogic that should be applied for each column type. Example:
```php
CRUD::addColumn([
        'name'             => 'email',
        'type'             => 'editable_text',
        'label'            => 'Email',
        
        'searchLogic'      => 'text', // this will tell siberfx to use the "text" column search logic.
        
        // or alternatively provide your own custom search logic in a closure as you would do for any other column
        'searchLogic'      => function ($query, $column, $searchTerm) {
                $query->orWhere('email', 'like', '%'.$searchTerm.'%');
            });
        
    ]);
```
For text based columns you can just tell Siberfx to use the text column searchLogic as shown in the example above.

At the moment the other columns don't have any default searchLogic so you should write your own if needed.

| Editable Column | Apply Search Logic From Column | |:-:|:-:| | editable_text | text | | editable_checkbox | write your custom | | editable_switch | write your custom | | editable_select | write your custom |

Security
If you discover any security related issues, please email info@siberfx.com instead of using the issue tracker.
