Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Toast exception support #344

Merged
merged 7 commits into from
Mar 21, 2024

Conversation

jedjones-uk
Copy link
Contributor

@jedjones-uk jedjones-uk commented Mar 19, 2024

Another small suggested improvement, to allow throwing standard exceptions anywhere in the stack that are output in mary as Toasts.

I have aimed to copy the defaults of the Toast as it is now, the only functionality missing is the redirects as it wouldn't make sense.

Usage is straight forward:

use throw \Mary\Exceptions\ToastException:

//Minimum required
throw ToastException::error(message: 'This is my description');

//with a title
throw ToastException::success(message: 'This is my description', title: 'System Error');

//Customisation
throw ToastException::info(message: 'This is my description', title: 'System Error', options: [
            'position' => 'toast-top toast-start',
            'timeout' => 5000
        ]);

throw ToastException::warning(message: 'This is as warning');

//this will not call preventDefault in the js stub included
throw ToastException::warning(message: 'This is as warning')->permitDefault();

@robsontenorio
Copy link
Owner

robsontenorio commented Mar 20, 2024

This is a interesting approach.

I am afraid that listener can conflict in some way within existing app listeners. Mostly, people maybe using this kind of hook on “app.js”

That is my case … I did exactly you have proposed on FLOW demo , but on my own App Exception and placed the hooks on “app.js”.

@jedjones-uk
Copy link
Contributor Author

@robsontenorio Would you be ok to share what your hook looks like? There may be something I can do to be flexible to that use case.

@robsontenorio
Copy link
Owner

document.addEventListener('livewire:init', () => {
    Livewire.hook('request', ({fail}) => {
        fail(({status, content, preventDefault}) => {
            try {
                content = JSON.parse(content)

                if (status === 419 || content.status === 419) {
                    window.location.reload()
                    preventDefault()
                }

                if (content.toast) {
                    toast({toast: content.toast});
                    preventDefault()
                }
            } catch (e) {
                console.log(e)
            }
        })
    })
})

@jedjones-uk
Copy link
Contributor Author

jedjones-uk commented Mar 20, 2024

I have just tested this locally, and it runs both hooks without issue.

Interestingly, it seems toast itself de-bounces the call in some way, which means if your code is in your app.js and mine remains in the toast component, both hooks are executed but only 1 toast is shown.

I have added try and catch to my use case as I think that is a good idea too.

@robsontenorio
Copy link
Owner

robsontenorio commented Mar 20, 2024

@jedjones-uk Nice!

Are you able to use the existing trait on your ToastException class instead of coding again all the toast feature?

https://github.com/robsontenorio/mary/blob/main/src/Traits/Toast.php

@jedjones-uk
Copy link
Contributor Author

@robsontenorio

Unfortunately, the way the trait is written means it doesn't help with my exception use case, but I did spend some time thinking about it. One solution we could consider is:

Create a 3rd DTO style class which is used to define the toast and it's data. This would provide shortcut methods and so on as we have, and then we update the trait "toast()" method and the exception method to take just the DTO and then render it how each use case makes sense.

The main issue is that for decent naming you'd have some heavy breaking changes, you want the DTO to be called toast, and then the trait something like canToast.

Your new usage might be

public function livewireMethod(){

  $toastDTO = Toast::error('title','description');
  $this->toast($toastDTO);
  //Or
  $this->toast(Toast::error('title','description'));
  //Or
  throw new ToastException::make($toastDTO);

}

public function methodAnywhereOutsideLivewire(){

  $toastDTO = Toast::error('title','description');
  throw new ToastException::make($toastDTO);
  //Or
  throw new ToastException::make(Toast::error('title','description'));

}

@robsontenorio
Copy link
Owner

Don't worry. Let's stick to your approach!

If you don't mind I appreciate if you can add a note about it on docs. Maybe on very bottom of this page.

https://github.com/robsontenorio/mary-ui.com/blob/main/resources/views/livewire/docs/components/toast.blade.php

It is very easy to setup docs on localhost.

@jedjones-uk
Copy link
Contributor Author

@robsontenorio Done here: robsontenorio/mary-ui.com#31

@robsontenorio
Copy link
Owner

Thanks !

@robsontenorio robsontenorio merged commit 061223b into robsontenorio:main Mar 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants