Can't update event after insert unless I refresh page first

Hi there,

If I create a new event and then drag it the new event is created in the db but the update is not saving in the db.

If I create a new event, then refresh the page, and then drag the event it saves in the db.

I can see that the pid / sid is some random generated id when I insert a new event. How can I change my code to correct this problem?

Here is my client side code:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
        <title></title>
</head>

<script src="dhtmlxScheduler/codebase/dhtmlxscheduler.js"  type="text/javascript" charset="utf-8"></script>
<script src="dhtmlxScheduler/codebase/ext/dhtmlxscheduler_year_view.js"  type="text/javascript" charset="utf-8"></script>
<script src="dhtmlxScheduler/codebase/ext/dhtmlxscheduler_pdf.js"  type="text/javascript" charset="utf-8"></script>
<script src="dhtmlxScheduler/codebase/ext/dhtmlxscheduler_active_links.js"  type="text/javascript" charset="utf-8"></script>
<script src="dhtmlxScheduler/codebase/ext/dhtmlxscheduler_url.js"  type="text/javascript" charset="utf-8"></script>
<script src="dhtmlxScheduler/codebase/ext/dhtmlxscheduler_minical.js" type="text/javascript" charset="utf-8"></script>
<script src="dhtmlxScheduler/codebase/ext/dhtmlxscheduler_week_agenda.js" type="text/javascript" charset="utf-8"></script>
<script src="dhtmlxScheduler/codebase/ext/dhtmlxscheduler_units.js" type="text/javascript" charset="utf-8"></script>
<script src="dhtmlxScheduler/codebase/ext/dhtmlxscheduler_key_nav.js" type="text/javascript" charset="utf-8"></script>

