anaseqal / nova-import

Laravel Nova Import Action
72 stars 28 forks source link

Nova v3.10.0+ Import "standalone" action #26

Open anaseqal opened 3 years ago

anaseqal commented 3 years ago

Hello,

Nova v3.10.0 introduce a new standalone action for running actions without selecting resources. which make a good use case to import data to your resource without using this package.

Result:

Screenshot

Step by step:

  1. create new action: php artisan nova:action ImportUsers

  2. enable stand alone option by adding:

    public $standalone = true;
  3. create an import class for your resource using Laravel Excel. composer require maatwebsite/excel php artisan make:import UsersImport --model=User then in action file:

    public function handle(ActionFields $fields)
    {
        \Maatwebsite\Excel\Facades\Excel::import(new \App\Imports\UsersImport, $fields->file);
        return Action::message('It worked!');
    }
    
    public function fields()
    {
        return [
            \Laravel\Nova\Fields\File::make('File')
                ->rules('required'),
        ];
    }
  4. register the action into your resource.

    public function actions(Request $request)
    {
    return [new Actions\ImportUsers];
    }

    Happy coding!

phoenixg commented 3 years ago

Good to see this feature!

MCKLtech commented 3 years ago

I'm getting the following error when running the action after following this tutorial:

Call to undefined method App\Nova\Actions\ImportUsers::validateFields()

It seems like Nova Action's have this method but Anaseqal\NovaImport\Actions\Action does not. My ImportUsers extends NovaImport, not Nova.

(Nova v3.21.0)

Solved

It would appear you should extend the Nova Action, not NovaImport.

Can the docs be updated to reflect this?

urbandario commented 2 years ago

Hello i getting this error, even if i think i setup all things correctly... Call to undefined method App\Nova\Actions\ImportProducts::shownOnIndex()

urbandario commented 2 years ago

I'm getting the following error when running the action after following this tutorial:

Call to undefined method App\Nova\Actions\ImportUsers::validateFields()

It seems like Nova Action's have this method but Anaseqal\NovaImport\Actions\Action does not. My ImportUsers extends NovaImport, not Nova.

(Nova v3.21.0)

Solved

It would appear you should extend the Nova Action, not NovaImport.

Can the docs be updated to reflect this?

When i change on from NovaImport to Nova i get Class "Anaseqal\Nova\Actions\Action" not found

LaravelLover069 commented 2 years ago

Hi there, I am getting the same error after applying all the mentioned setup steps:

Call to undefined method App\Nova\Actions\ImportSupervisors::shownOnIndex()

The import process itself is working however I cannot view the resource detail view (data not being displayed). The index view lists the records, however the error keeps showing up over and over. Please advise how to fix this.

Excel-Import-Error

LaravelLover069 commented 2 years ago

Hi all, I found the solution to this issue

Hello i getting this error, even if i think i setup all things correctly... Call to undefined method App\Nova\Actions\ImportProducts::shownOnIndex()

@Urbanizacija69 I faced the same issue and found the solution for this issue. I have created an issue record and provided the solution for this. https://github.com/anaseqal/nova-import/issues/33 Cheers

StevenBokesa commented 2 years ago

I am doing the following steps composer require anaseqal/nova-import I registered the tool in my NovaServiceProvider.php app/Providers/NovaServiceProvider.php I created a nova action file and added my importer to the handle() method I registered my action in my resource then had an error saying Class Anaseqal\NovaImport\NovaImport contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Laravel\Nova\Tool::menu) Any ideas on how to fix this please

CarlosHidalgo89 commented 2 years ago

no support laravel nova 4, @anaseqal is correct?

CarlosHidalgo89 commented 2 years ago

I registered the tool in my NovaServiceProvider.php app/Providers/NovaServiceProvider.php

is laravel nova 4 ?

Wilquey commented 1 year ago

i have the same problem did you get any solution?

Class Anaseqal\NovaImport\NovaImport contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Laravel\Nova\Tool::menu)

CarlosHidalgo89 commented 1 year ago

Hi! Wilquey.

LavareI Nova V4. corrected it by replacing two files. Anaseqal\NovaImport\NovaImport Anaseqal\NovaImport\Actions\Action

El mar, 22 nov 2022 a la(s) 20:29, Wilquey Caetano da Cruz ( @.***) escribió:

