From 5791dadbfbf5d374ab13660c9d9fc5eeb5b4dc9a Mon Sep 17 00:00:00 2001 From: Stefan Hanauska Date: Fri, 24 May 2024 10:17:20 +0200 Subject: [PATCH] MBS-8967: Add connection loss to error reporting --- amd/build/mutations.min.js | 2 +- amd/build/mutations.min.js.map | 2 +- amd/src/mutations.js | 33 +++++++++++++++++++++++++++++++++ lang/en/kanban.php | 2 ++ templates/board.mustache | 8 ++++++++ 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/amd/build/mutations.min.js b/amd/build/mutations.min.js index bc65f375..3135057a 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{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}}])[0];this.processUpdates(stateManager,result)}}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}}])[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}}])[0];this.processUpdates(stateManager,result)}async processUpdates(stateManager,result){let updates=JSON.parse(result.update);stateManager.processUpdates(updates)}},_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,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})); //# 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 29a4c569..72e04d1d 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 * Mutations library for mod_kanban.\n * The functions are just used to forward data to the webservice.\n */\nexport default class {\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 }])[0];\n\n this.processUpdates(stateManager, result);\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 }])[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 }])[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","result","Ajax","call","methodname","args","cmid","common","id","boardid","board","fail","processFail","processUpdates","ex","alert","undefined","setReadOnly","eventsToPublish","push","eventName","eventData","action","timestamp","discussions","forEach","c","kanban_card","history","updates","JSON","parse","update"],"mappings":"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"} \ 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/**\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 diff --git a/amd/src/mutations.js b/amd/src/mutations.js index d7e96092..40efcff7 100644 --- a/amd/src/mutations.js +++ b/amd/src/mutations.js @@ -2,11 +2,15 @@ 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. */ export default class { + // Attribute for counting update fails. + updateFails = 0; + async saveAsTemplate(stateManager) { await this._sendChange('save_as_template', stateManager); } @@ -228,9 +232,31 @@ export default class { boardid: state.board.id, timestamp: state.common.timestamp, }, + fail: () => { + this.processUpdateFail(); + }, }])[0]; this.processUpdates(stateManager, result); + this.resetUpdateFails(); + } + } + + /** + * Reset update fails. + */ + resetUpdateFails() { + this.updateFails = 0; + document.querySelector('.mod_kanban_update_error').classList.add('hidden'); + } + + /** + * Notify user about an error. + */ + processUpdateFail() { + this.updateFails++; + if (this.updateFails > 2) { + document.querySelector('.mod_kanban_update_error').classList.remove('hidden'); } } @@ -258,6 +284,9 @@ export default class { cardid: cardId, timestamp: timestamp, }, + fail: () => { + this.processUpdateFail(); + }, }])[0]; this.processUpdates(stateManager, result); @@ -287,6 +316,9 @@ export default class { cardid: cardId, timestamp: timestamp, }, + fail: () => { + this.processUpdateFail(); + }, }])[0]; this.processUpdates(stateManager, result); @@ -301,5 +333,6 @@ export default class { async processUpdates(stateManager, result) { let updates = JSON.parse(result.update); stateManager.processUpdates(updates); + this.resetUpdateFails(); } } diff --git a/lang/en/kanban.php b/lang/en/kanban.php index 24662a89..8e2dc2d1 100644 --- a/lang/en/kanban.php +++ b/lang/en/kanban.php @@ -45,6 +45,8 @@ $string['completioncomplete'] = 'Complete this number of cards'; $string['completiondetail:create'] = 'Create cards: {$a}'; $string['completiondetail:complete'] = 'Complete cards: {$a}'; +$string['connectionlost'] = 'Connection lost'; +$string['connectionlostmessage'] = 'Connection to the server was lost. Trying to reconnect...'; $string['courseboard'] = 'Shared board'; $string['closecard'] = 'Close card'; $string['createtemplate'] = 'Create template'; diff --git a/templates/board.mustache b/templates/board.mustache index 4d8f88f5..0a65682e 100644 --- a/templates/board.mustache +++ b/templates/board.mustache @@ -44,6 +44,14 @@ {{>mod_kanban/actionmenuboard}} +