Browse Source

flash toast

main
pvincent 2 months ago
parent
commit
f5db83ce87
  1. 14
      app/assets/stylesheets/tailwind/main.tailwind.css
  2. 25
      app/controllers/flash_controller.rb
  3. 5
      app/javascript/application.js
  4. 49
      app/javascript/controllers/flash_toast_controller.js
  5. 15
      app/views/flash/index.html.erb
  6. 8
      app/views/layouts/_navbar.html.erb
  7. 37
      app/views/layouts/_notification.html.erb
  8. 1
      app/views/layouts/application.html.erb
  9. 5
      config/routes.rb

14
app/assets/stylesheets/tailwind/main.tailwind.css

@ -4,9 +4,15 @@
@apply py-2 px-4 bg-blue-200; @apply py-2 px-4 bg-blue-200;
} }
} }
*/ */
.title {
@apply bg-gradient-to-r from-color-primary to-color-secondary text-yellow-400 sm:rounded-t-lg;
}
h1 { @apply text-5xl my-2}
h2 { @apply text-4xl my-2}
h3 { @apply text-3xl my-1}
h4 { @apply text-2xl my-1}
h5 { @apply text-xl}
h6 { @apply text-base }
.title { @apply bg-gradient-to-r from-color-primary to-color-secondary text-yellow-400 sm:rounded-t-lg; }
.button { @apply bg-slate-200 hover:bg-slate-500 cursor-pointer }
.menu { @apply text-slate-200 hover:bg-slate-700 p-2 text-2xl}

25
app/controllers/flash_controller.rb

@ -0,0 +1,25 @@
# interaction with the flash message
class FlashController < ApplicationController
def index; end
def turbo_notice
flash[:notice] = 'From Turbo'
flash[:alert] = 'Alert Turbo'
render turbo_stream: turbo_stream.replace(:notification, partial: 'layouts/notification')
end
def redirect_with_notice
redirect_to flash_path, notice: build_message(:notice)
end
def redirect_with_alert
redirect_to flash_path, alert: build_message(:alert)
end
private
def build_message(type_of_message)
session[:flash_iteration] = session[:flash_iteration].to_i + 1
"this is #{type_of_message} ##{session[:flash_iteration]}"
end
end

5
app/javascript/application.js

@ -12,10 +12,6 @@ import 'alpine-clipboard'
window.Alpine = Alpine window.Alpine = Alpine
Alpine.start() Alpine.start()
// Toastify
import Toastify from 'toastify-js'
window.Toastify = Toastify
// Font Awesome // Font Awesome
import { far } from "@fortawesome/free-regular-svg-icons" import { far } from "@fortawesome/free-regular-svg-icons"
import { fas } from "@fortawesome/free-solid-svg-icons" import { fas } from "@fortawesome/free-solid-svg-icons"
@ -24,3 +20,4 @@ import { library } from "@fortawesome/fontawesome-svg-core"
import "@fortawesome/fontawesome-free" import "@fortawesome/fontawesome-free"
library.add(far, fas, fab) library.add(far, fas, fab)
FontAwesome.config.mutateApproach = 'sync' // prevents flickering FontAwesome.config.mutateApproach = 'sync' // prevents flickering

49
app/javascript/controllers/flash_toast_controller.js

@ -0,0 +1,49 @@
import { Controller } from "@hotwired/stimulus"
import Toastify from 'toastify-js'
export default class extends Controller {
static initialized = false
static toastifyNotice
static toastifyAlert
static lastId
static load_once() {
this.initialized = true
const commonOptions = { gravity: 'top', position: 'center', duration: 4000, offset: { y: '1em' }, close: true, escapeMarkup: false }
this.toastifyNotice = Toastify({ className: 'toastify-notice', ...commonOptions })
this.toastifyAlert = Toastify({ className: 'toastify-alert', ...commonOptions })
this.lastId = 0
console.log('FlashController ready!')
}
initialize() {
// console.log('FlashController initialize')
if (!this.constructor.initialized) this.constructor.load_once()
}
connect() {
// console.log(`FlashController connect last_id=<${this.constructor.lastId}>`)
const id = this.element.dataset.id
if (id != this.constructor.lastId) {
const notice = this.element.dataset.notice
const alert = this.element.dataset.alert
while (this.element.firstChild) { this.element.removeChild(this.element.firstChild) }
if (notice.length > 0) this.toastMessageFrom(id, notice, this.constructor.toastifyNotice)
if (alert.length > 0) this.toastMessageFrom(id, alert, this.constructor.toastifyAlert)
this.constructor.lastId = id
}
// else console.log(`duplicate entry ${id}`)
}
toastMessageFrom(id, message, toastify) {
toastify.options.selector = this.element
toastify.options.text = message
toastify.showToast()
const toastType = toastify.options.className.split('-').pop()
console.info(`TOAST ${toastType}: ${message}`)
}
}

