diff --git a/amd/build/board.min.js b/amd/build/board.min.js index 65350a1f..190c0c26 100644 --- a/amd/build/board.min.js +++ b/amd/build/board.min.js @@ -1,3 +1,3 @@ -define("mod_kanban/board",["exports","core/reactive","mod_kanban/selectors","mod_kanban/capabilities","mod_kanban/exporter","mod_kanban/kanbancomponent","core/log","core/notification","core/str"],(function(_exports,_reactive,_selectors,_capabilities,_exporter,_kanbancomponent,_log,_notification,Str){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_selectors=_interopRequireDefault(_selectors),_capabilities=_interopRequireDefault(_capabilities),_exporter=_interopRequireDefault(_exporter),_kanbancomponent=_interopRequireDefault(_kanbancomponent),_log=_interopRequireDefault(_log),Str=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(Str);class _default extends _kanbancomponent.default{constructor(){super(...arguments),_defineProperty(this,"LOCKED_COLUMNS",1),_defineProperty(this,"LOCKED_COMPLETE",2)}static init(target){return new this({element:document.getElementById(target)})}create(){this.cmid=this.element.dataset.cmid,this.id=this.element.dataset.id}getWatchers(){return[{watch:"board:updated",handler:this._boardUpdated},{watch:"columns:created",handler:this._columnCreated},{watch:"board:deleted",handler:this._reload},{watch:"common:updated",handler:this._commonUpdated}]}async stateReady(state){this.addEventListener(this.getElement(_selectors.default.ADDCOLUMNFIRST),"click",this._addColumn),1==state.capabilities.get(_capabilities.default.MANAGEBOARD).value&&(this.addEventListener(this.getElement(_selectors.default.LOCKBOARDCOLUMNS),"click",this._lockColumns),this.addEventListener(this.getElement(_selectors.default.UNLOCKBOARDCOLUMNS),"click",this._unlockColumns),this.addEventListener(this.getElement(_selectors.default.SAVEASTEMPLATE),"click",this._templateConfirm),this.addEventListener(this.getElement(_selectors.default.SHOWTEMPLATE),"click",this._showTemplate),this.addEventListener(this.getElement(_selectors.default.DELETETEMPLATE),"click",this._deleteTemplateConfirm),this.addEventListener(this.getElement(_selectors.default.DELETEBOARD),"click",this._deleteConfirm)),this.addEventListener(this.getElement(_selectors.default.SCROLLLEFT),"click",this._scrollLeft),this.addEventListener(this.getElement(_selectors.default.SCROLLRIGHT),"click",this._scrollRight),this.addEventListener(this.getElement(_selectors.default.MAIN),"scroll",this._updateScrollButtons),this.dragdrop=new _reactive.DragDrop(this),state.common.liveupdate>0&&this._continuousUpdate(state.common.liveupdate),this.toggleClass("ontouchstart"in document.documentElement,"mod_kanban_touch"),this._updateScrollButtons()}_showTemplate(){window.location.href=M.cfg.wwwroot+"/mod/kanban/view.php?id="+this.reactive.state.common.id+"&boardid="+this.reactive.state.common.template}_reload(){window.location.replace(M.cfg.wwwroot+"/mod/kanban/view.php?id="+this.reactive.state.common.id+"&userid="+this.reactive.state.common.userid)}_continuousUpdate(){setInterval((()=>{this.reactive.dispatch("getUpdates")}),1e3*(arguments.length>0&&void 0!==arguments[0]?arguments[0]:10))}_commonUpdated(_ref){let{element:element}=_ref;this.toggleClass(0!=element.template,"mod_kanban_hastemplate")}destroy(){void 0!==this.dragdrop&&this.dragdrop.unregister(),this._reload()}_templateConfirm(){Str.get_strings([{key:"saveastemplate",component:"mod_kanban"},{key:"saveastemplateconfirm",component:"mod_kanban"},{key:"save",component:"core"}]).then((strings=>(0,_notification.saveCancel)(strings[0],strings[1],strings[2],(()=>{this._saveAsTemplate()})))).catch((error=>_log.default.debug(error)))}_saveAsTemplate(){this.reactive.dispatch("saveAsTemplate")}_deleteConfirm(){Str.get_strings([{key:"deleteboard",component:"mod_kanban"},{key:"deleteboardconfirm",component:"mod_kanban"},{key:"delete",component:"core"}]).then((strings=>(0,_notification.saveCancel)(strings[0],strings[1],strings[2],(()=>{this._deleteBoard()})))).catch((error=>_log.default.debug(error)))}_deleteTemplateConfirm(){Str.get_strings([{key:"deletetemplate",component:"mod_kanban"},{key:"deletetemplateconfirm",component:"mod_kanban"},{key:"delete",component:"core"}]).then((strings=>(0,_notification.saveCancel)(strings[0],strings[1],strings[2],(()=>{this._deleteBoard()})))).catch((error=>_log.default.debug(error)))}_deleteBoard(){this.reactive.dispatch("deleteBoard")}_boardUpdated(_ref2){let{element:element}=_ref2;const colcontainer=this.getElement(_selectors.default.COLUMNCONTAINER);if(void 0!==element.sequence){let sequence=element.sequence.split(",");[...colcontainer.children].forEach((node=>{node.classList.contains("mod_kanban_column")&&!sequence.includes(node.dataset.id)&&colcontainer.removeChild(node)})),[...colcontainer.children].sort(((a,b)=>sequence.indexOf(a.dataset.id)>sequence.indexOf(b.dataset.id)?1:-1)).forEach((node=>colcontainer.appendChild(node)))}this.toggleClass(element.locked,"mod_kanban_board_locked_columns"),this.toggleClass(element.hastemplate,"mod_kanban_hastemplate"),this._updateScrollButtons()}async _columnCreated(_ref3){let{element:element}=_ref3,data=Object.assign({id:element.id,title:element.title,options:element.options,sequence:element.sequence},_exporter.default.exportCapabilities(this.reactive.state)),placeholder=document.createElement("li");placeholder.setAttribute("data-id",data.id),this.getElement(_selectors.default.COLUMNCONTAINER).appendChild(placeholder);const newelement=(await this.renderComponent(placeholder,"mod_kanban/column",data)).getElement();this.getElement(_selectors.default.COLUMNCONTAINER).replaceChild(newelement,placeholder),this._updateScrollButtons()}_addColumn(){document.activeElement.blur(),this.reactive.dispatch("addColumn",0)}_lockColumns(){this.reactive.dispatch("lockColumns")}_unlockColumns(){this.reactive.dispatch("unlockColumns")}validateDropData(dropdata){return"column"==(null==dropdata?void 0:dropdata.type)}drop(dropdata){this.reactive.dispatch("moveColumn",dropdata.id,0)}showDropZone(){this.getElement(_selectors.default.ADDCOLUMNCONTAINER).classList.add("mod_kanban_insert")}hideDropZone(){this.getElement(_selectors.default.ADDCOLUMNCONTAINER).classList.remove("mod_kanban_insert")}_scrollLeft(){this.getElement(_selectors.default.MAIN).scrollLeft-=.75*document.querySelector(".mod_kanban_column").clientWidth}_scrollRight(){this.getElement(_selectors.default.MAIN).scrollLeft+=.75*document.querySelector(".mod_kanban_column").clientWidth}_updateScrollButtons(){let main=this.getElement(_selectors.default.MAIN);main.scrollLeft<=1?this.getElement(_selectors.default.SCROLLLEFT).style.setProperty("visibility","hidden"):this.getElement(_selectors.default.SCROLLLEFT).style.setProperty("visibility","visible"),main.clientWidth+main.scrollLeft0&&this._continuousUpdate(state.common.liveupdate),this.toggleClass("ontouchstart"in document.documentElement,"mod_kanban_touch"),this._updateScrollButtons()}_showTemplate(){window.location.href=M.cfg.wwwroot+"/mod/kanban/view.php?id="+this.reactive.state.common.id+"&boardid="+this.reactive.state.common.template}_reload(){window.location.replace(M.cfg.wwwroot+"/mod/kanban/view.php?id="+this.reactive.state.common.id+"&userid="+this.reactive.state.common.userid)}_continuousUpdate(){setInterval((()=>{this.reactive.dispatch("getUpdates")}),1e3*(arguments.length>0&&void 0!==arguments[0]?arguments[0]:10))}async _commonUpdated(_ref){let{element:element}=_ref;this.toggleClass(0!=element.template,"mod_kanban_hastemplate"),this.toggleClass(element.updatefails>0,"mod_kanban_updatefails")}destroy(){void 0!==this.dragdrop&&this.dragdrop.unregister(),this._reload()}_templateConfirm(){Str.get_strings([{key:"saveastemplate",component:"mod_kanban"},{key:"saveastemplateconfirm",component:"mod_kanban"},{key:"save",component:"core"}]).then((strings=>(0,_notification.saveCancel)(strings[0],strings[1],strings[2],(()=>{this._saveAsTemplate()})))).catch((error=>_log.default.debug(error)))}_saveAsTemplate(){this.reactive.dispatch("saveAsTemplate")}_deleteConfirm(){Str.get_strings([{key:"deleteboard",component:"mod_kanban"},{key:"deleteboardconfirm",component:"mod_kanban"},{key:"delete",component:"core"}]).then((strings=>(0,_notification.saveCancel)(strings[0],strings[1],strings[2],(()=>{this._deleteBoard()})))).catch((error=>_log.default.debug(error)))}_deleteTemplateConfirm(){Str.get_strings([{key:"deletetemplate",component:"mod_kanban"},{key:"deletetemplateconfirm",component:"mod_kanban"},{key:"delete",component:"core"}]).then((strings=>(0,_notification.saveCancel)(strings[0],strings[1],strings[2],(()=>{this._deleteBoard()})))).catch((error=>_log.default.debug(error)))}_deleteBoard(){this.reactive.dispatch("deleteBoard")}_boardUpdated(_ref2){let{element:element}=_ref2;const colcontainer=this.getElement(_selectors.default.COLUMNCONTAINER);if(void 0!==element.sequence){let sequence=element.sequence.split(",");[...colcontainer.children].forEach((node=>{node.classList.contains("mod_kanban_column")&&!sequence.includes(node.dataset.id)&&colcontainer.removeChild(node)})),[...colcontainer.children].sort(((a,b)=>sequence.indexOf(a.dataset.id)>sequence.indexOf(b.dataset.id)?1:-1)).forEach((node=>colcontainer.appendChild(node)))}this.toggleClass(element.locked,"mod_kanban_board_locked_columns"),this.toggleClass(element.hastemplate,"mod_kanban_hastemplate"),this._updateScrollButtons()}async _columnCreated(_ref3){let{element:element}=_ref3,data=Object.assign({id:element.id,title:element.title,options:element.options,sequence:element.sequence},_exporter.default.exportCapabilities(this.reactive.state)),placeholder=document.createElement("li");placeholder.setAttribute("data-id",data.id),this.getElement(_selectors.default.COLUMNCONTAINER).appendChild(placeholder);const newelement=(await this.renderComponent(placeholder,"mod_kanban/column",data)).getElement();this.getElement(_selectors.default.COLUMNCONTAINER).replaceChild(newelement,placeholder),this._updateScrollButtons()}_addColumn(){document.activeElement.blur(),this.reactive.dispatch("addColumn",0)}_lockColumns(){this.reactive.dispatch("lockColumns")}_unlockColumns(){this.reactive.dispatch("unlockColumns")}validateDropData(dropdata){return"column"==(null==dropdata?void 0:dropdata.type)}drop(dropdata){this.reactive.dispatch("moveColumn",dropdata.id,0)}showDropZone(){this.getElement(_selectors.default.ADDCOLUMNCONTAINER).classList.add("mod_kanban_insert")}hideDropZone(){this.getElement(_selectors.default.ADDCOLUMNCONTAINER).classList.remove("mod_kanban_insert")}_scrollLeft(){this.getElement(_selectors.default.MAIN).scrollLeft-=.75*document.querySelector(".mod_kanban_column").clientWidth}_scrollRight(){this.getElement(_selectors.default.MAIN).scrollLeft+=.75*document.querySelector(".mod_kanban_column").clientWidth}_updateScrollButtons(){let main=this.getElement(_selectors.default.MAIN);main.scrollLeft<=1?this.getElement(_selectors.default.SCROLLLEFT).style.setProperty("visibility","hidden"):this.getElement(_selectors.default.SCROLLLEFT).style.setProperty("visibility","visible"),main.clientWidth+main.scrollLeft 0) {\n this._continuousUpdate(state.common.liveupdate);\n }\n this.toggleClass('ontouchstart' in document.documentElement, 'mod_kanban_touch');\n this._updateScrollButtons();\n }\n\n /**\n * Called to show template.\n */\n _showTemplate() {\n window.location.href =\n M.cfg.wwwroot +\n '/mod/kanban/view.php?id=' +\n this.reactive.state.common.id +\n '&boardid=' +\n this.reactive.state.common.template;\n }\n\n /**\n * Reload current page.\n */\n _reload() {\n window.location.replace(\n M.cfg.wwwroot + '/mod/kanban/view.php?id=' + this.reactive.state.common.id +\n '&userid=' + this.reactive.state.common.userid);\n }\n\n /**\n * Start continuous update.\n * @param {number} seconds Seconds between two refresh calls, defaults to 10\n */\n _continuousUpdate(seconds = 10) {\n setInterval(() => {\n this.reactive.dispatch('getUpdates');\n }, seconds * 1000);\n }\n\n /**\n * Called when common data was updated\n * @param {*} param0\n */\n _commonUpdated({element}) {\n this.toggleClass(element.template != 0, 'mod_kanban_hastemplate');\n }\n\n /**\n * Remove all subcomponents dependencies.\n */\n destroy() {\n if (this.dragdrop !== undefined) {\n this.dragdrop.unregister();\n }\n this._reload();\n }\n\n /**\n * Display confirmation modal for saving a board as template.\n */\n _templateConfirm() {\n Str.get_strings([\n {key: 'saveastemplate', component: 'mod_kanban'},\n {key: 'saveastemplateconfirm', component: 'mod_kanban'},\n {key: 'save', component: 'core'},\n ]).then((strings) => {\n return saveCancel(\n strings[0],\n strings[1],\n strings[2],\n () => {\n this._saveAsTemplate();\n }\n );\n }).catch((error) => Log.debug(error));\n }\n\n /**\n * Called when current board should be saved as template.\n */\n _saveAsTemplate() {\n this.reactive.dispatch('saveAsTemplate');\n }\n\n /**\n * Display confirmation modal for deleting a board.\n */\n _deleteConfirm() {\n Str.get_strings([\n {key: 'deleteboard', component: 'mod_kanban'},\n {key: 'deleteboardconfirm', component: 'mod_kanban'},\n {key: 'delete', component: 'core'},\n ]).then((strings) => {\n return saveCancel(\n strings[0],\n strings[1],\n strings[2],\n () => {\n this._deleteBoard();\n }\n );\n }).catch((error) => Log.debug(error));\n }\n\n /**\n * Display confirmation modal for deleting a template.\n */\n _deleteTemplateConfirm() {\n Str.get_strings([\n {key: 'deletetemplate', component: 'mod_kanban'},\n {key: 'deletetemplateconfirm', component: 'mod_kanban'},\n {key: 'delete', component: 'core'},\n ]).then((strings) => {\n return saveCancel(\n strings[0],\n strings[1],\n strings[2],\n () => {\n this._deleteBoard();\n }\n );\n }).catch((error) => Log.debug(error));\n }\n\n /**\n * Called to delete current board.\n */\n _deleteBoard() {\n this.reactive.dispatch('deleteBoard');\n }\n\n /**\n * Called when board was updated.\n * @param {*} param0\n */\n _boardUpdated({element}) {\n const colcontainer = this.getElement(selectors.COLUMNCONTAINER);\n if (element.sequence !== undefined) {\n let sequence = element.sequence.split(',');\n // Remove all columns from frontend that are no longer present in the database.\n [...colcontainer.children]\n .forEach((node) => {\n if (node.classList.contains('mod_kanban_column') && !sequence.includes(node.dataset.id)) {\n colcontainer.removeChild(node);\n }\n });\n // Reorder columns according to sequence from the database.\n [...colcontainer.children]\n .sort((a, b) => sequence.indexOf(a.dataset.id) > sequence.indexOf(b.dataset.id) ? 1 : -1)\n .forEach(node => colcontainer.appendChild(node));\n }\n // Set CSS classes to show/hide action menu items.\n this.toggleClass(element.locked, 'mod_kanban_board_locked_columns');\n this.toggleClass(element.hastemplate, 'mod_kanban_hastemplate');\n this._updateScrollButtons();\n }\n\n /**\n * Called when a new column was added. Creates a new subcomponent.\n * @param {*} param0\n */\n async _columnCreated({element}) {\n let data = Object.assign({\n id: element.id,\n title: element.title,\n options: element.options,\n sequence: element.sequence,\n }, exporter.exportCapabilities(this.reactive.state));\n let placeholder = document.createElement('li');\n placeholder.setAttribute('data-id', data.id);\n this.getElement(selectors.COLUMNCONTAINER).appendChild(placeholder);\n const newcomponent = await this.renderComponent(placeholder, 'mod_kanban/column', data);\n const newelement = newcomponent.getElement();\n this.getElement(selectors.COLUMNCONTAINER).replaceChild(newelement, placeholder);\n // Make sure that the new column is recognized for the scroll buttons.\n this._updateScrollButtons();\n }\n\n /**\n * Called to add a column.\n */\n _addColumn() {\n document.activeElement.blur();\n // Board component only handles adding a column at the leftmost position, hence second parameter is always 0.\n this.reactive.dispatch('addColumn', 0);\n }\n\n /**\n * Called to lock all columns.\n */\n _lockColumns() {\n this.reactive.dispatch('lockColumns');\n }\n\n /**\n * Called to unlock all columns.\n */\n _unlockColumns() {\n this.reactive.dispatch('unlockColumns');\n }\n\n /**\n * Validate draggable data. This component only accepts columns.\n * @param {object} dropdata\n * @returns {boolean} if the data is valid for this drop-zone.\n */\n validateDropData(dropdata) {\n let type = dropdata?.type;\n return type == 'column';\n }\n\n /**\n * Executed when a valid dropdata is dropped over the drop-zone.\n * Moves the dropped column to the leftmost position (other positions are handled by column component).\n * @param {object} dropdata\n */\n drop(dropdata) {\n this.reactive.dispatch('moveColumn', dropdata.id, 0);\n }\n\n /**\n * Show some visual hints to the user.\n */\n showDropZone() {\n this.getElement(selectors.ADDCOLUMNCONTAINER).classList.add('mod_kanban_insert');\n }\n\n /**\n * Remove visual hints to the user.\n */\n hideDropZone() {\n this.getElement(selectors.ADDCOLUMNCONTAINER).classList.remove('mod_kanban_insert');\n }\n\n /**\n * Scroll to the left.\n */\n _scrollLeft() {\n this.getElement(selectors.MAIN).scrollLeft -= document.querySelector('.mod_kanban_column').clientWidth * 0.75;\n }\n\n /**\n * Scroll to the right.\n */\n _scrollRight() {\n this.getElement(selectors.MAIN).scrollLeft += document.querySelector('.mod_kanban_column').clientWidth * 0.75;\n }\n\n /**\n * Only show scroll buttons if it's possible to scroll in this direction.\n */\n _updateScrollButtons() {\n let main = this.getElement(selectors.MAIN);\n if (main.scrollLeft <= 1) {\n this.getElement(selectors.SCROLLLEFT).style.setProperty('visibility', 'hidden');\n } else {\n this.getElement(selectors.SCROLLLEFT).style.setProperty('visibility', 'visible');\n }\n if (main.clientWidth + main.scrollLeft < main.scrollWidth) {\n this.getElement(selectors.SCROLLRIGHT).style.setProperty('visibility', 'visible');\n } else {\n this.getElement(selectors.SCROLLRIGHT).style.setProperty('visibility', 'hidden');\n }\n }\n}\n"],"names":["KanbanComponent","target","this","element","document","getElementById","create","cmid","dataset","id","getWatchers","watch","handler","_boardUpdated","_columnCreated","_reload","_commonUpdated","state","addEventListener","getElement","selectors","ADDCOLUMNFIRST","_addColumn","capabilities","get","MANAGEBOARD","value","LOCKBOARDCOLUMNS","_lockColumns","UNLOCKBOARDCOLUMNS","_unlockColumns","SAVEASTEMPLATE","_templateConfirm","SHOWTEMPLATE","_showTemplate","DELETETEMPLATE","_deleteTemplateConfirm","DELETEBOARD","_deleteConfirm","SCROLLLEFT","_scrollLeft","SCROLLRIGHT","_scrollRight","MAIN","_updateScrollButtons","dragdrop","DragDrop","common","liveupdate","_continuousUpdate","toggleClass","documentElement","window","location","href","M","cfg","wwwroot","reactive","template","replace","userid","setInterval","dispatch","destroy","undefined","unregister","Str","get_strings","key","component","then","strings","_saveAsTemplate","catch","error","Log","debug","_deleteBoard","colcontainer","COLUMNCONTAINER","sequence","split","children","forEach","node","classList","contains","includes","removeChild","sort","a","b","indexOf","appendChild","locked","hastemplate","data","Object","assign","title","options","exporter","exportCapabilities","placeholder","createElement","setAttribute","newelement","renderComponent","replaceChild","activeElement","blur","validateDropData","dropdata","type","drop","showDropZone","ADDCOLUMNCONTAINER","add","hideDropZone","remove","scrollLeft","querySelector","clientWidth","main","style","setProperty","scrollWidth"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"board.min.js","sources":["../src/board.js"],"sourcesContent":["import {DragDrop} from 'core/reactive';\nimport selectors from 'mod_kanban/selectors';\nimport capabilities from 'mod_kanban/capabilities';\nimport exporter from 'mod_kanban/exporter';\nimport KanbanComponent from 'mod_kanban/kanbancomponent';\nimport Log from 'core/log';\nimport {saveCancel} from 'core/notification';\nimport * as Str from 'core/str';\n\n/**\n * Component representing a kanban board.\n */\nexport default class extends KanbanComponent {\n LOCKED_COLUMNS = 1;\n LOCKED_COMPLETE = 2;\n\n /**\n * Init component\n * @param {HTMLElement} target Element to attach the component to\n * @returns {KanbanComponent}\n */\n static init(target) {\n let element = document.getElementById(target);\n return new this({\n element: element,\n });\n }\n\n /**\n * Called before registering to reactive instance.\n */\n create() {\n this.cmid = this.element.dataset.cmid;\n this.id = this.element.dataset.id;\n }\n\n /**\n * Watchers defined by this component.\n * @returns {array}\n */\n getWatchers() {\n return [\n {watch: `board:updated`, handler: this._boardUpdated},\n {watch: `columns:created`, handler: this._columnCreated},\n {watch: `board:deleted`, handler: this._reload},\n {watch: `common:updated`, handler: this._commonUpdated},\n ];\n }\n\n /**\n * Called once when state is ready (also if component is registered after initial state was set), attaching event\n * isteners and initializing drag and drop.\n * @param {*} state The initial state\n */\n async stateReady(state) {\n this.addEventListener(\n this.getElement(selectors.ADDCOLUMNFIRST),\n 'click',\n this._addColumn\n );\n if (state.capabilities.get(capabilities.MANAGEBOARD).value == true) {\n this.addEventListener(\n this.getElement(selectors.LOCKBOARDCOLUMNS),\n 'click',\n this._lockColumns\n );\n this.addEventListener(\n this.getElement(selectors.UNLOCKBOARDCOLUMNS),\n 'click',\n this._unlockColumns\n );\n this.addEventListener(\n this.getElement(selectors.SAVEASTEMPLATE),\n 'click',\n this._templateConfirm\n );\n this.addEventListener(\n this.getElement(selectors.SHOWTEMPLATE),\n 'click',\n this._showTemplate\n );\n this.addEventListener(\n this.getElement(selectors.DELETETEMPLATE),\n 'click',\n this._deleteTemplateConfirm\n );\n this.addEventListener(\n this.getElement(selectors.DELETEBOARD),\n 'click',\n this._deleteConfirm\n );\n }\n this.addEventListener(\n this.getElement(selectors.SCROLLLEFT),\n 'click',\n this._scrollLeft\n );\n this.addEventListener(\n this.getElement(selectors.SCROLLRIGHT),\n 'click',\n this._scrollRight\n );\n this.addEventListener(\n this.getElement(selectors.MAIN),\n 'scroll',\n this._updateScrollButtons\n );\n this.dragdrop = new DragDrop(this);\n if (state.common.liveupdate > 0) {\n this._continuousUpdate(state.common.liveupdate);\n }\n this.toggleClass('ontouchstart' in document.documentElement, 'mod_kanban_touch');\n this._updateScrollButtons();\n }\n\n /**\n * Called to show template.\n */\n _showTemplate() {\n window.location.href =\n M.cfg.wwwroot +\n '/mod/kanban/view.php?id=' +\n this.reactive.state.common.id +\n '&boardid=' +\n this.reactive.state.common.template;\n }\n\n /**\n * Reload current page.\n */\n _reload() {\n window.location.replace(\n M.cfg.wwwroot + '/mod/kanban/view.php?id=' + this.reactive.state.common.id +\n '&userid=' + this.reactive.state.common.userid);\n }\n\n /**\n * Start continuous update.\n * @param {number} seconds Seconds between two refresh calls, defaults to 10\n */\n _continuousUpdate(seconds = 10) {\n setInterval(() => {\n this.reactive.dispatch('getUpdates');\n }, seconds * 1000);\n }\n\n /**\n * Called when common data was updated\n * @param {*} param0\n */\n async _commonUpdated({element}) {\n this.toggleClass(element.template != 0, 'mod_kanban_hastemplate');\n this.toggleClass(element.updatefails > 0, 'mod_kanban_updatefails');\n }\n\n /**\n * Remove all subcomponents dependencies.\n */\n destroy() {\n if (this.dragdrop !== undefined) {\n this.dragdrop.unregister();\n }\n this._reload();\n }\n\n /**\n * Display confirmation modal for saving a board as template.\n */\n _templateConfirm() {\n Str.get_strings([\n {key: 'saveastemplate', component: 'mod_kanban'},\n {key: 'saveastemplateconfirm', component: 'mod_kanban'},\n {key: 'save', component: 'core'},\n ]).then((strings) => {\n return saveCancel(\n strings[0],\n strings[1],\n strings[2],\n () => {\n this._saveAsTemplate();\n }\n );\n }).catch((error) => Log.debug(error));\n }\n\n /**\n * Called when current board should be saved as template.\n */\n _saveAsTemplate() {\n this.reactive.dispatch('saveAsTemplate');\n }\n\n /**\n * Display confirmation modal for deleting a board.\n */\n _deleteConfirm() {\n Str.get_strings([\n {key: 'deleteboard', component: 'mod_kanban'},\n {key: 'deleteboardconfirm', component: 'mod_kanban'},\n {key: 'delete', component: 'core'},\n ]).then((strings) => {\n return saveCancel(\n strings[0],\n strings[1],\n strings[2],\n () => {\n this._deleteBoard();\n }\n );\n }).catch((error) => Log.debug(error));\n }\n\n /**\n * Display confirmation modal for deleting a template.\n */\n _deleteTemplateConfirm() {\n Str.get_strings([\n {key: 'deletetemplate', component: 'mod_kanban'},\n {key: 'deletetemplateconfirm', component: 'mod_kanban'},\n {key: 'delete', component: 'core'},\n ]).then((strings) => {\n return saveCancel(\n strings[0],\n strings[1],\n strings[2],\n () => {\n this._deleteBoard();\n }\n );\n }).catch((error) => Log.debug(error));\n }\n\n /**\n * Called to delete current board.\n */\n _deleteBoard() {\n this.reactive.dispatch('deleteBoard');\n }\n\n /**\n * Called when board was updated.\n * @param {*} param0\n */\n _boardUpdated({element}) {\n const colcontainer = this.getElement(selectors.COLUMNCONTAINER);\n if (element.sequence !== undefined) {\n let sequence = element.sequence.split(',');\n // Remove all columns from frontend that are no longer present in the database.\n [...colcontainer.children]\n .forEach((node) => {\n if (node.classList.contains('mod_kanban_column') && !sequence.includes(node.dataset.id)) {\n colcontainer.removeChild(node);\n }\n });\n // Reorder columns according to sequence from the database.\n [...colcontainer.children]\n .sort((a, b) => sequence.indexOf(a.dataset.id) > sequence.indexOf(b.dataset.id) ? 1 : -1)\n .forEach(node => colcontainer.appendChild(node));\n }\n // Set CSS classes to show/hide action menu items.\n this.toggleClass(element.locked, 'mod_kanban_board_locked_columns');\n this.toggleClass(element.hastemplate, 'mod_kanban_hastemplate');\n this._updateScrollButtons();\n }\n\n /**\n * Called when a new column was added. Creates a new subcomponent.\n * @param {*} param0\n */\n async _columnCreated({element}) {\n let data = Object.assign({\n id: element.id,\n title: element.title,\n options: element.options,\n sequence: element.sequence,\n }, exporter.exportCapabilities(this.reactive.state));\n let placeholder = document.createElement('li');\n placeholder.setAttribute('data-id', data.id);\n this.getElement(selectors.COLUMNCONTAINER).appendChild(placeholder);\n const newcomponent = await this.renderComponent(placeholder, 'mod_kanban/column', data);\n const newelement = newcomponent.getElement();\n this.getElement(selectors.COLUMNCONTAINER).replaceChild(newelement, placeholder);\n // Make sure that the new column is recognized for the scroll buttons.\n this._updateScrollButtons();\n }\n\n /**\n * Called to add a column.\n */\n _addColumn() {\n document.activeElement.blur();\n // Board component only handles adding a column at the leftmost position, hence second parameter is always 0.\n this.reactive.dispatch('addColumn', 0);\n }\n\n /**\n * Called to lock all columns.\n */\n _lockColumns() {\n this.reactive.dispatch('lockColumns');\n }\n\n /**\n * Called to unlock all columns.\n */\n _unlockColumns() {\n this.reactive.dispatch('unlockColumns');\n }\n\n /**\n * Validate draggable data. This component only accepts columns.\n * @param {object} dropdata\n * @returns {boolean} if the data is valid for this drop-zone.\n */\n validateDropData(dropdata) {\n let type = dropdata?.type;\n return type == 'column';\n }\n\n /**\n * Executed when a valid dropdata is dropped over the drop-zone.\n * Moves the dropped column to the leftmost position (other positions are handled by column component).\n * @param {object} dropdata\n */\n drop(dropdata) {\n this.reactive.dispatch('moveColumn', dropdata.id, 0);\n }\n\n /**\n * Show some visual hints to the user.\n */\n showDropZone() {\n this.getElement(selectors.ADDCOLUMNCONTAINER).classList.add('mod_kanban_insert');\n }\n\n /**\n * Remove visual hints to the user.\n */\n hideDropZone() {\n this.getElement(selectors.ADDCOLUMNCONTAINER).classList.remove('mod_kanban_insert');\n }\n\n /**\n * Scroll to the left.\n */\n _scrollLeft() {\n this.getElement(selectors.MAIN).scrollLeft -= document.querySelector('.mod_kanban_column').clientWidth * 0.75;\n }\n\n /**\n * Scroll to the right.\n */\n _scrollRight() {\n this.getElement(selectors.MAIN).scrollLeft += document.querySelector('.mod_kanban_column').clientWidth * 0.75;\n }\n\n /**\n * Only show scroll buttons if it's possible to scroll in this direction.\n */\n _updateScrollButtons() {\n let main = this.getElement(selectors.MAIN);\n if (main.scrollLeft <= 1) {\n this.getElement(selectors.SCROLLLEFT).style.setProperty('visibility', 'hidden');\n } else {\n this.getElement(selectors.SCROLLLEFT).style.setProperty('visibility', 'visible');\n }\n if (main.clientWidth + main.scrollLeft < main.scrollWidth) {\n this.getElement(selectors.SCROLLRIGHT).style.setProperty('visibility', 'visible');\n } else {\n this.getElement(selectors.SCROLLRIGHT).style.setProperty('visibility', 'hidden');\n }\n }\n}\n"],"names":["KanbanComponent","target","this","element","document","getElementById","create","cmid","dataset","id","getWatchers","watch","handler","_boardUpdated","_columnCreated","_reload","_commonUpdated","state","addEventListener","getElement","selectors","ADDCOLUMNFIRST","_addColumn","capabilities","get","MANAGEBOARD","value","LOCKBOARDCOLUMNS","_lockColumns","UNLOCKBOARDCOLUMNS","_unlockColumns","SAVEASTEMPLATE","_templateConfirm","SHOWTEMPLATE","_showTemplate","DELETETEMPLATE","_deleteTemplateConfirm","DELETEBOARD","_deleteConfirm","SCROLLLEFT","_scrollLeft","SCROLLRIGHT","_scrollRight","MAIN","_updateScrollButtons","dragdrop","DragDrop","common","liveupdate","_continuousUpdate","toggleClass","documentElement","window","location","href","M","cfg","wwwroot","reactive","template","replace","userid","setInterval","dispatch","updatefails","destroy","undefined","unregister","Str","get_strings","key","component","then","strings","_saveAsTemplate","catch","error","Log","debug","_deleteBoard","colcontainer","COLUMNCONTAINER","sequence","split","children","forEach","node","classList","contains","includes","removeChild","sort","a","b","indexOf","appendChild","locked","hastemplate","data","Object","assign","title","options","exporter","exportCapabilities","placeholder","createElement","setAttribute","newelement","renderComponent","replaceChild","activeElement","blur","validateDropData","dropdata","type","drop","showDropZone","ADDCOLUMNCONTAINER","add","hideDropZone","remove","scrollLeft","querySelector","clientWidth","main","style","setProperty","scrollWidth"],"mappings":"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"} \ No newline at end of file diff --git a/amd/build/mutations.min.js b/amd/build/mutations.min.js index 3135057a..9aac823b 100644 --- a/amd/build/mutations.min.js +++ b/amd/build/mutations.min.js @@ -1,3 +1,3 @@ -define("mod_kanban/mutations",["exports","core/ajax","core/notification","core/str"],(function(_exports,_ajax,_notification,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_ajax=_interopRequireDefault(_ajax),_notification=_interopRequireDefault(_notification);return _exports.default=class{constructor(){var obj,key,value;value=0,(key="updateFails")in(obj=this)?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value}async saveAsTemplate(stateManager){await this._sendChange("save_as_template",stateManager)}async deleteCard(stateManager,cardId){await this._sendChange("delete_card",stateManager,{cardid:cardId})}async deleteBoard(stateManager){await this._sendChange("delete_board",stateManager)}async addCard(stateManager,columnId,afterCard){await this._sendChange("add_card",stateManager,{columnid:columnId,aftercard:afterCard})}async moveCard(stateManager,cardId,columnId,afterCard){await this._sendChange("move_card",stateManager,{cardid:cardId,columnid:columnId,aftercard:afterCard})}async deleteColumn(stateManager,columnId){await this._sendChange("delete_column",stateManager,{columnid:columnId})}async addColumn(stateManager,afterColumn){await this._sendChange("add_column",stateManager,{aftercol:afterColumn})}async moveColumn(stateManager,columnId,afterColumn){await this._sendChange("move_column",stateManager,{columnid:columnId,aftercol:afterColumn})}async assignUser(stateManager,cardId){let userId=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;await this._sendChange("assign_user",stateManager,{cardid:cardId,userid:userId})}async completeCard(stateManager,cardId){await this._sendChange("set_card_complete",stateManager,{cardid:cardId,state:1})}async uncompleteCard(stateManager,cardId){await this._sendChange("set_card_complete",stateManager,{cardid:cardId,state:0})}async unassignUser(stateManager,cardId){let userId=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;await this._sendChange("unassign_user",stateManager,{cardid:cardId,userid:userId})}async lockColumn(stateManager,columnId){await this._sendChange("set_column_locked",stateManager,{columnid:columnId,state:1})}async unlockColumn(stateManager,columnId){await this._sendChange("set_column_locked",stateManager,{columnid:columnId,state:0})}async lockColumns(stateManager){await this._sendChange("set_board_columns_locked",stateManager,{state:1})}async unlockColumns(stateManager){await this._sendChange("set_board_columns_locked",stateManager,{state:0})}async sendDiscussionMessage(stateManager,cardId,message){await this._sendChange("add_discussion_message",stateManager,{cardid:cardId,message:message})}async deleteMessage(stateManager,messageId){await this._sendChange("delete_discussion_message",stateManager,{messageid:messageId})}async pushCard(stateManager,cardId){await this._sendChange("push_card_copy",stateManager,{cardid:cardId})}async _sendChange(method,stateManager,data){const state=stateManager.state,result=await _ajax.default.call([{methodname:"mod_kanban_"+method,args:{cmid:state.common.id,boardid:state.board.id,data:data},fail:this.processFail}])[0];this.processUpdates(stateManager,result)}processFail(ex){_notification.default.alert((0,_str.get_string)("error"),ex.message,(0,_str.get_string)("cancel"))}async getUpdates(stateManager){const state=stateManager.state;if(void 0===state.board)stateManager.setReadOnly(!1),stateManager.eventsToPublish.push({eventName:"board:deleted",eventData:{},action:"deleted"}),stateManager.setReadOnly(!0);else{const result=await _ajax.default.call([{methodname:"mod_kanban_get_kanban_content_update",args:{cmid:state.common.id,boardid:state.board.id,timestamp:state.common.timestamp},fail:()=>{this.processUpdateFail()}}])[0];this.processUpdates(stateManager,result),this.resetUpdateFails()}}resetUpdateFails(){this.updateFails=0,document.querySelector(".mod_kanban_update_error").classList.add("hidden")}processUpdateFail(){this.updateFails++,this.updateFails>2&&document.querySelector(".mod_kanban_update_error").classList.remove("hidden")}async getDiscussionUpdates(stateManager,cardId){const state=stateManager.state;let timestamp=0;state.discussions.forEach((c=>{c.kanban_card==cardId&&c.timestamp>timestamp&&(timestamp=c.timestamp)}));const result=await _ajax.default.call([{methodname:"mod_kanban_get_discussion_update",args:{cmid:state.common.id,boardid:state.board.id,cardid:cardId,timestamp:timestamp},fail:()=>{this.processUpdateFail()}}])[0];this.processUpdates(stateManager,result)}async getHistoryUpdates(stateManager,cardId){const state=stateManager.state;let timestamp=0;state.history.forEach((c=>{c.kanban_card==cardId&&c.timestamp>timestamp&&(timestamp=c.timestamp)}));const result=await _ajax.default.call([{methodname:"mod_kanban_get_history_update",args:{cmid:state.common.id,boardid:state.board.id,cardid:cardId,timestamp:timestamp},fail:()=>{this.processUpdateFail()}}])[0];this.processUpdates(stateManager,result)}async processUpdates(stateManager,result){let updates=JSON.parse(result.update);stateManager.processUpdates(updates),this.resetUpdateFails()}},_exports.default})); +define("mod_kanban/mutations",["exports","core/ajax","core/notification","core/str"],(function(_exports,_ajax,_notification,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_ajax=_interopRequireDefault(_ajax),_notification=_interopRequireDefault(_notification);return _exports.default=class{constructor(){var obj,key,value;value=0,(key="updateFails")in(obj=this)?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value}async saveAsTemplate(stateManager){await this._sendChange("save_as_template",stateManager)}async deleteCard(stateManager,cardId){await this._sendChange("delete_card",stateManager,{cardid:cardId})}async deleteBoard(stateManager){await this._sendChange("delete_board",stateManager)}async addCard(stateManager,columnId,afterCard){await this._sendChange("add_card",stateManager,{columnid:columnId,aftercard:afterCard})}async moveCard(stateManager,cardId,columnId,afterCard){await this._sendChange("move_card",stateManager,{cardid:cardId,columnid:columnId,aftercard:afterCard})}async deleteColumn(stateManager,columnId){await this._sendChange("delete_column",stateManager,{columnid:columnId})}async addColumn(stateManager,afterColumn){await this._sendChange("add_column",stateManager,{aftercol:afterColumn})}async moveColumn(stateManager,columnId,afterColumn){await this._sendChange("move_column",stateManager,{columnid:columnId,aftercol:afterColumn})}async assignUser(stateManager,cardId){let userId=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;await this._sendChange("assign_user",stateManager,{cardid:cardId,userid:userId})}async completeCard(stateManager,cardId){await this._sendChange("set_card_complete",stateManager,{cardid:cardId,state:1})}async uncompleteCard(stateManager,cardId){await this._sendChange("set_card_complete",stateManager,{cardid:cardId,state:0})}async unassignUser(stateManager,cardId){let userId=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;await this._sendChange("unassign_user",stateManager,{cardid:cardId,userid:userId})}async lockColumn(stateManager,columnId){await this._sendChange("set_column_locked",stateManager,{columnid:columnId,state:1})}async unlockColumn(stateManager,columnId){await this._sendChange("set_column_locked",stateManager,{columnid:columnId,state:0})}async lockColumns(stateManager){await this._sendChange("set_board_columns_locked",stateManager,{state:1})}async unlockColumns(stateManager){await this._sendChange("set_board_columns_locked",stateManager,{state:0})}async sendDiscussionMessage(stateManager,cardId,message){await this._sendChange("add_discussion_message",stateManager,{cardid:cardId,message:message})}async deleteMessage(stateManager,messageId){await this._sendChange("delete_discussion_message",stateManager,{messageid:messageId})}async pushCard(stateManager,cardId){await this._sendChange("push_card_copy",stateManager,{cardid:cardId})}async _sendChange(method,stateManager,data){const state=stateManager.state,request={methodname:"mod_kanban_"+method,args:{cmid:state.common.id,boardid:state.board.id,data:data},fail:this.displayError},result=await _ajax.default.call([request])[0];this.processUpdates(stateManager,result)}async getUpdates(stateManager){const state=stateManager.state;if(void 0===state.board)stateManager.setReadOnly(!1),stateManager.eventsToPublish.push({eventName:"board:deleted",eventData:{},action:"deleted"}),stateManager.setReadOnly(!0);else{const result=await _ajax.default.call([{methodname:"mod_kanban_get_kanban_content_update",args:{cmid:state.common.id,boardid:state.board.id,timestamp:state.common.timestamp},fail:()=>{this.processUpdateFail(stateManager)}}])[0];this.processUpdates(stateManager,result)}}processUpdateFail(stateManager){const state=stateManager.state;stateManager.setReadOnly(!1),state.common.updatefails++,stateManager.setReadOnly(!0)}async displayError(data){data.message&&_notification.default.alert((0,_str.get_string)("error"),data.message,(0,_str.get_string)("cancel"))}async getDiscussionUpdates(stateManager,cardId){const state=stateManager.state;let timestamp=0;state.discussions.forEach((c=>{c.kanban_card==cardId&&c.timestamp>timestamp&&(timestamp=c.timestamp)}));const result=await _ajax.default.call([{methodname:"mod_kanban_get_discussion_update",args:{cmid:state.common.id,boardid:state.board.id,cardid:cardId,timestamp:timestamp},fail:()=>{this.processUpdateFail()}}])[0];this.processUpdates(stateManager,result)}async getHistoryUpdates(stateManager,cardId){const state=stateManager.state;let timestamp=0;state.history.forEach((c=>{c.kanban_card==cardId&&c.timestamp>timestamp&&(timestamp=c.timestamp)}));const result=await _ajax.default.call([{methodname:"mod_kanban_get_history_update",args:{cmid:state.common.id,boardid:state.board.id,cardid:cardId,timestamp:timestamp},fail:()=>{this.processUpdateFail()}}])[0];this.processUpdates(stateManager,result)}async processUpdates(stateManager,result){let updates=JSON.parse(result.update);stateManager.processUpdates(updates)}},_exports.default})); //# sourceMappingURL=mutations.min.js.map \ No newline at end of file diff --git a/amd/build/mutations.min.js.map b/amd/build/mutations.min.js.map index 72e04d1d..d2de9ec8 100644 --- a/amd/build/mutations.min.js.map +++ b/amd/build/mutations.min.js.map @@ -1 +1 @@ -{"version":3,"file":"mutations.min.js","sources":["../src/mutations.js"],"sourcesContent":["import Ajax from 'core/ajax';\nimport Notification from 'core/notification';\nimport {get_string as getString} from 'core/str';\n\n\n/**\n * Mutations library for mod_kanban.\n * The functions are just used to forward data to the webservice.\n */\nexport default class {\n // Attribute for counting update fails.\n updateFails = 0;\n\n async saveAsTemplate(stateManager) {\n await this._sendChange('save_as_template', stateManager);\n }\n\n /**\n * Delete a card.\n * @param {*} stateManager StateManager instance\n * @param {number} cardId Id of the card to be deleted\n */\n async deleteCard(stateManager, cardId) {\n await this._sendChange('delete_card', stateManager, {cardid: cardId});\n }\n\n /**\n * Delete the board.\n * @param {*} stateManager StateManager instance\n */\n async deleteBoard(stateManager) {\n await this._sendChange('delete_board', stateManager);\n }\n\n /**\n * Add a card after an existing one.\n * @param {*} stateManager StateManager instance\n * @param {number} columnId Id of the column\n * @param {number} afterCard Id of the card before (0 means to insert at the top of the column)\n */\n async addCard(stateManager, columnId, afterCard) {\n await this._sendChange('add_card', stateManager, {columnid: columnId, aftercard: afterCard});\n }\n\n /**\n * Move a card to another column.\n * @param {*} stateManager StateManager instance\n * @param {number} cardId Id of the card to be deleted\n * @param {number} columnId Id of the new column\n * @param {number} afterCard Id of the card before (0 means to move at the top of the column)\n */\n async moveCard(stateManager, cardId, columnId, afterCard) {\n await this._sendChange('move_card', stateManager, {cardid: cardId, columnid: columnId, aftercard: afterCard});\n }\n\n /**\n * Deletes a column and all cards within.\n * @param {*} stateManager StateManager instance\n * @param {number} columnId Id of the column to delete\n */\n async deleteColumn(stateManager, columnId) {\n await this._sendChange('delete_column', stateManager, {columnid: columnId});\n }\n\n /**\n * Adds a new column.\n * @param {*} stateManager StateManager instance\n * @param {number} afterColumn Id of the column before (0 means to insert at the left of the board)\n */\n async addColumn(stateManager, afterColumn) {\n await this._sendChange('add_column', stateManager, {aftercol: afterColumn});\n }\n\n /**\n * Moves a column to a new place.\n * @param {*} stateManager StateManager instance\n * @param {number} columnId Id of the column to move\n * @param {number} afterColumn Id of the column before (0 means to insert at the left of the board)\n */\n async moveColumn(stateManager, columnId, afterColumn) {\n await this._sendChange('move_column', stateManager, {columnid: columnId, aftercol: afterColumn});\n }\n\n /**\n * Assign a user to a card.\n * @param {*} stateManager StateManager instance.\n * @param {number} cardId Id of the card\n * @param {number} userId Id of the user to assign (0 means to assign the current user)\n */\n async assignUser(stateManager, cardId, userId = 0) {\n await this._sendChange('assign_user', stateManager, {cardid: cardId, userid: userId});\n }\n\n /**\n * Mark a card as completed.\n * @param {*} stateManager StateManager instance.\n * @param {number} cardId Id of the card\n */\n async completeCard(stateManager, cardId) {\n await this._sendChange('set_card_complete', stateManager, {cardid: cardId, state: 1});\n }\n\n /**\n * Mark a card as not completed.\n * @param {*} stateManager StateManager instance.\n * @param {number} cardId Id of the card\n */\n async uncompleteCard(stateManager, cardId) {\n await this._sendChange('set_card_complete', stateManager, {cardid: cardId, state: 0});\n }\n\n /**\n * Remove assignment for a user to a card.\n * @param {*} stateManager StateManager instance.\n * @param {number} cardId Id of the card\n * @param {number} userId Id of the user to unassign, defaults to 0 (current user)\n */\n async unassignUser(stateManager, cardId, userId = 0) {\n await this._sendChange('unassign_user', stateManager, {cardid: cardId, userid: userId});\n }\n\n /**\n * Locks a column.\n * @param {*} stateManager StateManager instance\n * @param {number} columnId Id of the column to lock\n */\n async lockColumn(stateManager, columnId) {\n await this._sendChange('set_column_locked', stateManager, {columnid: columnId, state: 1});\n }\n\n /**\n * Unlocks a column.\n * @param {*} stateManager StateManager instance\n * @param {number} columnId Id of the column to unlock\n */\n async unlockColumn(stateManager, columnId) {\n await this._sendChange('set_column_locked', stateManager, {columnid: columnId, state: 0});\n }\n\n /**\n * Locks all columns of the board.\n * @param {*} stateManager StateManager instance\n */\n async lockColumns(stateManager) {\n await this._sendChange('set_board_columns_locked', stateManager, {state: 1});\n }\n\n /**\n * Unlocks all columns of the board.\n * @param {*} stateManager StateManager instance\n */\n async unlockColumns(stateManager) {\n await this._sendChange('set_board_columns_locked', stateManager, {state: 0});\n }\n\n /**\n * Adds a message to discussion.\n * @param {*} stateManager\n * @param {*} cardId\n * @param {*} message\n */\n async sendDiscussionMessage(stateManager, cardId, message) {\n await this._sendChange('add_discussion_message', stateManager, {cardid: cardId, message: message});\n }\n\n /**\n * Delete a message from a discussion.\n * @param {*} stateManager StateManager instance\n * @param {number} messageId Id of the message to be deleted\n */\n async deleteMessage(stateManager, messageId) {\n await this._sendChange('delete_discussion_message', stateManager, {messageid: messageId});\n }\n\n /**\n * Push a copy of a card to all boards.\n * @param {*} stateManager StateManager instance\n * @param {number} cardId Id of the card to be pushed\n */\n async pushCard(stateManager, cardId) {\n await this._sendChange('push_card_copy', stateManager, {cardid: cardId});\n }\n\n /**\n * Send change request to webservice\n * @param {string} method Name of the method\n * @param {*} stateManager StateManager instance\n * @param {object} data Data to send\n */\n async _sendChange(method, stateManager, data) {\n const state = stateManager.state;\n const result = await Ajax.call([{\n methodname: 'mod_kanban_' + method,\n args: {\n cmid: state.common.id,\n boardid: state.board.id,\n data: data\n },\n fail: this.processFail,\n }])[0];\n\n this.processUpdates(stateManager, result);\n }\n\n /**\n * Notify user about an error.\n * @param {*} ex\n */\n processFail(ex) {\n Notification.alert(getString('error'), ex.message, getString('cancel'));\n }\n\n /**\n * Update state.\n * @param {*} stateManager\n */\n async getUpdates(stateManager) {\n const state = stateManager.state;\n if (state.board === undefined) {\n stateManager.setReadOnly(false);\n stateManager.eventsToPublish.push({\n eventName: `board:deleted`,\n eventData: {},\n action: `deleted`,\n });\n stateManager.setReadOnly(true);\n } else {\n const result = await Ajax.call([{\n methodname: 'mod_kanban_get_kanban_content_update',\n args: {\n cmid: state.common.id,\n boardid: state.board.id,\n timestamp: state.common.timestamp,\n },\n fail: () => {\n this.processUpdateFail();\n },\n }])[0];\n\n this.processUpdates(stateManager, result);\n this.resetUpdateFails();\n }\n }\n\n /**\n * Reset update fails.\n */\n resetUpdateFails() {\n this.updateFails = 0;\n document.querySelector('.mod_kanban_update_error').classList.add('hidden');\n }\n\n /**\n * Notify user about an error.\n */\n processUpdateFail() {\n this.updateFails++;\n if (this.updateFails > 2) {\n document.querySelector('.mod_kanban_update_error').classList.remove('hidden');\n }\n }\n\n /**\n * Update discussions for a card.\n * @param {*} stateManager\n * @param {number} cardId\n */\n async getDiscussionUpdates(stateManager, cardId) {\n const state = stateManager.state;\n let timestamp = 0;\n state.discussions.forEach((c) => {\n if (c.kanban_card == cardId) {\n if (c.timestamp > timestamp) {\n timestamp = c.timestamp;\n }\n }\n });\n\n const result = await Ajax.call([{\n methodname: 'mod_kanban_get_discussion_update',\n args: {\n cmid: state.common.id,\n boardid: state.board.id,\n cardid: cardId,\n timestamp: timestamp,\n },\n fail: () => {\n this.processUpdateFail();\n },\n }])[0];\n\n this.processUpdates(stateManager, result);\n }\n\n /**\n * Update history for a card.\n * @param {*} stateManager\n * @param {number} cardId\n */\n async getHistoryUpdates(stateManager, cardId) {\n const state = stateManager.state;\n let timestamp = 0;\n state.history.forEach((c) => {\n if (c.kanban_card == cardId) {\n if (c.timestamp > timestamp) {\n timestamp = c.timestamp;\n }\n }\n });\n\n const result = await Ajax.call([{\n methodname: 'mod_kanban_get_history_update',\n args: {\n cmid: state.common.id,\n boardid: state.board.id,\n cardid: cardId,\n timestamp: timestamp,\n },\n fail: () => {\n this.processUpdateFail();\n },\n }])[0];\n\n this.processUpdates(stateManager, result);\n }\n\n /**\n * Process updates.\n *\n * @param {*} stateManager\n * @param {*} result\n */\n async processUpdates(stateManager, result) {\n let updates = JSON.parse(result.update);\n stateManager.processUpdates(updates);\n this.resetUpdateFails();\n }\n}\n"],"names":["stateManager","this","_sendChange","cardId","cardid","columnId","afterCard","columnid","aftercard","afterColumn","aftercol","userId","userid","state","message","messageId","messageid","method","data","result","Ajax","call","methodname","args","cmid","common","id","boardid","board","fail","processFail","processUpdates","ex","alert","undefined","setReadOnly","eventsToPublish","push","eventName","eventData","action","timestamp","processUpdateFail","resetUpdateFails","updateFails","document","querySelector","classList","add","remove","discussions","forEach","c","kanban_card","history","updates","JSON","parse","update"],"mappings":"gcAWkB,6JAEOA,oBACXC,KAAKC,YAAY,mBAAoBF,+BAQ9BA,aAAcG,cACrBF,KAAKC,YAAY,cAAeF,aAAc,CAACI,OAAQD,2BAO/CH,oBACRC,KAAKC,YAAY,eAAgBF,4BAS7BA,aAAcK,SAAUC,iBAC5BL,KAAKC,YAAY,WAAYF,aAAc,CAACO,SAAUF,SAAUG,UAAWF,2BAUtEN,aAAcG,OAAQE,SAAUC,iBACrCL,KAAKC,YAAY,YAAaF,aAAc,CAACI,OAAQD,OAAQI,SAAUF,SAAUG,UAAWF,+BAQnFN,aAAcK,gBACvBJ,KAAKC,YAAY,gBAAiBF,aAAc,CAACO,SAAUF,2BAQrDL,aAAcS,mBACpBR,KAAKC,YAAY,aAAcF,aAAc,CAACU,SAAUD,+BASjDT,aAAcK,SAAUI,mBAC/BR,KAAKC,YAAY,cAAeF,aAAc,CAACO,SAAUF,SAAUK,SAAUD,+BAStET,aAAcG,YAAQQ,8DAAS,QACtCV,KAAKC,YAAY,cAAeF,aAAc,CAACI,OAAQD,OAAQS,OAAQD,4BAQ9DX,aAAcG,cACvBF,KAAKC,YAAY,oBAAqBF,aAAc,CAACI,OAAQD,OAAQU,MAAO,yBAQjEb,aAAcG,cACzBF,KAAKC,YAAY,oBAAqBF,aAAc,CAACI,OAAQD,OAAQU,MAAO,uBASnEb,aAAcG,YAAQQ,8DAAS,QACxCV,KAAKC,YAAY,gBAAiBF,aAAc,CAACI,OAAQD,OAAQS,OAAQD,0BAQlEX,aAAcK,gBACrBJ,KAAKC,YAAY,oBAAqBF,aAAc,CAACO,SAAUF,SAAUQ,MAAO,uBAQvEb,aAAcK,gBACvBJ,KAAKC,YAAY,oBAAqBF,aAAc,CAACO,SAAUF,SAAUQ,MAAO,sBAOxEb,oBACRC,KAAKC,YAAY,2BAA4BF,aAAc,CAACa,MAAO,wBAOzDb,oBACVC,KAAKC,YAAY,2BAA4BF,aAAc,CAACa,MAAO,gCASjDb,aAAcG,OAAQW,eACxCb,KAAKC,YAAY,yBAA0BF,aAAc,CAACI,OAAQD,OAAQW,QAASA,8BAQzEd,aAAce,iBACxBd,KAAKC,YAAY,4BAA6BF,aAAc,CAACgB,UAAWD,2BAQnEf,aAAcG,cACnBF,KAAKC,YAAY,iBAAkBF,aAAc,CAACI,OAAQD,2BASlDc,OAAQjB,aAAckB,YAC9BL,MAAQb,aAAaa,MACrBM,aAAeC,cAAKC,KAAK,CAAC,CAC5BC,WAAY,cAAgBL,OAC5BM,KAAM,CACFC,KAAMX,MAAMY,OAAOC,GACnBC,QAASd,MAAMe,MAAMF,GACrBR,KAAMA,MAEVW,KAAM5B,KAAK6B,eACX,QAECC,eAAe/B,aAAcmB,QAOtCW,YAAYE,0BACKC,OAAM,mBAAU,SAAUD,GAAGlB,SAAS,mBAAU,4BAOhDd,oBACPa,MAAQb,aAAaa,cACPqB,IAAhBrB,MAAMe,MACN5B,aAAamC,aAAY,GACzBnC,aAAaoC,gBAAgBC,KAAK,CAC9BC,0BACAC,UAAW,GACXC,mBAEJxC,aAAamC,aAAY,OACtB,OACGhB,aAAeC,cAAKC,KAAK,CAAC,CAC5BC,WAAY,uCACZC,KAAM,CACFC,KAAMX,MAAMY,OAAOC,GACnBC,QAASd,MAAMe,MAAMF,GACrBe,UAAW5B,MAAMY,OAAOgB,WAE5BZ,KAAM,UACGa,wBAET,QAECX,eAAe/B,aAAcmB,aAC7BwB,oBAObA,wBACSC,YAAc,EACnBC,SAASC,cAAc,4BAA4BC,UAAUC,IAAI,UAMrEN,yBACSE,cACD3C,KAAK2C,YAAc,GACnBC,SAASC,cAAc,4BAA4BC,UAAUE,OAAO,qCASjDjD,aAAcG,cAC/BU,MAAQb,aAAaa,UACvB4B,UAAY,EAChB5B,MAAMqC,YAAYC,SAASC,IACnBA,EAAEC,aAAelD,QACbiD,EAAEX,UAAYA,YACdA,UAAYW,EAAEX,oBAKpBtB,aAAeC,cAAKC,KAAK,CAAC,CAC5BC,WAAY,mCACZC,KAAM,CACFC,KAAMX,MAAMY,OAAOC,GACnBC,QAASd,MAAMe,MAAMF,GACrBtB,OAAQD,OACRsC,UAAWA,WAEfZ,KAAM,UACGa,wBAET,QAECX,eAAe/B,aAAcmB,gCAQdnB,aAAcG,cAC5BU,MAAQb,aAAaa,UACvB4B,UAAY,EAChB5B,MAAMyC,QAAQH,SAASC,IACfA,EAAEC,aAAelD,QACbiD,EAAEX,UAAYA,YACdA,UAAYW,EAAEX,oBAKpBtB,aAAeC,cAAKC,KAAK,CAAC,CAC5BC,WAAY,gCACZC,KAAM,CACFC,KAAMX,MAAMY,OAAOC,GACnBC,QAASd,MAAMe,MAAMF,GACrBtB,OAAQD,OACRsC,UAAWA,WAEfZ,KAAM,UACGa,wBAET,QAECX,eAAe/B,aAAcmB,6BASjBnB,aAAcmB,YAC3BoC,QAAUC,KAAKC,MAAMtC,OAAOuC,QAChC1D,aAAa+B,eAAewB,cACvBZ"} \ No newline at end of file +{"version":3,"file":"mutations.min.js","sources":["../src/mutations.js"],"sourcesContent":["import Ajax from 'core/ajax';\nimport Notification from 'core/notification';\nimport {get_string as getString} from 'core/str';\n\n/**\n * Mutations library for mod_kanban.\n * The functions are just used to forward data to the webservice.\n */\nexport default class {\n // Attribute for counting update fails.\n updateFails = 0;\n\n async saveAsTemplate(stateManager) {\n await this._sendChange('save_as_template', stateManager);\n }\n\n /**\n * Delete a card.\n * @param {*} stateManager StateManager instance\n * @param {number} cardId Id of the card to be deleted\n */\n async deleteCard(stateManager, cardId) {\n await this._sendChange('delete_card', stateManager, {cardid: cardId});\n }\n\n /**\n * Delete the board.\n * @param {*} stateManager StateManager instance\n */\n async deleteBoard(stateManager) {\n await this._sendChange('delete_board', stateManager);\n }\n\n /**\n * Add a card after an existing one.\n * @param {*} stateManager StateManager instance\n * @param {number} columnId Id of the column\n * @param {number} afterCard Id of the card before (0 means to insert at the top of the column)\n */\n async addCard(stateManager, columnId, afterCard) {\n await this._sendChange('add_card', stateManager, {columnid: columnId, aftercard: afterCard});\n }\n\n /**\n * Move a card to another column.\n * @param {*} stateManager StateManager instance\n * @param {number} cardId Id of the card to be deleted\n * @param {number} columnId Id of the new column\n * @param {number} afterCard Id of the card before (0 means to move at the top of the column)\n */\n async moveCard(stateManager, cardId, columnId, afterCard) {\n await this._sendChange('move_card', stateManager, {cardid: cardId, columnid: columnId, aftercard: afterCard});\n }\n\n /**\n * Deletes a column and all cards within.\n * @param {*} stateManager StateManager instance\n * @param {number} columnId Id of the column to delete\n */\n async deleteColumn(stateManager, columnId) {\n await this._sendChange('delete_column', stateManager, {columnid: columnId});\n }\n\n /**\n * Adds a new column.\n * @param {*} stateManager StateManager instance\n * @param {number} afterColumn Id of the column before (0 means to insert at the left of the board)\n */\n async addColumn(stateManager, afterColumn) {\n await this._sendChange('add_column', stateManager, {aftercol: afterColumn});\n }\n\n /**\n * Moves a column to a new place.\n * @param {*} stateManager StateManager instance\n * @param {number} columnId Id of the column to move\n * @param {number} afterColumn Id of the column before (0 means to insert at the left of the board)\n */\n async moveColumn(stateManager, columnId, afterColumn) {\n await this._sendChange('move_column', stateManager, {columnid: columnId, aftercol: afterColumn});\n }\n\n /**\n * Assign a user to a card.\n * @param {*} stateManager StateManager instance.\n * @param {number} cardId Id of the card\n * @param {number} userId Id of the user to assign (0 means to assign the current user)\n */\n async assignUser(stateManager, cardId, userId = 0) {\n await this._sendChange('assign_user', stateManager, {cardid: cardId, userid: userId});\n }\n\n /**\n * Mark a card as completed.\n * @param {*} stateManager StateManager instance.\n * @param {number} cardId Id of the card\n */\n async completeCard(stateManager, cardId) {\n await this._sendChange('set_card_complete', stateManager, {cardid: cardId, state: 1});\n }\n\n /**\n * Mark a card as not completed.\n * @param {*} stateManager StateManager instance.\n * @param {number} cardId Id of the card\n */\n async uncompleteCard(stateManager, cardId) {\n await this._sendChange('set_card_complete', stateManager, {cardid: cardId, state: 0});\n }\n\n /**\n * Remove assignment for a user to a card.\n * @param {*} stateManager StateManager instance.\n * @param {number} cardId Id of the card\n * @param {number} userId Id of the user to unassign, defaults to 0 (current user)\n */\n async unassignUser(stateManager, cardId, userId = 0) {\n await this._sendChange('unassign_user', stateManager, {cardid: cardId, userid: userId});\n }\n\n /**\n * Locks a column.\n * @param {*} stateManager StateManager instance\n * @param {number} columnId Id of the column to lock\n */\n async lockColumn(stateManager, columnId) {\n await this._sendChange('set_column_locked', stateManager, {columnid: columnId, state: 1});\n }\n\n /**\n * Unlocks a column.\n * @param {*} stateManager StateManager instance\n * @param {number} columnId Id of the column to unlock\n */\n async unlockColumn(stateManager, columnId) {\n await this._sendChange('set_column_locked', stateManager, {columnid: columnId, state: 0});\n }\n\n /**\n * Locks all columns of the board.\n * @param {*} stateManager StateManager instance\n */\n async lockColumns(stateManager) {\n await this._sendChange('set_board_columns_locked', stateManager, {state: 1});\n }\n\n /**\n * Unlocks all columns of the board.\n * @param {*} stateManager StateManager instance\n */\n async unlockColumns(stateManager) {\n await this._sendChange('set_board_columns_locked', stateManager, {state: 0});\n }\n\n /**\n * Adds a message to discussion.\n * @param {*} stateManager\n * @param {*} cardId\n * @param {*} message\n */\n async sendDiscussionMessage(stateManager, cardId, message) {\n await this._sendChange('add_discussion_message', stateManager, {cardid: cardId, message: message});\n }\n\n /**\n * Delete a message from a discussion.\n * @param {*} stateManager StateManager instance\n * @param {number} messageId Id of the message to be deleted\n */\n async deleteMessage(stateManager, messageId) {\n await this._sendChange('delete_discussion_message', stateManager, {messageid: messageId});\n }\n\n /**\n * Push a copy of a card to all boards.\n * @param {*} stateManager StateManager instance\n * @param {number} cardId Id of the card to be pushed\n */\n async pushCard(stateManager, cardId) {\n await this._sendChange('push_card_copy', stateManager, {cardid: cardId});\n }\n\n /**\n * Send change request to webservice\n * @param {string} method Name of the method\n * @param {*} stateManager StateManager instance\n * @param {object} data Data to send\n */\n async _sendChange(method, stateManager, data) {\n const state = stateManager.state;\n const request = {\n methodname: 'mod_kanban_' + method,\n args: {\n cmid: state.common.id,\n boardid: state.board.id,\n data: data\n },\n fail: this.displayError,\n };\n\n const result = await Ajax.call([request])[0];\n\n this.processUpdates(stateManager, result);\n }\n\n /**\n * Update state.\n * @param {*} stateManager\n */\n async getUpdates(stateManager) {\n const state = stateManager.state;\n if (state.board === undefined) {\n stateManager.setReadOnly(false);\n stateManager.eventsToPublish.push({\n eventName: `board:deleted`,\n eventData: {},\n action: `deleted`,\n });\n stateManager.setReadOnly(true);\n } else {\n const result = await Ajax.call([{\n methodname: 'mod_kanban_get_kanban_content_update',\n args: {\n cmid: state.common.id,\n boardid: state.board.id,\n timestamp: state.common.timestamp,\n },\n fail: () => {\n this.processUpdateFail(stateManager);\n },\n }])[0];\n\n this.processUpdates(stateManager, result);\n }\n }\n\n /**\n * Count update fails.\n * @param {*} stateManager\n */\n processUpdateFail(stateManager) {\n const state = stateManager.state;\n stateManager.setReadOnly(false);\n state.common.updatefails++;\n stateManager.setReadOnly(true);\n }\n\n /**\n * Show a modal to display an error message\n * @param {*} data\n */\n async displayError(data) {\n if (data.message) {\n Notification.alert(getString('error'), data.message, getString('cancel'));\n }\n }\n\n /**\n * Update discussions for a card.\n * @param {*} stateManager\n * @param {number} cardId\n */\n async getDiscussionUpdates(stateManager, cardId) {\n const state = stateManager.state;\n let timestamp = 0;\n state.discussions.forEach((c) => {\n if (c.kanban_card == cardId) {\n if (c.timestamp > timestamp) {\n timestamp = c.timestamp;\n }\n }\n });\n\n const result = await Ajax.call([{\n methodname: 'mod_kanban_get_discussion_update',\n args: {\n cmid: state.common.id,\n boardid: state.board.id,\n cardid: cardId,\n timestamp: timestamp,\n },\n fail: () => {\n this.processUpdateFail();\n },\n }])[0];\n\n this.processUpdates(stateManager, result);\n }\n\n /**\n * Update history for a card.\n * @param {*} stateManager\n * @param {number} cardId\n */\n async getHistoryUpdates(stateManager, cardId) {\n const state = stateManager.state;\n let timestamp = 0;\n state.history.forEach((c) => {\n if (c.kanban_card == cardId) {\n if (c.timestamp > timestamp) {\n timestamp = c.timestamp;\n }\n }\n });\n\n const result = await Ajax.call([{\n methodname: 'mod_kanban_get_history_update',\n args: {\n cmid: state.common.id,\n boardid: state.board.id,\n cardid: cardId,\n timestamp: timestamp,\n },\n fail: () => {\n this.processUpdateFail();\n },\n }])[0];\n\n this.processUpdates(stateManager, result);\n }\n\n /**\n * Process updates.\n *\n * @param {*} stateManager\n * @param {*} result\n */\n async processUpdates(stateManager, result) {\n let updates = JSON.parse(result.update);\n stateManager.processUpdates(updates);\n }\n}\n"],"names":["stateManager","this","_sendChange","cardId","cardid","columnId","afterCard","columnid","aftercard","afterColumn","aftercol","userId","userid","state","message","messageId","messageid","method","data","request","methodname","args","cmid","common","id","boardid","board","fail","displayError","result","Ajax","call","processUpdates","undefined","setReadOnly","eventsToPublish","push","eventName","eventData","action","timestamp","processUpdateFail","updatefails","alert","discussions","forEach","c","kanban_card","history","updates","JSON","parse","update"],"mappings":"gcAUkB,6JAEOA,oBACXC,KAAKC,YAAY,mBAAoBF,+BAQ9BA,aAAcG,cACrBF,KAAKC,YAAY,cAAeF,aAAc,CAACI,OAAQD,2BAO/CH,oBACRC,KAAKC,YAAY,eAAgBF,4BAS7BA,aAAcK,SAAUC,iBAC5BL,KAAKC,YAAY,WAAYF,aAAc,CAACO,SAAUF,SAAUG,UAAWF,2BAUtEN,aAAcG,OAAQE,SAAUC,iBACrCL,KAAKC,YAAY,YAAaF,aAAc,CAACI,OAAQD,OAAQI,SAAUF,SAAUG,UAAWF,+BAQnFN,aAAcK,gBACvBJ,KAAKC,YAAY,gBAAiBF,aAAc,CAACO,SAAUF,2BAQrDL,aAAcS,mBACpBR,KAAKC,YAAY,aAAcF,aAAc,CAACU,SAAUD,+BASjDT,aAAcK,SAAUI,mBAC/BR,KAAKC,YAAY,cAAeF,aAAc,CAACO,SAAUF,SAAUK,SAAUD,+BAStET,aAAcG,YAAQQ,8DAAS,QACtCV,KAAKC,YAAY,cAAeF,aAAc,CAACI,OAAQD,OAAQS,OAAQD,4BAQ9DX,aAAcG,cACvBF,KAAKC,YAAY,oBAAqBF,aAAc,CAACI,OAAQD,OAAQU,MAAO,yBAQjEb,aAAcG,cACzBF,KAAKC,YAAY,oBAAqBF,aAAc,CAACI,OAAQD,OAAQU,MAAO,uBASnEb,aAAcG,YAAQQ,8DAAS,QACxCV,KAAKC,YAAY,gBAAiBF,aAAc,CAACI,OAAQD,OAAQS,OAAQD,0BAQlEX,aAAcK,gBACrBJ,KAAKC,YAAY,oBAAqBF,aAAc,CAACO,SAAUF,SAAUQ,MAAO,uBAQvEb,aAAcK,gBACvBJ,KAAKC,YAAY,oBAAqBF,aAAc,CAACO,SAAUF,SAAUQ,MAAO,sBAOxEb,oBACRC,KAAKC,YAAY,2BAA4BF,aAAc,CAACa,MAAO,wBAOzDb,oBACVC,KAAKC,YAAY,2BAA4BF,aAAc,CAACa,MAAO,gCASjDb,aAAcG,OAAQW,eACxCb,KAAKC,YAAY,yBAA0BF,aAAc,CAACI,OAAQD,OAAQW,QAASA,8BAQzEd,aAAce,iBACxBd,KAAKC,YAAY,4BAA6BF,aAAc,CAACgB,UAAWD,2BAQnEf,aAAcG,cACnBF,KAAKC,YAAY,iBAAkBF,aAAc,CAACI,OAAQD,2BASlDc,OAAQjB,aAAckB,YAC9BL,MAAQb,aAAaa,MACrBM,QAAU,CACZC,WAAY,cAAgBH,OAC5BI,KAAM,CACFC,KAAMT,MAAMU,OAAOC,GACnBC,QAASZ,MAAMa,MAAMF,GACrBN,KAAMA,MAEVS,KAAM1B,KAAK2B,cAGTC,aAAeC,cAAKC,KAAK,CAACZ,UAAU,QAErCa,eAAehC,aAAc6B,yBAOrB7B,oBACPa,MAAQb,aAAaa,cACPoB,IAAhBpB,MAAMa,MACN1B,aAAakC,aAAY,GACzBlC,aAAamC,gBAAgBC,KAAK,CAC9BC,0BACAC,UAAW,GACXC,mBAEJvC,aAAakC,aAAY,OACtB,OACGL,aAAeC,cAAKC,KAAK,CAAC,CAC5BX,WAAY,uCACZC,KAAM,CACFC,KAAMT,MAAMU,OAAOC,GACnBC,QAASZ,MAAMa,MAAMF,GACrBgB,UAAW3B,MAAMU,OAAOiB,WAE5Bb,KAAM,UACGc,kBAAkBzC,kBAE3B,QAECgC,eAAehC,aAAc6B,SAQ1CY,kBAAkBzC,oBACRa,MAAQb,aAAaa,MAC3Bb,aAAakC,aAAY,GACzBrB,MAAMU,OAAOmB,cACb1C,aAAakC,aAAY,sBAOVhB,MACXA,KAAKJ,+BACQ6B,OAAM,mBAAU,SAAUzB,KAAKJ,SAAS,mBAAU,sCAS5Cd,aAAcG,cAC/BU,MAAQb,aAAaa,UACvB2B,UAAY,EAChB3B,MAAM+B,YAAYC,SAASC,IACnBA,EAAEC,aAAe5C,QACb2C,EAAEN,UAAYA,YACdA,UAAYM,EAAEN,oBAKpBX,aAAeC,cAAKC,KAAK,CAAC,CAC5BX,WAAY,mCACZC,KAAM,CACFC,KAAMT,MAAMU,OAAOC,GACnBC,QAASZ,MAAMa,MAAMF,GACrBpB,OAAQD,OACRqC,UAAWA,WAEfb,KAAM,UACGc,wBAET,QAECT,eAAehC,aAAc6B,gCAQd7B,aAAcG,cAC5BU,MAAQb,aAAaa,UACvB2B,UAAY,EAChB3B,MAAMmC,QAAQH,SAASC,IACfA,EAAEC,aAAe5C,QACb2C,EAAEN,UAAYA,YACdA,UAAYM,EAAEN,oBAKpBX,aAAeC,cAAKC,KAAK,CAAC,CAC5BX,WAAY,gCACZC,KAAM,CACFC,KAAMT,MAAMU,OAAOC,GACnBC,QAASZ,MAAMa,MAAMF,GACrBpB,OAAQD,OACRqC,UAAWA,WAEfb,KAAM,UACGc,wBAET,QAECT,eAAehC,aAAc6B,6BASjB7B,aAAc6B,YAC3BoB,QAAUC,KAAKC,MAAMtB,OAAOuB,QAChCpD,aAAagC,eAAeiB"} \ No newline at end of file diff --git a/amd/src/board.js b/amd/src/board.js index 016459b4..68a68734 100644 --- a/amd/src/board.js +++ b/amd/src/board.js @@ -148,8 +148,9 @@ export default class extends KanbanComponent { * Called when common data was updated * @param {*} param0 */ - _commonUpdated({element}) { + async _commonUpdated({element}) { this.toggleClass(element.template != 0, 'mod_kanban_hastemplate'); + this.toggleClass(element.updatefails > 0, 'mod_kanban_updatefails'); } /** diff --git a/amd/src/mutations.js b/amd/src/mutations.js index 40efcff7..998082e0 100644 --- a/amd/src/mutations.js +++ b/amd/src/mutations.js @@ -2,7 +2,6 @@ import Ajax from 'core/ajax'; import Notification from 'core/notification'; import {get_string as getString} from 'core/str'; - /** * Mutations library for mod_kanban. * The functions are just used to forward data to the webservice. @@ -189,25 +188,19 @@ export default class { */ async _sendChange(method, stateManager, data) { const state = stateManager.state; - const result = await Ajax.call([{ + const request = { methodname: 'mod_kanban_' + method, args: { cmid: state.common.id, boardid: state.board.id, data: data }, - fail: this.processFail, - }])[0]; + fail: this.displayError, + }; - this.processUpdates(stateManager, result); - } + const result = await Ajax.call([request])[0]; - /** - * Notify user about an error. - * @param {*} ex - */ - processFail(ex) { - Notification.alert(getString('error'), ex.message, getString('cancel')); + this.processUpdates(stateManager, result); } /** @@ -233,30 +226,33 @@ export default class { timestamp: state.common.timestamp, }, fail: () => { - this.processUpdateFail(); + this.processUpdateFail(stateManager); }, }])[0]; this.processUpdates(stateManager, result); - this.resetUpdateFails(); } } /** - * Reset update fails. + * Count update fails. + * @param {*} stateManager */ - resetUpdateFails() { - this.updateFails = 0; - document.querySelector('.mod_kanban_update_error').classList.add('hidden'); + processUpdateFail(stateManager) { + const state = stateManager.state; + stateManager.setReadOnly(false); + state.common.updatefails++; + stateManager.setReadOnly(true); } /** - * Notify user about an error. + * Show a modal to display an error message + * @param {*} data */ - processUpdateFail() { - this.updateFails++; - if (this.updateFails > 2) { - document.querySelector('.mod_kanban_update_error').classList.remove('hidden'); + async displayError(data) { + if (data.message) { + // Can switch to direct call of getString when dropping support for Moodle 4.1. + Notification.alert(getString('error'), data.message, getString('cancel')); } } @@ -333,6 +329,5 @@ export default class { async processUpdates(stateManager, result) { let updates = JSON.parse(result.update); stateManager.processUpdates(updates); - this.resetUpdateFails(); } } diff --git a/classes/external/get_kanban_content.php b/classes/external/get_kanban_content.php index 5c6b0ea2..bf8f9ef7 100644 --- a/classes/external/get_kanban_content.php +++ b/classes/external/get_kanban_content.php @@ -115,6 +115,7 @@ public static function get_kanban_content_init_returns(): external_single_struct 'groupselector' => new external_value(PARAM_RAW, 'group selector'), 'userboards' => new external_value(PARAM_INT, 'userboards'), 'history' => new external_value(PARAM_INT, 'history'), + 'updatefails' => new external_value(PARAM_INT, 'updatefails', VALUE_OPTIONAL, 0), ]), 'board' => new external_single_structure([ 'id' => new external_value(PARAM_INT, 'board id'), @@ -461,6 +462,7 @@ public static function execute(int $cmid, int $boardid, int $timestamp = 0, bool $common->groupmode = $groupmode; $common->groupselector = $groupselector; $common->history = $kanban->history; + $common->updatefails = 0; if (!$asupdate) { $common->template = $DB->get_field_sql( diff --git a/styles.css b/styles.css index feece6dc..d779c89b 100644 --- a/styles.css +++ b/styles.css @@ -429,3 +429,11 @@ a.mod_kanban_attachment_item { border-top-right-radius: 10px; border-bottom-right-radius: 10px; } + +.mod_kanban_updatefails .row.mod_kanban_update_error { + display: flex; +} + +.row.mod_kanban_update_error { + display: none; +} diff --git a/templates/board.mustache b/templates/board.mustache index 0a65682e..223851cb 100644 --- a/templates/board.mustache +++ b/templates/board.mustache @@ -44,7 +44,7 @@ {{>mod_kanban/actionmenuboard}} -