laravel-arcanist / arcanist Goto Github PK
View Code? Open in Web Editor NEW๐งโโ๏ธ Arcanist takes the pain out of building multi-step form wizards in Laravel.
Home Page: https://laravel-arcanist.com
License: MIT License
๐งโโ๏ธ Arcanist takes the pain out of building multi-step form wizards in Laravel.
Home Page: https://laravel-arcanist.com
License: MIT License
First of all we pushed our Renderer to GitHub today:
suenerds/arcanist-rest-api-renderer
We tried to implement a cancel button today and found a hardcoded
redirect response in the Wizard destroy
method.
Idea for a solution:
You have build a delete hook for clean up purposes.
As we need a way to overwrite the redirect response I want to use the same mechanism for completing the wizard
/**
* The action that gets executed after the last step of the
* wizard is completed.
*/
protected string $onDeleteAction = NullAction::class;
/**
* Gets called after the last step in the wizard is finished.
*/
protected function onAfterDelete(ActionResult $result): Response | Responsable | Renderable
{
return new JsonResponse([
'redirect' => [
'path' => '/wizard/assignments'
]
]);
}
public function destroy(Request $request, string $wizardId): Response | Responsable | Renderable
{
$this->load($wizardId);
$result = $this->actionResolver
->resolveAction($this->onDeleteAction)
->execute($this->transformWizardData());
if (!$result->successful()) {
return $this->responseRenderer->redirectWithError(
$this->currentStep(),
$this,
$result->error()
);
}
$this->wizardRepository->deleteWizard($this);
return $this->onAfterDelete($result);
}
The Delete Hook will be an Action Class
after that and we can use the onAfterDelete
function to do whatever we need to do after Delete.
I will update this issue when my PR is ready.
Good Morning,
First off, love the package ๐๐ป
We noticed that we are encountering an issue with the UnknownStepException being triggered if a user decided to change the step slug within the URL. This is of course intentional but is there a way in which we can capture the error and return a NotFoundHttpException instead or redirect the user back to the first step?
Thanks,
Matthew
Hi
Is there a way to have conditional steps
e.g. for a registration process, if one input on the first step say company, then the second step should be different that if the input say private
Hello
Thanks for your interesting package.
I know the documentation is not complete yet, but I have some questions about how to use the package.
I'm confused about creating view (blade) files and how to specify URLs for action forms, as well as next or previous buttons. Of course, I almost solved this, but I do not know exactly what the best method is, and I hope a clearer example will be given (especially for Blade).
The next question is how to use this form wizard in editing mode? What should we do if we want to edit an entity that has already been created and stored in DB? How to access the desired Model and share it between the various step forms? Especially based on Laravel model binding.
Suppose we have defined a Wizard to register a Post, which consists of several steps (PostWizard
), now if on our website it is possible for both regular users and admins (in the admin panel) to insert a post How can we use this PostWizard in both sections? (With different routes)
For example
exampl.com/user/wizard/post
exampl.com/admin/wizard/post
From there, access to the wizard is possible through the ID and the address wizard/example/wizardId
, now if one person comes and completes part of a form (for example, wizard number 5) and another person in his own browser enters the desired address Enter (wizard/example/5
) seems to have access to information entered by the previous user. Isn't this a problem? Maybe I misunderstood this!
Thank You
I'm looking at Arcanist for a project which needs to create multilingual routes to support different locales. For example, I'd need something like:
/en/forms/profile/1/about-me
/fr/formulaires/profil/1/a-propos
Is there a way to override the default registerRoutes
method to handle multilingual routes? My project uses Laravel Multilingual Routes, but I think any solution to this use case in Arcanist should be as agnostic as possible. Perhaps an option might be to allow an integrator to bypass Arcanist's automatic registration of routes and document the process for creating all necessary routes independently in a routes/arcanist.php
file or something like that.
As we discussed early in issue #9 (I cannot reopen it), we have one thing left:
To render fields in the frontend SPA we need to access the field list from the Render like this:
public function renderStep(WizardStep $step, AbstractWizard $wizard, array $data = [] ): Response | Responsable | Renderable
{
return new JsonResponse([
'wizard' => $wizard->summary(),
'step' => $step,
'fields' => $step->getFields(),
'formData' => $data,
]);
}
As you see we call a custom function getFields()
. We only need this because the fields()
function is protected.
Is there any chance to change that to public
?
I opened a PR (#17) to change it.
Hi there,
Firstly, I'm having an amazing time playing with this package, thank you for the time & effort you've put in to it!
I noticed that I was getting a 500 error when trying to access data in the payload of my Action class but only on the first time I tried to submit, if I refreshed it worked fine.
I traced this through in the code (AbstractWizard.php
) and found that the instance doesn't have access to the updated data yet in processLastStep
- I'm assuming it's been persisted but not reloaded/attached to the instance straight away.
I fixed this on the example I'm working with by reloading the wizard after the saveStepData
call in the update function.
EDIT: I'm also using the inertia-response-renderer package incase that infromation is helpful
Disclaimer
It's highly likely I'm using this wrong so if I am, I apologise for wasting your time,
Cheers!
Publishing then running the migrations fails with the following error:
SQLSTATE[42000]: Syntax error or access violation: 1101 BLOB, TEXT, GEOMETRY or JSON column 'data' can't have a default value (SQL: create table `wizards` (`id` int unsigned not null auto_increment primary key, `class` varchar(255) not null, `data` json not null default '[]', `created_at` timestamp null, `updated_at` timestamp null) default character set utf8mb4 collate 'utf8mb4_unicode_ci')
Currently, invalidating fields if one of their dependencies changed does not cascade. This means that given I have the following fields
A --> B --> C
Depends on A Depends on B
if A
gets changed, B
should be invalidated. Since B
has now been changed as well, C
should also be invalidated.
This is currently not the case. Right now, only B
would get invalidated and it would not cascade further.
Hi,
I'm experiencing with this package and I have a trouble with file uploading:
WizardAction
I'm reading a file field (e.g. avatar) through $payload
and i want to do something like Storage::putFile('avatars', $payload['avatar']);
to store file in a local storage, but $payload['avatar']
is always an empty array. How to fix that?Hi
I'm trying to make a new registration Wizard, but I don't want to create user, subscriptions etc. unless the email address is validated, so I was wondering if it is possible to some how send a notification email to the email entered in step 1, then in step two, ask for the verification code and not allow step 3 until the code is received ?
I was hoping to do this via events, but I'm not sure if there a 'Step started event' and the documentation on events is not yet complete :)
Something to automatically create a new wizard folder in the App\Wizards
namespace and steps in App\Wizards\<name>\Steps
would be nice.
Proposed commands:
php artisan make:arcanist Registration
Would create a Wizard at App\Wizards\Registration
.
php artisan make:arcanist Registration --steps=UsernameAndPasswordStep,AnnoyingNewsletterStep
Would create a Wizard at App\Wizards\Registration
if not exists and add two steps.
If you are willing to accept it, I'd contribute it.
Hi, is there a way to make a step repeatable? For example, we would have an additional button to save and new
Hi there, I see this package very useful for something my company is trying to do
Also we're using InertiaJS, it will be very nice to have compatibility with this package like the "Custom renderers" (which seems wip in the docs page) and sharing data will be much easier reusing Inertia's methods.
I am not sure how should I go about validating my data that I am passing as array of objects to my field. I can't make those fields individually because fields are generated dynamically. It's in a questionairre format where I am sending questions from database to front end and sending array of responses with questions id back to Field::make('responses'). Any help will be appreciated
The wizard have the SharedData, which should be shared for all step, but in a step it is not possible to get the data
Currently there are renderers available for blade templates and Inertia.js (I am not familiar with this, so bare with me). If I have a JavaScript frontend project (Vue, React, Svelte, etc.) that is separate from the Laravel side, how best would I pass the data back and forth? I suppose I could start with WizardStep::viewData, I would just need to dig into the source code and docs a bit more to figure that out. Are there any caveats I should know about?
I'd like to use Arcanist to rewrite an existing form that is pretty complicated right now.
I've read the 'getting started' guide on the documentation but I'm still not sure if the package fits my needs: can I use it to write multi-step forms that are also kind of "multi-route"?
To be more clear: my existing form shows/skips some steps based on the data that have been already selected. Is it possible to tell Arcanist to skip a step in a use case like this?
This is currently just a vague idea that popped into my mind. I think it should be possible to define a Field
as an upload
or something similar and let Arcanist take care of actually saving the file.
Currently, you would have to implement the process
method of the Step to deal with uploaded files. This is something I want to discourage as much as possible and provide built-in solutions to problems that require that escape hatch instead.
The API could look something like this
Field::make('avatar')
->file()
->saveTo(storage_path('avatars'));
Arcanist could then take care of saving the uploaded file using whatever storage you have configured in your application and store the file path in the avatar
key.
This idea could potentially be generalized further to add more behavior to fields.
Hi
I'm beginning to use this in a project, and it's quite intuitive so far, however, I was wondering how one would go about writing tests for a wizard that's written in this package.
Hi,
I'm just getting started with this package but I have one security related question:
When brute forcing the IDs of a wizard it is possible to access pending wizards (from other sessions) which might have stored sensitive data already (like names, addresses or email addresses for example). Is it possible to prevent this behavior?
An example:
/wizard/{slug}/1/sensitive-step
in his browser and sees the data of User A.In my opinion the data should be bound to the session (and not to an URL parameter) or the ID should be stored in an encrypted cookie for example if there's no other solution with the current implementation via URL.
Let the discussion begin ๐๐
Hello,
First of all I'd like to say I'm loving Arcanist and the documentation is cheeky and spectacular.
I am currently using Laravel Homestead which has PHP 8 and Laravel 8. The error I get is
2022/01/19 17:03:17 [error] 17605#17605: *746 FastCGI sent in stderr: "PHP message: PHP Fatal error: Access level to App\Wizards\Application\Steps\Step01_BasicInformation::fields() must be public (as in class Arcanist\WizardStep) in /home/vagrant/code/.../app/Wizards/Application/Steps/Step01_BasicInformation.php on line 20PHP message: PHP Fatal error: Access level to App\Wizards\Application\Steps\Step01_BasicInformation::fields() must be public (as in class Arcanist\WizardStep) in /home/vagrant/code/.../app/Wizards/Application/Steps/Step01_BasicInformation.php on line 20" while reading response header from upstream, client: 10.22.33.1, server: app.test, request: "GET /wizard/apply HTTP/1.1", upstream: "fastcgi://unix:/var/run/php/php8.1-fpm.sock:", host: "app.test"
I ran into an issue when deploying it today following the documentation here: https://laravel-arcanist.com/getting-started. It shows under the step slug example that the fields functions should be protected as seen below:
protected function fields(): array { return [ // Field::make('field-name') // ->rules(['required']), ]; }
However when doing this I get the error seen above. I followed this over to src/WizardStep.php and modified it from
public function fields(): array { return []; }
to
protected function fields(): array { return []; }
I'm still in the middle of deploying this so I'm not sure what the effects of this are, but it seems to have cleared up the error for now. I'm not quite sure what the correct state should be for the fields function, but I thought I'd pass this along to see if this is user error or a mixup between when the documentation was written and a github revision.
Appreciate the insight and your time.
When I do an arc lint, I only get 7/100+ files in the directory
Tried different regex for include but cant seem to get it to see everything
arclint file
{ "linters": { "cppcheck": { "type": "cppcheck", "exclude" : [ ], "include": [ "(.*\\.c$)", "(.*\\.h$)" ] } } }
I've created a POC for optional steps, which extends an omit
function on the WizardStep class, which, if returns true, the step is omitted from the wizard at that time. This omit function allows the wizard to be considerably more dynamic, as a step can be omitted based on configurable user state, or even data from previous steps.
I need to pass data back to the wizard from the action, in the docs
In case you need to pass data back to the wizard from the action, you can provide an associative array to the success method of the action.
so I'm already did this
return $this->success(['user' => $user]);
but, how to access / get the var in the wizard?
tried this way at wizard, but only get null
$this->data('user');
also tried to dd $this, but can't find the var that passed
Have been trying to get this package work for my project for about two days now, have spend the time to read this package and it appears to fail silently at steps validations, what i have discovered is that for some reasons the validation rules for step one is used to validate step two and since step one rules does not match with step two incoming fields it fails and bounce you back without throwing any errors.
For some strange reasons step one forms get submitted successfully after validation and marked as completed in the database, yet when you call iscomplete on step one form it returns false instead of true. i guess thats where the problem starts
I am really looking forward to using this package! Thanks for making this open source!
I have a few questions, specifically about Livewire. From reading the docs, and a little bit of source diving, I think it will be difficult to support it. The package is pretty opinionated. The concept is great, but I would love to be able to use it generically.
This goes for standard controllers, too. We validate our data in controllers using form requests. It would be cool if we can make them part of a wizard. It would only have set and get data from the wizard, instead of a model for example. Most concepts can stay, a little bit more flexibility in the controller/routes would be very useful, I think. It allows us to stick to what we do, while using the power of your package to deal with all the difficulties of wizards.
Is this something you would consider in the future?
I'm wondering if there's a separate repository or branch for this upcoming version? There appears to be only the main branch for this repository, and I cannot find any other reference to the upcoming 1.0 version - other than it's under development, and coming soon.
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Root composer.json requires laravel-arcanist/inertia-response-renderer ^0.5.0 -> satisfiable by laravel-arcanist/inertia-response-renderer[0.5.0].
- laravel-arcanist/inertia-response-renderer 0.5.0 requires inertiajs/inertia-laravel ^0.4.1 -> found inertiajs/inertia-laravel[v0.4.1, ..., v0.4.5] but it conflicts with your root composer.json require (^0.5.1).
Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions
It will be great if there is a prepareForValidation() method just like in Form Request. Will be helpful for checkbox fields especially. Where we want to do a $this->boolean('checkbox_field')
I see that the Field class has a transform() method, but not sure if it is equivalent to Laravel FormRequest's prepareForValidation() as I didn't see it get called before the $this->validate(...) in WizardStep processStep() method
Hi there,
Thank you for your work.
It seems like the documentation still misses a lot of information. Is there a way to also contribute to the documentation? It doesn't seem to be located in this repository.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.