<link rel="stylesheet" href="dhtmlxScheduler/codebase/dhtmlxscheduler_glossy.css" type="text/css" media="screen" title="no title" charset="utf-8">
    <link rel="stylesheet" href="dhtmlxScheduler/codebase/ext/dhtmlxscheduler_ext.css" type="text/css" media="screen" title="no title" charset="utf-8">

        <style type="text/css" media="screen">
            html, body{
                margin:0px;
                padding:0px;
                height:100%;
                overflow:hidden;
            }

            .dhx_cal_event.user_site div, .dhx_cal_event_line.user_site{
                background-color:#D6F8CD !important;
                color:#000 !important;
            }

            .dhx_cal_event.user_course div , .dhx_cal_event_line.user_course{
                background-color:#FFD3BD !important;
                color:#000 !important;
            }

            .dhx_cal_event.user_group div , .dhx_cal_event_line.user_group{
                background-color:#FEE7AE !important;
                color:#000 !important;
            }

            .dhx_cal_event.user_user div , .dhx_cal_event_line.user_user{
                background-color:#DCE7EC !important;
                color:#000 !important;
            }
            
            .dhx_cal_light {
                top:80px !important;
                left:80px !important;
            }
        </style>

        <script type="text/javascript" charset="utf-8">
            function init() {

                scheduler.config.mark_now = true;

                var eventtypes=[
                    {key:"site", label:"Global"},
                    {key:"course", label:"Course"},
                    {key:"group", label:"Group"},
                    {key:"user", label:"Admin User"}
                ];

                var group_select_options = {
                    site: [
                        { key: "0", label: "-" }
                    ],
                    course: [
                        { key: "0", label: "-" }
                    ],
                    group: [
{ key: "4", label: "Group 1" },{ key: "5", label: "Group 2" }],
            user: [
                { key: "0", label: "-" }
            ]
        };

        var update_select_options = function(select, options) { // helper function
            select.options.length = 0;
            for (var i=0; i<options.length; i++) {
                var option = options[i];
                select[i] = new Option(option.label, option.key);
            }
        };

        var eventtype_onchange = function(event) {
            var new_group_options = group_select_options[this.value];
            update_select_options(scheduler.formSection('group').control, new_group_options);
        };

        scheduler.locale.labels.unit_tab = "Unit"
        scheduler.locale.labels.section_eventtype="Type of event";
        scheduler.locale.labels.section_group = "Group";
        scheduler.config.details_on_create=true;
        scheduler.config.details_on_dblclick=true;
        scheduler.config.xml_date="%Y-%m-%d %H:%i";
        scheduler.config.time_step = 15;
        scheduler.config.multi_day = true;

        scheduler.templates.week_agenda_event_text = function(start_date, end_date, event, date, position) {
            switch(position){
                case "middle":
                    return "-- " + event.text;
                case "end":
                    return "End: "+scheduler.templates.event_date(start_date) + " " + event.text;
                case "start":
                    return "Start: "+scheduler.templates.event_date(start_date) + " " + event.text;
                default:
                    return scheduler.templates.event_date(start_date) + " " + event.text;
            }
        };

        scheduler.attachEvent("onBeforeLightbox", function(id){
            
            var ev = scheduler.getEvent(id);
            var eventtype = ev.eventtype||eventtypes[0].key;
            var new_group_options = group_select_options[eventtype];
            update_select_options(scheduler.formSection('group').control, new_group_options);
            return true;
        });

        scheduler.config.lightbox.sections=[
            {name:"name", height:30, type:"textarea", map_to:"text", focus:true },
            {name:"description", height:30, map_to:"description", type:"textarea"},
            {name:"eventtype", height:23, type:"select", options:eventtypes, map_to:"eventtype", onchange:eventtype_onchange },
            {name:"group", height:23, type:"select", options: group_select_options, map_to:"groupid" },
            {name:"time", height:72, type:"calendar_time", map_to:"auto"}
        ]
        
        scheduler.showLightbox;

        scheduler.templates.event_class=function(start,end,event){
            return "user_"+event.eventtype;
        }

        scheduler.createUnitsView({
            name:"unit",
            property:"eventtype",
            list:eventtypes
        });

        scheduler.config.first_hour=8;
        scheduler.config.last_hour=18;

        scheduler.locale.labels.section_name="Name";
        scheduler.config.details_on_create=true;
        scheduler.config.details_on_dblclick=true;

        scheduler.init('scheduler_here',new Date(2012,11,1),"month");
        scheduler.setLoadMode("month")
        scheduler.load("dhtmlxScheduler/samples/01_initialization_loading/data/moodle_events.php?att_id=100&userid=2&courseid=2&defaultgroup=4");

        var dp = new dataProcessor("dhtmlxScheduler/samples/01_initialization_loading/data/moodle_events.php?att_id=100&userid=2&courseid=2&defaultgroup=4");
        dp.init(scheduler);

    }

    function show_minical(){
        if (scheduler.isCalendarVisible())
            scheduler.destroyCalendar();
        else
            scheduler.renderCalendar({
                position:"dhx_minical_icon",
                date:scheduler._date,
                navigation:true,
                handler:function(date,calendar){
                    scheduler.setCurrentView(date);
                    scheduler.destroyCalendar()
                }
        });
    }
        </script>

        <body onload="init();">

            <div id="scheduler_here" class="dhx_cal_container" style='width:735px; height:100%;'>
                <div class="dhx_cal_navline">
                    <input type="button" name="print" value="PDF" onclick="scheduler.toPDF('scheduler-pdf-php/generate.php')">

                        <div class="dhx_cal_prev_button">&nbsp;</div>
                        <div class="dhx_cal_next_button">&nbsp;</div>
                        <div class="dhx_cal_today_button"></div>
                        <div class="dhx_cal_date"></div>

                        <div class="dhx_minical_icon" id="dhx_minical_icon" onclick="show_minical()">&nbsp;</div>
                        <div class="dhx_cal_tab" name="unit_tab" style="right:250px;"></div>
                        <div class="dhx_cal_tab" name="week_agenda_tab" style="right:200px;"></div>
                        <div class="dhx_cal_tab" name="year_tab" style="right:150px;"></div>
                        <div class="dhx_cal_tab" name="day_tab" style="right:100px;"></div>
                        <div class="dhx_cal_tab" name="week_tab" style="right:50px;"></div>
                        <div class="dhx_cal_tab" name="month_tab" style="right:0px;"></div>

                </div>
                <div class="dhx_cal_header">
                </div>
                <div class="dhx_cal_data">
                </div>
            </div>
        </body>

Here is my server side code:

<?php

include ('../../../codebase/connector/scheduler_connector.php');
include ('../../common/config.php');

require_once('../../../../../../../config.php');

$id = required_param('courseid', PARAM_INT);       // course id
$att_id = required_param('att_id', PARAM_INT);

$scheduler = new stdClass();
$scheduler->att_id = $att_id;

$res = mysql_connect($CFG->dbhost, $CFG->dbuser, $CFG->dbpass);
mysql_select_db($CFG->dbname);

$course = $DB->get_record('course', array('id' => $id), '*', MUST_EXIST);
require_login($course);

/**
 * Get calendar's allowed types
 *
 * @param stdClass $allowed list of allowed edit for event  type
 * @param stdClass|int $course object of a course or course id
 */
