Changeset 06b76b in indico


Ignore:
Timestamp:
01/24/12 11:15:33 (17 months ago)
Author:
Pedro Ferreira <jose.pedro.ferreira@…>
Branches:
master, hello-world-walkthrough, ipv6, v0.98-series, v0.98.2, v0.98.3, v0.99, b8c30da8ebdbdcbd675a873997cc3e95f567de49, 4287315ec967a3da168d83963c14001db8487d53
Children:
44e7c3
Parents:
c82c67
git-author:
Pedro Ferreira <jose.pedro.ferreira@…> (10/28/11 14:28:22)
git-committer:
Pedro Ferreira <jose.pedro.ferreira@…> (01/24/12 11:15:33)
Message:

[IMP] Full undo support

  • Deferred-based events;
Files:
5 added
16 edited

Legend:

Unmodified
Added
Removed
  • etc/js/indico.cfg

    refa98d r06b76b  
    6161    Layout.js 
    6262    Base.js 
     63    DragAndDrop.js 
     64    Undo.js 
    6365    Draw.js 
    6466    Management.js 
  • indico/MaKaC/common/Configuration.py

    r1a3173 r06b76b  
    115115                 "indico_co": "indico_co.png", 
    116116                 "login": "pict_login.png", 
     117                 "tt_time": "tt_time.png", 
    117118                 "table": "img_table.png", 
    118119                 "lectureMenu": "pict_event_negb.png", 
  • indico/MaKaC/services/implementation/base.py

    rb58f4b r06b76b  
    9696        value = self._paramList.get(paramName) 
    9797 
    98  
    9998        if (not allowEmpty) and (value == None): 
    10099            raise EmptyParameterException(paramName) 
  • indico/MaKaC/services/implementation/schedule.py

    r05eb0f r06b76b  
    10741074        self._sessionId = pManager.extract("sessionId", pType=str, allowEmpty=True, defaultValue=None) 
    10751075        self._sessionSlotId = pManager.extract("sessionSlotId", pType=str, allowEmpty=True, defaultValue=None) 
    1076  
    1077     def _performOperation(self): 
    1078  
     1076        self._keepTime = pManager.extract("keepTime", pType=bool, allowEmpty=True, defaultValue=False) 
     1077 
     1078    def _performOperation(self): 
    10791079        if (self._sessionId != None and self._sessionSlotId != None): 
    10801080            self._schEntry = self._conf.getSessionById(self._sessionId).getSlotById(self._sessionSlotId).getSchedule().getEntryById(self._schEntryId) 
     
    11131113                            self._schEntry.setDuration(dur=slot.getDuration()) 
    11141114                        else: 
    1115                             self._schEntry.setStartDate(slot.getSchedule().calculateEndDate()) 
     1115                            if self._keepTime: 
     1116                                self._schEntry.setStartDate(oldDate) 
     1117                            else: 
     1118                                self._schEntry.setStartDate(slot.getSchedule().calculateEndDate()) 
    11161119                            #self._schEntry.setDuration(dur=session.getContribDuration()) 
    11171120                        # add it to new container 
  • indico/MaKaC/webinterface/tpls/ConfModifScheduleGraphic.tpl

    rc0de5a r06b76b  
    11<div class="groupTitleNoBorder">${ _("Timetable")} <em>(${ _("from") } ${ start_date } ${ _("to") } ${ end_date } <a href=${ editURL }>[${_("edit")}]</a> ${_("Timezone")}: ${ timezone })</em></div> 
     2 
    23<div id="timetableDiv" style="position: relative;"> 
    34 
  • indico/MaKaC/webinterface/tpls/ConferenceTimeTable.tpl

    r1a8f22 r06b76b  
    1  
    21<div id="timetable" style="position: relative;"> 
    32 
  • indico/MaKaC/webinterface/tpls/js/vars.js.tpl

    r6d8443 r06b76b  
    8585        indico_small: "${ iconFileName("indico_small")}", 
    8686        protected: "${ iconFileName("protected")}", 
    87         calendarWidget: "${ iconFileName("calendarWidget") }" 
     87        calendarWidget: "${ iconFileName("calendarWidget") }", 
     88        tt_time: "${ iconFileName("tt_time") }" 
    8889    }, 
    8990    FileTypeIcons: 
  • indico/htdocs/css/Default.css

    rc82c67 r06b76b  
    50135013} 
    50145014 
    5015 /* Timetable drag n drop, 
    5016    droppable styles starts here. */ 
     5015.timetableBlock { 
     5016    box-shadow: 0px 0px 5px #DDD; 
     5017} 
     5018 
     5019/* Timetable drag n drop */ 
     5020 
     5021#tt_hour_tip { 
     5022    cursor: pointer; 
     5023    overflow: auto; 
     5024    background: white; 
     5025    position: absolute; 
     5026    z-index: 1; 
     5027} 
     5028 
     5029#tt_hour_tip:hover { 
     5030    opacity: 0.7; 
     5031} 
     5032 
     5033.hourLine { 
     5034    position: absolute; 
     5035    border-top: 1px solid #E8E8E8; 
     5036    font-size: 11px; 
     5037} 
     5038 
     5039.ui-state-disabled.hourLine { 
     5040    opacity: 1.0 !important; 
     5041} 
     5042 
     5043.ui-droppable-disabled { 
     5044    opacity: 0.7 !important; 
     5045} 
    50175046 
    50185047/* For when the  Shift is held down */ 
     
    50485077 
    50495078div.ui-draggable-dragging { 
    5050     border: 3px solid gold; 
    5051     /*background-color: gold;*/ 
    5052     /*To make the current dragged element 
    5053       on top of everything*/ 
    50545079    z-index: 9000; 
    5055 } 
    5056  
    5057 div.dragTip { 
    5058     /* Just over 9000! (To be "above" the draggable, which has z-index 9000) */ 
    5059     z-index: 9001; 
    5060     position: absolute; 
    5061     width: 100%; 
    5062     top: 350; 
    5063     border-top: 1px dotted red; 
    5064     font-weight: bold; 
     5080    opacity: 0.5; 
    50655081} 
    50665082 
     
    57935809} 
    57945810 
    5795 div.blockMoveProgressText { 
    5796 /* 
    5797     position: fixed; 
    5798     bottom: 0px;*/ 
     5811#tt_status_info .text { 
    57995812    padding: 3px 8px 3px; 
    58005813    text-align: center; 
    5801     color: #DDD; 
    5802 } 
    5803  
    5804 div.blockMoveProgressImage { 
    5805     background: transparent url("../images/load_lightblue.gif") no-repeat center center; 
    5806     padding-bottom: 49px; 
    5807 } 
    5808  
    5809 div.blockMoveProgress { 
    5810     width: 100px; 
    5811     background-color: #424242; 
     5814    color: #aaa; 
     5815    float: right; 
     5816} 
     5817 
     5818#tt_status_info img { 
     5819    margin-top: 2px; 
     5820} 
     5821 
     5822#tt_status_info { 
     5823    background: #fefefe; 
     5824    border: 1px solid #eee; 
     5825    padding: 5px; 
    58125826    position: fixed; 
    5813     bottom: 1px; 
    5814     left: 91.8%; 
     5827    bottom: 5px; 
     5828    right: 5px; 
    58155829    -moz-border-radius: 5px; 
    58165830    -webkit-border-radius: 5px; 
     5831    opacity: 0.9; 
     5832    box-shadow: 0px 0px 2px rgba(220, 220, 200, 0.4); 
    58175833} 
    58185834 
     
    73887404    background: white url("../images/drag.png") left top no-repeat; 
    73897405} 
     7406 
    73907407.arrow { 
    73917408    background: #ECECEC; 
     
    75767593} 
    75777594 
     7595#dragTip { 
     7596    position: absolute; 
     7597    background: #f0f0f0; 
     7598    border: 1px solid #aaa; 
     7599    border-radius: 4px; 
     7600    font-size: 10px; 
     7601    padding: 4px; 
     7602    opacity: 0.7; 
     7603    box-shadow: 0px 0px 4px rgba(0,0,0,0.3); 
     7604} 
     7605 
     7606#dragTip .pointer { 
     7607    position: absolute; 
     7608    background: url('../images/pointer_tip.png'); 
     7609    height: 7px; 
     7610    width: 5px; 
     7611    top: 6px; 
     7612    right: -5px; 
     7613} 
     7614 
     7615.ui-resizable-resizing { 
     7616    opacity: 0.9; 
     7617    z-index: 1000; 
     7618} 
  • indico/htdocs/js/indico/Core/Data.js

    r791f15 r06b76b  
    166166    dateTimeIndicoToJS: function(obj) { 
    167167        m1 = obj.date.match(/(\d+)[\-\/](\d+)[\-\/](\d+)/); 
    168         m2 = obj.time.match(/(\d+):(\d+):(\d+)/); 
    169  
    170  
    171         var date = new Date(m1[1],m1[2] - 1,m1[3]); 
     168        m2 = obj.time.match(/(\d+):(\d+)(?::(\d+))?/); 
     169 
     170 
     171        var date = new Date(m1[1],m1[2] - 1,m1[3]||0); 
    172172        setTime(date, [m2[1],m2[2],m2[3]]); 
    173173 
  • indico/htdocs/js/indico/Core/Dialogs/Util.js

    r791f15 r06b76b  
    2020    }, 
    2121 
    22     blockMoveProgress: function(text) { 
    23       var message = (text != undefined) ? $T(text) : ""; 
    24       var loadingImage = $('<div class= "blockMoveProgressImage"></div>'); 
    25       var loadingText = $('<div class="blockMoveProgressText"></div>').html(message); 
    26       var progress = $('<div class="blockMoveProgress"></div>').append(loadingImage, loadingText); 
     22    ttStatusInfo: function(text) { 
     23        var stext = $('<div class="text"></div>').text(text ? $T(text) : null); 
     24        var image = $('<img/>', { 
     25            src: "images/loading.gif", 
     26            alt: $T('Loading...') 
     27        }); 
    2728 
    28       $('body').append(progress); 
     29        var progress = $('<div id="tt_status_info"></div>'). 
     30            append(image, stext); 
     31 
     32        if (!$('#tt_status_info').length) { 
     33            $('body').append(progress); 
     34        } else { 
     35            $('#tt_status_info').replaceWith(progress); 
     36        } 
     37 
    2938        return function() { 
    30           $(progress).remove(); 
     39            $(progress).remove(); 
    3140        }; 
    3241    }, 
  • indico/htdocs/js/indico/Management/Timetable.js

    r791f15 r06b76b  
    10351035 
    10361036                // disable the radio button where the item already belongs to 
    1037                 if (!this.inSession && this.startDate.replaceAll('-', '') == currentDay) { 
     1037                if (!this.inSession && Util.formatDateTime(this.eventData.startDate, IndicoDateTimeFormats.Ordinal) == currentDay) { 
    10381038                    rb.dom.disabled = 'disabled'; 
    10391039                } 
     
    10561056                    rb.dom.value = value.sessionId + ':' + value.sessionSlotId; 
    10571057 
    1058                     if (this.inSession && value.sessionId == this.sessionId && value.sessionSlotId == this.slotId) { 
     1058                    if (this.inSession && value.sessionId == this.eventData.sessionId && value.sessionSlotId == this.eventData.sessionSlotId) { 
    10591059                        rb.dom.disabled = 'disabled'; 
    10601060                    } 
     
    11081108 
    11091109                        var value = self.getChosenValue(); 
    1110                         self.handleBlockMove(self, value); 
    1111  
    1112                         var killProgress = IndicoUI.Dialogs.Util.progress($T('Moving the entry...')); 
    1113  
    1114                         indicoRequest(self.managementActions.methods[self.inSession?'SessionEntry':'Event'].moveEntry, { 
    1115                             value : value, 
    1116                             conference : self.confId, 
    1117                             scheduleEntryId : self.scheduleEntryId, 
    1118                             sessionId : self.sessionId, 
    1119                             sessionSlotId : self.slotId 
    1120                         }, function(result, error) { 
    1121                             if (error) { 
    1122                                 killProgress(); 
    1123                                 IndicoUtil.errorReport(error); 
    1124                             } else { 
    1125                                 // change json and repaint timetable 
    1126                                 self.managementActions.timetable._updateMovedEntry(result, result.old.id); 
    1127                                 killProgress(); 
    1128                                 self.close(); 
    1129                             } 
    1130                         }); 
     1110                        self.managementActions.moveToSession(self.eventData, value, 'drop'); 
    11311111                    }], 
    11321112                    [$T('Cancel'), function() { 
     
    11381118            draw: function() { 
    11391119                var self = this; 
    1140                 this.inSession = true; 
    1141  
    1142                 if (self.sessionId === null && self.slotId === null) { 
     1120 
     1121                if (this.eventData.sessionId === null && this.eventData.slotId === null) { 
    11431122                    this.inSession = false; 
    11441123                } 
    11451124                // populate the tabslist 
    1146                 var tabData = self.topLevelTimetableData; 
     1125                var tabData = this.topLevelTimetableData; 
    11471126 
    11481127                // sort tabs according to days 
     
    11631142                var contribLocation = null; 
    11641143                if (this.inSession) { 
    1165                     contribLocation = self.topLevelTimetableData[self.currentDay]['s' + self.sessionId + 'l' + self.slotId].title + 
     1144                    contribLocation = self.topLevelTimetableData[this.currentDay] 
     1145                    ['s' + this.eventData.sessionId + 'l' + this.eventData.sessionSlotId].title + 
    11661146                        " (interval #" + self.slotId + ")"; 
    11671147                } else { 
     
    12061186                this.tabWidget.postDraw(); 
    12071187                this.ExclusivePopupWithButtons.prototype.postDraw.call(this); 
    1208             }, 
    1209  
    1210           /* Takes care of moving a contribution/timeblock to another session/timetable. 
    1211            * This goes for both "drag and drop" as well as the regular "MoveEntry Dialog clicking"*/ 
    1212           handleBlockMove: function(eventData, value) { 
    1213             var self = this; 
    1214  
    1215             // if nothing has been selected yet 
    1216             if (!value) { 
    1217               return false; 
    12181188            } 
    1219  
    1220             //Displays a "loading ..." div at the righthand bottom side 
    1221             var killProgress = IndicoUI.Dialogs.Util.blockMoveProgress("Moving the entry..."); 
    1222  
    1223             self.inSession = true; 
    1224             if (eventData.sessionId == null && eventData.sessionSlotId == null) { 
    1225               self.inSession = false; 
    1226             } 
    1227  
    1228             indicoRequest(self.managementActions.methods[self.inSession?'SessionEntry':'Event'].moveEntry, { 
    1229                             value : value, 
    1230                             conference : self.confId, 
    1231                             scheduleEntryId : eventData.scheduleEntryId, 
    1232                             sessionId : eventData.sessionId, 
    1233                             sessionSlotId : self.slotId 
    1234                           }, function(result, error) { 
    1235                             if (error) { 
    1236                               killProgress(); 
    1237                               IndicoUtil.errorReport(error); 
    1238                             } else { 
    1239                               // change json and repaint timetable 
    1240                               self.managementActions.timetable._updateMovedEntry(result, result.old.id); 
    1241                               killProgress(); 
    1242                               self.close(); 
    1243                             }}); 
    1244           } 
    12451189        }, 
    1246         function(managementActions, timetable, entryType, sessionId, slotId, currentDay, scheduleEntryId, confId, startDate) { 
    1247             this.managementActions = managementActions; 
    1248             this.timetableData = timetable.getData(); 
    1249             this.topLevelTimetableData = timetable.parentTimetable?timetable.parentTimetable.getData():this.timetableData; 
    1250             this.timetable = timetable ; 
    1251             this.entryType = entryType; 
    1252             this.sessionId = sessionId; 
    1253             this.slotId = slotId; 
    1254             this.currentDay = currentDay; 
    1255             this.scheduleEntryId = scheduleEntryId; 
    1256             this.confId = confId; 
    1257             this.startDate = startDate; 
    1258  
    1259             var self = this; 
    1260  
    1261             this.ExclusivePopupWithButtons($T("Move Timetable Entry"), 
     1190     function(managementActions, timetable, eventData, currentDay) { 
     1191         this.managementActions = managementActions; 
     1192         this.timetableData = timetable.getData(); 
     1193         this.topLevelTimetableData = timetable.parentTimetable?timetable.parentTimetable.getData():this.timetableData; 
     1194         this.timetable = timetable; 
     1195         this.currentDay = currentDay; 
     1196         this.eventData = eventData; 
     1197 
     1198         this.inSession = (eventData.sessionId != null) && (eventData.sessionSlotId != null); 
     1199 
     1200         var self = this; 
     1201 
     1202         this.ExclusivePopupWithButtons($T("Move Timetable Entry"), 
    12621203            function() { 
    1263               self.close(); 
     1204                self.close(); 
    12641205            }); 
    1265         }); 
     1206     }); 
    12661207 
    12671208 
  • indico/htdocs/js/indico/Timetable/Base.js

    r791f15 r06b76b  
    5252            $('<div/>').css('display', 'block'), 
    5353            this.legend, 
    54             this.header.dom, 
     54            this.header, 
    5555            timetableDiv.dom, 
    5656            this.loadingIndicator.dom).get(); 
     
    6868    getData: function() { 
    6969        return this.data; 
     70    }, 
     71 
     72    get_elem: function(blkId) { 
     73        return $(this.getTimetableDrawer()._blockMap[blkId]); 
    7074    }, 
    7175 
     
    97101    }, 
    98102 
     103    setSelectedTab: function(val) { 
     104        // same as inherited, but return deferred 
     105        var dfr = $.Deferred(); 
     106        $('body').one('timetable_ready', function() { 
     107            dfr.resolve(); 
     108        }); 
     109        this.LookupTabWidget.prototype.setSelectedTab.call(this, val) 
     110        return dfr.promise(); 
     111    }, 
     112 
    99113    getTimetableDrawer: function() { 
    100114        return this.timetableDrawer; 
     
    135149    }, 
    136150 
    137     _shiftKeyListener: function() { 
    138       var indicatorDiv = $('.shiftIndicator'); 
    139  
    140       //If its not already drawn/appended 
    141       if(!(indicatorDiv.length > 0)) { 
    142         indicatorDiv = (Html.div('shiftIndicator', $T("Shifting later entries ENABLED"))).dom; 
    143         $('body').append(indicatorDiv); 
    144       } 
    145  
    146       //< Keyboard Key "Shift" held down > listener for shifting while dragging blocks 
    147       $(window).keydown(function(e) { 
    148         //if Shift is pushed down 
    149         if(e.keyCode == '16') { 
    150           $(window).data('shiftIsPressed', true); 
    151           $(indicatorDiv).fadeIn("fast"); 
    152         }}).keyup(function(e){ 
    153           if(e.keyCode == '16') { 
    154             $(window).data('shiftIsPressed', false); 
    155             $(indicatorDiv).fadeOut("fast"); 
    156           } 
    157         }); 
    158  
    159       $(window).data('shiftIsPressed', false); //default value is false 
    160     } 
    161151}, 
    162152     function(data, width, wrappingElement, detailLevel, managementMode) { 
    163153         var self = this; 
    164          this._shiftKeyListener(); 
    165  
    166154         this.data = data; 
    167155 
     
    448436 
    449437    switchToInterval : function(intervalId) { 
     438        var dfr = $.Deferred(); 
    450439        this.disable(); 
    451440 
     
    466455        var content = this.intervalTimeTable.draw(); 
    467456        this.canvas.html(content[0]); 
     457        this.intervalTimeTable.postDraw(); 
    468458        $(this.menu.dom).hide(); 
    469459 
     460        $('body').trigger('timetable_switch_interval', this.intervalTimeTable); 
     461 
     462        dfr.resolve(); 
     463        return dfr.promise(); 
    470464    }, 
    471465 
     
    474468    }, 
    475469 
    476     switchToTopLevel : function() { 
     470    switchToTopLevel : function(day) { 
     471        var dfr = $.Deferred(); 
    477472        this.enable(); 
    478         this.setSelectedTab(this.currentDay); 
     473        this.setSelectedTab(day || this.currentDay); 
    479474        $(this.menu.dom).show(); 
    480475        this._generateContent(this.getSelectedPanel()); 
    481476        this.timetableDrawer.redraw(); 
     477        $('body').trigger('timetable_switch_toplevel', this); 
     478 
     479        dfr.resolve(); 
     480        return dfr.promise(); 
    482481    } 
    483482}, 
     
    592591    }, 
    593592 
     593    postDraw: function() { 
     594        this.timetableDrawer.postDraw(); 
     595    }, 
     596 
    594597    setData: function(data) { 
    595598        var day = IndicoUtil.formatDate2(IndicoUtil.parseJsonDate(data.startDate)); 
     
    622625 
    623626}, 
    624      function(parent, width, wrappingElement, managementActions) { 
     627     function(parent, width, wrappingElement, managementActions, layout) { 
    625628 
    626629         this.managementActions = managementActions; 
     
    632635                                                            this.loadingIndicator, 
    633636                                                            !!managementActions, 
    634                                                             managementActions); 
     637                                                            managementActions, 
     638                                                            layout || 'compact'); 
    635639     }); 
    636640 
     
    694698    }, 
    695699 
     700 
     701    _updateMovedEntry: function(result, oldEntryId) { 
     702        return this._updateEntry(result, oldEntryId, function(data){ 
     703 
     704            var oldDay = Util.formatDateTime(Util.parseDateTime(result.old.startDate, IndicoDateTimeFormats.Default), 
     705                                          IndicoDateTimeFormats.Ordinal); 
     706 
     707            if (result.old.sessionId) { 
     708                // block was inside session slot 
     709                delete data[oldDay]['s' + result.old.sessionId + 'l' + result.old.sessionSlotId].entries[result.old.id]; 
     710            } else { 
     711                // block was in top level 
     712                delete data[oldDay][result.old.id]; 
     713            } 
     714 
     715            if(result.slotEntry){ 
     716                // block moves inside session slot 
     717                data[result.day][result.slotEntry.id].entries[result.id] = result.entry; 
     718                // updates the time of the session if it has to be extended 
     719                data[result.day][result.slotEntry.id].startDate.time = result.slotEntry.startDate.time; 
     720                data[result.day][result.slotEntry.id].endDate.time = result.slotEntry.endDate.time; 
     721            } else { 
     722                // block moves to top level 
     723                data[result.day][result.id]=result.entry; 
     724            } 
     725        }); 
     726    }, 
     727 
    696728    /* 
    697729     * 
     
    846878                             this.contextInfo.isPoster?null:this.fitInnerTimetableLink, 
    847879                             customLinks); 
    848         return Html.div({}, this.warningArea, Html.div('clearfix', this.menu, this.infoBox)); 
     880 
     881        var tt_hour_tip = $('<div id="tt_hour_tip"/>').hide().append($('<img/>', {src: imageSrc(Indico.SystemIcons.tt_time), 
     882                                                                                  title:"Add one hour"})) 
     883 
     884        return $('<div/>').append(this.warningArea.dom, $('<div class="clearfix"/>'). 
     885                                  append(this.menu.dom, this.infoBox.dom, tt_hour_tip)); 
    849886        }, 
    850887 
     
    11011138    _updateEntry: function(result, oldEntryId, updateCycle) { 
    11021139 
     1140        var self = this; 
    11031141        var data = this.getData(); 
    11041142 
     
    11401178        } 
    11411179 
     1180        var dfr = $.Deferred(); 
     1181        $('body').one('timetable_redraw', function() { 
     1182            $('body').trigger('timetable_update', self); 
     1183            dfr.resolve(); 
     1184        }); 
    11421185        this.timetableDrawer.redraw(); 
     1186        return dfr.promise(); 
    11431187    }, 
    11441188 
     
    11821226 
    11831227        this.timetableDrawer.redraw(); 
    1184     }, 
    1185  
    1186     _updateMovedEntry: function(result, oldEntryId) { 
    1187         this._updateEntry(result, oldEntryId, function(data){ 
    1188             if (exists(result.slotEntry)) { 
    1189                 // move into a session slot 
    1190                 data[result.day][result.slotEntry.id].entries[result.id] = result.entry; 
    1191                 // updates the time of the session if it has to be extended 
    1192                 data[result.day][result.slotEntry.id].startDate.time = result.slotEntry.startDate.time; 
    1193                 data[result.day][result.slotEntry.id].endDate.time = result.slotEntry.endDate.time; 
    1194             } else { 
    1195                 data[result.day][result.id] = result.entry; 
    1196             } 
    1197         }); 
     1228        $('body').trigger('timetable_update', this); 
     1229 
    11981230    }, 
    11991231 
     
    12701302    _updateEntry: function(result, oldEntryId, updateCycle) { 
    12711303 
     1304        var self = this; 
    12721305        var slot = this.contextInfo; 
    12731306        var data = this.getData(); 
     
    13071340        } 
    13081341 
     1342        var dfr = $.Deferred(); 
     1343        $('body').one('timetable_redraw', function() { 
     1344            $('body').trigger('timetable_update', self); 
     1345            dfr.resolve(); 
     1346        }); 
    13091347        this.timetableDrawer.redraw(); 
    1310  
    1311     }, 
    1312  
    1313     _updateMovedEntry: function(result, oldEntryId) { 
    1314         this._updateEntry(result, oldEntryId, function(data){ 
    1315             if(exists(result.slotEntry)){ 
    1316                 // from slot to slot 
    1317                 data[result.day][result.slotEntry.id].entries[result.id] = result.entry; 
    1318                 // updates the time of the session if it has to be extended 
    1319                 data[result.day][result.slotEntry.id].startDate.time = result.slotEntry.startDate.time; 
    1320                 data[result.day][result.slotEntry.id].endDate.time = result.slotEntry.endDate.time; 
    1321             } else { 
    1322                 // from slot to top level 
    1323                 data[result.day][result.id]=result.entry; 
    1324             } 
    1325         }); 
     1348        return dfr.promise(); 
    13261349    }, 
    13271350 
     
    13641387        } 
    13651388 
     1389        var dfr = $.Deferred(); 
     1390        $('body').bind('timetable_redraw', function() { 
     1391            dfr.resolve(); 
     1392        }); 
    13661393        this.timetableDrawer.redraw(); 
     1394        return dfr.promise(); 
    13671395    }, 
    13681396 
     
    13981426         this.ManagementTimeTable(data, contextInfo, eventInfo, width, wrappingElement, detailLevel, customLinks); 
    13991427         var managementActions = new IntervalTimeTableManagementActions(this, eventInfo, contextInfo, isSessionTimetable); 
    1400          this.IntervalTimeTableMixin(parent, width, wrappingElement, managementActions); 
     1428         this.IntervalTimeTableMixin(parent, width, wrappingElement, managementActions, 'proportional'); 
    14011429 
    14021430         this.canvas = Html.div({}); 
     
    14051433         this.setData = IntervalTimeTableMixin.prototype.setData; 
    14061434         this.getById = IntervalTimeTableMixin.prototype.getById; 
     1435         this.postDraw = IntervalTimeTableMixin.prototype.postDraw; 
    14071436 
    14081437     }); 
  • indico/htdocs/js/indico/Timetable/Draw.js

    r791f15 r06b76b  
    2727         openPopup: function(event) { 
    2828             var self = this; 
    29  
    30              //All elements currently being dragged 
    31              /* We don't want to trigger the popup 
    32               if something is being dragged by the mouse */ 
    33              var draggingElements = $('.ui-draggable-dragging'); 
    34  
    35               // If popup alredy shown do nothing 
    36              if (self.popupActive || self.materialMenuOpen || 
    37                  (draggingElements.length > 0)) { 
    38  
    39                  return; 
    40              } 
    41  
    4229             self.popupActive = true; 
    4330             self.div.dom.style.cursor = 'default'; 
     
    8168             var self = this; 
    8269 
    83              this.materialMenuOpen = false; 
     70            this.materialMenuOpen = false; 
    8471 
    8572             var button = Html.div('timetableBlockMaterial'); 
     
    230217             }; 
    231218 
    232                 this.block = Html.div({style: 
    233                         { 
    234                             position: 'absolute', 
    235                             top: pixels(this.topPos), 
    236                             height: pixels(this.height), 
    237                             backgroundColor: this.printableVersion ? 'white' : this.eventData.color, 
    238                             color: this.printableVersion ? 'black' : this.eventData.textColor, 
    239                             borderColor: this.printableVersion ? 'black' : '', 
    240                             left: pixels(this.leftPos), 
    241                             width: pixels(this.width-3), 
    242                             borderBottomStyle: this.blockData.unfinished?'dashed':'' 
    243                         }, 
    244                                        className: 'timetableBlock ' + classTable[this.eventData.entryType] 
    245                                       }, this._blockDescription() 
    246                ); 
    247  
    248               self.makeDraggable(self.block, self.eventData); 
    249               self.makeResizable(self.block, self.eventData); 
    250  
    251               //When you drop something on a session timeBlock. 
    252               if(this.eventData.entryType == 'Session') { 
    253                 self.makeMoveDroppable(self.block, self.eventData); 
    254               } 
     219                $(this.block.dom).css({ 
     220                    position: 'absolute', 
     221                    top: pixels(this.topPos), 
     222                    height: pixels(this.height), 
     223                    'background-color': this.printableVersion ? 'white' : this.eventData.color, 
     224                    color: this.printableVersion ? 'black' : this.eventData.textColor, 
     225                    'border-color': this.printableVersion ? 'black' : '', 
     226                    left: pixels(this.leftPos), 
     227                    width: pixels(this.width-3), 
     228                    'border-bottom-style': this.blockData.unfinished?'dashed':'' 
     229                }); 
     230 
     231                $(this.block.dom).addClass('timetableBlock ' + 
     232                                           classTable[this.eventData.entryType]); 
     233 
     234                this.block.set(this._blockDescription()); 
    255235 
    256236               // This is a special case, when users shows contribution details it doesn't 
     
    279259               if (!self.printableVersion) { 
    280260                   $(this.block.dom).click(function(e) { 
    281                      self.openPopup(e); 
     261                       if (!self.timetable.getTimetableDrawer().eventsDisabled) { 
     262                           $(this).trigger('tt_block.balloon', e); 
     263                       } 
    282264                   }); 
    283265                   highlightWithMouse(this.div, this.block); 
     
    287269            }, 
    288270 
    289           makeResizable: function(block, eventData) { 
    290             var self = this; 
    291             var originalHeight = $(block.dom).height(); 
    292             $(block.dom).data('originalheight', originalHeight); 
    293             var currentEndHour = null; 
    294             var currentStartHour = null; 
    295  
    296             var resizable = $(block.dom).resizable({ 
    297               containment: $('#timetableDiv'), 
    298               maxWidth: $(block.dom).width(), 
    299               minWidth: $(block.dom).width(), 
    300  
    301               resize: function(event, ui) { 
    302                 //Array of the form [hour] = '..position().top' (relative to timetable) 
    303                 var hourLines = self.timetable.timetableDrawer.hourLinesArray; 
    304                 var mouseTop = event.pageY; 
    305  
    306                 var curBestDiff = Number.MAX_VALUE; 
    307                 var curHour = null; 
    308                 var diff = null; 
    309  
    310                 //This loop extracts the hour you're resizing on. 
    311                 //"The older for loop" is much faster than jQuery by the way 
    312                 for(i in hourLines) { 
    313                   if(hourLines[i] != undefined) { 
    314  
    315                     // If you pull the resize "edge" where there is 
    316                     // no hourLine div 
    317                     if(!($("#hourLine_"+i).length > 0)) { 
    318                       return; 
    319                     } 
    320  
    321                     diff = (mouseTop - $("#hourLine_"+i).offset().top); 
    322                     if((diff > 0) && (diff < curBestDiff)) { 
    323                       curBestDiff = diff; 
    324                       curHour = i; 
    325                     } 
    326                   } 
    327                 } 
    328  
    329                 //returns array, with array[0] = ending hour, array[1] = ending minute (rounded to closest 5-divisible) 
    330                 var gridTime = self.timetable.getTimetableDrawer().fetchTimeDragOnHour($(block.dom), $("#hourLine_"+curHour), curHour, "end"); 
    331                 if(gridTime != null) { 
    332                   currentStartHour = gridTime[0]; 
    333                   currentEndHour = gridTime[1]; 
    334                 } 
    335                 return; 
    336               }, 
    337               stop: function(event, ui) { 
    338                 $('.dragTip').hide(); 
    339                 self.timetable.getTimetableDrawer().releaseResizeOnHour(currentStartHour, currentEndHour, eventData, block); 
    340               } 
    341             }); 
    342           }, 
    343  
    344           makeDraggable: function(block, eventData) { 
    345             var self = this; 
    346  
    347             var originalWidth = $(block.dom).width(); 
    348             var originalHeight = $(block.dom).height(); 
    349  
    350             /* Resize timeblock if nedeed */ 
    351             var maxCol = self.timetable.getTimetableDrawer().maxCol; 
    352             var newWidth = (Math.round($('#timetableDiv').width()/(maxCol))); 
    353  
    354             var heightThreshold = 450; 
    355             var heightChange = (originalHeight > heightThreshold); 
    356             var newHeight =  (heightChange) ? heightThreshold : originalHeight; 
    357  
    358             var widthChange = (!(newWidth == originalWidth)); 
    359  
    360             var draggable = $(block.dom).draggable({ 
    361               //Center the mouse in the middle of the block while dragging 
    362               cursorAt: { 
    363                 left: ((newWidth == undefined) ? 0 : Math.round(newWidth/2)), 
    364                 top: Math.round(newHeight/2) }, 
    365               containment: $('#timetableDiv'), 
    366               revert: 'invalid', 
    367               start: function() { 
    368                 /* Resize timeblock if nedeed */ 
    369                 maxCol = self.timetable.getTimetableDrawer().maxCol; 
    370                 newWidth = (maxCol > 1) ? Math.round($('#timetableDiv').width()/(maxCol)) : originalWidth; 
    371  
    372                 $(block.dom).width(newWidth); 
    373                 $(block.dom).height(newHeight); 
    374  
    375                 //(fulhack) Ugly hack [Begin] on jQuery to make the changed width come in to effect while dragging 
    376                 $(this).data('draggable').helperProportions.width = newWidth; 
    377                 $(this).data('draggable').helperProportions.height = newHeight; 
    378                 $(this).data('draggable')._setContainment(); 
    379                 //Ugly hack [End] 
    380  
    381                 self.timetable.getTimetableDrawer().createDragToolTip(); 
    382  
    383                 var pos = $(block.dom).position(); 
    384                 draggable.data('initialPosition', pos); 
    385               }, 
    386               stop: function() { 
    387                 //reset original width 
    388                 if(widthChange || heightChange) { 
    389                   $(block.dom).animate({ 
    390                     width: originalWidth, 
    391                     height: originalHeight 
    392                   }); 
    393                 } 
    394                 $('.dragTip').remove(); 
    395               }, 
    396               drag: function(event) { 
    397               }}); 
    398  
    399             draggable.data('blockInfo', block); 
    400             draggable.data('eventData', eventData); 
    401           }, 
    402  
    403           /* This is the function that take care of time block drops 
    404             ON a session */ 
    405           makeMoveDroppable: function(block, eventData) { 
    406             var self = this; 
    407  
    408             function isSession(ui) { 
    409               return ($(ui.draggable).hasClass("timetableSession")); 
    410             } 
    411  
    412             function isTouchingWall(ui) { 
    413              var ret = (($(ui.draggable).position().left == 0) 
    414                         || ($(ui.draggable).position().left == 
    415                          ($('#timetableDiv').width()-$(ui.draggable).width()))); 
    416               return ret; 
    417             }; 
    418  
    419             $(block.dom).droppable({ 
    420               drop: function( event, ui ) { 
    421                 $('.dragTip').remove(); 
    422  
    423                 //If a session is dropped on top do nothing. 
    424                 if(isSession(ui)) { 
    425                   return; 
    426                 } 
    427  
    428                 /* If the dragged block dropped to the left most side, 
    429                  * or the right most side (touches left/right wall) 
    430                  * AND.. 
    431                  * the drop is handled by the drop-on-session-handler (since we're inside here now...) 
    432                  * THEN 
    433                  * handle it as a normal "HourLine drop". */ 
    434  
    435                 if(isTouchingWall(ui)) { 
    436                     $('.ui-droppable').droppable('enable'); 
    437                     var ttDrawer = self.timetable.getTimetableDrawer(); 
    438                     ttDrawer.releaseDragOnHour(ui, ttDrawer.curStartHour, ttDrawer.curStartMinute); 
    439                     return; 
    440                 } 
    441  
    442                 var blockInfo = $(ui.draggable).data('blockInfo'); 
    443                 var blockEventData = $(ui.draggable).data('eventData'); 
    444  
    445                 var moveEntryDialog = new MoveEntryDialog( 
    446                   self.managementActions, 
    447                   self.timetable, 
    448                   eventData.entryType, 
    449                   eventData.sessionId, 
    450                   eventData.sessionSlotId, 
    451                   timetable.currentDay, 
    452                   eventData.scheduleEntryId, 
    453                   eventData.conferenceId, 
    454                   eventData.startDate.date); 
    455  
    456                 var chosenValue = eventData.sessionId + ':' + eventData.sessionSlotId; 
    457  
    458                 var initialPosition = $(ui.draggable).data('initialPosition'); 
    459  
    460                 //Store Undo data 
    461                 // TODO - not functioning at the moment 
    462                 //self.timetable.getTimetableDrawer().enableUndo("drop", blockEventData); 
    463  
    464                 moveEntryDialog.handleBlockMove(blockEventData, chosenValue); 
    465  
    466                 // Non-instanced call, which fails on self.slotId inside the indicoRequest, inside moveEntryDialog(...) 
    467                 /* MoveEntryDialog.prototype.handleBlockMove.call(self, blockEventData, 
    468                   chosenValue, self.managementActions); */ 
    469  
    470                 return; 
    471               }, 
    472               greedy: true, 
    473               tolerance: 'intersect', 
    474               activate: function() { 
    475                 $(block.dom).css('border', '2px solid green'); 
    476               }, 
    477               deactivate: function() { 
    478                 $(block.dom).css('border', ''); 
    479               }, 
    480               over: function(event, ui) { 
    481                 /* If you touch the wall while also 
    482                  * over a session - show that session with the style of 
    483                  * "not current drop target" 
    484                  * 
    485                  */ 
    486                   function(event) { 
    487                     if(isTouchingWall(ui)) { 
    488                       $('.ui-droppable').droppable('enable'); 
    489                     } 
    490                   }; 
    491  
    492                 if(isSession(ui) || isTouchingWall(ui)) { 
    493                   return; 
    494                 } 
    495  
    496                 $('.dragTip').hide(); 
    497                 $('.ui-droppable').not(this).droppable('disable'); 
    498               }, 
    499               out: function(event, ui) { 
    500                 if(isSession(ui)) { 
    501                   return; 
    502                 } 
    503                 $('.dragTip').show(); 
    504                 $('.ui-droppable').not(this).droppable('enable'); 
    505               }, 
    506            }); 
    507           }, 
     271            _postDraw: function() { 
     272            }, 
    508273 
    509274            postDraw: function(hook) { 
     
    585350 
    586351                // If content height <= div height then nothing needs to be done 
    587                 if (contentHeight() <= parentDivHeight) { 
    588                     return; 
     352                if (contentHeight() > parentDivHeight) { 
     353                    // Try to remove the location info, and set title font weight to non bold, 
     354                    // if this works, then we're done. Otherwise, start to truncate the title as well. 
     355                    if (this.timeDiv.dom.style.display == 'none') { 
     356                        this.locationDiv.dom.style.display = 'none'; 
     357                    } 
     358 
     359                    if (contentHeight() > parentDivHeight) { 
     360                        // Calculates the the width of title, presenters and possible arrows 
     361                        var topContentWidth = function() { 
     362                            var width = 2 * self.margin; 
     363                            if(self.titleDiv) 
     364                                width += self.titleDiv.dom.offsetWidth; 
     365                            if(self.presentersDiv) 
     366                                width += self.presentersDiv.dom.offsetWidth; 
     367 
     368                            self._postDraw() 
     369                            return width; 
     370                        } 
     371 
     372                        // Truncate title based on a ratio: div height / content height 
     373                        title = this.truncateTitle(Math.ceil(title.length * ((parentDivHeight) / contentHeight())), title); 
     374                        this.titleDiv.set(title); 
     375                        //String will be shorten by the value of 'step' 
     376                        var step = 2; 
     377                        //Truncating the title since it can be displayed in a single line 
     378                        // title !== "..." avoids the endless loop 
     379                        while (title !== "..." && contentHeight() > parentDivHeight && topContentWidth() > parentDivWidth * 0.8) { 
     380                            title = this.truncateTitle(-step, title); 
     381                            this.titleDiv.set(title); 
     382                        } 
     383                    } 
    589384                } 
    590385 
    591                 // Try to remove the location info, and set title font weight to non bold, 
    592                 // if this works, then we're done. Otherwise, start to truncate the title as well. 
    593                 if (this.timeDiv.dom.style.display == 'none') { 
    594                     this.locationDiv.dom.style.display = 'none'; 
    595                 } 
    596  
    597                 if (contentHeight() <= parentDivHeight) { 
    598                     return; 
    599                 } 
    600  
    601                 //Calculates the the width of title, presenters and possible arrows 
    602                 var topContentWidth = function() { 
    603                     var width = 2 * self.margin; 
    604                     if(self.titleDiv) 
    605                         width += self.titleDiv.dom.offsetWidth; 
    606                     if(self.presentersDiv) 
    607                         width += self.presentersDiv.dom.offsetWidth; 
    608  
    609                     return width; 
    610                 } 
    611  
    612                 // Truncate title based on a ratio: div height / content height 
    613                 title = this.truncateTitle(Math.ceil(title.length * ((parentDivHeight) / contentHeight())), title); 
    614                 this.titleDiv.set(title); 
    615                 //String will be shorten by the value of 'step' 
    616                 var step = 2; 
    617                 //Truncating the title since it can be displayed in a single line 
    618                 // title !== "..." avoids the endless loop 
    619                 while (title !== "..." && contentHeight() > parentDivHeight && topContentWidth() > parentDivWidth * 0.8) { 
    620                     title = this.truncateTitle(-step, title); 
    621                     this.titleDiv.set(title); 
    622                 } 
    623  
     386                this._postDraw(); 
     387                return null; 
    624388            }, 
    625389            createPileEffect: function() { 
     
    643407                this.block.dom.style.color = textColor; 
    644408            } 
     409 
    645410        }, 
    646411     function(timetable, eventData, blockData, compactMode, printableVersion, detailLevel){ 
    647  
    648412         this.TimetableBlockBase(timetable); 
    649413         this.compactMode = compactMode; 
     
    654418         this.detailLevel = detailLevel; 
    655419         this.arrows = Html.span({}); 
     420         this.block = Html.div({}); 
     421 
     422         var self = this; 
     423         $(this.block.dom).bind('tt_block.balloon', function(event, originalEvent){ 
     424             if (!self.popupActive) { 
     425                 self.openPopup(originalEvent); 
     426             } 
     427         }) 
    656428        } 
    657429   ); 
     
    747519     }); 
    748520 
    749 type("TimetableBlockManagementMixin",[], 
     521type("TimetableBlockManagementMixin", ["DragAndDropBlockMixin"], 
    750522     { 
    751523         _drawPopup: function() { 
     
    803575                             Html.div({className: "ttentryArrowsBackground"}), 
    804576                             Html.div({className: "ttentryArrows"}, arrowUp, arrowDown)); 
     577         this.DragAndDropBlockMixin(); 
    805578     }); 
    806579 
     
    821594 
    822595         this._getRightSideDecorators = TimetableBlockManagementMixin.prototype._getRightSideDecorators; 
    823  
     596         this._postDraw = TimetableBlockManagementMixin.prototype._postDraw; 
    824597     }); 
    825598 
     
    854627 
    855628         this._getRightSideDecorators = TimetableBlockManagementMixin.prototype._getRightSideDecorators; 
    856  
     629         this._postDraw = TimetableBlockManagementMixin.prototype._postDraw; 
    857630     }); 
    858631 
     
    15861359    ); 
    15871360 
    1588 type("TimetableDrawer", ["IWidget"], 
     1361type("TimetableDrawer", ["IWidget", "DroppableTimetableMixin"], 
    15891362     { 
    15901363 
     
    15971370 
    15981371         _drawGrid: function(scale) { 
    1599            var scaleDiv = Html.div({style: { 
    1600              position:'relative', 
    1601              top: pixels(TimetableDefaults.topMargin) 
    1602            }}); 
     1372 
     1373           var scaleDiv = Html.div({ 
     1374               id: 'timetable_grid', 
     1375               style: { 
     1376                   position:'relative', 
     1377                   top: pixels(TimetableDefaults.topMargin), 
     1378               }}); 
    16031379 
    16041380             last = scale[scale.length-1][0]; 
     
    16141390                         top: pixels(px), 
    16151391                         width: pixels(this.width), 
    1616                          height: hour==last?'20px':scale[n+1][1]-px, 
     1392                         height: hour==last?'0px':scale[n+1][1]-px, 
    16171393                         borderTop: '1px dotted red', 
    16181394                         fontSize: '11px'}})); 
     
    16201396                 } 
    16211397 
    1622                var hourLineDiv = Html.div({id: 'hourLine_'+parseInt(hour), className: 'hourLine', style: 
    1623                                            { position: 'absolute', 
    1624                                            top: pixels(px), 
    1625                                            width: pixels(this.width), 
    1626                                            height: hour==last?'20px':scale[n+1][1]-px, 
    1627                                            borderTop: '1px solid #E8E8E8', 
    1628                                            fontSize: '11px'}}, zeropad(hour)+':00'); 
    1629                this._makeHourLineDroppable(hourLineDiv, parseInt(hour)); 
    1630  
    1631                this.hourLinesArray[hour] = px; 
    1632  
    1633                scaleDiv.append(hourLineDiv); 
     1398                 var hourLineDiv = Html.div({id: 'hourLine_' + parseInt(hour), className: 'hourLine', style: 
     1399                                             { top: pixels(px), 
     1400                                               width: pixels(this.width), 
     1401                                               height: hour == last ? '20px' : scale[n + 1][1] - px} 
     1402                                            }, zeropad(hour) + ':00'); 
     1403 
     1404                 this.make_droppable($(hourLineDiv.dom), parseInt(hour)); 
     1405 
     1406                 scaleDiv.append(hourLineDiv); 
    16341407             } 
    16351408             return Html.div({}, this.layoutChooser.get().getHeader(this.width), scaleDiv); 
    16361409         }, 
    1637  
    1638  
    1639        createDragToolTip: function() { 
    1640          /*A dragging "tooltip" line that follows wherever a timeblock 
    1641           * is being dragged and displays the current start time 
    1642           * at that current dragging position.  */ 
    1643            $('#timetableDiv').append($('<div class="dragTip"></div>')); 
    1644        }, 
    1645  
    1646  
    1647          _calculateRelativeMinuteOffset: function(position, hour) { 
    1648              //If the current hour does not have an hourLine div 
    1649              if(($("#hourLine_"+hour).position() == null)) { 
    1650                  return null; 
    1651              } 
    1652  
    1653              var hourTop = $("#hourLine_"+hour).position().top; 
    1654              var hourHeight = $("#hourLine_"+hour).height(); 
    1655  
    1656              var offsetHeight = (position - hourTop); 
    1657  
    1658              var minute = Math.floor((offsetHeight/hourHeight) * 59); 
    1659              return ((minute > 60) || (minute < 0))? null : minute; 
    1660          }, 
    1661  
    1662        _makeHourLineDroppable: function(hourDiv, hour) { 
    1663          var self = this; 
    1664  
    1665          var checkpoints = self.layoutChooser.get().checkpoints; 
    1666  
    1667          ///* Just a small function to pick out smallest + largest value... 
    1668          var maxMinExtract = function(operator, list) { 
    1669  
    1670            var significantValue = (operator == "min") ? (Number.MAX_VALUE) : null; 
    1671            _(keys(list)).each(function(x) { 
    1672              //We're actually only interested in the value x for these checkpoints 
    1673              if(operator == "max") { 
    1674                significantValue = (x > significantValue) ? x : significantValue; 
    1675              } else if(operator == "min") { 
    1676                significantValue = (x < significantValue) ? x : significantValue; 
    1677              } 
    1678              }); 
    1679            return significantValue; 
    1680          }; 
    1681  
    1682          //Extract the hours from the strings of the form: HHMMSS 
    1683          var dayStartHour = parseInt(new String(maxMinExtract("min", checkpoints)).substring(0,2)); 
    1684          var dayEndHour = parseInt(new String(maxMinExtract("max", checkpoints)).substring(0,2)); 
    1685  
    1686          self.dayEndHour = (dayEndHour == 24) ? 00 : dayEndHour; 
    1687          self.dayStartHour = dayStartHour; 
    1688  
    1689          var isDisallowedTime = function(ui, hourCompare) { 
    1690            /* IF its outside the timetable div topside OR before day-start-hour OR 
    1691             * past midnight, when the day ends prior to 00:00 */ 
    1692            return ($(ui.draggable).offset().top < $(hourDiv.dom).offset().top) 
    1693              || (hourCompare < dayStartHour) || ((dayEndHour == 0) && (hourCompare > 0)); 
    1694          }; 
    1695  
    1696          //"unique" name for each drag-handler per hourLine 
    1697          var thisDragSpaceName = ("drag."+hour); 
    1698  
    1699          //These variables are used below 
    1700          var startHour = null; 
    1701          var startMinute = null; 
    1702  
    1703          $(hourDiv.dom).droppable({ 
    1704            drop: function(event, ui) { 
    1705              if(isDisallowedTime(ui, startHour)) { 
    1706                self.revertBlockPos(ui.draggable); 
    1707                return; 
    1708              } 
    1709  
    1710              self.releaseDragOnHour(ui, startHour, startMinute); 
    1711            }, 
    1712            tolerance: 'touch', 
    1713            over: function(event, ui) { 
    1714              $(ui.draggable).bind(thisDragSpaceName, function(newEvent, newUi) { 
    1715                if(isDisallowedTime(ui, hour)) { 
    1716                  return; 
    1717                } 
    1718  
    1719                var gridTime = self.fetchTimeDragOnHour(ui.draggable, hourDiv.dom, hour, "start"); 
    1720  
    1721                //null means that the drag is not allowed 
    1722                if((gridTime == null)) { 
    1723                  return; 
    1724                } 
    1725                startHour = gridTime[0]; 
    1726                startMinute = gridTime[1]; 
    1727                self.curStartHour = startHour; 
    1728                self.curStartMinute = startMinute; 
    1729  
    1730                }); 
    1731            }, 
    1732            out: function(event, ui) { 
    1733              if(thisDragSpaceName != null) { 
    1734                $(ui.draggable).unbind(thisDragSpaceName); 
    1735              } 
    1736              $('.dragTip').hide(); 
    1737            } 
    1738            }); 
    1739        }, 
    1740  
    1741        /* This function determines what hour + minute the time block 
    1742         * should start at for the current dragging pixel position in the timetable. 
    1743         * This function is used by over:, in _makeHourLineDroppable 
    1744         * Args: 
    1745         * ui is the same one that drop(ui,events) is using. 
    1746         * hour = the current "hourLineDiv" being dragged upon 
    1747         * 
    1748         * significantEdge = start or end, whichever is being used to measure with 
    1749         * (start = dragging, end = resizing..) 
    1750         * 
    1751         * Returns an array, where array[0] = startHour, array[1] = startMinute 
    1752         * */ 
    1753        fetchTimeDragOnHour: function(draggingBlock, hourDiv, hour, significantEdge) { 
    1754          var self = this; 
    1755  
    1756          var setToolTipPos = function(newTop) { 
    1757            //Sets the drag-tooltip at the current dragging/resizing position 
    1758            $('.dragTip').offset({ 
    1759              left: $('.dragTip').offset().left, 
    1760              top: newTop 
    1761            }); 
    1762          }; 
    1763  
    1764          var dragTipTop = null; 
    1765          try { 
    1766            //If we're DRAGGING, and the dragTip is already created... 
    1767            dragTipTop = $(draggingBlock).offset().top; 
    1768          } catch (Exception) { 
    1769            dragTipTop = 0; 
    1770            dragTipTop = $(draggingBlock).offset().top; 
    1771            setToolTipPos(dragTipTop); 
    1772          } 
    1773  
    1774          //Top left Position of the current hourLine div 
    1775          var hourPos = $(hourDiv).position(); 
    1776  
    1777          var blockPosTop = $(draggingBlock).position().top; 
    1778          var blockHeight = $(draggingBlock).height(); 
    1779          var hourLowerLeftCorner = (hourPos.top+$(hourDiv).height()); 
    1780          var hourTopLeftCorner = (hourPos.top); 
    1781  
    1782          //Difference of time block and hour block in height 
    1783          var diffBlockTopLine = blockPosTop - hourTopLeftCorner; 
    1784  
    1785          var startHour = hour; 
    1786          var startMinute = self._calculateRelativeMinuteOffset(blockPosTop, startHour); 
    1787  
    1788          var endHour = hour; 
    1789  
    1790          var blockEnd = (blockPosTop+blockHeight); 
    1791          endMinute = self._calculateRelativeMinuteOffset(blockEnd, endHour); 
    1792  
    1793          if(!($('.dragTip').length > 0)) { 
    1794            self.timetable.getTimetableDrawer().createDragToolTip(); 
    1795          } 
    1796  
    1797          var gridTime = null; 
    1798          //significantEdge is set by the caller of this whole function 
    1799          // It represents the significant edge to measure with of a time block 
    1800          //That is, if youre resizing, then it will be "end" 
    1801          //Dragging --> "start" 
    1802          if(significantEdge == "start") { 
    1803            setToolTipPos($(draggingBlock).offset().top); 
    1804            //Returns closest 5-minute-divisible, hour and minute in an array 
    1805            gridTime = self.round5(startHour, startMinute); 
    1806          } else if(significantEdge == "end") { 
    1807            setToolTipPos($(draggingBlock).offset().top+blockHeight); 
    1808            gridTime = self.round5(startHour, endMinute); 
    1809          } 
    1810  
    1811          if(gridTime == null) { 
    1812            return null; 
    1813          } 
    1814  
    1815          if($('.dragTip').length > 0) { 
    1816            $('.dragTip').show(); 
    1817            $('.dragTip').html(gridTime[0]+":"+gridTime[1]); 
    1818          } 
    1819  
    1820          return gridTime; 
    1821        }, 
    1822  
    1823        enableUndo: function(undoLabel, currentEventData, shifted) { 
    1824          var undoArrayInfo = new Array(); 
    1825          undoArrayInfo[0] = undoLabel; 
    1826  
    1827          //Copying original values before they get modified 
    1828          undoArrayInfo[1] = currentEventData.startDate.date; 
    1829          undoArrayInfo[2] = currentEventData.startDate.time; 
    1830          undoArrayInfo[3] = currentEventData.endDate.date; 
    1831          undoArrayInfo[4] = currentEventData.endDate.time; 
    1832          undoArrayInfo[5] = currentEventData.duration; 
    1833          undoArrayInfo[6] = currentEventData.entryType; 
    1834          undoArrayInfo[7] = currentEventData.conferenceId; 
    1835  
    1836          //If shifting entries was enabled 
    1837          undoArrayInfo[8] = shifted; 
    1838          //Also keep a reference to the soon-to-be modified eventData 
    1839          undoArrayInfo[9] = currentEventData; 
    1840          $(window).data('undo', undoArrayInfo); 
    1841          this.drawUndoDiv(); 
    1842        }, 
    1843  
    1844        undoLastAction: function() { 
    1845          var self = this; 
    1846          var undoArrayInfo = $(window).data('undo'); 
    1847          var undoLabel = undoArrayInfo[0]; 
    1848  
    1849          //[**] Fetch stored values for undo 
    1850  
    1851          //String of the form "HH:MM:SS" 
    1852          var startDate = new Object(); 
    1853          startDate.date = undoArrayInfo[1]; 
    1854          startDate.time = undoArrayInfo[2]; 
    1855  
    1856          var endDate = new Object(); 
    1857          endDate.date = undoArrayInfo[3]; 
    1858          endDate.time = undoArrayInfo[4]; 
    1859  
    1860          var duration = undoArrayInfo[5]; 
    1861          var entryType = undoArrayInfo[6]; 
    1862          var conferenceId = undoArrayInfo[7]; 
    1863  
    1864          var shifted = undoArrayInfo[8]; 
    1865  
    1866          var currentEventData = undoArrayInfo[9]; 
    1867  
    1868          //[**] end 
    1869  
    1870          /* conferenceId and entryType is cleared it seems at some point when 
    1871           * running editEntryStartEndDate on the original... hmm... 
    1872           *  - so here the values are just re-assigned from the original (stored PRIOR to calling editEntrySt...) */ 
    1873          currentEventData.entryType = entryType; 
    1874          currentEventData.conferenceId = conferenceId; 
    1875  
    1876          var startDT = new Date((Util.dateTimeIndicoToJS(startDate)).getTime()); 
    1877          var endDT = new Date((Util.dateTimeIndicoToJS(endDate)).getTime()); 
    1878  
    1879          if((undoLabel == "placementChange") || (undoLabel == "resize")) { 
    1880            self.managementActions.editEntryStartEndDate(Util.formatDateTime(startDT, IndicoDateTimeFormats.Server), 
    1881              Util.formatDateTime(endDT, IndicoDateTimeFormats.Server), currentEventData, $(window).data('shiftIsPressed')); 
    1882          } else if(undoLabel == "drop") { 
    1883            // Here goes code to handle drop undo 
    1884            // However I didnt have time to find a reasonable way 
    1885  
    1886              // Something in the right direction below (debug/test) 
    1887            /* 
    1888            var moveEntryDiag = new MoveEntryDialog( 
    1889              self.managementActions, 
    1890              self.timetable, 
    1891              currentEventData.entryType, 
    1892              currentEventData.sessionId, 
    1893              currentEventData.sessionSlotId, 
    1894              self.timetable.currentDay, 
    1895              currentEventData.scheduleEntryId, 
    1896              currentEventData.conferenceId, 
    1897              currentEventData.startDate.date); 
    1898  
    1899            var chosenValue = currentEventData.sessionId; 
    1900            moveEntryDiag.handleBlockMove(currentEventData, chosenValue+":0", self.managementActions); 
    1901             */ 
    1902          } 
    1903  
    1904          $(window).data('undo', undefined); 
    1905          $('#undoDiv').remove(); 
    1906          return; 
    1907        }, 
    1908  
    1909        /* A "button" that appears after an action is performed */ 
    1910        drawUndoDiv: function() { 
    1911          //If it isnt drawn already 
    1912          if(!($('#undoDiv').length > 0)) { 
    1913            var self = this; 
    1914            var undoLink = Html.a({}, "Undo last action"); 
    1915            undoLink.observeClick( 
    1916              function(e) { 
    1917                self.undoLastAction(); 
    1918              }); 
    1919  
    1920            var undoDiv = 
    1921              Html.div({ 
    1922              id: 'undoDiv', 
    1923              className: 'undoDiv', 
    1924                style: { 
    1925                  padding: '5px', 
    1926                  background: '#FFF', 
    1927                  border: '3px solid black', 
    1928                  position: 'fixed', 
    1929                  bottom: '0px', 
    1930                  left: '50%' 
    1931                }}, undoLink); 
    1932            $('#timetableDiv').append(undoDiv.dom); 
    1933          } 
    1934        }, 
    1935  
    1936        /* The function to execute when a drop occurs ON an hour. 
    1937         * The argument ui is the same one that drop(ui,events) is using. 
    1938         * 
    1939         * startHour is the hour where it is being dropped (0 to 23) 
    1940         * startMinute is the minute where it is being dropped, a 5-divisible in the range 0-55 
    1941         * startHour and startMinute is determined by fetchTimeDragOnHour(..) 
    1942         * 
    1943         * This function is used by drop:, in _makeHourLineDroppable 
    1944         */ 
    1945        releaseDragOnHour: function(ui, startHour, startMinute) { 
    1946          var self = this; 
    1947          $('.dragTip').remove(); 
    1948  
    1949          if((startMinute == null) || (startHour == 00)) { 
    1950            self.revertBlockPos(ui.draggable); 
    1951            return false; 
    1952          } 
    1953  
    1954            //originalEventData is used for the undo functionality 
    1955            var eventData = $(ui.draggable).data('eventData'); 
    1956  
    1957            //Store Undo data 
    1958            self.enableUndo("placementChange", eventData, $(window).data('shiftIsPressed')); 
    1959  
    1960            eventData.startDate.time = startHour+":"+startMinute+":00"; 
    1961  
    1962            var startDT = Util.dateTimeIndicoToJS(eventData.startDate); 
    1963            var endDT = new Date(startDT.getTime() + eventData.duration*60000); 
    1964  
    1965            //If it doesnt end on the same day, revert drag 
    1966            if(endDT.getDay() > startDT.getDay()) { 
    1967              self.revertBlockPos(ui.draggable); 
    1968              return false; 
    1969            } 
    1970  
    1971          self.managementActions.editEntryStartEndDate(Util.formatDateTime(eventData.startDate, IndicoDateTimeFormats.Server), 
    1972                                                       Util.formatDateTime(endDT, IndicoDateTimeFormats.Server), eventData, $(window).data('shiftIsPressed')); 
    1973  
    1974          return true; 
    1975        }, 
    1976  
    1977        releaseResizeOnHour: function(endHour, endMinute, eventData, block) { 
    1978          var self = this; 
    1979          self.enableUndo("resize", eventData); 
    1980  
    1981          eventData.endDate.time = endHour+":"+endMinute+":00"; 
    1982          var endDT = Util.dateTimeIndicoToJS(eventData.endDate); 
    1983          var startDT = Util.dateTimeIndicoToJS(eventData.startDate); 
    1984  
    1985          // HERE GOES CODE TO LIMIT RESIZE FOR THE CURRENT DAY ONLY 
    1986          //If it doesnt end on the same day, revert drag 
    1987          /* 
    1988          if((self.dayEndHour == 0) && (false))  { 
    1989            self.revertBlockHeight(block); 
    1990            return false; 
    1991          } 
    1992           */ 
    1993  
    1994          self.managementActions.editEntryStartEndDate(Util.formatDateTime(eventData.startDate, IndicoDateTimeFormats.Server), 
    1995            Util.formatDateTime(endDT, IndicoDateTimeFormats.Server), 
    1996            eventData, false); 
    1997  
    1998          //Store Undo-data 
    1999          return true; 
    2000        }, 
    2001  
    2002        revertBlockHeight: function(block) { 
    2003          $(block.dom).animate({ 
    2004          height: $(block.dom).data('originalheight') 
    2005            }); 
    2006        }, 
    2007  
    2008        /* Returns a draggable to its initial position */ 
    2009        revertBlockPos: function(draggable) { 
    2010          var initPos = $(draggable).data('initialPosition'); 
    2011  
    2012          $(draggable).animate({ 
    2013            left: initPos.left, 
    2014            top: initPos.top 
    2015          }); 
    2016          $('.dragTip').remove(); 
    2017        }, 
    2018  
    2019        round5: function (hour, minute) { 
    2020  
    2021          //Rounds the number to the closest 5-divisible,.. 
    2022          //Also appends padding to the number, such that 0 = 00, 1 = 01... 
    2023          closestFive = (minute % 5) >= 2.5 ? parseInt(minute / 5) * 5 + 5 : parseInt(minute / 5) * 5; 
    2024          var newHour = ((minute > 55) && (closestFive == 60)) ? (hour+1) : hour; 
    2025          var timeArray = new Array(); 
    2026          if(newHour > 23) { 
    2027            return null; 
    2028          } 
    2029          timeArray[0] = zeropad(newHour); 
    2030          timeArray[1] = zeropad((closestFive == 60) ? 00 : closestFive); 
    2031          return timeArray; 
    2032        }, 
    2033  
    2034        /* Since javascripts mod (%) function/operator can't 
    2035         * properly handle negative numbers here's a real one */ 
    2036        properModulus: function(num, modn) { 
    2037          return ((num%modn)+modn)%modn; 
    2038        }, 
    20391410 
    20401411         _drawWholeDayBlocks: function(data, blocks) { 
     
    20811452                                      } 
    20821453                                     }); 
    2083  
    2084              self.blocks = [] 
     1454             this.blocks = [] 
     1455             this._blockMap = {} 
    20851456 
    20861457             each(blocks, function(blockData) { 
     
    21191490 
    21201491                 if (self.managementMode) { 
    2121  
    21221492                     block = new TimetableBlockNormalManagement(self.timetable, eventData, blockData, compactMode, self.printableVersion, self.detail.get(), self.managementActions); 
     1493 
    21231494                 } else { 
    21241495                     block = new TimetableBlockNormalDisplay(self.timetable, eventData, blockData, compactMode, self.printableVersion, self.detail.get()); 
    21251496                 } 
    21261497                 blockDiv.append(block.draw(leftPos, width)); 
     1498                 self._blockMap[blockData.id] = block.block.dom; 
    21271499                 self.blocks.push(block); 
    21281500             }); 
     
    21321504 
    21331505         setLayout: function(layout) { 
     1506             this.layout.set(layout); 
    21341507             this.layoutChooser.set(layout); 
    21351508         }, 
    21361509 
    21371510         redraw: function(day) { 
     1511 
    21381512             if (this.preventRedraw) { 
    21391513                 return; 
     
    21581532             this.wrappingElement.setStyle('height', pixels(height + (this.printableVersion ? 0 : 100))); // +100 to have margin for the tabs 
    21591533 
    2160              var grid = this._drawGrid(dayData[1]); 
     1534             this.grid.length = 0; 
     1535             $.merge(this.grid, dayData[1]) 
     1536 
     1537             var gridElems = this._drawGrid(this.grid); 
    21611538             var blocks = this._drawBlocks(dayFiltered, dayData[2], dayData[3]); 
    21621539             var wholeDayBlocks = this._drawWholeDayBlocks(dayFiltered, dayData[4]); 
    21631540 
    21641541             // Only do if not all days are drawn 
    2165              this.canvas.set([wholeDayBlocks, Html.div({style: {position: 'relative'}}, grid, blocks)]); 
     1542             this.canvas.set([wholeDayBlocks, Html.div({style: {position: 'relative'}}, gridElems, blocks)]); 
    21661543             var totalHeight = height + wholeDayBlocks.dom.offsetHeight; 
    21671544 
     
    21691546 
    21701547             this.postDraw(); 
     1548 
     1549             $('body').trigger('timetable_redraw', this); 
    21711550 
    21721551             return totalHeight; 
     
    23491728                 this.loadingIndicator.dom.style.visibility = 'visible'; 
    23501729                 setTimeout(function() { 
     1730                     // call redraw function 
    23511731                     funcToCall.call(self, arg); 
     1732                     $('body').trigger('timetable_ready', self.timetable); 
    23521733                     self.setLoading(false); 
    23531734                 }, 100); 
     
    23621743             this.data = data; 
    23631744             this.redraw(); 
     1745         }, 
     1746         toggleEvents: function(value) { 
     1747             if (value === undefined) { 
     1748                 this.eventsDisabled = !this.eventsDisabled; 
     1749             } else { 
     1750                 this.eventsDisabled = !value; 
     1751             } 
    23641752         } 
     1753 
    23651754     }, 
    23661755     function(timetable, width, wrappingElement, detailLevel, extraButtons, loadingIndicator, managementMode, managementActions, defaultLayout) { 
    23671756 
    2368  
    23691757         var self = this; 
    23701758 
    2371          this.hourLinesArray = new Array(); 
    2372  
     1759         this.grid = []; 
    23731760         this.wrappingElement = wrappingElement; 
    2374          this.canvas = Html.div({}); 
     1761         this.canvas = Html.div({'id': 'timetable_canvas'}); 
    23751762         this.filterList = new WatchList(); 
    23761763         this.data = timetable.data; 
     
    24041791         // default detail level is 'session' 
    24051792         this.detail.set(any(detailLevel, 'session')); 
    2406  
     1793         this.eventsDisabled = false; 
    24071794 
    24081795         var filterState = map(TimetableDefaults.filters, 
     
    24281815             } 
    24291816         }); 
     1817 
     1818         this.DroppableTimetableMixin(); 
    24301819     }); 
    24311820 
     
    24971886        }, 
    24981887 
    2499         postDraw: function() { 
    2500  
    2501         }, 
    2502  
    25031888        setData: function(data, day, isPoster) { 
    25041889            this.isPoster = isPoster; 
     
    25071892                this.setLayout('poster'); 
    25081893            } else { 
    2509                 this.setLayout('compact'); 
     1894                this.setLayout(this.layout.get()); 
    25101895            } 
    25111896            this.TimetableDrawer.prototype.setData.call(this, data); 
    25121897        } 
    25131898    }, 
    2514     function(data, canvas, width, wrappingElement, extraButtons, loadingIndicator, managementMode, managementActions) { 
    2515         this.TimetableDrawer(data, canvas, width, wrappingElement, 'session', extraButtons, loadingIndicator, managementMode, managementActions, data.isPoster?'poster':null); 
     1899     function(data, width, wrappingElement, extraButtons, loadingIndicator, managementMode, managementActions, layout) { 
     1900         this.TimetableDrawer(data, width, wrappingElement, 'session', extraButtons, loadingIndicator, managementMode, managementActions, data.isPoster?'poster':'proportional'); 
    25161901        this.wrappingElement = data.parentTimetable.timetableDrawer.wrappingElement; 
    25171902 
  • indico/htdocs/js/indico/Timetable/Layout.js

    r791f15 r06b76b  
    216216type("IncrementalLayoutManager", ["TimetableLayoutManager"], 
    217217     { 
     218         name: 'incremental', 
    218219         drawDay: function(data, detailLevel, startTime, endTime) { 
    219220             var self = this; 
     
    265266             var hEnd; 
    266267 
     268             // add hour before start 
     269             if (startingHour > 0) { 
     270                 for (var min = 0; min < 60 ; min += TimetableDefaults.resolution) { 
     271                     self.processTimeBlock(startingHour - 1, startingHour, (startingHour - 1) * 60, min, algData); 
     272                 } 
     273             } 
     274 
    267275             for (var minutes = 0; minutes < ((endingHour + 1 - startingHour) * 60); minutes += TimetableDefaults.resolution) { 
    268  
    269276                 // current block is [minutes, minutes + 5] 
    270277                 var startMin = (startingHour * 60 + minutes); 
     
    274281 
    275282                 self.processTimeBlock(hStart, hEnd, startMin, minutes, algData); 
    276  
    277283             } 
    278284 
    279285             if ($L(ks).indexOf('nextday') !== null) { 
    280286                 self.processTimeBlock('nextday', 'nextday', (startingHour * 60 + minutes), minutes, algData); 
    281              } else { 
     287             } else if (endMin/60 < 25){ 
    282288                 // add last hour + 1 to the grid 
     289                 // (only if the next hour is not after midnight) 
    283290                 algData.grid.push([(endMin/60) % 24, algData.topPx]); 
    284291             } 
     
    292299                 counter++; 
    293300             }); 
    294  
    295301             return [algData.topPx, algData.grid, algData.blocks, algData.groups, algData.wholeDayBlocks]; 
    296302 
     
    302308     { 
    303309 
     310         name: 'compact', 
    304311         processTimeBlock: function(hStart, hEnd, startMin, minutes, algData) { 
    305312             var self = this; 
     
    411418type("ProportionalLayoutManager", ["IncrementalLayoutManager"], 
    412419     { 
    413  
     420         name: 'proportional', 
    414421         processTimeBlock: function(hStart, hEnd, startMin, minutes, algData) { 
    415422             var self = this; 
     
    458465             }); 
    459466 
    460              if (minutes % 60 === 0) { 
    461                  algData.grid.push([startMin/60%24, algData.topPx]); 
     467             var hour = startMin / 60; 
     468             if (minutes % 60 === 0 && hour <= 24) { 
     469                 algData.grid.push([hour % 24, algData.topPx]); 
    462470             } 
    463471 
     
    581589        } 
    582590    }); 
    583  
  • indico/htdocs/js/indico/Timetable/Loader.js

    rae6179 r06b76b  
    11include(ScriptRoot + "indico/Timetable/Layout.js"); 
     2include(ScriptRoot + "indico/Timetable/DragAndDrop.js"); 
     3include(ScriptRoot + "indico/Timetable/Undo.js"); 
    24include(ScriptRoot + "indico/Timetable/Draw.js"); 
    35include(ScriptRoot + "indico/Timetable/Management.js"); 
  • indico/htdocs/js/indico/Timetable/Management.js

    r791f15 r06b76b  
    1 type("TimetableManagementActions", [], { 
     1type("TimetableManagementActions", ["UndoMixin"], { 
    22    methods: { 
    33        'SessionSlot': { 
     
    144144     * Edit start and end date. date format has to be dd/mm/yy mm:hh 
    145145     */ 
    146     editEntryStartEndDate: function(startDate, endDate, eventData, reschedule) { 
     146    editEntryStartEndDate: function(startDate, endDate, eventData, reschedule, undo) { 
    147147        var self = this; 
    148148        var info = new WatchObject(); 
     
    171171        } 
    172172 
    173       //Displays a "loading ..." div at the righthand bottom side 
    174       var killProgress = IndicoUI.Dialogs.Util.blockMoveProgress(); 
     173        var dfr = $.Deferred(); 
     174 
     175        //Displays a "loading ..." div at the righthand bottom side 
     176        var killProgress = IndicoUI.Dialogs.Util.ttStatusInfo($T('saving...')); 
    175177 
    176178        indicoRequest(this.methods[type].modifyStartEndDate, info, function(result, error){ 
    177             killProgress(); 
     179            if (!undo) { 
     180                killProgress(); 
     181            } 
     182 
    178183            if (error) { 
    179184                IndicoUtil.errorReport(error); 
    180             } 
    181             else { 
     185                dfr.reject(error); 
     186                if (undo) { 
     187                    killProgress(); 
     188                } 
     189            } else { 
    182190                // Depending on whether 'reschedule' was selected or not, 
    183191                // update the whole day or just one entry 
    184192 
     193                if(undo) { 
     194                    self.enableUndo(undo, {eventData: eventData, 
     195                                           shifted: reschedule}); 
     196                } 
     197 
    185198                if (reschedule) { 
    186                     self.timetable._updateDay(result); 
     199                    self.timetable._updateDay(result).done(function() { 
     200                        dfr.resolve(); 
     201                    }); 
    187202                } else { 
    188                     self.timetable._updateEntry(result, result.id); 
     203                    self.timetable._updateEntry(result, result.id).done(function() { 
     204                        dfr.resolve(); 
     205                    }); 
    189206                } 
    190207            } 
    191208        }); 
     209 
     210        return dfr.promise(); 
     211    }, 
     212 
     213    /* Takes care of moving a contribution/timeblock to another session/timetable. 
     214     * This goes for both "drag and drop" as well as the regular "MoveEntry Dialog clicking"*/ 
     215    moveToSession: function(eventData, value, undo, keep_time) { 
     216        var self = this; 
     217 
     218        // if nothing has been selected yet 
     219        if (value === null || value === undefined) { 
     220            return false; 
     221        } 
     222 
     223        // Displays a "loading ..." div at the righthand bottom side 
     224        var killProgress = IndicoUI.Dialogs.Util.ttStatusInfo($T("saving...")); 
     225        var dfr = $.Deferred(); 
     226 
     227        indicoRequest(this.methods[this.isSessionTimetable ? 'SessionEntry' : 'Event'].moveEntry, { 
     228            value : value, 
     229            conference : eventData.conferenceId, 
     230            scheduleEntryId : eventData.scheduleEntryId, 
     231            sessionId : eventData.sessionId, 
     232            sessionSlotId : eventData.sessionSlotId, 
     233            keepTime: keep_time || false 
     234        }, function(result, error) { 
     235 
     236            if (!undo) { 
     237                killProgress(); 
     238            } 
     239 
     240            if (error) { 
     241                IndicoUtil.errorReport(error); 
     242                dfr.reject(error); 
     243            } else { 
     244                if (undo) { 
     245                    self.enableUndo(undo, {'eventData': eventData, 
     246                                           'entry': result.entry}, null); 
     247                    self.drawUndoDiv(); 
     248                } 
     249                // change json and repaint timetable 
     250                self.timetable._updateMovedEntry(result, result.old.id).done(function() { 
     251                    dfr.resolve() 
     252                }); 
     253            }}); 
     254        return dfr.promise(); 
    192255    }, 
    193256 
     
    587650            this, 
    588651            this.timetable, 
    589             eventData.entryType, 
    590             eventData.sessionId, 
    591             eventData.sessionSlotId, 
    592             timetable.currentDay, 
    593             eventData.scheduleEntryId, 
    594             eventData.conferenceId, 
    595             eventData.startDate.date ); 
     652            eventData, 
     653            timetable.currentDay); 
    596654        moveEntryDiag.open(); 
    597655    }, 
Note: See TracChangeset for help on using the changeset viewer.