i have the same problem did you get any solution?

Class Anaseqal\NovaImport\NovaImport contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Laravel\Nova\Tool::menu)

— Reply to this email directly, view it on GitHub https://github.com/anaseqal/nova-import/issues/26#issuecomment-1324436591, or unsubscribe https://github.com/notifications/unsubscribe-auth/AVFA4NWRDX57ZPC366J5VUTWJVXPHANCNFSM4UQ5KYNQ . You are receiving this because you commented.Message ID: @.***>

-- Saludos,

Ing. Carlos Hidalgo Reyes Software Developer p: +593 9 822 71342 a: Guayaquil: Av. Juan Tanca Marengo Km 0.5 Edif. Francisco Sánchez Piso 2 Of. 10 w: www.siberian.com.ec e: @. @.>

Este correo y sus documentos adjuntos son confidenciales. Cualquier divulgación, distribución y/o copia de dicha información se encuentra prohibida y sancionada por la ley. Si usted ha recibido este mensaje por error, por favor notifíquenos de inmediato.

This e-mail and its attachments contains confidential information. Any disclosure, distribution and/or copying of the information is prohibited and sanctioned by law. If you received this email in error, please notify the sender immediately and delete this message.

<?php

namespace Anaseqal\NovaImport\Actions;

use Closure; use JsonSerializable; use Laravel\Nova\Nova; use Laravel\Nova\Metable; use Illuminate\Support\Str; use Illuminate\Http\Request; use Laravel\Nova\AuthorizedToSee; use Laravel\Nova\Fields\ActionFields; use Laravel\Nova\ProxiesCanSeeToGate; use Laravel\Nova\Http\Requests\ActionRequest; use Laravel\Nova\Exceptions\MissingActionHandlerException; use Illuminate\Bus\PendingBatch; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Traits\Macroable; use Laravel\Nova\Http\Requests\NovaRequest; use Laravel\Nova\Makeable;

use ReflectionClass;

