diff --git a/amd/build/card.min.js b/amd/build/card.min.js index 1dbf51f5..7d7e221b 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&&(this.getElement(_selectors.default.INPLACEEDITABLE).setAttribute("data-value",element.title),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),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.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 titlehelper=document.createElement("textarea");titlehelper.innerHTML=element.title,this.getElement(_selectors.default.INPLACEEDITABLE).setAttribute("data-value",titlehelper.value),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})); //# 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 5eb28f7d..e97fc276 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 this.getElement(selectors.INPLACEEDITABLE).setAttribute('data-value', element.title);\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","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.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 titlehelper = document.createElement('textarea');\n titlehelper.innerHTML = element.title;\n this.getElement(selectors.INPLACEEDITABLE).setAttribute('data-value', titlehelper.value);\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","titlehelper","createElement","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 diff --git a/amd/build/column.min.js.map b/amd/build/column.min.js.map index cabdff53..acc9048a 100644 --- a/amd/build/column.min.js.map +++ b/amd/build/column.min.js.map @@ -1 +1 @@ -{"version":3,"file":"column.min.js","sources":["../src/column.js"],"sourcesContent":["import {DragDrop} from 'core/reactive';\nimport selectors from 'mod_kanban/selectors';\nimport capabilities from 'mod_kanban/capabilities';\nimport exporter from 'mod_kanban/exporter';\nimport {saveCancel} from 'core/notification';\nimport * as Str from 'core/str';\nimport {get_string as getString} from 'core/str';\nimport ModalForm from 'core_form/modalform';\nimport KanbanComponent from 'mod_kanban/kanbancomponent';\nimport Log from \"core/log\";\n\n/**\n * Component representing a column in a kanban board.\n */\nexport default class extends KanbanComponent {\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}\n */\n getWatchers() {\n return [\n {watch: `columns[${this.id}]:updated`, handler: this._columnUpdated},\n {watch: `columns[${this.id}]:deleted`, handler: this._columnDeleted},\n {watch: `cards:created`, handler: this._cardCreated}\n ];\n }\n\n /**\n * Called once when state is ready, attaching event listeners and initializing drag and drop.\n * @param {object} state\n */\n stateReady(state) {\n this.addEventListener(\n this.getElement(selectors.DELETECOLUMN, this.id),\n 'click',\n this._removeConfirm\n );\n this.addEventListener(\n this.getElement(selectors.ADDCARDFIRST),\n 'click',\n this._addCard\n );\n this.addEventListener(\n this.getElement(selectors.ADDCOLUMN, this.id),\n 'click',\n this._addColumn\n );\n this.addEventListener(\n this.getElement(selectors.LOCKCOLUMN, this.id),\n 'click',\n this._lockColumn\n );\n this.addEventListener(\n this.getElement(selectors.UNLOCKCOLUMN, this.id),\n 'click',\n this._unlockColumn\n );\n this.addEventListener(\n this.getElement(selectors.EDITDETAILS, this.id),\n 'click',\n this._editDetails\n );\n this.addEventListener(\n this.getElement(selectors.SHOWHIDDEN),\n 'click',\n this._showHidden\n );\n this.addEventListener(\n this.getElement(selectors.HIDEHIDDEN),\n 'click',\n this._hideHidden\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 }\n\n /**\n * Display confirmation modal for deleting a card.\n * @param {*} event\n */\n _removeConfirm(event) {\n Str.get_strings([\n {key: 'deletecolumn', component: 'mod_kanban'},\n {key: 'deletecolumnconfirm', 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._removeColumn(event);\n }\n );\n }).catch((error) => Log.debug(error));\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 *\n * @returns {Object} the draggable data.\n */\n getDraggableData() {\n return {id: this.id, type: 'column'};\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\n if (state.capabilities.get(capabilities.MANAGECOLUMNS).value && state.columns.get(this.id).locked == 0) {\n this.dragdrop.setDraggable(true);\n } else {\n this.dragdrop.setDraggable(false);\n }\n }\n\n /**\n * Validate draggable data. This component accepts cards and columns.\n * @param {object} dropdata\n * @returns {boolean} if the data is valid for this drop-zone.\n */\n validateDropData(dropdata) {\n let type = dropdata?.type;\n return type == 'card' || type == 'column';\n }\n\n /**\n * Executed when a valid dropdata is dropped over the drop-zone.\n * @param {object} dropdata\n * @param {object} event\n */\n drop(dropdata, event) {\n if (dropdata.type == 'card') {\n let cards = this.getElements(selectors.CARD);\n let aftercard = 0;\n for (let i = 0; i < cards.length; i++) {\n if (cards[i].offsetTop + cards[i].clientHeight / 2 <= event.layerY) {\n aftercard = cards[i].dataset.id;\n }\n }\n this.reactive.dispatch('moveCard', dropdata.id, this.id, aftercard);\n }\n if (dropdata.type == 'column') {\n if (dropdata.id != this.id) {\n this.reactive.dispatch('moveColumn', dropdata.id, this.id);\n }\n }\n }\n\n /**\n * Show some visual hints to the user.\n * @param {object} dropdata\n * @param {object} event\n */\n showDropZone(dropdata, event) {\n if (dropdata.type == 'card') {\n let cards = this.getElements(selectors.CARD);\n let aftercard = 0;\n for (let i = 0; i < cards.length; i++) {\n if (cards[i].offsetTop + cards[i].clientHeight / 2 <= event.layerY) {\n aftercard = cards[i].dataset.id;\n }\n }\n if (aftercard == 0) {\n this.getElement(selectors.ADDCARDCONTAINER).classList.add('mod_kanban_insert');\n } else {\n this.getElement(selectors.ADDCARDCONTAINER, aftercard).classList.add('mod_kanban_insert');\n }\n }\n if (dropdata.type == 'column') {\n this.getElement(selectors.ADDCOLUMNCONTAINER).classList.add('mod_kanban_insert');\n }\n }\n\n /**\n * Remove visual hints to the user.\n */\n hideDropZone() {\n this.getElement(selectors.ADDCOLUMNCONTAINER).classList.remove('mod_kanban_insert');\n this.getElements(selectors.ADDCARDCONTAINER).forEach((e) => {\n e.classList.remove('mod_kanban_insert');\n });\n }\n\n /**\n * Dispatch event to add a column after this column.\n * @param {*} event\n */\n _addColumn(event) {\n document.activeElement.blur();\n let target = event.target.closest(selectors.ADDCOLUMN);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('addColumn', data.id);\n }\n\n /**\n * Called when a card was created in this column.\n * @param {*} param0\n */\n async _cardCreated({element}) {\n if (element.kanban_column == this.id) {\n let data = JSON.parse(JSON.stringify(element));\n Object.assign(data, exporter.exportCapabilities(this.reactive.state));\n let placeholder = document.createElement('li');\n placeholder.setAttribute('data-id', data.id);\n let node = this.getElement(selectors.COLUMNINNER, this.id);\n node.appendChild(placeholder);\n const newcomponent = await this.renderComponent(placeholder, 'mod_kanban/card', data);\n const newelement = newcomponent.getElement();\n node.replaceChild(newelement, placeholder);\n }\n }\n\n /**\n * Dispatch event to add a card in this column.\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, 0);\n }\n\n /**\n * Called when column is updated.\n * @param {*} param0\n */\n _columnUpdated({element}) {\n const el = this.getElement(selectors.COLUMNINNER, this.id);\n if (element.sequence !== undefined) {\n let sequence = element.sequence.split(',');\n // Remove all cards from frontend that are no longer present in the database.\n [...el.children]\n .forEach((node) => {\n if (node.classList.contains('mod_kanban_card') && !sequence.includes(node.dataset.id)) {\n el.removeChild(node);\n }\n });\n // Reorder cards according to sequence from the database.\n [...el.children]\n .sort((a, b) => sequence.indexOf(a.dataset.id) > sequence.indexOf(b.dataset.id) ? 1 : -1)\n .forEach(node => el.appendChild(node));\n }\n if (element.locked !== undefined) {\n this.toggleClass(element.locked != 0, 'mod_kanban_locked_column');\n // Inplace editing of the column title is disabled if the column is locked.\n if (element.locked != 0) {\n this.getElement(selectors.INPLACEEDITABLE).removeAttribute('data-inplaceeditable');\n } else {\n this.getElement(selectors.INPLACEEDITABLE).setAttribute('data-inplaceeditable', '1');\n }\n }\n // Update data for inplace editing if title was updated (this is important if title was modified by another user).\n if (element.title !== undefined) {\n let titlehelper = document.createElement('textarea');\n titlehelper.innerHTML = element.title;\n this.getElement(selectors.INPLACEEDITABLE).setAttribute('data-value', titlehelper.value);\n this.getElement(selectors.INPLACEEDITABLE).querySelector('a').innerHTML = element.title;\n }\n // Only autohide option is relevant for the frontend for now. autoclose option is handled by the backend.\n if (element.options !== undefined) {\n let options = JSON.parse(element.options);\n this.toggleClass(options.autohide, 'mod_kanban_autohide');\n }\n // Enable/disable dragging (e.g. if column is locked).\n this.checkDragging();\n }\n\n /**\n * Called when this column is deleted.\n */\n _columnDeleted() {\n this.destroy();\n }\n\n /**\n * Dispatch event to remove this column.\n * @param {*} event\n */\n _removeColumn(event) {\n let target = event.target.closest(selectors.DELETECOLUMN);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('deleteColumn', data.id);\n }\n\n /**\n * Dispatch event to lock this column.\n * @param {*} event\n */\n _lockColumn(event) {\n let target = event.target.closest(selectors.LOCKCOLUMN);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('lockColumn', data.id);\n }\n\n /**\n * Dispatch event to unlock this column.\n * @param {*} event\n */\n _unlockColumn(event) {\n let target = event.target.closest(selectors.UNLOCKCOLUMN);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('unlockColumn', data.id);\n }\n\n /**\n * Show modal form to edit column details.\n * @param {*} event\n */\n _editDetails(event) {\n event.preventDefault();\n\n const modalForm = new ModalForm({\n formClass: \"mod_kanban\\\\form\\\\edit_column_form\",\n args: {\n id: this.id,\n boardid: this.boardid,\n cmid: this.cmid\n },\n modalConfig: {title: getString('editcolumn', 'mod_kanban')},\n returnFocus: this.getElement(),\n });\n this.addEventListener(modalForm, modalForm.events.FORM_SUBMITTED, this._updateColumn);\n modalForm.show();\n }\n\n /**\n * Dispatch an event to update column data from the detail modal.\n * @param {*} event\n */\n _updateColumn(event) {\n this.reactive.dispatch('processUpdates', event.detail);\n }\n\n /**\n * Show hidden cards.\n */\n _showHidden() {\n this.getElement().classList.add('mod_kanban_show_hidden');\n }\n\n /**\n * Hide hidden cards.\n */\n _hideHidden() {\n this.getElement().classList.remove('mod_kanban_show_hidden');\n }\n}\n"],"names":["KanbanComponent","target","this","element","document","getElementById","create","id","dataset","getWatchers","watch","handler","_columnUpdated","_columnDeleted","_cardCreated","stateReady","state","addEventListener","getElement","selectors","DELETECOLUMN","_removeConfirm","ADDCARDFIRST","_addCard","ADDCOLUMN","_addColumn","LOCKCOLUMN","_lockColumn","UNLOCKCOLUMN","_unlockColumn","EDITDETAILS","_editDetails","SHOWHIDDEN","_showHidden","HIDEHIDDEN","_hideHidden","draggable","dragdrop","DragDrop","checkDragging","boardid","board","cmid","common","event","Str","get_strings","key","component","then","strings","_removeColumn","catch","error","Log","debug","destroy","undefined","unregister","getDraggableData","type","reactive","stateManager","capabilities","get","MANAGECOLUMNS","value","columns","locked","setDraggable","validateDropData","dropdata","drop","cards","getElements","CARD","aftercard","i","length","offsetTop","clientHeight","layerY","dispatch","showDropZone","ADDCARDCONTAINER","classList","add","ADDCOLUMNCONTAINER","hideDropZone","remove","forEach","e","activeElement","blur","closest","data","Object","assign","kanban_column","JSON","parse","stringify","exporter","exportCapabilities","placeholder","createElement","setAttribute","node","COLUMNINNER","appendChild","newelement","renderComponent","replaceChild","ADDCARD","columnid","el","sequence","split","children","contains","includes","removeChild","sort","a","b","indexOf","toggleClass","INPLACEEDITABLE","removeAttribute","title","titlehelper","innerHTML","querySelector","options","autohide","preventDefault","modalForm","ModalForm","formClass","args","modalConfig","returnFocus","events","FORM_SUBMITTED","_updateColumn","show","detail"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"column.min.js","sources":["../src/column.js"],"sourcesContent":["import {DragDrop} from 'core/reactive';\nimport selectors from 'mod_kanban/selectors';\nimport capabilities from 'mod_kanban/capabilities';\nimport exporter from 'mod_kanban/exporter';\nimport {saveCancel} from 'core/notification';\nimport * as Str from 'core/str';\nimport {get_string as getString} from 'core/str';\nimport ModalForm from 'core_form/modalform';\nimport KanbanComponent from 'mod_kanban/kanbancomponent';\nimport Log from \"core/log\";\n\n/**\n * Component representing a column in a kanban board.\n */\nexport default class extends KanbanComponent {\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}\n */\n getWatchers() {\n return [\n {watch: `columns[${this.id}]:updated`, handler: this._columnUpdated},\n {watch: `columns[${this.id}]:deleted`, handler: this._columnDeleted},\n {watch: `cards:created`, handler: this._cardCreated}\n ];\n }\n\n /**\n * Called once when state is ready, attaching event listeners and initializing drag and drop.\n * @param {object} state\n */\n stateReady(state) {\n this.addEventListener(\n this.getElement(selectors.DELETECOLUMN, this.id),\n 'click',\n this._removeConfirm\n );\n this.addEventListener(\n this.getElement(selectors.ADDCARDFIRST),\n 'click',\n this._addCard\n );\n this.addEventListener(\n this.getElement(selectors.ADDCOLUMN, this.id),\n 'click',\n this._addColumn\n );\n this.addEventListener(\n this.getElement(selectors.LOCKCOLUMN, this.id),\n 'click',\n this._lockColumn\n );\n this.addEventListener(\n this.getElement(selectors.UNLOCKCOLUMN, this.id),\n 'click',\n this._unlockColumn\n );\n this.addEventListener(\n this.getElement(selectors.EDITDETAILS, this.id),\n 'click',\n this._editDetails\n );\n this.addEventListener(\n this.getElement(selectors.SHOWHIDDEN),\n 'click',\n this._showHidden\n );\n this.addEventListener(\n this.getElement(selectors.HIDEHIDDEN),\n 'click',\n this._hideHidden\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 }\n\n /**\n * Display confirmation modal for deleting a card.\n * @param {*} event\n */\n _removeConfirm(event) {\n Str.get_strings([\n {key: 'deletecolumn', component: 'mod_kanban'},\n {key: 'deletecolumnconfirm', 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._removeColumn(event);\n }\n );\n }).catch((error) => Log.debug(error));\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 *\n * @returns {Object} the draggable data.\n */\n getDraggableData() {\n return {id: this.id, type: 'column'};\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\n if (state.capabilities.get(capabilities.MANAGECOLUMNS).value && state.columns.get(this.id).locked == 0) {\n this.dragdrop.setDraggable(true);\n } else {\n this.dragdrop.setDraggable(false);\n }\n }\n\n /**\n * Validate draggable data. This component accepts cards and columns.\n * @param {object} dropdata\n * @returns {boolean} if the data is valid for this drop-zone.\n */\n validateDropData(dropdata) {\n let type = dropdata?.type;\n return type == 'card' || type == 'column';\n }\n\n /**\n * Executed when a valid dropdata is dropped over the drop-zone.\n * @param {object} dropdata\n * @param {object} event\n */\n drop(dropdata, event) {\n if (dropdata.type == 'card') {\n let cards = this.getElements(selectors.CARD);\n let aftercard = 0;\n for (let i = 0; i < cards.length; i++) {\n if (cards[i].offsetTop + cards[i].clientHeight / 2 <= event.layerY) {\n aftercard = cards[i].dataset.id;\n }\n }\n this.reactive.dispatch('moveCard', dropdata.id, this.id, aftercard);\n }\n if (dropdata.type == 'column') {\n if (dropdata.id != this.id) {\n this.reactive.dispatch('moveColumn', dropdata.id, this.id);\n }\n }\n }\n\n /**\n * Show some visual hints to the user.\n * @param {object} dropdata\n * @param {object} event\n */\n showDropZone(dropdata, event) {\n if (dropdata.type == 'card') {\n let cards = this.getElements(selectors.CARD);\n let aftercard = 0;\n for (let i = 0; i < cards.length; i++) {\n if (cards[i].offsetTop + cards[i].clientHeight / 2 <= event.layerY) {\n aftercard = cards[i].dataset.id;\n }\n }\n if (aftercard == 0) {\n this.getElement(selectors.ADDCARDCONTAINER).classList.add('mod_kanban_insert');\n } else {\n this.getElement(selectors.ADDCARDCONTAINER, aftercard).classList.add('mod_kanban_insert');\n }\n }\n if (dropdata.type == 'column') {\n this.getElement(selectors.ADDCOLUMNCONTAINER).classList.add('mod_kanban_insert');\n }\n }\n\n /**\n * Remove visual hints to the user.\n */\n hideDropZone() {\n this.getElement(selectors.ADDCOLUMNCONTAINER).classList.remove('mod_kanban_insert');\n this.getElements(selectors.ADDCARDCONTAINER).forEach((e) => {\n e.classList.remove('mod_kanban_insert');\n });\n }\n\n /**\n * Dispatch event to add a column after this column.\n * @param {*} event\n */\n _addColumn(event) {\n document.activeElement.blur();\n let target = event.target.closest(selectors.ADDCOLUMN);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('addColumn', data.id);\n }\n\n /**\n * Called when a card was created in this column.\n * @param {*} param0\n */\n async _cardCreated({element}) {\n if (element.kanban_column == this.id) {\n let data = JSON.parse(JSON.stringify(element));\n Object.assign(data, exporter.exportCapabilities(this.reactive.state));\n let placeholder = document.createElement('li');\n placeholder.setAttribute('data-id', data.id);\n let node = this.getElement(selectors.COLUMNINNER, this.id);\n node.appendChild(placeholder);\n const newcomponent = await this.renderComponent(placeholder, 'mod_kanban/card', data);\n const newelement = newcomponent.getElement();\n node.replaceChild(newelement, placeholder);\n }\n }\n\n /**\n * Dispatch event to add a card in this column.\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, 0);\n }\n\n /**\n * Called when column is updated.\n * @param {*} param0\n */\n _columnUpdated({element}) {\n const el = this.getElement(selectors.COLUMNINNER, this.id);\n if (element.sequence !== undefined) {\n let sequence = element.sequence.split(',');\n // Remove all cards from frontend that are no longer present in the database.\n [...el.children]\n .forEach((node) => {\n if (node.classList.contains('mod_kanban_card') && !sequence.includes(node.dataset.id)) {\n el.removeChild(node);\n }\n });\n // Reorder cards according to sequence from the database.\n [...el.children]\n .sort((a, b) => sequence.indexOf(a.dataset.id) > sequence.indexOf(b.dataset.id) ? 1 : -1)\n .forEach(node => el.appendChild(node));\n }\n if (element.locked !== undefined) {\n this.toggleClass(element.locked != 0, 'mod_kanban_locked_column');\n // Inplace editing of the column title is disabled if the column is locked.\n if (element.locked != 0) {\n this.getElement(selectors.INPLACEEDITABLE).removeAttribute('data-inplaceeditable');\n } else {\n this.getElement(selectors.INPLACEEDITABLE).setAttribute('data-inplaceeditable', '1');\n }\n }\n // Update data for inplace editing if title was updated (this is important if title was modified by another user).\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 titlehelper = document.createElement('textarea');\n titlehelper.innerHTML = element.title;\n this.getElement(selectors.INPLACEEDITABLE).setAttribute('data-value', titlehelper.value);\n this.getElement(selectors.INPLACEEDITABLE).querySelector('a').innerHTML = element.title;\n }\n // Only autohide option is relevant for the frontend for now. autoclose option is handled by the backend.\n if (element.options !== undefined) {\n let options = JSON.parse(element.options);\n this.toggleClass(options.autohide, 'mod_kanban_autohide');\n }\n // Enable/disable dragging (e.g. if column is locked).\n this.checkDragging();\n }\n\n /**\n * Called when this column is deleted.\n */\n _columnDeleted() {\n this.destroy();\n }\n\n /**\n * Dispatch event to remove this column.\n * @param {*} event\n */\n _removeColumn(event) {\n let target = event.target.closest(selectors.DELETECOLUMN);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('deleteColumn', data.id);\n }\n\n /**\n * Dispatch event to lock this column.\n * @param {*} event\n */\n _lockColumn(event) {\n let target = event.target.closest(selectors.LOCKCOLUMN);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('lockColumn', data.id);\n }\n\n /**\n * Dispatch event to unlock this column.\n * @param {*} event\n */\n _unlockColumn(event) {\n let target = event.target.closest(selectors.UNLOCKCOLUMN);\n let data = Object.assign({}, target.dataset);\n this.reactive.dispatch('unlockColumn', data.id);\n }\n\n /**\n * Show modal form to edit column details.\n * @param {*} event\n */\n _editDetails(event) {\n event.preventDefault();\n\n const modalForm = new ModalForm({\n formClass: \"mod_kanban\\\\form\\\\edit_column_form\",\n args: {\n id: this.id,\n boardid: this.boardid,\n cmid: this.cmid\n },\n modalConfig: {title: getString('editcolumn', 'mod_kanban')},\n returnFocus: this.getElement(),\n });\n this.addEventListener(modalForm, modalForm.events.FORM_SUBMITTED, this._updateColumn);\n modalForm.show();\n }\n\n /**\n * Dispatch an event to update column data from the detail modal.\n * @param {*} event\n */\n _updateColumn(event) {\n this.reactive.dispatch('processUpdates', event.detail);\n }\n\n /**\n * Show hidden cards.\n */\n _showHidden() {\n this.getElement().classList.add('mod_kanban_show_hidden');\n }\n\n /**\n * Hide hidden cards.\n */\n _hideHidden() {\n this.getElement().classList.remove('mod_kanban_show_hidden');\n }\n}\n"],"names":["KanbanComponent","target","this","element","document","getElementById","create","id","dataset","getWatchers","watch","handler","_columnUpdated","_columnDeleted","_cardCreated","stateReady","state","addEventListener","getElement","selectors","DELETECOLUMN","_removeConfirm","ADDCARDFIRST","_addCard","ADDCOLUMN","_addColumn","LOCKCOLUMN","_lockColumn","UNLOCKCOLUMN","_unlockColumn","EDITDETAILS","_editDetails","SHOWHIDDEN","_showHidden","HIDEHIDDEN","_hideHidden","draggable","dragdrop","DragDrop","checkDragging","boardid","board","cmid","common","event","Str","get_strings","key","component","then","strings","_removeColumn","catch","error","Log","debug","destroy","undefined","unregister","getDraggableData","type","reactive","stateManager","capabilities","get","MANAGECOLUMNS","value","columns","locked","setDraggable","validateDropData","dropdata","drop","cards","getElements","CARD","aftercard","i","length","offsetTop","clientHeight","layerY","dispatch","showDropZone","ADDCARDCONTAINER","classList","add","ADDCOLUMNCONTAINER","hideDropZone","remove","forEach","e","activeElement","blur","closest","data","Object","assign","kanban_column","JSON","parse","stringify","exporter","exportCapabilities","placeholder","createElement","setAttribute","node","COLUMNINNER","appendChild","newelement","renderComponent","replaceChild","ADDCARD","columnid","el","sequence","split","children","contains","includes","removeChild","sort","a","b","indexOf","toggleClass","INPLACEEDITABLE","removeAttribute","title","titlehelper","innerHTML","querySelector","options","autohide","preventDefault","modalForm","ModalForm","formClass","args","modalConfig","returnFocus","events","FORM_SUBMITTED","_updateColumn","show","detail"],"mappings":"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"} \ No newline at end of file diff --git a/amd/src/card.js b/amd/src/card.js index 866dd269..a3584392 100644 --- a/amd/src/card.js +++ b/amd/src/card.js @@ -388,7 +388,12 @@ export default class extends KanbanComponent { } // Update title (also in modals). if (element.title !== undefined) { - this.getElement(selectors.INPLACEEDITABLE).setAttribute('data-value', element.title); + // For Moodle inplace editing title is once needed plain and once with html entities encoded. + // This avoids double encoding of html entities as the value of "data-value" is exactly what is shown + // in the input field when clicking on the inplace editable. + let titlehelper = document.createElement('textarea'); + titlehelper.innerHTML = element.title; + this.getElement(selectors.INPLACEEDITABLE).setAttribute('data-value', titlehelper.value); this.getElement(selectors.INPLACEEDITABLE).querySelector('a').innerHTML = element.title; this.getElement(selectors.DESCRIPTIONMODALTITLE).innerHTML = element.title; this.getElement(selectors.DISCUSSIONMODALTITLE).innerHTML = element.title; diff --git a/amd/src/column.js b/amd/src/column.js index 5a06eca2..3f4cbb7d 100644 --- a/amd/src/column.js +++ b/amd/src/column.js @@ -290,6 +290,9 @@ export default class extends KanbanComponent { } // Update data for inplace editing if title was updated (this is important if title was modified by another user). if (element.title !== undefined) { + // For Moodle inplace editing title is once needed plain and once with html entities encoded. + // This avoids double encoding of html entities as the value of "data-value" is exactly what is shown + // in the input field when clicking on the inplace editable. let titlehelper = document.createElement('textarea'); titlehelper.innerHTML = element.title; this.getElement(selectors.INPLACEEDITABLE).setAttribute('data-value', titlehelper.value);