how to make a live update events in schedule

hello

tell me pls, how to implement live event updates on all connected clients when changes are made or a new event is added by one of the users. I use react on the frontend and express on the backend with mongodb.3 people will use the scheduler and it is extremely important to see all changes in real time without refreshing the page.  thanks!

8 Replies 1 reply marked as answer

SK Sergei Kozlov January 13, 2021 10:33 AM UTC

Can I using websocket for it? How to setup Adaptor and dinamic render component?


HB Hareesh Balasubramanian Syncfusion Team January 13, 2021 12:42 PM UTC

Hi Sergei, 

Greetings from Syncfusion Support..! 

We have validated your shared query at our end and for that, we have prepared a CRUD sample with MongoDB as a service which can downloaded from the below link. Yes you can use web socket to update the events as a real-time application. 


In the above sample, we have added CRUD actions code snippet in server.js. 
var MongoClient = require('mongodb').MongoClient; 
const express = require('express'); 
const bodyParser = require('body-parser'); 
const app = express(); 
var url = "mongodb://localhost:27017/"; 
app.use(bodyParser.json()); 
app.use(bodyParser.urlencoded({ extended: false })) 
app.listen(5000, function () { 
    console.log('listening on 5000') 
}) 
app.use(express.static(__dirname)) 
 
MongoClient.connect(url, function (err, db) { 
    if (err) throw err; 
    var dbo = db.db("mydb"); 
    app.use(function (req, res, next) { 
        res.header("Access-Control-Allow-Origin", "*"); 
        res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); 
        next(); 
    }); 
    app.post("/GetData", (req, res) => { 
        dbo.collection('ScheduleData').find({}).toArray((err, cus) => { 
            res.send(cus); 
        }); 
    }); 
    app.post("/BatchData", (req, res) => { 
        var eventData = []; 
        if (req.body.action == "insert" || (req.body.action == "batch" && req.body.added.length > 0)) { 
            (req.body.action == "insert") ? eventData.push(req.body.value) : eventData = req.body.added; 
            for (var i = 0; i < eventData.length; i++) { 
                var sdate = new Date(eventData[i].StartTime); 
                var edate = new Date(eventData[i].EndTime); 
                eventData[i].StartTime = (new Date(+sdate - (sdate.getTimezoneOffset() * 60000))); 
                eventData[i].EndTime = (new Date(+edate - (edate.getTimezoneOffset() * 60000))); 
                dbo.collection('ScheduleData').insertOne(eventData[i]); 
            } 
        } 
        if (req.body.action == "update" || (req.body.action == "batch" && req.body.changed.length > 0)) { 
            (req.body.action == "update") ? eventData.push(req.body.value) : eventData = req.body.changed; 
            for (var i = 0; i < eventData.length; i++) { 
                delete eventData[i]._id; 
                var sdate = new Date(eventData[i].StartTime); 
                var edate = new Date(eventData[i].EndTime); 
                eventData[i].StartTime = (new Date(+sdate - (sdate.getTimezoneOffset() * 60000))); 
                eventData[i].EndTime = (new Date(+edate - (edate.getTimezoneOffset() * 60000))); 
                dbo.collection('ScheduleData').updateOne({ "Id": eventData[i].Id }, eventData[i]); 
            } 
        } 
        if (req.body.action == "remove" || (req.body.action == "batch" && req.body.deleted.length > 0)) { 
            (req.body.action == "remove") ? eventData.push(req.body.value) : eventData = req.body.deleted; 
            for (var i = 0; i < eventData.length; i++) { 
                dbo.collection('ScheduleData').deleteOne({ "Id": eventData[i].Id }, eventData[i]); 
            } 
        } 
        res.send(req.body); 
    }); 
}); 
  
Note: We have removed the local offset time before inserting and updating the events in the database collection to render the appointments without considering system UTC in the scheduler. 
 
In the below code we have given the GetData and BatchData url path to initial fetching and for performing CRUD actions using UrlAdaptor and assigned it to the scheduler datasource. 
 
let data = new DataManager({ url: 'http://localhost:5000/GetData', crudUrl: 'http://localhost:5000/BatchData', adaptor: new UrlAdaptor, crossDomain: true }); 
 
export default class App extends React.Component<{}, {}> { 
 