function calendar_estudio_get_allowed_types(&$allowed, $course = null) {
    global $USER, $CFG, $DB;
    $allowed = new stdClass();
    $allowed->user = has_capability('moodle/calendar:manageownentries', get_system_context());
    $allowed->groups = false; // This may change just below
    $allowed->courses = false; // This may change just below
    $allowed->site = has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_COURSE, SITEID));

    if (!empty($course)) {
        if (!is_object($course)) {
            $course = $DB->get_record('course', array('id' => $course), '*', MUST_EXIST);
        }
        if ($course->id != SITEID) {
            $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
            $allowed->user = has_capability('moodle/calendar:manageownentries', $coursecontext);

            if (has_capability('moodle/calendar:manageentries', $coursecontext)) {
                $allowed->courses = array($course->id => 1);

                if ($course->groupmode != NOGROUPS || !$course->groupmodeforce) {
                    $allowed->groups = groups_get_all_groups($course->id);
                }
            } else if (has_capability('moodle/calendar:managegroupentries', $coursecontext)) {
                if ($course->groupmode != NOGROUPS || !$course->groupmodeforce) {
                    $allowed->groups = groups_get_all_groups($course->id);
                }
            }
        }
    }
    return $allowed;
}

$formoptions = new stdClass;
$allowed_units = calendar_estudio_get_allowed_types($formoptions->eventtypes, $course);

// update events
function update_events($action) {

    global $scheduler;
    global $CFG;
    global $allowed_units;

    $status = $action->get_status();
    $session_start = $action->get_value("start_time");
    $courseid = $action->get_value("courseid");
    $userid = $action->get_value("userid");
    $defaultgroup = $_GET['defaultgroup'];
    $start = strtotime($session_start);
    $session_end = $action->get_value("end_time");
    $name = $action->get_value("name");
    $id = $action->get_value("id");
    $new_id = $action->get_new_id();
    $description = $action->get_value("description");
    $groupid = $action->get_value("groupid");
    $eventtype = $action->get_value("eventtype");
    $end = strtotime($session_end);
    $duration = $end - $start;

    if ($status == "updated") {
        if ($eventtype == "group") {

            if ($allowed_units->groups) {
                if ($groupid == '' || $groupid == '0') {

                    $thisgroupid = $defaultgroup;
                } else {

                    $thisgroupid = $groupid;
                }

                $scheduler->sql->query("UPDATE " . $CFG->prefix . "event SET timestart='" . $start . "' , timeduration='" . $duration
                        . "' , courseid='0', userid='0', eventtype='group', groupid='" . $thisgroupid . "' WHERE id='" . $id . "'");
                $scheduler->sql->query("UPDATE " . $CFG->prefix . "event SET start_time='" . $session_start . "' , end_time='"
                        . $session_end . "' , name='" . $name . "' , description='" . $description . "' WHERE id='" . $id . "'");
            }
        } else {

            if ($eventtype == "course") {
                if ($allowed_units->courses) {
                    $scheduler->sql->query("UPDATE " . $CFG->prefix . "event SET start_time='" . $session_start . "' , end_time='" . $session_end . "' , name='" . $name . "' , description='" . $description . "', eventtype='course' WHERE id='" . $id . "'");
                    $scheduler->sql->query("UPDATE " . $CFG->prefix . "event SET timestart='" . $start . "' , timeduration='" . $duration . "' , userid='0' , courseid='" . $courseid . "' , groupid='0' WHERE id='" . $id . "'");
                }
            } else {
                if ($eventtype == "site") {

                    if ($allowed_units->site) {
                        $scheduler->sql->query("UPDATE " . $CFG->prefix . "event SET start_time='" . $session_start . "' , end_time='" . $session_end . "' , name='" . $name . "' , description='" . $description . "', eventtype='site' WHERE id='" . $id . "'");
                        $scheduler->sql->query("UPDATE " . $CFG->prefix . "event SET timestart='" . $start . "' , timeduration='" . $duration . "' , userid='0' , courseid='0', groupid='0' WHERE id='" . $id . "'");
                    }
                } else {
                    if ($eventtype == "user") {
                        if ($allowed_units->user) {
                            $scheduler->sql->query("UPDATE " . $CFG->prefix . "event SET start_time='" . $session_start . "' , end_time='" . $session_end . "' , name='" . $name . "' , description='" . $description . "', eventtype='user' WHERE id='" . $id . "'");
                            $scheduler->sql->query("UPDATE " . $CFG->prefix . "event SET timestart='" . $start . "' , timeduration='" . $duration . "' , courseid='0' , userid='" . $userid . "' , groupid='0' WHERE id='" . $id . "'");
                        }
                    } else {
                        // eventtype not recognised
                    }
                }
            }
        }
    } else {
        // Handle deleted events
        if ($status == "deleted") {

            $scheduler->sql->query("DELETE FROM `" . $CFG->prefix . "event` WHERE id='" . $id . "'");
        }
    }
    $action->success($new_id);
}

// insert events
function insert_events($action) {

    global $scheduler;
    global $CFG;
    global $allowed_units;

    $status = $action->get_status();
    $session_start = $action->get_value("start_time");
    $courseid = $action->get_value("courseid");
    $userid = $action->get_value("userid");
    $defaultgroup = $_GET['defaultgroup'];
    $start = strtotime($session_start);
    $session_end = $action->get_value("end_time");
    $name = $action->get_value("name");
    $description = $action->get_value("description");
    $groupid = $action->get_value("groupid");
    $eventtype = $action->get_value("eventtype");
    $end = strtotime($session_end);
    $duration = $end - $start;
    $id = $action->get_new_id();

    if ($status == "inserted") {
        if ($eventtype == "group") {
            if ($allowed_units->groups) {
                if ($groupid == '') {
                    $thisgroupid = $defaultgroup;
                } else {
                    $thisgroupid = $groupid;
                }
                $scheduler->sql->query("INSERT INTO "
                        . $CFG->prefix . "event(`start_time`,`end_time`,`name`,`description`,`eventtype`,`groupid`, `timestart`, `timeduration`, `courseid`, `userid`)
                        VALUES ( '"
                        . $session_start . "' , '"
                        . $session_end . "' , '"
                        . $name . "' , '"
                        . $description . "' ,'group','"
                        . $thisgroupid . "' , '"
                        . $start . "' , '"
                        . $duration . "' , '0' , '0' )"
                );
            }
        } else {
            if ($eventtype == "course") {
                if ($allowed_units->courses) {
                    $scheduler->sql->query("INSERT INTO "
                            . $CFG->prefix . "event(`start_time`,`end_time`,`name`,`description`,`eventtype`,`groupid`, `timestart`, `timeduration`, `courseid`, `userid`)
                        VALUES ( '"
                            . $session_start . "' , '"
                            . $session_end . "' , '"
                            . $name . "' , '"
                            . $description . "' ,'course','0' , '"
                            . $start . "' , '"
                            . $duration . "' , '"
                            . $courseid . "' , '0' )"
                    );
                }
            } else {
                if ($eventtype == "site") {
                    if ($allowed_units->site) {
                        $scheduler->sql->query("INSERT INTO "
                                . $CFG->prefix . "event(`start_time`,`end_time`,`name`,`description`,`eventtype`,`groupid`, `timestart`, `timeduration`, `courseid`, `userid`)
                        VALUES ( '"
                                . $session_start . "' , '"
                                . $session_end . "' , '"
                                . $name . "' , '"
                                . $description . "' ,'site','0' , '"
                                . $start . "' , '"
                                . $duration . "' , '0' , '0' )"
                        );
                    }
                } else {
                    if ($eventtype == "user") {
                        if ($allowed_units->user) {
                            $scheduler->sql->query("INSERT INTO "
                                    . $CFG->prefix . "event(`start_time`,`end_time`,`name`,`description`,`eventtype`,`groupid`, `timestart`, `timeduration`, `courseid`, `userid`)
                        VALUES ( '"
                                    . $session_start . "' , '"
                                    . $session_end . "' , '"
                                    . $name . "' , '"
                                    . $description . "' ,'user','0' , '"
                                    . $start . "' , '"
                                    . $duration . "' , '0' , '"
                                    . $userid . "' )"
                            );
                        }
                    } else {
                        // eventtype not recognised
                    }
                }
            }
        }
    } else {
        
    }

    $action->success($id);
    $action->set_new_id($id);
}

function custom_code($action) {
    $action->add_field("userid", $_GET['userid']);
    $action->add_field("courseid", $_GET['courseid']);
    $action->success();
}

$scheduler = new schedulerConnector($res);
$scheduler->enable_log("log.txt", true);
$scheduler->event->attach("beforeProcessing", 'custom_code');
$scheduler->event->attach("beforeProcessing", "update_events");
$scheduler->event->attach("afterProcessing", "insert_events");

$userid = $_GET['userid'];
$scheduler->render_sql("select id, start_time, end_time, name, description, eventtype, groupid from ".$CFG->prefix."event where userid = '".$userid."' or userid = '0'","id","start_time, end_time, name, description, eventtype, groupid");
?>

I tried adding the following but it did not help

    $action->success($id);
    $action->set_new_id($id);

Much appreciated.
Barry

Hi,
actually $action->set_new_id($new_id); should do exactly the same - set new id for item.
If still doesn’t work, could you provide complete demo inclulding test database dump to get sample to work at local machine?

I managed to fix it like this:

    $action->success();
    $new_id = mysql_insert_id();
    $action->set_new_id($new_id);
    $action->success($new_id);

Thanks,
Barry

I ran into this as well. The problem is that the javascript never calls the “afterUpdate” event required to clear the in_progress state of the event. It’s easy to reproduce… just refresh the page, drag an event to a different time, and then drag it again. The second (and subsequent) changes will not save because the javascript thinks that event is still being processed from the first change. A call to the afterUpdate event handler addresses this.

The reason the event is not called is because the dhtmlObject readyState is returning “complete” instead of an integer “4”.

To fix, change line 97 in the dhtmlxscheduler.js to add another condition checking for the word “complete”. It should read as so:
if ((!dhtmlObject.xmlDoc.readyState)||(dhtmlObject.xmlDoc.readyState == 4 || dhtmlObject.xmlDoc.readyState == “complete”)){

And then you’ll be able to update events after creating or changing earlier without refreshing.

-Eric

The reason the event is not called is because the dhtmlObject readyState is returning “complete” instead of an integer “4”.

Can you please provide some more details, in which browser such behavior occurs ?
Value of “4” is part of standard - w3schools.com/ajax/ajax_xmlh … change.asp
so it is quite strange that browser provides some other value.

HI,
I also faced the same problem , it works first time. If i update the same event again or if i drag n drop that event that will not work. Even i placed the code
if((!B.xmlDoc.readyState)||(B.xmlDoc.readyState==4 || B.xmlDoc.readyState==“complete”)).But still it is not working. Please help me in this regard.Eagerly waiting for your response.

Thanks in advance.

Hi,
are you able to update a new event after refreshing the page?
Does your server response contains a correct new ID of the inserted event (same as in the database)?

HI Serge,

I am able to insert / update event after refreshing the page.But the problem is the same event is not update more than one time.Please suggest me if any clue…

Hi,
do you use build-in dataProcessor with server-side dataConnector or your custom server-side insert/update/delete logic ?

So I was having this same problem with a system that I was put in charge to fix issues, like this. I was able to update each event once until the page was refreshed. I updated the script to the most recent version (4.0 build 130813).

It was using a custom server-side processing script. I tried the documentation, which is really bad and has no entries on data formats required (at least I couldn’t find it) - the problem with open source software: bad documentation… I was able to fix it by looking at the results returned by the demo

Anyway, the problem was that the software wasn’t responding with a XML - had to set header “Content-type:text/xml” AND return:

<?xml version="1.0" ?>

For delete return:

<?xml version='1.0' ?>

And for insert:

<?xml version='1.0' ?>

Where tid is the event_id… sid is the event_id in update/delete, but returns a number that made no sense in insert, while testing.

Hope this helps someone! And the devs update the docs.

Hi all, I’m suffering from the same problem, though I have discovered the cause - PDO driver doesn’t support the lastInsertId method.

Log Message:
PDO::lastInsertId(): SQLSTATE[IM001]: Driver does not support this function: driver does not support lastInsertId() at db_pdo.php line 54

This doesn’t mean I have the solution… Other than changing the connection method, which I want to avoid.

I am running the PDO driver to an odbc connection to MSSQL DB on a different server.

Any ideas on how to get round this issue?

You can override INSERT sql query, with some other logic to retrieve the new ID
Without new Id value, connector will not be able to function correctly.

Thanks, - my thoughts were to use after Insert function on dataconnector

$scheduler->event->attach(“afterInsert”,“my_update”);

function my_update($data){
global $conn;
$job=$data->get_value(“job”);
$conn->sql->query(“SELECT event_id FROM schedule where id={$job}”);

$data->set_new_id($value);

$data->success(); 

}

though, it’s with: $data->set_new_id($value);
Where I have difficulty fetching the value from the query and assigning it as the new event_id.

Any ideas on fetching values from a custom select query ?

Okay, so a solution is to run a max(id) query in place of lastInsertId() inside db_pdo.php
This works as get_new_id runs immediately after the insert query, and will only return the id for that event.

protected function get_new_id(){
	// return $this->connection->lastInsertId();

	require_once '\setup\mac_config.inc.php';
	$queryinvnum = "SELECT max(event_id) FROM schedule";
	$resinvnum=odbc_exec($mac_conn,$queryinvnum);
	while(odbc_fetch_row($resinvnum)){ 	
	$res = odbc_result($resinvnum, 1);	}
	return $res;			
}

Not the most elegant solution, but a solution none the less.