TipOfTheDayWindow.js (8254B)
1 /** 2 * This class represents the tip of the day window and its logic. 3 */ 4 Ext.define("PartKeepr.TipOfTheDayWindow", { 5 extend: 'Ext.window.Window', 6 7 /* Defines the title template. */ 8 titleTemplate: i18n("Tip of the Day"), 9 10 /* Cosmetic settings */ 11 width: 600, 12 height: 300, 13 14 minWidth: 600, 15 minHeight: 300, 16 17 layout: 'fit', 18 19 /** 20 * Stores the currently displayed tip, or null if none is displayed 21 * @var Ext.data.Record 22 */ 23 currentTip: null, 24 25 /** 26 * Holds an instance of the TipOfTheDay store. 27 */ 28 tipStore: null, 29 30 /** 31 * Holds an instance of the TipOfTheDayHistory store 32 */ 33 tipHistoryStore: null, 34 35 /** 36 * Initializes the window. Adds the iframe used for displaying tips, as well 37 * as the user controls (prev/next buttons, config checkboxes). 38 */ 39 initComponent: function () 40 { 41 // Initialize the window with the title template 42 this.title = this.titleTemplate; 43 44 // Set the tip store 45 this.tipStore = Ext.data.StoreManager.lookup('TipOfTheDayStore'); 46 this.tipHistoryStore = Ext.data.StoreManager.lookup('TipOfTheDayHistoryStore'); 47 48 // Set the tip display iframe and add it to the items 49 this.tipDisplay = Ext.create("Ext.ux.IFrame", { 50 border: false 51 }); 52 53 this.items = this.tipDisplay; 54 55 // Initialize previous and next buttons 56 this.previousButton = Ext.create("Ext.button.Button", { 57 text: i18n("Previous Tip"), 58 handler: Ext.bind(this.displayPreviousTip, this), 59 iconCls: 'partkeepr-icon tip_previous', 60 disabled: true 61 }); 62 63 this.nextButton = Ext.create("Ext.button.Button", { 64 text: i18n("Next Tip"), 65 iconCls: 'partkeepr-icon tip_next', 66 handler: Ext.bind(this.displayNextTip, this) 67 }); 68 69 // Initializes the "show tips on login" checkbox as well as the "show read tips" checkbox 70 this.showTipsCheckbox = Ext.create("Ext.form.field.Checkbox", { 71 boxLabel: i18n("Show Tips on login"), 72 handler: Ext.bind(this.showTipsHandler, this) 73 }); 74 75 this.displayReadTipsCheckbox = Ext.create("Ext.form.field.Checkbox", { 76 boxLabel: i18n("Show read tips"), 77 handler: Ext.bind(this.showReadTipsHandler, this) 78 }); 79 80 // Initialize the "show tips" checkbox with the user preference 81 if (PartKeepr.getApplication().getUserPreference("partkeepr.tipoftheday.showtips") === false) { 82 this.showTipsCheckbox.setValue(false); 83 } else { 84 this.showTipsCheckbox.setValue(true); 85 } 86 87 // Append the controls to the bottom toolbar 88 this.dockedItems = [ 89 { 90 xtype: 'toolbar', 91 dock: 'bottom', 92 ui: 'footer', 93 defaults: {minWidth: 100}, 94 pack: 'start', 95 items: [ 96 this.previousButton, 97 this.nextButton, 98 '->', 99 this.showTipsCheckbox, 100 this.displayReadTipsCheckbox 101 ] 102 } 103 ]; 104 105 // Auto-load the next unread tip on window display 106 this.updateFilter(); 107 this.currentTip = this.tipStore.getAt(0); 108 this.on("show", this.displayTip, this); 109 110 // Window destroy handler 111 this.on("destroy", this.onDestroy, this); 112 this.callParent(); 113 }, 114 /** 115 * Displays the previous tip 116 */ 117 displayPreviousTip: function () 118 { 119 var idx = this.tipStore.indexOf(this.currentTip); 120 this.currentTip = this.tipStore.getAt(idx - 1); 121 122 if (this.currentTip === null) { 123 this.currentTip = this.tipStore.getAt(0); 124 } 125 this.displayTip(this.currentTip); 126 }, 127 /** 128 * Displays the next tip 129 */ 130 displayNextTip: function () 131 { 132 var idx = this.tipStore.indexOf(this.currentTip); 133 this.currentTip = this.tipStore.getAt(idx + 1); 134 135 if (this.currentTip === null) { 136 this.currentTip = this.tipStore.getAt(0); 137 } 138 this.displayTip(this.currentTip); 139 }, 140 /** 141 * Updates the filter for the tip store to exclude read tips. 142 */ 143 updateFilter: function () 144 { 145 this.tipStore.clearFilter(); 146 147 if (this.displayReadTipsCheckbox.getValue() === true) { 148 return; 149 } 150 var filterItems = []; 151 152 this.tipHistoryStore.each(function (record) 153 { 154 filterItems.push(record.get("name")); 155 }); 156 157 var tipFilter = Ext.create("PartKeepr.util.Filter", { 158 property: "name", 159 operator: "notin", 160 value: filterItems 161 }); 162 163 this.tipStore.addFilter(tipFilter); 164 }, 165 /** 166 * If the "show read tips" checkbox was clicked, update the buttons 167 * to reflect the tip navigation. 168 */ 169 showReadTipsHandler: function () 170 { 171 this.updateFilter(); 172 this.updateButtons(this.currentTip); 173 }, 174 /** 175 * Destroy handler. Removes the "read tip" timer. 176 */ 177 onDestroy: function () 178 { 179 this.cancelReadTimer(); 180 }, 181 /** 182 * Cancels the read timer. 183 */ 184 cancelReadTimer: function () 185 { 186 if (this.markAsReadTask) { 187 this.markAsReadTask.cancel(); 188 } 189 }, 190 /** 191 * Handler when the "show tips" checkbox was clicked. 192 */ 193 showTipsHandler: function (checkbox, checked) 194 { 195 PartKeepr.getApplication().setUserPreference("partkeepr.tipoftheday.showtips", checked); 196 }, 197 /** 198 * Displays a specific tip of the day. 199 * @param record The record which contains the information regarding the tip 200 */ 201 displayTip: function () 202 { 203 if (!this.currentTip) { 204 return; 205 } 206 207 // Cancel the old read timer 208 this.cancelReadTimer(); 209 210 // Update buttons to reflect position 211 this.updateButtons(this.currentTip); 212 213 // Set the title to the tip name 214 this.setTitle(this.titleTemplate + ": " + this.currentTip.get("name")); 215 216 // Set iframe to the tip url 217 this.tipDisplay.load( 218 sprintf(PartKeepr.getApplication().getParameter("tip_of_the_day_uri"), this.currentTip.get("name"))); 219 220 // Fire up delayed task to mark the tip as read 221 if (this.markAsReadTask) { 222 this.markAsReadTask.cancel(); 223 } 224 225 this.markAsReadTask = new Ext.util.DelayedTask(this.markTipRead, this); 226 this.markAsReadTask.delay(5000); 227 228 }, 229 /** 230 * Updates the navigation buttons. 231 * 232 * This method has two modes, depending on which state the "show read tips" checkbox is in. 233 * @param record The currently displayed tip 234 */ 235 updateButtons: function (record) 236 { 237 if (this.tipStore.indexOf(record) > 0) { 238 this.previousButton.enable(); 239 } else { 240 this.previousButton.disable(); 241 } 242 243 if (this.tipStore.indexOf(record) === this.tipStore.getCount() - 1) { 244 this.nextButton.disable(); 245 } else { 246 this.nextButton.enable(); 247 } 248 249 }, 250 /** 251 * Marks the current tip as read. Commits the information to the server. 252 */ 253 markTipRead: function () 254 { 255 this.currentTip.callPutAction("markTipRead", {}, Ext.bind(this.onMarkTipRead, this)); 256 }, 257 /** 258 * Callback for when the markTipRead action has been completed. Re-loads the history store 259 */ 260 onMarkTipRead: function () 261 { 262 this.tipHistoryStore.load({ 263 scope: this, 264 callback: this.onHistoryStoreLoaded 265 }); 266 }, 267 /** 268 * Callback for when the history store has been loaded. Updates the filter 269 */ 270 onHistoryStoreLoaded: function () 271 { 272 this.updateFilter(); 273 }, 274 /** 275 * Returns if there are tips in the tip database which aren't read. 276 * 277 * @return {Boolean} True if there are tips available, false otherwise 278 */ 279 hasTips: function () 280 { 281 if (this.tipStore.count() > 0) { 282 return true; 283 } else { 284 return false; 285 } 286 287 } 288 });