15
app/views/flash/index.html.erb

@ -0,0 +1,15 @@
<h1>Flash experiments</h1>
<ul>
<li>
<%= link_to 'redirect with flash notice', flash_redirect_with_notice_path, class: :button %>
</li>
<li>
<%= link_to 'redirect with flash alert', flash_redirect_with_alert_path, class: :button %>
</li>
<li>
<%= link_to 'turbo notice', flash_turbo_notice_path, class: :button, 'data-turbo-method': :post %>
</li>
<li></li>
<li></li>
</ul>

8
app/views/layouts/_navbar.html.erb

@ -1,6 +1,10 @@
<nav class='bg-slate-800 text-2xl justify-items-center p-2 flex text-slate-200'>
<%= link_to root_path, class: 'items-center flex gap-4 hover:bg-slate-700 p-2 text-2xl' do %>
<nav class='bg-slate-800 text-2xl p-2 text-slate-200 flex justify-between items-center'>
<%= link_to root_path, class: 'menu items-center flex gap-4 ' do %>
<%= fa_icon :road, size: 2 %> <%= fa_icon :road, size: 2 %>
<%= Rails.configuration.application_title %> <%= Rails.configuration.application_title %>
<% end %> <% end %>
<div>
<%= link_to 'Flash', flash_path, class: :menu %>
</div>
</nav> </nav>

37
app/views/layouts/_notification.html.erb

@ -1,35 +1,10 @@
<%= turbo_frame_tag 'notification' do %>
<%= turbo_frame_tag :notification do %>
<% if flash.count.positive? %> <% if flash.count.positive? %>
<script>
var commonOptions
var noticeOptions
var alertOptions
if (typeof commonOptions === 'undefined'){
commonOptions={
gravity: 'top',
position: 'center',
duration: 4000,
offset: { y: '1em' },
close: true
}
noticeOptions={ className: 'toastify-notice', ...commonOptions }
alertOptions={ className: 'toastify-alert', ...commonOptions }
}
var notice='<%= flash.notice %>'
var alert='<%= flash.alert %>'
<div data-controller="flash-toast"
data-id="<%= flash.object_id %>"
data-alert="<%= flash.alert %>"
data-notice="<%= flash.notice %>">
</div>
<% flash.clear %> <% flash.clear %>
if (notice.length>0){
console.info(`TOAST notice: ${notice}`)
Toastify({ text: notice, ...noticeOptions }).showToast();
notice=''
}
if (alert.length>0){
console.warn(`TOAST alert: ${alert}`)
Toastify({ text: alert, ...alertOptions }).showToast();
alert=''
}
</script>
<% end %> <% end %>
<% end %> <% end %>

1
app/views/layouts/application.html.erb

@ -10,6 +10,7 @@
<!--META --> <!--META -->
<%= csrf_meta_tags %> <%= csrf_meta_tags %>
<%= csp_meta_tag %> <%= csp_meta_tag %>
<%= turbo_refreshes_with method: :morph, scroll: :preserve %>
<%= tag :meta, name: :viewport, content: 'width=device-width,initial-scale=1' %> <%= tag :meta, name: :viewport, content: 'width=device-width,initial-scale=1' %>
<% if Rails.env.development? %> <% if Rails.env.development? %>
<%= tag :meta, name: 'turbo-prefetch', content: false %> <%= tag :meta, name: 'turbo-prefetch', content: false %>

5
config/routes.rb

@ -8,4 +8,9 @@ Rails.application.routes.draw do
# Defines the root path route ("/") # Defines the root path route ("/")
root 'scores#index' root 'scores#index'
get 'flash' => 'flash#index'
get 'flash/redirect_with_notice' => 'flash#redirect_with_notice', as: :flash_redirect_with_notice
get 'flash/redirect_with_alert' => 'flash#redirect_with_alert', as: :flash_redirect_with_alert
post 'flash/turbo_notice' => 'flash#turbo_notice', as: :flash_turbo_notice
end end
Loading…
Cancel
Save