From e08473f851077b6c3aa61c45620840f9d784abdf Mon Sep 17 00:00:00 2001 From: Stefan Hanauska Date: Thu, 25 Jan 2024 08:25:33 +0100 Subject: [PATCH] MBS-8689: Fix inplace editing when user is assignes --- amd/build/card.min.js | 2 +- amd/build/card.min.js.map | 2 +- amd/src/card.js | 25 ++++++++++++------------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/amd/build/card.min.js b/amd/build/card.min.js index 129240d2..ccf53fa9 100644 --- a/amd/build/card.min.js +++ b/amd/build/card.min.js @@ -1,3 +1,3 @@ -define("mod_kanban/card",["exports","core/reactive","mod_kanban/selectors","mod_kanban/exporter","core/notification","core_form/modalform","core/str","core/templates","mod_kanban/kanbancomponent","core/log"],(function(_exports,_reactive,_selectors,_exporter,_notification,_modalform,Str,_templates,_kanbancomponent,_log){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}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_selectors=_interopRequireDefault(_selectors),_exporter=_interopRequireDefault(_exporter),_modalform=_interopRequireDefault(_modalform),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),_templates=_interopRequireDefault(_templates),_kanbancomponent=_interopRequireDefault(_kanbancomponent),_log=_interopRequireDefault(_log);class _default extends _kanbancomponent.default{constructor(){var obj,key,value;super(...arguments),value={year:31536e6,month:2628e6,day:864e5,hour:36e5,minute:6e4,second:1e3},(key="_units")in(obj=this)?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value}static init(target){return new this({element:document.getElementById(target)})}create(){this.id=this.element.dataset.id}getWatchers(){return[{watch:"cards[".concat(this.id,"]:updated"),handler:this._cardUpdated},{watch:"cards[".concat(this.id,"]:deleted"),handler:this._cardDeleted},{watch:"discussions:created",handler:this._discussionUpdated},{watch:"discussions:updated",handler:this._discussionUpdated},{watch:"discussions:deleted",handler:this._discussionUpdated},{watch:"history:created",handler:this._historyUpdated},{watch:"history:updated",handler:this._historyUpdated},{watch:"history:deleted",handler:this._historyUpdated}]}stateReady(state){let lang="en";void 0!==state.common.lang&&(lang=state.common.lang);try{this.rtf=new Intl.RelativeTimeFormat(lang,{numeric:"auto"})}catch(e){this.rtf=new Intl.RelativeTimeFormat("en",{numeric:"auto"})}this.addEventListener(this.getElement(_selectors.default.DELETECARD,this.id),"click",this._removeConfirm),this.addEventListener(this.getElement(_selectors.default.ADDCARD,this.id),"click",this._addCard),this.addEventListener(this.getElement(_selectors.default.COMPLETE,this.id),"click",this._completeCard),this.addEventListener(this.getElement(_selectors.default.UNCOMPLETE,this.id),"click",this._uncompleteCard),this.addEventListener(this.getElement(_selectors.default.ASSIGNSELF,this.id),"click",this._assignSelf),this.addEventListener(this.getElement(_selectors.default.UNASSIGNSELF,this.id),"click",this._unassignSelf),this.addEventListener(this.getElement(_selectors.default.EDITDETAILS,this.id),"click",this._editDetails),this.addEventListener(this.getElement(_selectors.default.DISCUSSIONMODALTRIGGER),"click",this._updateDiscussion),this.addEventListener(this.getElement(_selectors.default.DISCUSSIONSHOW,this.id),"click",this._updateDiscussion),this.addEventListener(this.getElement(_selectors.default.DISCUSSIONSEND),"click",this._sendMessage),this.addEventListener(this.getElement(_selectors.default.HISTORYMODALTRIGGER),"click",this._updateHistory),this.addEventListener(this.getElement(_selectors.default.MOVEMODALTRIGGER),"click",this._showMoveModal),this.addEventListener(this.getElement(_selectors.default.PUSHCARD),"click",this._pushCardConfirm),this.draggable=!1,this.dragdrop=new _reactive.DragDrop(this),this.checkDragging(state),this.boardid=state.board.id,this.cmid=state.common.id,this.userid=state.board.userid,this.groupid=state.board.groupid,this._dueDateFormat()}_showMoveModal(){let data=_exporter.default.exportStateForTemplate(this.reactive.state);data.cardid=this.id,data.kanbancolumn=this.reactive.state.cards.get(this.id).kanban_column,Str.get_strings([{key:"movecard",component:"mod_kanban"},{key:"move",component:"core"}]).then((strings=>(0,_notification.saveCancel)(strings[0],_templates.default.render("mod_kanban/movemodal",data),strings[1],(()=>{let column=document.querySelector(_selectors.default.MOVECARDCOLUMN+'[data-id="'.concat(this.id,'"]')).value,aftercard=document.querySelector(_selectors.default.MOVECARDAFTERCARD+'[data-id="'.concat(this.id,'"]')).value;this.reactive.dispatch("moveCard",this.id,column,aftercard)})))).catch((error=>_log.default.debug(error)))}_pushCardConfirm(event){Str.get_strings([{key:"pushcard",component:"mod_kanban"},{key:"pushcardconfirm",component:"mod_kanban"},{key:"copy",component:"core"}]).then((strings=>(0,_notification.saveCancel)(strings[0],strings[1],strings[2],(()=>{this._pushCard(event)})))).catch((error=>_log.default.debug(error)))}_removeConfirm(event){Str.get_strings([{key:"deletecard",component:"mod_kanban"},{key:"deletecardconfirm",component:"mod_kanban"},{key:"delete",component:"core"}]).then((strings=>(0,_notification.saveCancel)(strings[0],strings[1],strings[2],(()=>{this._removeCard(event)})))).catch((error=>_log.default.debug(error)))}_removeMessageConfirm(event){Str.get_strings([{key:"deletemessage",component:"mod_kanban"},{key:"deletemessageconfirm",component:"mod_kanban"},{key:"delete",component:"core"}]).then((strings=>(0,_notification.saveCancel)(strings[0],strings[1],strings[2],(()=>{this._removeMessage(event)})))).catch((error=>_log.default.debug(error)))}_sendMessage(){let el=this.getElement(_selectors.default.DISCUSSIONINPUT),message=el.value.trim();""!=message&&(this.reactive.dispatch("sendDiscussionMessage",this.id,message),el.value="")}_updateDiscussion(){this.getElement(_selectors.default.DISCUSSIONMODAL).classList.add("mod_kanban_loading"),this.reactive.dispatch("getDiscussionUpdates",this.id)}async _discussionUpdated(){let data={discussions:_exporter.default.exportDiscussion(this.reactive.state,this.id)};_templates.default.renderForPromise("mod_kanban/discussionmessages",data).then((_ref=>{let{html:html}=_ref;this.getElement(_selectors.default.DISCUSSION,this.id).innerHTML=html,this.getElement(_selectors.default.DISCUSSIONMODAL,this.id).classList.remove("mod_kanban_loading");let el=this.getElement(_selectors.default.DISCUSSIONMESSAGES);return el.scrollTop=el.scrollHeight,data.discussions.forEach((d=>{d.candelete&&this.addEventListener(this.getElement(_selectors.default.DELETEMESSAGE,d.id),"click",this._removeMessageConfirm)})),!0})).catch((error=>(0,_notification.exception)(error)))}_updateHistory(){this.getElement(_selectors.default.HISTORYMODAL).classList.add("mod_kanban_loading"),this.reactive.dispatch("getHistoryUpdates",this.id)}async _historyUpdated(){let data={historyitems:_exporter.default.exportHistory(this.reactive.state,this.id)};_templates.default.renderForPromise("mod_kanban/historyitems",data).then((_ref2=>{let{html:html}=_ref2;this.getElement(_selectors.default.HISTORY,this.id).innerHTML=html,this.getElement(_selectors.default.HISTORYMODAL).classList.remove("mod_kanban_loading");let el=this.getElement(_selectors.default.HISTORYITEMS);return el.scrollTop=el.scrollHeight,!0})).catch((error=>(0,_notification.exception)(error)))}_assignSelf(event){let target=event.target.closest(_selectors.default.ASSIGNSELF),data=Object.assign({},target.dataset);this.reactive.dispatch("assignUser",data.id)}_addCard(event){document.activeElement.blur();let target=event.target.closest(_selectors.default.ADDCARD),data=Object.assign({},target.dataset);this.reactive.dispatch("addCard",data.columnid,data.id)}async _cardUpdated(_ref3){let{element:element}=_ref3;const card=this.getElement();if(card.dataset.columnid!=element.kanban_column){document.querySelector(_selectors.default.COLUMNINNER+'[data-id="'+element.kanban_column+'"]').appendChild(card),this.getElement(_selectors.default.ADDCARD,this.id).setAttribute("data-columnid",element.kanban_column),card.setAttribute("data-columnid",element.kanban_column)}const assignees=this.getElement(_selectors.default.ASSIGNEES,this.id),assignedUsers=this.getElements(_selectors.default.ASSIGNEDUSER,this.id),userids=[...assignedUsers].map((v=>v.dataset.userid));if(void 0!==element.assignees){const additional=element.assignees.filter((x=>!userids.includes(x)));null!==assignedUsers&&assignedUsers.forEach((assignedUser=>{element.assignees.includes(assignedUser.dataset.userid)||assignedUser.parentNode.removeChild(assignedUser)})),this.toggleClass(0==element.assignees.length,"mod_kanban_unassigned"),element.assignees.length>0&&additional.forEach((async user=>{let userdata=this.reactive.state.users.get(user),data=Object.assign({cardid:element.id},userdata);data=Object.assign(data,_exporter.default.exportCapabilities(this.reactive.state)),_templates.default.renderForPromise("mod_kanban/user",data).then((_ref4=>{let{html:html,js:js}=_ref4;return _templates.default.appendNodeContents(assignees,html,js),!0})).catch((error=>(0,_notification.exception)(error)))}))}if(this.toggleClass(element.selfassigned,"mod_kanban_selfassigned"),void 0!==element.completed&&(this.toggleClass(1==element.completed,"mod_kanban_closed"),1==element.completed?this.getElement(_selectors.default.INPLACEEDITABLE).removeAttribute("data-inplaceeditable"):this.getElement(_selectors.default.INPLACEEDITABLE).setAttribute("data-inplaceeditable","1")),void 0!==element.title){let doc=(new DOMParser).parseFromString(element.title,"text/html");this.getElement(_selectors.default.INPLACEEDITABLE).setAttribute("data-value",doc.documentElement.textContent),this.getElement(_selectors.default.INPLACEEDITABLE).querySelector("a").innerHTML=element.title,this.getElement(_selectors.default.DESCRIPTIONMODALTITLE).innerHTML=element.title,this.getElement(_selectors.default.DISCUSSIONMODALTITLE).innerHTML=element.title}if(void 0!==element.description&&(this.getElement(_selectors.default.DESCRIPTIONMODALBODY).innerHTML=element.description),void 0!==element.attachments&&_templates.default.renderForPromise("mod_kanban/attachmentitems",{attachments:element.attachments}).then((_ref5=>{let{html:html}=_ref5;return this.getElement(_selectors.default.DESCRIPTIONMODALFOOTER).innerHTML=html,!0})).catch((error=>(0,_notification.exception)(error))),this.toggleClass(element.hasdescription,"mod_kanban_hasdescription"),this.toggleClass(element.hasattachment,"mod_kanban_hasattachment"),void 0!==element.duedate&&(this.getElement(_selectors.default.DUEDATE).setAttribute("data-date",element.duedate),this._dueDateFormat()),this.toggleClass(element.discussion,"mod_kanban_hasdiscussion"),void 0!==element.options){let options=JSON.parse(element.options);void 0===options.background?this.getElement().removeAttribute("style"):this.getElement().setAttribute("style","background-color: "+options.background)}this.checkDragging()}_cardDeleted(){this.destroy()}_removeCard(event){let target=event.target.closest(_selectors.default.DELETECARD),data=Object.assign({},target.dataset);this.reactive.dispatch("deleteCard",data.id)}_pushCard(event){let target=event.target.closest(_selectors.default.PUSHCARD),data=Object.assign({},target.dataset);this.reactive.dispatch("pushCard",data.id)}_removeMessage(event){let target=event.target.closest(_selectors.default.DELETEMESSAGE),data=Object.assign({},target.dataset);this.reactive.dispatch("deleteMessage",data.id)}_completeCard(event){let target=event.target.closest(_selectors.default.COMPLETE),data=Object.assign({},target.dataset);this.reactive.dispatch("completeCard",data.id)}_uncompleteCard(event){let target=event.target.closest(_selectors.default.UNCOMPLETE),data=Object.assign({},target.dataset);this.reactive.dispatch("uncompleteCard",data.id)}destroy(){void 0!==this.dragdrop&&this.dragdrop.unregister()}getDraggableData(){return{id:this.id,type:"card"}}checkDragging(state){void 0===state&&(state=this.reactive.stateManager.state),state.cards.get(this.id).canedit?(this.draggable=!0,this.dragdrop.setDraggable(!0)):(this.draggable=!1,this.dragdrop.setDraggable(!1)),this.toggleClass(state.cards.get(this.id).canedit,"mod_kanban_canedit")}validateDropData(dropdata){return"card"==(null==dropdata?void 0:dropdata.type)}drop(dropdata){if(dropdata.id!=this.id){let newcolumn=this.getElement(_selectors.default.ADDCARD,this.id).dataset.columnid,aftercard=this.id;this.reactive.dispatch("moveCard",dropdata.id,newcolumn,aftercard)}}_unassignSelf(event){let target=event.target.closest(_selectors.default.UNASSIGNSELF),data=Object.assign({},target.dataset);this.reactive.dispatch("unassignUser",data.id)}_editDetails(event){event.preventDefault();const modalForm=new _modalform.default({formClass:"mod_kanban\\form\\edit_card_form",args:{id:this.id,boardid:this.boardid,cmid:this.cmid,groupid:this.groupid,userid:this.userid},modalConfig:{title:(0,Str.get_string)("editcard","mod_kanban")},returnFocus:this.getElement()});this.addEventListener(modalForm,modalForm.events.FORM_SUBMITTED,this._updateCard),modalForm.show()}_updateCard(event){this.reactive.dispatch("processUpdates",event.detail)}updateRelativeTime(timestamp){let elapsed=new Date(timestamp)-new Date;for(var u in this._units)if(Math.abs(elapsed)>this._units[u]||"second"==u)return this.rtf.format(Math.round(elapsed/this._units[u]),u);return""}_dueDateFormat(){let duedate=1e3*this.getElement(_selectors.default.DUEDATE).dataset.date;if(duedate>0){let element=this.getElement(_selectors.default.DUEDATE);element.innerHTML=this.updateRelativeTime(duedate),duedate<(new Date).getTime()?element.classList.add("mod_kanban_overdue"):element.classList.remove("mod_kanban_overdue")}else this.getElement(_selectors.default.DUEDATE).innerHTML=""}}return _exports.default=_default,_exports.default})); +define("mod_kanban/card",["exports","core/reactive","mod_kanban/selectors","mod_kanban/exporter","core/notification","core_form/modalform","core/str","core/templates","mod_kanban/kanbancomponent","core/log"],(function(_exports,_reactive,_selectors,_exporter,_notification,_modalform,Str,_templates,_kanbancomponent,_log){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}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_selectors=_interopRequireDefault(_selectors),_exporter=_interopRequireDefault(_exporter),_modalform=_interopRequireDefault(_modalform),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),_templates=_interopRequireDefault(_templates),_kanbancomponent=_interopRequireDefault(_kanbancomponent),_log=_interopRequireDefault(_log);class _default extends _kanbancomponent.default{constructor(){var obj,key,value;super(...arguments),value={year:31536e6,month:2628e6,day:864e5,hour:36e5,minute:6e4,second:1e3},(key="_units")in(obj=this)?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value}static init(target){return new this({element:document.getElementById(target)})}create(){this.id=this.element.dataset.id}getWatchers(){return[{watch:"cards[".concat(this.id,"]:updated"),handler:this._cardUpdated},{watch:"cards[".concat(this.id,"]:deleted"),handler:this._cardDeleted},{watch:"discussions:created",handler:this._discussionUpdated},{watch:"discussions:updated",handler:this._discussionUpdated},{watch:"discussions:deleted",handler:this._discussionUpdated},{watch:"history:created",handler:this._historyUpdated},{watch:"history:updated",handler:this._historyUpdated},{watch:"history:deleted",handler:this._historyUpdated}]}stateReady(state){let lang="en";void 0!==state.common.lang&&(lang=state.common.lang);try{this.rtf=new Intl.RelativeTimeFormat(lang,{numeric:"auto"})}catch(e){this.rtf=new Intl.RelativeTimeFormat("en",{numeric:"auto"})}this.addEventListener(this.getElement(_selectors.default.DELETECARD,this.id),"click",this._removeConfirm),this.addEventListener(this.getElement(_selectors.default.ADDCARD,this.id),"click",this._addCard),this.addEventListener(this.getElement(_selectors.default.COMPLETE,this.id),"click",this._completeCard),this.addEventListener(this.getElement(_selectors.default.UNCOMPLETE,this.id),"click",this._uncompleteCard),this.addEventListener(this.getElement(_selectors.default.ASSIGNSELF,this.id),"click",this._assignSelf),this.addEventListener(this.getElement(_selectors.default.UNASSIGNSELF,this.id),"click",this._unassignSelf),this.addEventListener(this.getElement(_selectors.default.EDITDETAILS,this.id),"click",this._editDetails),this.addEventListener(this.getElement(_selectors.default.DISCUSSIONMODALTRIGGER),"click",this._updateDiscussion),this.addEventListener(this.getElement(_selectors.default.DISCUSSIONSHOW,this.id),"click",this._updateDiscussion),this.addEventListener(this.getElement(_selectors.default.DISCUSSIONSEND),"click",this._sendMessage),this.addEventListener(this.getElement(_selectors.default.HISTORYMODALTRIGGER),"click",this._updateHistory),this.addEventListener(this.getElement(_selectors.default.MOVEMODALTRIGGER),"click",this._showMoveModal),this.addEventListener(this.getElement(_selectors.default.PUSHCARD),"click",this._pushCardConfirm),this.draggable=!1,this.dragdrop=new _reactive.DragDrop(this),this.checkEditing(state),this.boardid=state.board.id,this.cmid=state.common.id,this.userid=state.board.userid,this.groupid=state.board.groupid,this._dueDateFormat()}_showMoveModal(){let data=_exporter.default.exportStateForTemplate(this.reactive.state);data.cardid=this.id,data.kanbancolumn=this.reactive.state.cards.get(this.id).kanban_column,Str.get_strings([{key:"movecard",component:"mod_kanban"},{key:"move",component:"core"}]).then((strings=>(0,_notification.saveCancel)(strings[0],_templates.default.render("mod_kanban/movemodal",data),strings[1],(()=>{let column=document.querySelector(_selectors.default.MOVECARDCOLUMN+'[data-id="'.concat(this.id,'"]')).value,aftercard=document.querySelector(_selectors.default.MOVECARDAFTERCARD+'[data-id="'.concat(this.id,'"]')).value;this.reactive.dispatch("moveCard",this.id,column,aftercard)})))).catch((error=>_log.default.debug(error)))}_pushCardConfirm(event){Str.get_strings([{key:"pushcard",component:"mod_kanban"},{key:"pushcardconfirm",component:"mod_kanban"},{key:"copy",component:"core"}]).then((strings=>(0,_notification.saveCancel)(strings[0],strings[1],strings[2],(()=>{this._pushCard(event)})))).catch((error=>_log.default.debug(error)))}_removeConfirm(event){Str.get_strings([{key:"deletecard",component:"mod_kanban"},{key:"deletecardconfirm",component:"mod_kanban"},{key:"delete",component:"core"}]).then((strings=>(0,_notification.saveCancel)(strings[0],strings[1],strings[2],(()=>{this._removeCard(event)})))).catch((error=>_log.default.debug(error)))}_removeMessageConfirm(event){Str.get_strings([{key:"deletemessage",component:"mod_kanban"},{key:"deletemessageconfirm",component:"mod_kanban"},{key:"delete",component:"core"}]).then((strings=>(0,_notification.saveCancel)(strings[0],strings[1],strings[2],(()=>{this._removeMessage(event)})))).catch((error=>_log.default.debug(error)))}_sendMessage(){let el=this.getElement(_selectors.default.DISCUSSIONINPUT),message=el.value.trim();""!=message&&(this.reactive.dispatch("sendDiscussionMessage",this.id,message),el.value="")}_updateDiscussion(){this.getElement(_selectors.default.DISCUSSIONMODAL).classList.add("mod_kanban_loading"),this.reactive.dispatch("getDiscussionUpdates",this.id)}async _discussionUpdated(){let data={discussions:_exporter.default.exportDiscussion(this.reactive.state,this.id)};_templates.default.renderForPromise("mod_kanban/discussionmessages",data).then((_ref=>{let{html:html}=_ref;this.getElement(_selectors.default.DISCUSSION,this.id).innerHTML=html,this.getElement(_selectors.default.DISCUSSIONMODAL,this.id).classList.remove("mod_kanban_loading");let el=this.getElement(_selectors.default.DISCUSSIONMESSAGES);return el.scrollTop=el.scrollHeight,data.discussions.forEach((d=>{d.candelete&&this.addEventListener(this.getElement(_selectors.default.DELETEMESSAGE,d.id),"click",this._removeMessageConfirm)})),!0})).catch((error=>(0,_notification.exception)(error)))}_updateHistory(){this.getElement(_selectors.default.HISTORYMODAL).classList.add("mod_kanban_loading"),this.reactive.dispatch("getHistoryUpdates",this.id)}async _historyUpdated(){let data={historyitems:_exporter.default.exportHistory(this.reactive.state,this.id)};_templates.default.renderForPromise("mod_kanban/historyitems",data).then((_ref2=>{let{html:html}=_ref2;this.getElement(_selectors.default.HISTORY,this.id).innerHTML=html,this.getElement(_selectors.default.HISTORYMODAL).classList.remove("mod_kanban_loading");let el=this.getElement(_selectors.default.HISTORYITEMS);return el.scrollTop=el.scrollHeight,!0})).catch((error=>(0,_notification.exception)(error)))}_assignSelf(event){let target=event.target.closest(_selectors.default.ASSIGNSELF),data=Object.assign({},target.dataset);this.reactive.dispatch("assignUser",data.id)}_addCard(event){document.activeElement.blur();let target=event.target.closest(_selectors.default.ADDCARD),data=Object.assign({},target.dataset);this.reactive.dispatch("addCard",data.columnid,data.id)}async _cardUpdated(_ref3){let{element:element}=_ref3;const card=this.getElement();if(card.dataset.columnid!=element.kanban_column){document.querySelector(_selectors.default.COLUMNINNER+'[data-id="'+element.kanban_column+'"]').appendChild(card),this.getElement(_selectors.default.ADDCARD,this.id).setAttribute("data-columnid",element.kanban_column),card.setAttribute("data-columnid",element.kanban_column)}const assignees=this.getElement(_selectors.default.ASSIGNEES,this.id),assignedUsers=this.getElements(_selectors.default.ASSIGNEDUSER,this.id),userids=[...assignedUsers].map((v=>v.dataset.userid));if(void 0!==element.assignees){const additional=element.assignees.filter((x=>!userids.includes(x)));null!==assignedUsers&&assignedUsers.forEach((assignedUser=>{element.assignees.includes(assignedUser.dataset.userid)||assignedUser.parentNode.removeChild(assignedUser)})),this.toggleClass(0==element.assignees.length,"mod_kanban_unassigned"),element.assignees.length>0&&additional.forEach((async user=>{let userdata=this.reactive.state.users.get(user),data=Object.assign({cardid:element.id},userdata);data=Object.assign(data,_exporter.default.exportCapabilities(this.reactive.state)),_templates.default.renderForPromise("mod_kanban/user",data).then((_ref4=>{let{html:html,js:js}=_ref4;return _templates.default.appendNodeContents(assignees,html,js),!0})).catch((error=>(0,_notification.exception)(error)))}))}if(this.toggleClass(element.selfassigned,"mod_kanban_selfassigned"),this.toggleClass(1==element.completed,"mod_kanban_closed"),void 0!==element.title){let doc=(new DOMParser).parseFromString(element.title,"text/html");this.getElement(_selectors.default.INPLACEEDITABLE).setAttribute("data-value",doc.documentElement.textContent),this.getElement(_selectors.default.INPLACEEDITABLE).querySelector("a").innerHTML=element.title,this.getElement(_selectors.default.DESCRIPTIONMODALTITLE).innerHTML=element.title,this.getElement(_selectors.default.DISCUSSIONMODALTITLE).innerHTML=element.title}if(void 0!==element.description&&(this.getElement(_selectors.default.DESCRIPTIONMODALBODY).innerHTML=element.description),void 0!==element.attachments&&_templates.default.renderForPromise("mod_kanban/attachmentitems",{attachments:element.attachments}).then((_ref5=>{let{html:html}=_ref5;return this.getElement(_selectors.default.DESCRIPTIONMODALFOOTER).innerHTML=html,!0})).catch((error=>(0,_notification.exception)(error))),this.toggleClass(element.hasdescription,"mod_kanban_hasdescription"),this.toggleClass(element.hasattachment,"mod_kanban_hasattachment"),void 0!==element.duedate&&(this.getElement(_selectors.default.DUEDATE).setAttribute("data-date",element.duedate),this._dueDateFormat()),this.toggleClass(element.discussion,"mod_kanban_hasdiscussion"),void 0!==element.options){let options=JSON.parse(element.options);void 0===options.background?this.getElement().removeAttribute("style"):this.getElement().setAttribute("style","background-color: "+options.background)}this.checkEditing()}_cardDeleted(){this.destroy()}_removeCard(event){let target=event.target.closest(_selectors.default.DELETECARD),data=Object.assign({},target.dataset);this.reactive.dispatch("deleteCard",data.id)}_pushCard(event){let target=event.target.closest(_selectors.default.PUSHCARD),data=Object.assign({},target.dataset);this.reactive.dispatch("pushCard",data.id)}_removeMessage(event){let target=event.target.closest(_selectors.default.DELETEMESSAGE),data=Object.assign({},target.dataset);this.reactive.dispatch("deleteMessage",data.id)}_completeCard(event){let target=event.target.closest(_selectors.default.COMPLETE),data=Object.assign({},target.dataset);this.reactive.dispatch("completeCard",data.id)}_uncompleteCard(event){let target=event.target.closest(_selectors.default.UNCOMPLETE),data=Object.assign({},target.dataset);this.reactive.dispatch("uncompleteCard",data.id)}destroy(){void 0!==this.dragdrop&&this.dragdrop.unregister()}getDraggableData(){return{id:this.id,type:"card"}}checkEditing(state){void 0===state&&(state=this.reactive.stateManager.state),state.cards.get(this.id).canedit?(this.draggable=!0,this.dragdrop.setDraggable(!0)):(this.draggable=!1,this.dragdrop.setDraggable(!1)),1!=state.cards.get(this.id).completed&&state.cards.get(this.id).canedit?this.getElement(_selectors.default.INPLACEEDITABLE).setAttribute("data-inplaceeditable","1"):this.getElement(_selectors.default.INPLACEEDITABLE).removeAttribute("data-inplaceeditable"),this.toggleClass(state.cards.get(this.id).canedit,"mod_kanban_canedit")}validateDropData(dropdata){return"card"==(null==dropdata?void 0:dropdata.type)}drop(dropdata){if(dropdata.id!=this.id){let newcolumn=this.getElement(_selectors.default.ADDCARD,this.id).dataset.columnid,aftercard=this.id;this.reactive.dispatch("moveCard",dropdata.id,newcolumn,aftercard)}}_unassignSelf(event){let target=event.target.closest(_selectors.default.UNASSIGNSELF),data=Object.assign({},target.dataset);this.reactive.dispatch("unassignUser",data.id)}_editDetails(event){event.preventDefault();const modalForm=new _modalform.default({formClass:"mod_kanban\\form\\edit_card_form",args:{id:this.id,boardid:this.boardid,cmid:this.cmid,groupid:this.groupid,userid:this.userid},modalConfig:{title:(0,Str.get_string)("editcard","mod_kanban")},returnFocus:this.getElement()});this.addEventListener(modalForm,modalForm.events.FORM_SUBMITTED,this._updateCard),modalForm.show()}_updateCard(event){this.reactive.dispatch("processUpdates",event.detail)}updateRelativeTime(timestamp){let elapsed=new Date(timestamp)-new Date;for(var u in this._units)if(Math.abs(elapsed)>this._units[u]||"second"==u)return this.rtf.format(Math.round(elapsed/this._units[u]),u);return""}_dueDateFormat(){let duedate=1e3*this.getElement(_selectors.default.DUEDATE).dataset.date;if(duedate>0){let element=this.getElement(_selectors.default.DUEDATE);element.innerHTML=this.updateRelativeTime(duedate),duedate<(new Date).getTime()?element.classList.add("mod_kanban_overdue"):element.classList.remove("mod_kanban_overdue")}else this.getElement(_selectors.default.DUEDATE).innerHTML=""}}return _exports.default=_default,_exports.default})); //# sourceMappingURL=card.min.js.map \ No newline at end of file diff --git a/amd/build/card.min.js.map b/amd/build/card.min.js.map index d56f7b70..9d3f0b19 100644 --- a/amd/build/card.min.js.map +++ b/amd/build/card.min.js.map @@ -1 +1 @@ -{"version":3,"file":"card.min.js","sources":["../src/card.js"],"sourcesContent":["import {DragDrop} from 'core/reactive';\nimport selectors from 'mod_kanban/selectors';\nimport exporter from 'mod_kanban/exporter';\nimport {exception as displayException, saveCancel} from 'core/notification';\nimport ModalForm from 'core_form/modalform';\nimport * as Str from 'core/str';\nimport {get_string as getString} from 'core/str';\nimport Templates from 'core/templates';\nimport KanbanComponent from 'mod_kanban/kanbancomponent';\nimport Log from 'core/log';\n\n/**\n * Component representing a card in a kanban board.\n */\nexport default class extends KanbanComponent {\n /**\n * For relative time helper.\n */\n _units = {\n year: 24 * 60 * 60 * 1000 * 365,\n month: 24 * 60 * 60 * 1000 * 365 / 12,\n day: 24 * 60 * 60 * 1000,\n hour: 60 * 60 * 1000,\n minute: 60 * 1000,\n second: 1000\n };\n\n /**\n * Function to initialize component, called by mustache template.\n * @param {*} target The id of the HTMLElement to attach to\n * @returns {BaseComponent} New component attached to the HTMLElement represented by target\n */\n static init(target) {\n let element = document.getElementById(target);\n return new this({\n element: element,\n });\n }\n\n /**\n * Called after the component was created.\n */\n create() {\n this.id = this.element.dataset.id;\n }\n\n /**\n * Watchers for this component.\n * @returns {array} All watchers for this component\n */\n getWatchers() {\n return [\n {watch: `cards[${this.id}]:updated`, handler: this._cardUpdated},\n {watch: `cards[${this.id}]:deleted`, handler: this._cardDeleted},\n {watch: `discussions:created`, handler: this._discussionUpdated},\n {watch: `discussions:updated`, handler: this._discussionUpdated},\n {watch: `discussions:deleted`, handler: this._discussionUpdated},\n {watch: `history:created`, handler: this._historyUpdated},\n {watch: `history:updated`, handler: this._historyUpdated},\n {watch: `history:deleted`, handler: this._historyUpdated},\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 stateReady(state) {\n // Get language for relative time formatting.\n let lang = 'en';\n if (state.common.lang !== undefined) {\n lang = state.common.lang;\n }\n // The property state.common.lang contains the locale extracted from the currently used moodle language pack.\n // This should be a real locale and thus suitable for RelativeTimeFormat, for edge cases however we are\n // using a fallback locale here.\n try {\n this.rtf = new Intl.RelativeTimeFormat(lang, {numeric: 'auto'});\n } catch (e) {\n // Fallback if there is no valid lang found.\n this.rtf = new Intl.RelativeTimeFormat('en', {numeric: 'auto'});\n }\n\n this.addEventListener(\n this.getElement(selectors.DELETECARD, this.id),\n 'click',\n this._removeConfirm\n );\n this.addEventListener(\n this.getElement(selectors.ADDCARD, this.id),\n 'click',\n this._addCard\n );\n this.addEventListener(\n this.getElement(selectors.COMPLETE, this.id),\n 'click',\n this._completeCard\n );\n this.addEventListener(\n this.getElement(selectors.UNCOMPLETE, this.id),\n 'click',\n this._uncompleteCard\n );\n this.addEventListener(\n this.getElement(selectors.ASSIGNSELF, this.id),\n 'click',\n this._assignSelf\n );\n this.addEventListener(\n this.getElement(selectors.UNASSIGNSELF, this.id),\n 'click',\n this._unassignSelf\n );\n this.addEventListener(\n this.getElement(selectors.EDITDETAILS, this.id),\n 'click',\n this._editDetails\n );\n this.addEventListener(\n this.getElement(selectors.DISCUSSIONMODALTRIGGER),\n 'click',\n this._updateDiscussion\n );\n this.addEventListener(\n this.getElement(selectors.DISCUSSIONSHOW, this.id),\n 'click',\n this._updateDiscussion\n );\n this.addEventListener(\n this.getElement(selectors.DISCUSSIONSEND),\n 'click',\n this._sendMessage\n );\n this.addEventListener(\n this.getElement(selectors.HISTORYMODALTRIGGER),\n 'click',\n this._updateHistory\n );\n this.addEventListener(\n this.getElement(selectors.MOVEMODALTRIGGER),\n 'click',\n this._showMoveModal\n );\n this.addEventListener(\n this.getElement(selectors.PUSHCARD),\n 'click',\n this._pushCardConfirm\n );\n\n this.draggable = false;\n this.dragdrop = new DragDrop(this);\n this.checkDragging(state);\n this.boardid = state.board.id;\n this.cmid = state.common.id;\n this.userid = state.board.userid;\n this.groupid = state.board.groupid;\n this._dueDateFormat();\n }\n\n /**\n * Show modal to move a column.\n */\n _showMoveModal() {\n let data = exporter.exportStateForTemplate(this.reactive.state);\n data.cardid = this.id;\n data.kanbancolumn = this.reactive.state.cards.get(this.id).kanban_column;\n Str.get_strings([\n {key: 'movecard', component: 'mod_kanban'},\n {key: 'move', component: 'core'},\n ]).then((strings) => {\n return saveCancel(\n strings[0],\n Templates.render('mod_kanban/movemodal', data),\n strings[1],\n () => {\n let column = document.querySelector(selectors.MOVECARDCOLUMN + `[data-id=\"${this.id}\"]`).value;\n let aftercard = document.querySelector(selectors.MOVECARDAFTERCARD + `[data-id=\"${this.id}\"]`).value;\n this.reactive.dispatch('moveCard', this.id, column, aftercard);\n }\n );\n }).catch((error) => Log.debug(error));\n }\n\n /**\n * Display confirmation modal for pushing a card.\n * @param {*} event\n */\n _pushCardConfirm(event) {\n Str.get_strings([\n {key: 'pushcard', component: 'mod_kanban'},\n {key: 'pushcardconfirm', component: 'mod_kanban'},\n {key: 'copy', component: 'core'},\n ]).then((strings) => {\n return saveCancel(\n strings[0],\n strings[1],\n strings[2],\n () => {\n this._pushCard(event);\n }\n );\n }).catch((error) => Log.debug(error));\n }\n\n /**\n * Display confirmation modal for deleting a card.\n * @param {*} event\n */\n _removeConfirm(event) {\n Str.get_strings([\n {key: 'deletecard', component: 'mod_kanban'},\n {key: 'deletecardconfirm', 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._removeCard(event);\n }\n );\n }).catch((error) => Log.debug(error));\n }\n\n /**\n * Display confirmation modal for deleting a discussion message.\n * @param {*} event\n */\n _removeMessageConfirm(event) {\n Str.get_strings([\n {key: 'deletemessage', component: 'mod_kanban'},\n {key: 'deletemessageconfirm', 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._removeMessage(event);\n }\n );\n }).catch((error) => Log.debug(error));\n }\n\n /**\n * Dispatch event to add a message to discussion.\n */\n _sendMessage() {\n let el = this.getElement(selectors.DISCUSSIONINPUT);\n let message = el.value.trim();\n if (message != '') {\n this.reactive.dispatch('sendDiscussionMessage', this.id, message);\n el.value = '';\n }\n }\n\n /**\n * Dispatch event to update the discussion data.\n */\n _updateDiscussion() {\n this.getElement(selectors.DISCUSSIONMODAL).classList.add('mod_kanban_loading');\n this.reactive.dispatch('getDiscussionUpdates', this.id);\n }\n\n /**\n * Called when discussion was updated.\n */\n async _discussionUpdated() {\n let data = {\n discussions: exporter.exportDiscussion(this.reactive.state, this.id)\n };\n Templates.renderForPromise('mod_kanban/discussionmessages', data).then(({html}) => {\n this.getElement(selectors.DISCUSSION, this.id).innerHTML = html;\n this.getElement(selectors.DISCUSSIONMODAL, this.id).classList.remove('mod_kanban_loading');\n let el = this.getElement(selectors.DISCUSSIONMESSAGES);\n // Scroll down to latest message.\n el.scrollTop = el.scrollHeight;\n data.discussions.forEach((d) => {\n if (d.candelete) {\n this.addEventListener(this.getElement(selectors.DELETEMESSAGE, d.id), 'click', this._removeMessageConfirm);\n }\n });\n return true;\n }).catch((error) => displayException(error));\n }\n\n /**\n * Dispatch event to update the history data.\n */\n _updateHistory() {\n this.getElement(selectors.HISTORYMODAL).classList.add('mod_kanban_loading');\n this.reactive.dispatch('getHistoryUpdates', this.id);\n }\n\n /**\n * Called when history was updated.\n */\n async _historyUpdated() {\n let data = {\n historyitems: exporter.exportHistory(this.reactive.state, this.id)\n };\n Templates.renderForPromise('mod_kanban/historyitems', data).then(({html}) => {\n this.getElement(selectors.HISTORY, this.id).innerHTML = html;\n this.getElement(selectors.HISTORYMODAL).classList.remove('mod_kanban_loading');\n // Scroll down to latest history item.\n let el = this.getElement(selectors.HISTORYITEMS);\n el.scrollTop = el.scrollHeight;\n return true;\n }).catch((error) => displayException(error));\n }\n\n /**\n * Dispatch event to assign the current user to the card.\n * @param {*} event\n */\n _assignSelf(event) {\n let target = event.target.closest(selectors.ASSIGNSELF);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('assignUser', data.id);\n }\n\n /**\n * Dispatch event to add a card after this card.\n * @param {*} event\n */\n _addCard(event) {\n document.activeElement.blur();\n let target = event.target.closest(selectors.ADDCARD);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('addCard', data.columnid, data.id);\n }\n\n /**\n * Called when card is updated.\n * @param {*} param0\n */\n async _cardUpdated({element}) {\n const card = this.getElement();\n // Card was moved to another column. Move the element to new card (right position is handled by column component).\n if (card.dataset.columnid != element.kanban_column) {\n const col = document.querySelector(selectors.COLUMNINNER + '[data-id=\"' + element.kanban_column + '\"]');\n col.appendChild(card);\n this.getElement(selectors.ADDCARD, this.id).setAttribute('data-columnid', element.kanban_column);\n card.setAttribute('data-columnid', element.kanban_column);\n }\n const assignees = this.getElement(selectors.ASSIGNEES, this.id);\n const assignedUsers = this.getElements(selectors.ASSIGNEDUSER, this.id);\n const userids = [...assignedUsers].map(v => {\n return v.dataset.userid;\n });\n // Update assignees.\n if (element.assignees !== undefined) {\n const additional = element.assignees.filter(x => !userids.includes(x));\n // Remove all elements that represent users that are no longer assigned to this card.\n if (assignedUsers !== null) {\n assignedUsers.forEach(assignedUser => {\n if (!element.assignees.includes(assignedUser.dataset.userid)) {\n assignedUser.parentNode.removeChild(assignedUser);\n }\n });\n }\n this.toggleClass(element.assignees.length == 0, 'mod_kanban_unassigned');\n // Add new assignees.\n if (element.assignees.length > 0) {\n additional.forEach(async user => {\n let userdata = this.reactive.state.users.get(user);\n let data = Object.assign({cardid: element.id}, userdata);\n data = Object.assign(data, exporter.exportCapabilities(this.reactive.state));\n Templates.renderForPromise('mod_kanban/user', data).then(({html, js}) => {\n Templates.appendNodeContents(assignees, html, js);\n return true;\n }).catch((error) => displayException(error));\n });\n }\n }\n this.toggleClass(element.selfassigned, 'mod_kanban_selfassigned');\n // Set card completion state.\n if (element.completed !== undefined) {\n this.toggleClass(element.completed == 1, 'mod_kanban_closed');\n if (element.completed == 1) {\n this.getElement(selectors.INPLACEEDITABLE).removeAttribute('data-inplaceeditable');\n } else {\n this.getElement(selectors.INPLACEEDITABLE).setAttribute('data-inplaceeditable', '1');\n }\n }\n // Update title (also in modals).\n if (element.title !== undefined) {\n // For Moodle inplace editing title is once needed plain and once with html entities encoded.\n // This avoids double encoding of html entities as the value of \"data-value\" is exactly what is shown\n // in the input field when clicking on the inplace editable.\n let doc = new DOMParser().parseFromString(element.title, 'text/html');\n this.getElement(selectors.INPLACEEDITABLE).setAttribute('data-value', doc.documentElement.textContent);\n this.getElement(selectors.INPLACEEDITABLE).querySelector('a').innerHTML = element.title;\n this.getElement(selectors.DESCRIPTIONMODALTITLE).innerHTML = element.title;\n this.getElement(selectors.DISCUSSIONMODALTITLE).innerHTML = element.title;\n }\n // Update description.\n if (element.description !== undefined) {\n this.getElement(selectors.DESCRIPTIONMODALBODY).innerHTML = element.description;\n }\n // Render attachments in description modal.\n if (element.attachments !== undefined) {\n Templates.renderForPromise('mod_kanban/attachmentitems', {attachments: element.attachments}).then(({html}) => {\n this.getElement(selectors.DESCRIPTIONMODALFOOTER).innerHTML = html;\n return true;\n }).catch((error) => displayException(error));\n }\n this.toggleClass(element.hasdescription, 'mod_kanban_hasdescription');\n this.toggleClass(element.hasattachment, 'mod_kanban_hasattachment');\n // Update due date.\n if (element.duedate !== undefined) {\n this.getElement(selectors.DUEDATE).setAttribute('data-date', element.duedate);\n this._dueDateFormat();\n }\n this.toggleClass(element.discussion, 'mod_kanban_hasdiscussion');\n // Only option for now is background color.\n if (element.options !== undefined) {\n let options = JSON.parse(element.options);\n if (options.background === undefined) {\n this.getElement().removeAttribute('style');\n } else {\n this.getElement().setAttribute('style', 'background-color: ' + options.background);\n }\n }\n // Enable/disable dragging (e.g. if user is not assigned to the card anymore).\n this.checkDragging();\n }\n\n /**\n * Delete this card.\n */\n _cardDeleted() {\n this.destroy();\n }\n\n /**\n * Dispatch event to remove this card.\n * @param {*} event\n */\n _removeCard(event) {\n let target = event.target.closest(selectors.DELETECARD);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('deleteCard', data.id);\n }\n\n /**\n * Dispatch event to push this card.\n * @param {*} event\n */\n _pushCard(event) {\n let target = event.target.closest(selectors.PUSHCARD);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('pushCard', data.id);\n }\n\n /**\n * Dispatch event to remove this card.\n * @param {*} event\n */\n _removeMessage(event) {\n let target = event.target.closest(selectors.DELETEMESSAGE);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('deleteMessage', data.id);\n }\n\n /**\n * Dispatch event to complete this card.\n * @param {*} event\n */\n _completeCard(event) {\n let target = event.target.closest(selectors.COMPLETE);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('completeCard', data.id);\n }\n\n /**\n * Dispatch event to complete this card.\n * @param {*} event\n */\n _uncompleteCard(event) {\n let target = event.target.closest(selectors.UNCOMPLETE);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('uncompleteCard', data.id);\n }\n\n /**\n * Remove all subcomponents dependencies.\n */\n destroy() {\n if (this.dragdrop !== undefined) {\n this.dragdrop.unregister();\n }\n }\n\n /**\n * Get the draggable data of this component.\n * @returns {object}\n */\n getDraggableData() {\n return {\n id: this.id,\n type: 'card',\n };\n }\n\n /**\n * Conditionally enable / disable dragging.\n * @param {*} state\n */\n checkDragging(state) {\n if (state === undefined) {\n state = this.reactive.stateManager.state;\n }\n if (state.cards.get(this.id).canedit) {\n this.draggable = true;\n this.dragdrop.setDraggable(true);\n } else {\n this.draggable = false;\n this.dragdrop.setDraggable(false);\n }\n this.toggleClass(state.cards.get(this.id).canedit, 'mod_kanban_canedit');\n }\n\n /**\n * Validate draggable data.\n * @param {object} dropdata\n * @returns {boolean} if the data is valid for this drop-zone.\n */\n validateDropData(dropdata) {\n return dropdata?.type == 'card';\n }\n\n /**\n * Executed when a valid dropdata is dropped over the drop-zone.\n * @param {object} dropdata\n */\n drop(dropdata) {\n if (dropdata.id != this.id) {\n let newcolumn = this.getElement(selectors.ADDCARD, this.id).dataset.columnid;\n let aftercard = this.id;\n this.reactive.dispatch('moveCard', dropdata.id, newcolumn, aftercard);\n }\n }\n\n /**\n * Dispatch event to unassign the current user.\n * @param {*} event\n */\n _unassignSelf(event) {\n let target = event.target.closest(selectors.UNASSIGNSELF);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('unassignUser', data.id);\n }\n\n /**\n * Show modal form to edit card details.\n * @param {*} event\n */\n _editDetails(event) {\n event.preventDefault();\n\n const modalForm = new ModalForm({\n formClass: \"mod_kanban\\\\form\\\\edit_card_form\",\n args: {\n id: this.id,\n boardid: this.boardid,\n cmid: this.cmid,\n groupid: this.groupid,\n userid: this.userid\n },\n modalConfig: {title: getString('editcard', 'mod_kanban')},\n returnFocus: this.getElement(),\n });\n this.addEventListener(modalForm, modalForm.events.FORM_SUBMITTED, this._updateCard);\n modalForm.show();\n }\n\n /**\n * Dispatch an event to update card data from the detail modal.\n * @param {*} event\n */\n _updateCard(event) {\n this.reactive.dispatch('processUpdates', event.detail);\n }\n\n /**\n * Update relative time.\n * @param {int} timestamp\n * @returns {string}\n */\n updateRelativeTime(timestamp) {\n let elapsed = new Date(timestamp) - new Date();\n for (var u in this._units) {\n if (Math.abs(elapsed) > this._units[u] || u == 'second') {\n return this.rtf.format(Math.round(elapsed / this._units[u]), u);\n }\n }\n return '';\n }\n\n /**\n * Format due date using relative time.\n */\n _dueDateFormat() {\n // Convert timestamp to ms.\n let duedate = this.getElement(selectors.DUEDATE).dataset.date * 1000;\n if (duedate > 0) {\n let element = this.getElement(selectors.DUEDATE);\n element.innerHTML = this.updateRelativeTime(duedate);\n if (duedate < new Date().getTime()) {\n element.classList.add('mod_kanban_overdue');\n } else {\n element.classList.remove('mod_kanban_overdue');\n }\n } else {\n this.getElement(selectors.DUEDATE).innerHTML = '';\n }\n }\n}\n"],"names":["KanbanComponent","year","month","day","hour","minute","second","target","this","element","document","getElementById","create","id","dataset","getWatchers","watch","handler","_cardUpdated","_cardDeleted","_discussionUpdated","_historyUpdated","stateReady","state","lang","undefined","common","rtf","Intl","RelativeTimeFormat","numeric","e","addEventListener","getElement","selectors","DELETECARD","_removeConfirm","ADDCARD","_addCard","COMPLETE","_completeCard","UNCOMPLETE","_uncompleteCard","ASSIGNSELF","_assignSelf","UNASSIGNSELF","_unassignSelf","EDITDETAILS","_editDetails","DISCUSSIONMODALTRIGGER","_updateDiscussion","DISCUSSIONSHOW","DISCUSSIONSEND","_sendMessage","HISTORYMODALTRIGGER","_updateHistory","MOVEMODALTRIGGER","_showMoveModal","PUSHCARD","_pushCardConfirm","draggable","dragdrop","DragDrop","checkDragging","boardid","board","cmid","userid","groupid","_dueDateFormat","data","exporter","exportStateForTemplate","reactive","cardid","kanbancolumn","cards","get","kanban_column","Str","get_strings","key","component","then","strings","Templates","render","column","querySelector","MOVECARDCOLUMN","value","aftercard","MOVECARDAFTERCARD","dispatch","catch","error","Log","debug","event","_pushCard","_removeCard","_removeMessageConfirm","_removeMessage","el","DISCUSSIONINPUT","message","trim","DISCUSSIONMODAL","classList","add","discussions","exportDiscussion","renderForPromise","_ref","html","DISCUSSION","innerHTML","remove","DISCUSSIONMESSAGES","scrollTop","scrollHeight","forEach","d","candelete","DELETEMESSAGE","HISTORYMODAL","historyitems","exportHistory","_ref2","HISTORY","HISTORYITEMS","closest","Object","assign","activeElement","blur","columnid","card","COLUMNINNER","appendChild","setAttribute","assignees","ASSIGNEES","assignedUsers","getElements","ASSIGNEDUSER","userids","map","v","additional","filter","x","includes","assignedUser","parentNode","removeChild","toggleClass","length","async","userdata","users","user","exportCapabilities","_ref4","js","appendNodeContents","selfassigned","completed","INPLACEEDITABLE","removeAttribute","title","doc","DOMParser","parseFromString","documentElement","textContent","DESCRIPTIONMODALTITLE","DISCUSSIONMODALTITLE","description","DESCRIPTIONMODALBODY","attachments","_ref5","DESCRIPTIONMODALFOOTER","hasdescription","hasattachment","duedate","DUEDATE","discussion","options","JSON","parse","background","destroy","unregister","getDraggableData","type","stateManager","canedit","setDraggable","validateDropData","dropdata","drop","newcolumn","preventDefault","modalForm","ModalForm","formClass","args","modalConfig","returnFocus","events","FORM_SUBMITTED","_updateCard","show","detail","updateRelativeTime","timestamp","elapsed","Date","u","_units","Math","abs","format","round","date","getTime"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"card.min.js","sources":["../src/card.js"],"sourcesContent":["import {DragDrop} from 'core/reactive';\nimport selectors from 'mod_kanban/selectors';\nimport exporter from 'mod_kanban/exporter';\nimport {exception as displayException, saveCancel} from 'core/notification';\nimport ModalForm from 'core_form/modalform';\nimport * as Str from 'core/str';\nimport {get_string as getString} from 'core/str';\nimport Templates from 'core/templates';\nimport KanbanComponent from 'mod_kanban/kanbancomponent';\nimport Log from 'core/log';\n\n/**\n * Component representing a card in a kanban board.\n */\nexport default class extends KanbanComponent {\n /**\n * For relative time helper.\n */\n _units = {\n year: 24 * 60 * 60 * 1000 * 365,\n month: 24 * 60 * 60 * 1000 * 365 / 12,\n day: 24 * 60 * 60 * 1000,\n hour: 60 * 60 * 1000,\n minute: 60 * 1000,\n second: 1000\n };\n\n /**\n * Function to initialize component, called by mustache template.\n * @param {*} target The id of the HTMLElement to attach to\n * @returns {BaseComponent} New component attached to the HTMLElement represented by target\n */\n static init(target) {\n let element = document.getElementById(target);\n return new this({\n element: element,\n });\n }\n\n /**\n * Called after the component was created.\n */\n create() {\n this.id = this.element.dataset.id;\n }\n\n /**\n * Watchers for this component.\n * @returns {array} All watchers for this component\n */\n getWatchers() {\n return [\n {watch: `cards[${this.id}]:updated`, handler: this._cardUpdated},\n {watch: `cards[${this.id}]:deleted`, handler: this._cardDeleted},\n {watch: `discussions:created`, handler: this._discussionUpdated},\n {watch: `discussions:updated`, handler: this._discussionUpdated},\n {watch: `discussions:deleted`, handler: this._discussionUpdated},\n {watch: `history:created`, handler: this._historyUpdated},\n {watch: `history:updated`, handler: this._historyUpdated},\n {watch: `history:deleted`, handler: this._historyUpdated},\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 stateReady(state) {\n // Get language for relative time formatting.\n let lang = 'en';\n if (state.common.lang !== undefined) {\n lang = state.common.lang;\n }\n // The property state.common.lang contains the locale extracted from the currently used moodle language pack.\n // This should be a real locale and thus suitable for RelativeTimeFormat, for edge cases however we are\n // using a fallback locale here.\n try {\n this.rtf = new Intl.RelativeTimeFormat(lang, {numeric: 'auto'});\n } catch (e) {\n // Fallback if there is no valid lang found.\n this.rtf = new Intl.RelativeTimeFormat('en', {numeric: 'auto'});\n }\n\n this.addEventListener(\n this.getElement(selectors.DELETECARD, this.id),\n 'click',\n this._removeConfirm\n );\n this.addEventListener(\n this.getElement(selectors.ADDCARD, this.id),\n 'click',\n this._addCard\n );\n this.addEventListener(\n this.getElement(selectors.COMPLETE, this.id),\n 'click',\n this._completeCard\n );\n this.addEventListener(\n this.getElement(selectors.UNCOMPLETE, this.id),\n 'click',\n this._uncompleteCard\n );\n this.addEventListener(\n this.getElement(selectors.ASSIGNSELF, this.id),\n 'click',\n this._assignSelf\n );\n this.addEventListener(\n this.getElement(selectors.UNASSIGNSELF, this.id),\n 'click',\n this._unassignSelf\n );\n this.addEventListener(\n this.getElement(selectors.EDITDETAILS, this.id),\n 'click',\n this._editDetails\n );\n this.addEventListener(\n this.getElement(selectors.DISCUSSIONMODALTRIGGER),\n 'click',\n this._updateDiscussion\n );\n this.addEventListener(\n this.getElement(selectors.DISCUSSIONSHOW, this.id),\n 'click',\n this._updateDiscussion\n );\n this.addEventListener(\n this.getElement(selectors.DISCUSSIONSEND),\n 'click',\n this._sendMessage\n );\n this.addEventListener(\n this.getElement(selectors.HISTORYMODALTRIGGER),\n 'click',\n this._updateHistory\n );\n this.addEventListener(\n this.getElement(selectors.MOVEMODALTRIGGER),\n 'click',\n this._showMoveModal\n );\n this.addEventListener(\n this.getElement(selectors.PUSHCARD),\n 'click',\n this._pushCardConfirm\n );\n\n this.draggable = false;\n this.dragdrop = new DragDrop(this);\n this.checkEditing(state);\n this.boardid = state.board.id;\n this.cmid = state.common.id;\n this.userid = state.board.userid;\n this.groupid = state.board.groupid;\n this._dueDateFormat();\n }\n\n /**\n * Show modal to move a column.\n */\n _showMoveModal() {\n let data = exporter.exportStateForTemplate(this.reactive.state);\n data.cardid = this.id;\n data.kanbancolumn = this.reactive.state.cards.get(this.id).kanban_column;\n Str.get_strings([\n {key: 'movecard', component: 'mod_kanban'},\n {key: 'move', component: 'core'},\n ]).then((strings) => {\n return saveCancel(\n strings[0],\n Templates.render('mod_kanban/movemodal', data),\n strings[1],\n () => {\n let column = document.querySelector(selectors.MOVECARDCOLUMN + `[data-id=\"${this.id}\"]`).value;\n let aftercard = document.querySelector(selectors.MOVECARDAFTERCARD + `[data-id=\"${this.id}\"]`).value;\n this.reactive.dispatch('moveCard', this.id, column, aftercard);\n }\n );\n }).catch((error) => Log.debug(error));\n }\n\n /**\n * Display confirmation modal for pushing a card.\n * @param {*} event\n */\n _pushCardConfirm(event) {\n Str.get_strings([\n {key: 'pushcard', component: 'mod_kanban'},\n {key: 'pushcardconfirm', component: 'mod_kanban'},\n {key: 'copy', component: 'core'},\n ]).then((strings) => {\n return saveCancel(\n strings[0],\n strings[1],\n strings[2],\n () => {\n this._pushCard(event);\n }\n );\n }).catch((error) => Log.debug(error));\n }\n\n /**\n * Display confirmation modal for deleting a card.\n * @param {*} event\n */\n _removeConfirm(event) {\n Str.get_strings([\n {key: 'deletecard', component: 'mod_kanban'},\n {key: 'deletecardconfirm', 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._removeCard(event);\n }\n );\n }).catch((error) => Log.debug(error));\n }\n\n /**\n * Display confirmation modal for deleting a discussion message.\n * @param {*} event\n */\n _removeMessageConfirm(event) {\n Str.get_strings([\n {key: 'deletemessage', component: 'mod_kanban'},\n {key: 'deletemessageconfirm', 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._removeMessage(event);\n }\n );\n }).catch((error) => Log.debug(error));\n }\n\n /**\n * Dispatch event to add a message to discussion.\n */\n _sendMessage() {\n let el = this.getElement(selectors.DISCUSSIONINPUT);\n let message = el.value.trim();\n if (message != '') {\n this.reactive.dispatch('sendDiscussionMessage', this.id, message);\n el.value = '';\n }\n }\n\n /**\n * Dispatch event to update the discussion data.\n */\n _updateDiscussion() {\n this.getElement(selectors.DISCUSSIONMODAL).classList.add('mod_kanban_loading');\n this.reactive.dispatch('getDiscussionUpdates', this.id);\n }\n\n /**\n * Called when discussion was updated.\n */\n async _discussionUpdated() {\n let data = {\n discussions: exporter.exportDiscussion(this.reactive.state, this.id)\n };\n Templates.renderForPromise('mod_kanban/discussionmessages', data).then(({html}) => {\n this.getElement(selectors.DISCUSSION, this.id).innerHTML = html;\n this.getElement(selectors.DISCUSSIONMODAL, this.id).classList.remove('mod_kanban_loading');\n let el = this.getElement(selectors.DISCUSSIONMESSAGES);\n // Scroll down to latest message.\n el.scrollTop = el.scrollHeight;\n data.discussions.forEach((d) => {\n if (d.candelete) {\n this.addEventListener(this.getElement(selectors.DELETEMESSAGE, d.id), 'click', this._removeMessageConfirm);\n }\n });\n return true;\n }).catch((error) => displayException(error));\n }\n\n /**\n * Dispatch event to update the history data.\n */\n _updateHistory() {\n this.getElement(selectors.HISTORYMODAL).classList.add('mod_kanban_loading');\n this.reactive.dispatch('getHistoryUpdates', this.id);\n }\n\n /**\n * Called when history was updated.\n */\n async _historyUpdated() {\n let data = {\n historyitems: exporter.exportHistory(this.reactive.state, this.id)\n };\n Templates.renderForPromise('mod_kanban/historyitems', data).then(({html}) => {\n this.getElement(selectors.HISTORY, this.id).innerHTML = html;\n this.getElement(selectors.HISTORYMODAL).classList.remove('mod_kanban_loading');\n // Scroll down to latest history item.\n let el = this.getElement(selectors.HISTORYITEMS);\n el.scrollTop = el.scrollHeight;\n return true;\n }).catch((error) => displayException(error));\n }\n\n /**\n * Dispatch event to assign the current user to the card.\n * @param {*} event\n */\n _assignSelf(event) {\n let target = event.target.closest(selectors.ASSIGNSELF);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('assignUser', data.id);\n }\n\n /**\n * Dispatch event to add a card after this card.\n * @param {*} event\n */\n _addCard(event) {\n document.activeElement.blur();\n let target = event.target.closest(selectors.ADDCARD);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('addCard', data.columnid, data.id);\n }\n\n /**\n * Called when card is updated.\n * @param {*} param0\n */\n async _cardUpdated({element}) {\n const card = this.getElement();\n // Card was moved to another column. Move the element to new card (right position is handled by column component).\n if (card.dataset.columnid != element.kanban_column) {\n const col = document.querySelector(selectors.COLUMNINNER + '[data-id=\"' + element.kanban_column + '\"]');\n col.appendChild(card);\n this.getElement(selectors.ADDCARD, this.id).setAttribute('data-columnid', element.kanban_column);\n card.setAttribute('data-columnid', element.kanban_column);\n }\n const assignees = this.getElement(selectors.ASSIGNEES, this.id);\n const assignedUsers = this.getElements(selectors.ASSIGNEDUSER, this.id);\n const userids = [...assignedUsers].map(v => {\n return v.dataset.userid;\n });\n // Update assignees.\n if (element.assignees !== undefined) {\n const additional = element.assignees.filter(x => !userids.includes(x));\n // Remove all elements that represent users that are no longer assigned to this card.\n if (assignedUsers !== null) {\n assignedUsers.forEach(assignedUser => {\n if (!element.assignees.includes(assignedUser.dataset.userid)) {\n assignedUser.parentNode.removeChild(assignedUser);\n }\n });\n }\n this.toggleClass(element.assignees.length == 0, 'mod_kanban_unassigned');\n // Add new assignees.\n if (element.assignees.length > 0) {\n additional.forEach(async user => {\n let userdata = this.reactive.state.users.get(user);\n let data = Object.assign({cardid: element.id}, userdata);\n data = Object.assign(data, exporter.exportCapabilities(this.reactive.state));\n Templates.renderForPromise('mod_kanban/user', data).then(({html, js}) => {\n Templates.appendNodeContents(assignees, html, js);\n return true;\n }).catch((error) => displayException(error));\n });\n }\n }\n this.toggleClass(element.selfassigned, 'mod_kanban_selfassigned');\n // Set card completion state.\n this.toggleClass(element.completed == 1, 'mod_kanban_closed');\n // Update title (also in modals).\n if (element.title !== undefined) {\n // For Moodle inplace editing title is once needed plain and once with html entities encoded.\n // This avoids double encoding of html entities as the value of \"data-value\" is exactly what is shown\n // in the input field when clicking on the inplace editable.\n let doc = new DOMParser().parseFromString(element.title, 'text/html');\n this.getElement(selectors.INPLACEEDITABLE).setAttribute('data-value', doc.documentElement.textContent);\n this.getElement(selectors.INPLACEEDITABLE).querySelector('a').innerHTML = element.title;\n this.getElement(selectors.DESCRIPTIONMODALTITLE).innerHTML = element.title;\n this.getElement(selectors.DISCUSSIONMODALTITLE).innerHTML = element.title;\n }\n // Update description.\n if (element.description !== undefined) {\n this.getElement(selectors.DESCRIPTIONMODALBODY).innerHTML = element.description;\n }\n // Render attachments in description modal.\n if (element.attachments !== undefined) {\n Templates.renderForPromise('mod_kanban/attachmentitems', {attachments: element.attachments}).then(({html}) => {\n this.getElement(selectors.DESCRIPTIONMODALFOOTER).innerHTML = html;\n return true;\n }).catch((error) => displayException(error));\n }\n this.toggleClass(element.hasdescription, 'mod_kanban_hasdescription');\n this.toggleClass(element.hasattachment, 'mod_kanban_hasattachment');\n // Update due date.\n if (element.duedate !== undefined) {\n this.getElement(selectors.DUEDATE).setAttribute('data-date', element.duedate);\n this._dueDateFormat();\n }\n this.toggleClass(element.discussion, 'mod_kanban_hasdiscussion');\n // Only option for now is background color.\n if (element.options !== undefined) {\n let options = JSON.parse(element.options);\n if (options.background === undefined) {\n this.getElement().removeAttribute('style');\n } else {\n this.getElement().setAttribute('style', 'background-color: ' + options.background);\n }\n }\n // Enable/disable dragging and inplace editing (e.g. if user is not assigned to the card anymore).\n this.checkEditing();\n }\n\n /**\n * Delete this card.\n */\n _cardDeleted() {\n this.destroy();\n }\n\n /**\n * Dispatch event to remove this card.\n * @param {*} event\n */\n _removeCard(event) {\n let target = event.target.closest(selectors.DELETECARD);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('deleteCard', data.id);\n }\n\n /**\n * Dispatch event to push this card.\n * @param {*} event\n */\n _pushCard(event) {\n let target = event.target.closest(selectors.PUSHCARD);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('pushCard', data.id);\n }\n\n /**\n * Dispatch event to remove this card.\n * @param {*} event\n */\n _removeMessage(event) {\n let target = event.target.closest(selectors.DELETEMESSAGE);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('deleteMessage', data.id);\n }\n\n /**\n * Dispatch event to complete this card.\n * @param {*} event\n */\n _completeCard(event) {\n let target = event.target.closest(selectors.COMPLETE);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('completeCard', data.id);\n }\n\n /**\n * Dispatch event to complete this card.\n * @param {*} event\n */\n _uncompleteCard(event) {\n let target = event.target.closest(selectors.UNCOMPLETE);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('uncompleteCard', data.id);\n }\n\n /**\n * Remove all subcomponents dependencies.\n */\n destroy() {\n if (this.dragdrop !== undefined) {\n this.dragdrop.unregister();\n }\n }\n\n /**\n * Get the draggable data of this component.\n * @returns {object}\n */\n getDraggableData() {\n return {\n id: this.id,\n type: 'card',\n };\n }\n\n /**\n * Conditionally enable / disable dragging and inplace editing.\n * @param {*} state\n */\n checkEditing(state) {\n if (state === undefined) {\n state = this.reactive.stateManager.state;\n }\n if (state.cards.get(this.id).canedit) {\n this.draggable = true;\n this.dragdrop.setDraggable(true);\n } else {\n this.draggable = false;\n this.dragdrop.setDraggable(false);\n }\n if (state.cards.get(this.id).completed != 1 && state.cards.get(this.id).canedit) {\n this.getElement(selectors.INPLACEEDITABLE).setAttribute('data-inplaceeditable', '1');\n } else {\n this.getElement(selectors.INPLACEEDITABLE).removeAttribute('data-inplaceeditable');\n }\n\n this.toggleClass(state.cards.get(this.id).canedit, 'mod_kanban_canedit');\n }\n\n /**\n * Validate draggable data.\n * @param {object} dropdata\n * @returns {boolean} if the data is valid for this drop-zone.\n */\n validateDropData(dropdata) {\n return dropdata?.type == 'card';\n }\n\n /**\n * Executed when a valid dropdata is dropped over the drop-zone.\n * @param {object} dropdata\n */\n drop(dropdata) {\n if (dropdata.id != this.id) {\n let newcolumn = this.getElement(selectors.ADDCARD, this.id).dataset.columnid;\n let aftercard = this.id;\n this.reactive.dispatch('moveCard', dropdata.id, newcolumn, aftercard);\n }\n }\n\n /**\n * Dispatch event to unassign the current user.\n * @param {*} event\n */\n _unassignSelf(event) {\n let target = event.target.closest(selectors.UNASSIGNSELF);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('unassignUser', data.id);\n }\n\n /**\n * Show modal form to edit card details.\n * @param {*} event\n */\n _editDetails(event) {\n event.preventDefault();\n\n const modalForm = new ModalForm({\n formClass: \"mod_kanban\\\\form\\\\edit_card_form\",\n args: {\n id: this.id,\n boardid: this.boardid,\n cmid: this.cmid,\n groupid: this.groupid,\n userid: this.userid\n },\n modalConfig: {title: getString('editcard', 'mod_kanban')},\n returnFocus: this.getElement(),\n });\n this.addEventListener(modalForm, modalForm.events.FORM_SUBMITTED, this._updateCard);\n modalForm.show();\n }\n\n /**\n * Dispatch an event to update card data from the detail modal.\n * @param {*} event\n */\n _updateCard(event) {\n this.reactive.dispatch('processUpdates', event.detail);\n }\n\n /**\n * Update relative time.\n * @param {int} timestamp\n * @returns {string}\n */\n updateRelativeTime(timestamp) {\n let elapsed = new Date(timestamp) - new Date();\n for (var u in this._units) {\n if (Math.abs(elapsed) > this._units[u] || u == 'second') {\n return this.rtf.format(Math.round(elapsed / this._units[u]), u);\n }\n }\n return '';\n }\n\n /**\n * Format due date using relative time.\n */\n _dueDateFormat() {\n // Convert timestamp to ms.\n let duedate = this.getElement(selectors.DUEDATE).dataset.date * 1000;\n if (duedate > 0) {\n let element = this.getElement(selectors.DUEDATE);\n element.innerHTML = this.updateRelativeTime(duedate);\n if (duedate < new Date().getTime()) {\n element.classList.add('mod_kanban_overdue');\n } else {\n element.classList.remove('mod_kanban_overdue');\n }\n } else {\n this.getElement(selectors.DUEDATE).innerHTML = '';\n }\n }\n}\n"],"names":["KanbanComponent","year","month","day","hour","minute","second","target","this","element","document","getElementById","create","id","dataset","getWatchers","watch","handler","_cardUpdated","_cardDeleted","_discussionUpdated","_historyUpdated","stateReady","state","lang","undefined","common","rtf","Intl","RelativeTimeFormat","numeric","e","addEventListener","getElement","selectors","DELETECARD","_removeConfirm","ADDCARD","_addCard","COMPLETE","_completeCard","UNCOMPLETE","_uncompleteCard","ASSIGNSELF","_assignSelf","UNASSIGNSELF","_unassignSelf","EDITDETAILS","_editDetails","DISCUSSIONMODALTRIGGER","_updateDiscussion","DISCUSSIONSHOW","DISCUSSIONSEND","_sendMessage","HISTORYMODALTRIGGER","_updateHistory","MOVEMODALTRIGGER","_showMoveModal","PUSHCARD","_pushCardConfirm","draggable","dragdrop","DragDrop","checkEditing","boardid","board","cmid","userid","groupid","_dueDateFormat","data","exporter","exportStateForTemplate","reactive","cardid","kanbancolumn","cards","get","kanban_column","Str","get_strings","key","component","then","strings","Templates","render","column","querySelector","MOVECARDCOLUMN","value","aftercard","MOVECARDAFTERCARD","dispatch","catch","error","Log","debug","event","_pushCard","_removeCard","_removeMessageConfirm","_removeMessage","el","DISCUSSIONINPUT","message","trim","DISCUSSIONMODAL","classList","add","discussions","exportDiscussion","renderForPromise","_ref","html","DISCUSSION","innerHTML","remove","DISCUSSIONMESSAGES","scrollTop","scrollHeight","forEach","d","candelete","DELETEMESSAGE","HISTORYMODAL","historyitems","exportHistory","_ref2","HISTORY","HISTORYITEMS","closest","Object","assign","activeElement","blur","columnid","card","COLUMNINNER","appendChild","setAttribute","assignees","ASSIGNEES","assignedUsers","getElements","ASSIGNEDUSER","userids","map","v","additional","filter","x","includes","assignedUser","parentNode","removeChild","toggleClass","length","async","userdata","users","user","exportCapabilities","_ref4","js","appendNodeContents","selfassigned","completed","title","doc","DOMParser","parseFromString","INPLACEEDITABLE","documentElement","textContent","DESCRIPTIONMODALTITLE","DISCUSSIONMODALTITLE","description","DESCRIPTIONMODALBODY","attachments","_ref5","DESCRIPTIONMODALFOOTER","hasdescription","hasattachment","duedate","DUEDATE","discussion","options","JSON","parse","background","removeAttribute","destroy","unregister","getDraggableData","type","stateManager","canedit","setDraggable","validateDropData","dropdata","drop","newcolumn","preventDefault","modalForm","ModalForm","formClass","args","modalConfig","returnFocus","events","FORM_SUBMITTED","_updateCard","show","detail","updateRelativeTime","timestamp","elapsed","Date","u","_units","Math","abs","format","round","date","getTime"],"mappings":"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"} \ No newline at end of file diff --git a/amd/src/card.js b/amd/src/card.js index 56d5a153..eba0e145 100644 --- a/amd/src/card.js +++ b/amd/src/card.js @@ -150,7 +150,7 @@ export default class extends KanbanComponent { this.draggable = false; this.dragdrop = new DragDrop(this); - this.checkDragging(state); + this.checkEditing(state); this.boardid = state.board.id; this.cmid = state.common.id; this.userid = state.board.userid; @@ -378,14 +378,7 @@ export default class extends KanbanComponent { } this.toggleClass(element.selfassigned, 'mod_kanban_selfassigned'); // Set card completion state. - if (element.completed !== undefined) { - this.toggleClass(element.completed == 1, 'mod_kanban_closed'); - if (element.completed == 1) { - this.getElement(selectors.INPLACEEDITABLE).removeAttribute('data-inplaceeditable'); - } else { - this.getElement(selectors.INPLACEEDITABLE).setAttribute('data-inplaceeditable', '1'); - } - } + this.toggleClass(element.completed == 1, 'mod_kanban_closed'); // Update title (also in modals). if (element.title !== undefined) { // For Moodle inplace editing title is once needed plain and once with html entities encoded. @@ -425,8 +418,8 @@ export default class extends KanbanComponent { this.getElement().setAttribute('style', 'background-color: ' + options.background); } } - // Enable/disable dragging (e.g. if user is not assigned to the card anymore). - this.checkDragging(); + // Enable/disable dragging and inplace editing (e.g. if user is not assigned to the card anymore). + this.checkEditing(); } /** @@ -507,10 +500,10 @@ export default class extends KanbanComponent { } /** - * Conditionally enable / disable dragging. + * Conditionally enable / disable dragging and inplace editing. * @param {*} state */ - checkDragging(state) { + checkEditing(state) { if (state === undefined) { state = this.reactive.stateManager.state; } @@ -521,6 +514,12 @@ export default class extends KanbanComponent { this.draggable = false; this.dragdrop.setDraggable(false); } + if (state.cards.get(this.id).completed != 1 && state.cards.get(this.id).canedit) { + this.getElement(selectors.INPLACEEDITABLE).setAttribute('data-inplaceeditable', '1'); + } else { + this.getElement(selectors.INPLACEEDITABLE).removeAttribute('data-inplaceeditable'); + } + this.toggleClass(state.cards.get(this.id).canedit, 'mod_kanban_canedit'); }