  public render() { 
    return ( 
      <ScheduleComponent id="schedule" height="550px" selectedDate={new Date(2018, 11, 11)} eventSettings={{ dataSource: data }} currentView="Week"> 
        <ViewsDirective> 
          <ViewDirective option="Day" /> 
          <ViewDirective option="Week" /> 
          <ViewDirective option="WorkWeek" /> 
          <ViewDirective option="Month" /> 
          <ViewDirective option="Agenda" /> 
          <ViewDirective option="MonthAgenda" /> 
        </ViewsDirective> 
        <Inject services={[Day, Week, WorkWeek, Month, Agenda, MonthAgenda]} /> 
      </ScheduleComponent> 
    ); 
  } 
} 
 
  
Steps to run the sample:  
  1. Run MongoDB and create the collection named ‘ScheduleData’ in ‘mydb’ database.
  2. Run the below comments.
  • npm install 
  • npm run server 
  • npm start 

Please revert if you have any concern. 

Regard, 
Hareesh 


Marked as answer

SK Sergei Kozlov January 14, 2021 10:18 AM UTC

Thanks for your reply!

I have already implemented the front and back. I am wondering how to integrate a websocket into a scheduler.
in the adapter we change the http request for the ws?


HB Hareesh Balasubramanian Syncfusion Team January 21, 2021 12:17 PM UTC

Hi Sergei, 

Thanks for being patience. 

We have modified our previously updated sample based on your shared “how to make a live update events in schedule” query using SignalR WS service and in that we can able to maintain the live updates between the different users without refreshing the browser/Scheduler and the sample can be downloaded from the following link. 


  public componentDidMount() { 
    this.signalr = new HubConnectionBuilder().withUrl("http://localhost:62869/hubs/schedulehub").withAutomaticReconnect().build(); 
 
    this.signalr.on("UpdateClient", (action: string, data: View | Object[]) => { 
      if (action == "view") { 
        this.scheduleObj.currentView = data as View; 
      } 
      if (action === "eventCreated" || action === "eventChanged" || action === "eventRemoved") { 
        this.scheduleObj.eventSettings.dataSource = data as Object[]; 
      } 
    }); 
    this.signalr.start().then(() => { console.log("Hub Connected..!"); }).catch((err: any) => { console.log(err); }); 
  } 
 
  public componentWillUnmount(): void { 
    this.signalr.stop().then(() => { console.log("Hub Disconnected.."); }).catch((err: any) => { console.log(err); }); 
  } 

Kindly try the above solution and get back to us if you need any further assistance. 

We will happy to assist you. 

Regards, 
Hareesh 



KO kotac January 25, 2021 01:42 PM UTC

Quick question on this, changing the data source like you have it there, will it make the whole schedule component flicker/re-render for a second or will it just add a new slot and wont re-render the whole scheduler?
I have a realtime implementation with signalR connection that is working fine just except that little annoying thing where the whole scheduler flickers after we change the datasource (even by adding 1 new appointment to it.) 
It would be cool if we could just make only the new appointment slot poping out.


HB Hareesh Balasubramanian Syncfusion Team January 26, 2021 05:22 AM UTC

Hi Kotac, 

Thanks for the update. 

We have validated your shared “little annoying thing where the whole scheduler flickers after we change the datasource (even by adding 1 new appointment to it” query at our end and we have ensured our previously updated sample and by performing CRUD actions in it, unfortunately, the events are properly bounded to it without any flickering and for the same, we have taken a video demo of it, which can be downloaded from the following link. 


Kindly try the above solution and if the issue still persists at your end kindly share the below details to serve you better? 
  1. Replicate the issue in the above sample.
  2. Share the issue replicating sample (if possible)
  
We will happy to assist you. 
  
Regards, 
Hareesh 



KO kotac January 27, 2021 10:58 AM UTC

Hi Hareesh,
Ok i managed to find one of my earlier recorded sessions, so have a look, i am not sure will this give any insight to you... 
http://g.recordit.co/opEKIzD1qU.gif

The only difference is that my events are changing the state in redux and scheduler is subscribed to redux slice of the state.

I think you are also doing something that might be useful in your componentDidMount() part with
if (action === "eventCreated" || action === "eventChanged" || action === "eventRemoved") { 
        this.scheduleObj.eventSettings.dataSource = data as Object[]; 
      } 

And in this case - is your "data as Object[]" just one new/edited appointment, or it is the whole updated data source/all appointments?


Many thanks,



BS Balasubramanian Sattanathan Syncfusion Team January 28, 2021 10:33 AM UTC

Hi Kotac, 

Thanks for your reply. 

We have analyzed your query “is your "data as Object[]" just one new/edited appointment, or it is the whole updated data source/all appointments” at our end and let you know that if we create/edit/delete a appointment the data will returns only one appointment, if we do multiple appointments the data will return multiple appointments. So, the data’s value will be based on the dynamic CRUD actions only. 

If we misunderstood your query, kindly share your exact requirement with details to provide the prompt solution at the earliest. 

Regards, 
Balasubramanian S 


Loader.
Up arrow icon