Open
anaseqal
opened this issue 4 years ago
•
12 comments
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:
Step by step:
create new action:
php artisan nova:action ImportUsers
enable stand alone option by adding:
public $standalone = true;
create an import class for your resource using Laravel Excel.
composer require maatwebsite/excelphp 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'),
];
}
register the action into your resource.
public function actions(Request $request)
{
return [new Actions\ImportUsers];
}
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.
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
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
Class Anaseqal\NovaImport\NovaImport contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Laravel\Nova\Tool::menu)
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)
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.
runCallback ? call_user_func($this->runCallback, $request, $model) : true;
}
/**
* Return a message response from the action.
*
* @param string $message
* @return array
*/
public static function message($message)
{
return ['message' => $message];
}
/**
* Return a dangerous message response from the action.
*
* @param string $message
* @return array
*/
public static function danger($message)
{
return ['danger' => $message];
}
/**
* Return a delete response from the action.
*
* @return array
*/
public static function deleted()
{
return ['deleted' => true];
}
/**
* Return a redirect response from the action.
*
* @param string $url
* @return array
*/
public static function redirect($url)
{
return ['redirect' => $url];
}
/**
* Return a Inertia visit from the action.
*
* @deprecated
*
* @param string $path
* @param array $options
* @return array>
*/
public static function push($path, $query = [])
{
return [
'push' => [
'path' => $path,
'query' => $query,
],
];
}
/**
* Return a Inertia visit from the action.
*
* @param string $path
* @param array $options
* @return array>
*/
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
*/
public static function openInNewTab($url)
{
return ['openInNewTab' => $url];
}
/**
* Return a download response from the action.
*
* @param string $url
* @param string $name
* @return array
*/
public static function download($url, $name)
{
return ['download' => $url, 'name' => $name];
}
/**
* Return an action modal response from the action.
*
* @param string $modal
* @param array $data
* @return array
*/
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 $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)
{
//
}
/**
* Mark the action event record for the model as finished.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return int
*/
protected function markAsFinished($model)
{
return $this->batchId ? ActionEvent::markAsFinished($this->batchId, $model) : 0;
}
/**
* Mark the action event record for the model as failed.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param \Throwable|string $e
* @return int
*/
protected function markAsFailed($model, $e = null)
{
return $this->batchId ? ActionEvent::markAsFailed($this->batchId, $model, $e) : 0;
}
/**
* Indicate that this action can be run for the entire resource at once.
*
* @param bool $value
* @return $this
*/
public function availableForEntireResource($value = true)
{
$this->availableForEntireResource = $value;
return $this;
}
/**
* Get the fields available on the action.
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @return array
*/
public function fields(NovaRequest $request)
{
return [];
}
/**
* Validate the given request.
*
* @param \Laravel\Nova\Http\Requests\ActionRequest $request
* @return array
*
* @throws \Illuminate\Validation\ValidationException
*/
public function validateFields(ActionRequest $request)
{
$fields = collect($this->fields($request));
return Validator::make(
$request->all(),
$fields->mapWithKeys(function ($field) use ($request) {
return $field->getCreationRules($request);
})->all(),
[],
$fields->reject(function ($field) {
return empty($field->name);
})->mapWithKeys(function ($field) {
return [$field->attribute => $field->name];
})->all()
)->after(function ($validator) use ($request) {
$this->afterValidation($request, $validator);
})->validate();
}
/**
* Indicate that this action is only available on the resource index view.
*
* @param bool $value
* @return $this
*/
public function onlyOnIndex($value = true)
{
$this->onlyOnIndex = $value;
$this->showOnIndex = $value;
$this->showOnDetail = ! $value;
$this->showInline = ! $value;
return $this;
}
/**
* Indicate that this action is available except on the resource index view.
*
* @return $this
*/
public function exceptOnIndex()
{
$this->showOnDetail = true;
$this->showInline = true;
$this->showOnIndex = false;
return $this;
}
/**
* Indicate that this action is only available on the resource detail view.
*
* @param bool $value
* @return $this
*/
public function onlyOnDetail($value = true)
{
$this->onlyOnDetail = $value;
$this->showOnDetail = $value;
$this->showOnIndex = ! $value;
$this->showInline = ! $value;
return $this;
}
/**
* Indicate that this action is available except on the resource detail view.
*
* @return $this
*/
public function exceptOnDetail()
{
$this->showOnIndex = true;
$this->showOnDetail = false;
$this->showInline = true;
return $this;
}
/**
* Indicate that this action is only available on the resource's table row.
*
* @param bool $value
* @return $this
*/
public function onlyOnTableRow($value = true)
{
return $this->onlyInline($value);
}
/**
* Indicate that this action is only available on the resource's table row.
*
* @param bool $value
* @return $this
*/
public function onlyInline($value = true)
{
$this->showInline = $value;
$this->showOnIndex = ! $value;
$this->showOnDetail = ! $value;
return $this;
}
/**
* Indicate that this action is available except on the resource's table row.
*
* @return $this
*/
public function exceptOnTableRow()
{
return $this->exceptInline();
}
/**
* Indicate that this action is available except on the resource's table row.
*
* @return $this
*/
public function exceptInline()
{
$this->showInline = false;
$this->showOnIndex = true;
$this->showOnDetail = true;
return $this;
}
/**
* Show the action on the index view.
*
* @return $this
*/
public function showOnIndex()
{
$this->showOnIndex = true;
return $this;
}
/**
* Show the action on the detail view.
*
* @return $this
*/
public function showOnDetail()
{
$this->showOnDetail = true;
return $this;
}
/**
* Show the action on the table row.
*
* @deprecated
*
* @return $this
*/
public function showOnTableRow()
{
return $this->showInline();
}
/**
* Show the action on the table row.
*
* @return $this
*/
public function showInline()
{
$this->showInline = true;
return $this;
}
/**
* Register a callback that should be invoked after the action is finished executing.
*
* @param callable(\Illuminate\Support\Collection):mixed $callback
* @return $this
*/
public function then($callback)
{
$this->thenCallback = $callback;
return $this;
}
/**
* Set the current batch ID being handled by the action.
*
* @param string $actionBatchId
* @return $this
*/
public function withActionBatchId(string $batchId)
{
$this->batchId = $batchId;
return $this;
}
/**
* Register `then`, `catch`, and `finally` callbacks on the pending batch.
*
* @param \Laravel\Nova\Fields\ActionFields $fields
* @param \Illuminate\Bus\PendingBatch $batch
* @return void
*/
public function withBatch(ActionFields $fields, PendingBatch $batch)
{
//
}
/**
* Set the current batch ID being handled by the action.
*
* @param string $batchId
* @return $this
*/
public function withBatchId($batchId)
{
$this->batchId = $batchId;
return $this;
}
/**
* Set the callback to be run to authorize running the action.
*
* @param \Closure(\Laravel\Nova\Http\Requests\NovaRequest, mixed):bool $callback
* @return $this
*/
public function canRun(Closure $callback)
{
$this->runCallback = $callback;
return $this;
}
/**
* Get the component name for the action.
*
* @return string
*/
public function component()
{
return $this->component;
}
/**
* Get the displayable name of the action.
*
* @return string
*/
public function name()
{
return $this->name ?: Nova::humanize($this);
}
/**
* Get the URI key for the action.
*
* @return string
*/
public function uriKey()
{
return Str::slug($this->name(), '-', null);
}
/**
* Set the action to execute instantly.
*
* @return $this
*/
public function withoutConfirmation()
{
$this->withoutConfirmation = true;
return $this;
}
/**
* Set the action to skip action events for models.
*
* @return $this
*/
public function withoutActionEvents()
{
$this->withoutActionEvents = true;
return $this;
}
/**
* Return the CSS classes for the Action.
*
* @return string
*/
public function actionClass()
{
return $this instanceof DestructiveAction
? 'btn-danger'
: 'btn-primary';
}
/**
* Determine if the action is to be shown on the index view.
*
* @return bool
*/
public function shownOnIndex()
{
if ($this->onlyOnIndex == true) {
return true;
}
if ($this->onlyOnDetail) {
return false;
}
return $this->showOnIndex;
}
/**
* Determine if the action is to be shown on the detail view.
*
* @return bool
*/
public function shownOnDetail()
{
if ($this->onlyOnDetail) {
return true;
}
if ($this->onlyOnIndex) {
return false;
}
return $this->showOnDetail;
}
/**
* Determine if the action is to be shown inline on the table row.
*
* @return bool
*/
public function shownOnTableRow()
{
return $this->showInline;
}
/**
* Set the text for the action's confirmation button.
*
* @param string $text
* @return $this
*/
public function confirmButtonText($text)
{
$this->confirmButtonText = $text;
return $this;
}
/**
* Set the text for the action's cancel button.
*
* @param string $text
* @return $this
*/
public function cancelButtonText($text)
{
$this->cancelButtonText = $text;
return $this;
}
/**
* Set the text for the action's confirmation message.
*
* @param string $text
* @return $this
*/
public function confirmText($text)
{
$this->confirmText = $text;
return $this;
}
/**
* Mark the action as a standalone action.
*
* @return $this
*/
public function standalone()
{
$this->standalone = true;
return $this;
}
/**
* Determine if the action is a standalone action.
*
* @return bool
*/
public function isStandalone()
{
return $this->standalone;
}
/**
* Prepare the action for JSON serialization.
*
* @return array
*/
public function jsonSerialize(): array
{
$request = app(NovaRequest::class);
return array_merge([
'component' => $this->component(),
'destructive' => $this instanceof DestructiveAction,
'name' => $this->name(),
'uriKey' => $this->uriKey(),
'fields' => collect($this->fields($request))->filter->authorizedToSee($request)->each->resolveForAction($request)->all(),
'availableForEntireResource' => $this->availableForEntireResource,
'onlyOnDetail' => $this->onlyOnDetail,
'onlyOnIndex' => $this->onlyOnIndex,
'withoutConfirmation' => $this->withoutConfirmation,
'cancelButtonText' => __($this->cancelButtonText),
'confirmButtonText' => __($this->confirmButtonText),
'confirmText' => __($this->confirmText),
'class' => $this->actionClass(),
'showOnDetail' => $this->shownOnDetail(),
'showOnIndex' => $this->shownOnIndex(),
'showOnTableRow' => $this->shownOnTableRow(),
'standalone' => $this->isStandalone(),
'responseType' => $this->responseType,
], $this->meta());
}
/**
* Prepare the instance for serialization.
*
* @return array
*/
public function __sleep()
{
$properties = (new ReflectionClass($this))->getProperties();
return array_values(array_filter(array_map(function ($p) {
return ($p->isStatic() || in_array($name = $p->getName(), ['runCallback', 'seeCallback', 'thenCallback'])) ? null : $name;
}, $properties)));
}
}
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)