Attaching CSV / Excel import function on Laravel-Admin

# Why

I wanted to handle many data at one time for updating on Laravel-Admin.
According to my research, we have to take 2 steps.
1. Customize list page to use custom tools which is prepared on Laravel-Admin.
2. Import CSV or Excel file using something.

### Custom Tools

Going by documentation, we could custom admin page using custom tool.

> model-grid provides custom tool functionality if there are more operational requirements

### Import CSV / Excel file

At first, I tried to use [Laravel Excel](https://laravel-excel.com/) which is powerful library to handle Excel file includes import and export.
However, It's hard to prepare environments for requirements and too powerful for my request, so I decided to use "str_getcsv" which is default function.

Here is the requirements for Laravel-Excel.
> PHP: ^7.0
> Laravel: ^5.5
> PhpSpreadsheet: ^1.6
> PHP extension php_zip enabled
> PHP extension php_xml enabled
> PHP extension php_gd2 enabled


# Code

On the condition, please finish to install Laravel-Admin and create some admin page that you'd like to manage at this time.

```sql:questions
 CREATE TABLE `questions` (
  `id` bigint(20) unsigned NOT NULL,
  `content` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
```

```csv:import.csv
1, What is your name?
2, How do you do?
```

You have to make directory at first to use custom tools on Laravel-Admin.

```bash
$ mkdir app/Admin/Extensions && mkdir app/Admin/Extensions/Tools
```

Then, you can create custom tool class.
I decided class name which is "ImportButton" this time.

```bash
$ vim app/Admin/Extensions/Tools/ImportButton.php
```

```php:app/Admin/Extensions/Tools/ImportButton.php
<?php

namespace App\Admin\Extensions\Tools;

use Encore\Admin\Admin;
use Encore\Admin\Grid;
use Encore\Admin\Grid\Tools\AbstractTool;
use Illuminate\Support\Facades\Request;

class ImportButton extends AbstractTool
{

    /**
     * Set up script for import button.
     */
    protected function setUpScripts()
    {
        $script = <<<SCRIPT
function handleFileSelect(evt) {
    var file = evt.target.files; // FileList object
    var fileName = file[0].name;

    $('#input').hide();
    $('#confirm').show();
    $('#confirm .text').text(fileName);
}

$('#files').on('change', handleFileSelect);

$('#confirm').on('click', function() {

    var formData = new FormData();
    if ($("input[name='csvfile']").val()!== '') {
        formData.append( "file", $("input[name='csvfile']").prop("files")[0] );
    }
    formData.append("_token", LA.token);

    $.ajax({
        method: 'POST',
        url: '/admin/questions/csv/import',
        data: formData,
        processData: false,
        contentType: false,
        success: function () {
            $.pjax.reload('#pjax-container');
            toastr.success('Uploading Success');
        }
    });
});
SCRIPT;
        Admin::script($script);
    }

    /**
     * Render Import button.
     *
     * @return string
     */
    public function render()
    {

        $this->setUpScripts();

        $import = 'Import';

        return <<<EOT

            <div class="pull-right" style="margin-right: 10px">
            <label id="input">
            <span class="btn btn-sm btn-twitter">
            <span><i class="fa fa-upload"></i> {$import}</span>
            <input type="file" id="files" name="csvfile" style="display:none">
            </span>
            </label>
            <span id="confirm" class="btn btn-sm btn-twitter" style="display:none">
            <span><i class="fa fa-upload"></i> <span class="text"></span></span>
            </span>
            </div>
EOT;

    }
}
```

```php:app/Admin/Controllers/QuestionController.php 
<?php
                                                                                   
namespace App\Admin\Controllers;                                                                                              

use App\Question;                                                                      
use Encore\Admin\Controllers\AdminController;                                      
use Encore\Admin\Form;                                                             
use Encore\Admin\Grid;                                                             
use Encore\Admin\Show;
use Encore\Admin\Controllers\ModelForm;                                            

use App\Admin\Extensions\Tools\ImportButton; // Add
use Encore\Admin\Layout\Content; // Add
use Illuminate\Http\Request; // Add
                                                                                   
class QuestionController extends AdminController                                       
{                                                                                  

    .
    .
    .
    
    /**                                                                            
     * Make a grid builder.   
     *                                                                             
     * @return Grid                                                                
     */                                                                            
    protected function grid()
    {                                                                              
        $grid = new Grid(new Question);                                                
                                                                                   
        $grid->column('id', __('Id'));                                             
        $grid->column('content', __('Content'));                               
        $grid->column('created_at', __('Created at'));                             
        $grid->column('updated_at', __('Updated at'));

        // Use custom tools here which you made above.
        $grid->tools(function ($tools) {
            $tools->append(new ImportButton());
        });

        return $grid;                                                              
    } 

    .
    .
    .
                                       
    /**                                                                         
     * Import interface.                                                        
     */                                                                         
    protected function import(Content $content, Request $request)               
    {                                                                           
        $file = $request->file('file');
        $csv = array_map('str_getcsv', file($file));                            
                                          
        foreach ($csv as $row){                                                 
            $id = (Int) $row[0];                                         
            $content  = $row[1];                                         
                                                                                
            $question = \App\Question::where('id', $id)->first();                       
            if(!$question){                                                         
                $req = new Question();                                              
                $req->id = $id;                                                 
                $req->content = $content;                                   
                $req->save();                                                   
            }else{                                                              
                $question->conetnt = $content;
                $question->save();                                                  
            }                                                                   
        }                                                                       
        return redirect('admin/questions');                                   
    }                                                                           
}                                                            
```

```php:app/Admin/route.php
$router->post('questions/csv/import', 'QuestionController@import'); // Add this line.
```


# Refs
[Custom tools
](https://laravel-admin.org/docs/#/en/model-grid-custom-tools)