class Action implements JsonSerializable { use AuthorizedToSee, Macroable, Makeable, Metable, ProxiesCanSeeToGate;

/**
 * The displayable name of the action.
 *
 * @var string
 */
public $name;

/**
 * The action's component.
 *
 * @var string
 */
public $component = 'confirm-action-modal';

/**
 * Indicates if need to skip log action events for models.
 *
 * @var bool
 */
public $withoutActionEvents = false;

/**
 * Indicates if this action is available to run against the entire resource.
 *
 * @var bool
 */
public $availableForEntireResource = false;

/**
 * Determine where the action redirection should be without confirmation.
 *
 * @var bool
 */
public $withoutConfirmation = false;

/**
 * Indicates if this action is only available on the resource index view.
 *
 * @var bool
 */
public $onlyOnIndex = false;

/**
 * Indicates if this action is only available on the resource detail view.
 *
 * @var bool
 */
public $onlyOnDetail = false;

/**
 * Indicates if this action is available on the resource index view.
 *
 * @var bool
 */
public $showOnIndex = true;

/**
 * Indicates if this action is available on the resource detail view.
 *
 * @var bool
 */
public $showOnDetail = true;

/**
 * Indicates if this action is available on the resource's table row.
 *
 * @var bool
 */
public $showInline = false;

/**
 * The current batch ID being handled by the action.
 *
 * @var string|null
 */
public $batchId;

/**
 * The callback used to authorize running the action.
 *
 * @var (\Closure(\Laravel\Nova\Http\Requests\NovaRequest, mixed):bool)|null
 */
public $runCallback;

/**
 * The callback that should be invoked when the action has completed.
 *
 * @var (\Closure(\Illuminate\Support\Collection):mixed)|null
 */
public $thenCallback;

/**
 * The number of models that should be included in each chunk.
 *
 * @var int
 */
public static $chunkCount = 200;

/**
 * The text to be used for the action's confirm button.
 *
 * @var string
 */
public $confirmButtonText = 'Run Action';

/**
 * The text to be used for the action's cancel button.
 *
 * @var string
 */
public $cancelButtonText = 'Cancel';

/**
 * The text to be used for the action's confirmation text.
 *
 * @var string
 */
public $confirmText = 'Are you sure you want to run this action?';

/**
 * Indicates if the action can be run without any models.
 *
 * @var bool
 */
public $standalone = false;

/**
 * The XHR response type on executing the action.
 *
 * @var string
 */
public $responseType = 'json';

/**
 * Determine if the action is executable for the given request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Illuminate\Database\Eloquent\Model  $model
 * @return bool
 */
public function authorizedToRun(Request $request, $model)
{
    return $this->runCallback ? call_user_func($this->runCallback, $request, $model) : true;
}

/**
 * Return a message response from the action.
 *
 * @param  string  $message
 * @return array<string, string>
 */
public static function message($message)
{
    return ['message' => $message];
}

/**
 * Return a dangerous message response from the action.
 *
 * @param  string  $message
 * @return array<string, string>
 */
public static function danger($message)
{
    return ['danger' => $message];
}

/**
 * Return a delete response from the action.
 *
 * @return array<string, bool>
 */
public static function deleted()
{
    return ['deleted' => true];
}

/**
 * Return a redirect response from the action.
 *
 * @param  string  $url
 * @return array<string, string>
 */
public static function redirect($url)
{
    return ['redirect' => $url];
}

/**
 * Return a Inertia visit from the action.
 *
 * @deprecated
 *
 * @param  string  $path
 * @param  array<string, mixed>  $options
 * @return array<string, array<string, mixed>>
 */
public static function push($path, $query = [])
{
    return [
        'push' => [
            'path' => $path,
            'query' => $query,
        ],
    ];
}

/**
 * Return a Inertia visit from the action.
 *
 * @param  string  $path
 * @param  array<string, mixed>  $options
 * @return array<string, array<string, mixed>>
 */
public static function visit($path, $options = [])
{
    return [
        'visit' => [
            'path' => '/'.ltrim($path, '/'),
            'options' => $options,
        ],
    ];
}

/**
 * Return an open new tab response from the action.
 *
 * @param  string  $url
 * @return array<string, string>
 */
public static function openInNewTab($url)
{
    return ['openInNewTab' => $url];
}

/**
 * Return a download response from the action.
 *
 * @param  string  $url
 * @param  string  $name
 * @return array<string, string>
 */
public static function download($url, $name)
{
    return ['download' => $url, 'name' => $name];
}

/**
 * Return an action modal response from the action.
 *
 * @param  string  $modal
 * @param  array<string, mixed>  $data
 * @return array<string, string|mixed>
 */
public static function modal($modal, $data)
{
    return array_merge(['modal' => $modal], $data);
}

/**
 * Execute the action for the given request.
 *
 * @param  \Laravel\Nova\Http\Requests\ActionRequest  $request
 * @return mixed
 * @throws MissingActionHandlerException
 */
public function handleRequest(ActionRequest $request)
{
    $method = ActionMethod::determine($this, $request->targetModel());

    if (! method_exists($this, $method)) {
        throw MissingActionHandlerException::make($this, $method);
    }

    $fields = $request->resolveFields();

    return DispatchAction::forModels(
        $request, $this, $method, collect([]), $fields
    );

    return $this->handleResult($fields, $results);
}

/**
 * Handle chunk results.
 *
 * @param  \Laravel\Nova\Fields\ActionFields  $fields
 * @param  array<int, mixed>  $results
 * @return mixed
 */
public function handleResult(ActionFields $fields, $results)
{
    return count($results) ? end($results) : null;
}

/**
 * Handle any post-validation processing.
 *
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
 * @param  \Illuminate\Contracts\Validation\Validator  $validator
 * @return void
 */
protected function afterValidation(NovaRequest $request, $validator)
{
    //
}

/**

<?php

namespace Anaseqal\NovaImport;

use Illuminate\Http\Request; use Laravel\Nova\Nova; use Laravel\Nova\Menu\MenuSection; use Laravel\Nova\Tool;

class NovaImport extends Tool { /**

Wilquey commented 1 year ago

Thank you CarlosHidalgo89 for the instructions, the replacements were carried out. However, another error appeared that I could not identify.

Declaration of App\Nova\Actions\ImportUsers::fields() should be compatible with Anaseqal\NovaImport\Actions\Action::fields(Laravel\Nova\Http\Requests\NovaRequest $request)

did you get any solution?