# Terminal
bin/rails g stimulus appointment_refresh
# appointment_controller.js
import { Controller } from "@hotwired/stimulus"
import { Calendar } from '@fullcalendar/core'
import timeGridPlugin from '@fullcalendar/timegrid'
import interactionPlugin, { Draggable } from '@fullcalendar/interaction'
// Connects to data-controller="appointment"
export default class extends Controller {
static values = { fetched: Number }
connect() {
this.initializeCalendar()
this.initializeDraggable()
// let _this = this
// setInterval(function() {
// _this.calendar.refetchEvents()
// }, 500)
}
disconnect() {
this.calendar.destroy()
this.draggable.destroy()
}
fetchedValueChanged() {
if (this.calendar) {
this.calendar.refetchEvents()
}
}
initializeCalendar() {
let _this = this
this.calendar = new Calendar(this.element, {
plugins: [interactionPlugin, timeGridPlugin],
initialView: 'timeGridWeek',
events: '/events.json',
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: ''
},
businessHours: {
daysOfWeek: [1,2,3,4,5],
startTime: '08:00',
endTime: '17:00'
},
eventConstraint: 'businessHours',
eventDurationEditable: false,
weekends: false,
slotDuration: "01:00:00",
editable: true,
eventDrop: function (info) { _this.fetch(info) },
eventReceive: function (info) {
_this.fetch(info)
info.event.remove()
}
})
this.calendar.render()
}
initializeDraggable() {
let element = document.getElementById("external-events")
this.draggable = new Draggable(element, {
itemSelector: '.fc-event',
eventData: function(event) {
return {
duration: "01:00"
}
}
})
}
fetch(info) {
let url = info.event.url ? info.event.url : '/events'
let method = info.event.url ? 'PUT' : 'POST'
let csrf_token = document.head.querySelector('meta[name="csrf-token"]').getAttribute('content')
fetch(url, {
method: method,
headers: {
"Content-Type": "application/json",
Accept: "text/vnd.turbo-stream.html",
"X-CSRF-Token": csrf_token
},
body: JSON.stringify({ event: { appointment: info.event.start } })
})
}
}
# appointment_refresh_controller.js
import { Controller } from "@hotwired/stimulus"
// Connects to data-controller="appointment-refresh"
export default class extends Controller {
connect() {
this.array = document.querySelectorAll('[data-controller="appointment"]')
this.array.forEach(element => {
element.setAttribute('data-appointment-fetched-value', Math.floor(Math.random() * 10000000000))
})
}
}
# events_controller.rb
def create
# @event = current_user.events.create(event_params)
@event = current_user.events.new(event_params)
if @event.save
# Perform Background Jobs
ActionCable.server.broadcast("appointments", turbo_stream.replace(
"appointments",
partial: "events/event"
))
end
head :ok
end
def update
@event = current_user.events.find(params[:id])
if @event.update(event_params)
# Perform Background Jobs
ActionCable.server.broadcast("appointments", turbo_stream.replace(
"appointments",
partial: "events/event"
))
end
head :ok
end
# views/events/_event.html.erb
<%= turbo_frame_tag :appointments do %>
<div data-controller="appointment-refresh"></div>
<% end %>
# views/welcome/index.html.erb
<%= turbo_stream_from :appointments %>
<%= turbo_frame_tag :appointments %>
<div data-controller="appointment"></div>