/***********************************************************************************
 * The contents of this file are subject to the Extension License Agreement
 * ("Agreement") which can be viewed at
 * https://www.espocrm.com/extension-license-agreement/.
 * By copying, installing downloading, or using this file, You have unconditionally
 * agreed to the terms and conditions of the Agreement, and You may not use this
 * file except in compliance with the Agreement. Under the terms of the Agreement,
 * You shall not license, sublicense, sell, resell, rent, lease, lend, distribute,
 * redistribute, market, publish, commercialize, or otherwise transfer rights or
 * usage to the software or any modified version or derivative work of the software
 * created by or for you.
 *
 * Copyright (C) 2024-2025 Letrium Ltd.
 *
 * License ID: f27e70ce6801a13265271f5669c8bc5c
 ************************************************************************************/
define("modules/project/views/project/record/plan/group-task-count",["exports","view"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{templateContent="{{#if show}}{{count}}{{/if}}";constructor(e){super(e)}data(){return{show:this.collection.total>0,count:this.getHelper().numberUtil.formatInt(this.collection.total)}}setup(){this.listenTo(this.collection,"update update-total",(()=>this.reRender()))}}e.default=a})),define("modules/project/views/project/record/plan/total-task-count",["exports","view"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{templateContent='\n        {{#if show}}\n            <span class="total-count-span" title="{{translate \'Total\'}}">{{count}}</span>\n        {{/if}}\n    ';constructor(e){super(e),this.state=e.state}data(){return{show:this.state.totalTaskCount>0,count:this.state.totalTaskCount}}}e.default=a})),define("modules/project/views/project/record/plan/group-buttons",["exports","view","modules/project/views/project/record/plan/group-task-count"],(function(e,t,s){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=a(t),s=a(s);class i extends t.default{templateContent='\n        {{#if showTaskCount}}\n            <span class="text-muted" data-role="taskCount" title="{{translate \'Total\'}}">{{{taskCount}}}</span>\n        {{/if}}\n        {{#if hasCreateTask}}\n            <button\n                type="button"\n                class="btn btn-default btn-sm panel-action action"\n                data-action="createTaskInGroup"\n                title="{{translate \'Create ProjectTask\' scope=\'ProjectTask\'}}"\n            ><span class="fas fa-plus"></span></button>\n        {{/if}}\n        {{#if hasDropdown}}\n            <button\n                type="button"\n                class="btn btn-default btn-sm dropdown-toggle"\n                data-toggle="dropdown"\n            ><span class="fas fa-ellipsis-h"></span></button>\n            <ul class="dropdown-menu">\n                {{#if hasEditAccess}}\n                    <li>\n                        <a\n                            tabindex="0"\n                            role="button"\n                            data-action="editGroup"\n                        >{{translate \'Edit Group\' scope=\'ProjectGroup\'}}</a>\n                    </li>\n                    <li>\n                        <a\n                            tabindex="0"\n                            role="button"\n                            data-action="removeGroup"\n                        >{{translate \'Remove Group\' scope=\'ProjectGroup\'}}</a>\n                    </li>\n                    <li class="divider"></li>\n                {{/if}}\n                {{#if hasCreateTask}}\n                    <li>\n                        <a\n                            tabindex="0"\n                            role="button"\n                            data-action="createMilestoneInGroup"\n                        >{{translate \'Create Milestone\' scope=\'ProjectTask\'}}</a>\n                    </li>\n                {{/if}}\n                <li>\n                    <a\n                        tabindex="0"\n                        role="button"\n                        data-action="viewList"\n                    >{{translate \'View List\'}}</a>\n                </li>\n            </ul>\n        {{/if}}\n    ';constructor(e){super(e),this.state=e.state}data(){return{hasCreateTask:this.state.hasCreateTaskAccess,hasEditAccess:this.state.hasEditAccess,hasDropdown:!0,showTaskCount:!0}}setup(){this.taskCountView=new s.default({collection:this.collection}),this.assignView("taskCount",this.taskCountView,'[data-role="taskCount"]'),this.collection.parentModel&&void 0===this.collection.parentModel.attributes.memberRoleData&&this.listenToOnce(this.collection.parentModel,"sync",(async()=>{await this.whenRendered(),await this.reRender()}))}}e.default=i})),define("modules/project/views/project/record/group",["exports","view","views/record/list","views/modals/edit","views/modals/related-list","modules/project/views/project/record/plan/group-buttons"],(function(e,t,s,a,i,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=o(t),s=o(s),a=o(a),i=o(i),n=o(n);class r extends t.default{templateContent='\n        <div class="panel panel-default">\n            <div class="panel-heading">\n                <div class="pull-right btn-group panel-actions-container" data-role="groupButtons">{{{buttons}}}</div>\n                <div class="panel-actions-container-left">\n                    {{#if isCollapsed}}\n                        <button\n                            class="pull-left btn-text btn btn-sm"\n                            data-action="expandGroup"\n                            title="{{translate \'Expand\'}}"\n                            style="width: 30px;"\n                        ><span class="fas fa-chevron-right"></span></button>\n                    {{else}}\n                        <button\n                            class="pull-left btn-text btn btn-sm"\n                            data-action="collapseGroup"\n                            title="{{translate \'Collapse\'}}"\n                            style="width: 30px;"\n                        ><span class="fas fa-chevron-down"></span></button>\n                    {{/if}}\n                </div>\n                <h4 class="panel-title">\n                    <span\n                        class="action"\n                        title="{{translate \'clickToRefresh\' category=\'messages\'}}"\n                        style="cursor: pointer;"\n                        data-action="refreshGroup"\n                    >\n                        {{~#if color}}\n                            <span\n                                class="color-icon fas fa-square" style="color: {{color}}"\n                            ></span><span class="user-select: none">&nbsp;</span>\n                        {{~/if}}\n                        {{~name~}}\n                    </span>\n                </h4>\n            </div>\n            <div class="panel-body">\n                <div class="list-container{{#if toHideList}} hidden{{/if}}">{{{list}}}</div>\n            </div>\n        </div>\n    ';constructor(e){super(e),this.isCollapsed=e.isCollapsed,this.listLayout=e.state.taskListLayout,this.onTaskCreate=e.onTaskCreate,this.onMilestoneCreate=e.onMilestoneCreate,this.afterGroupRemove=e.afterGroupRemove,this.onToggleCollapse=e.onToggleCollapse,this.onCheck=e.onCheck,this.listSettingsHelper=e.listSettingsHelper,this.state=e.state,this.isLoading=!1}data(){let e=this.getColor();return{hasCreateTask:this.state.hasCreateTaskAccess,hasEditAccess:this.state.hasEditAccess,hasDropdown:!0,name:this.model.attributes.name,isCollapsed:this.isCollapsed,toHideList:this.isCollapsed||this.isLoading,color:e,showTaskCount:!0}}setup(){this.setupListView(),this.setupButtonsView(),this.addActionHandler("refreshGroup",(()=>this.actionRefresh())),this.addActionHandler("createTaskInGroup",(()=>this.onTaskCreate())),this.addActionHandler("createMilestoneInGroup",(()=>this.onMilestoneCreate())),this.addActionHandler("editGroup",(()=>this.actionEditGroup())),this.addActionHandler("removeGroup",(()=>this.actionRemoveGroup())),this.addActionHandler("collapseGroup",(()=>this.actionToggleCollapse(!0))),this.addActionHandler("expandGroup",(()=>this.actionToggleCollapse(!1))),this.addActionHandler("viewList",(()=>this.actionViewList()))}setupButtonsView(){this.buttonsView=new n.default({state:this.state,collection:this.collection}),this.assignView("buttons",this.buttonsView,'[data-role="groupButtons"]')}setupListView(){this.listView=new s.default({collection:this.collection,listLayout:this.listLayout,additionalRowActionList:["complete","changeColumn","selfAssign","moveToTop","moveToBottom"],forceStickyBar:!0,settingsEnabled:!0,settingsHelper:this.listSettingsHelper,keepCurrentRootUrl:!0}),this.assignView("list",this.listView,".list-container");let e=!1;this.listenTo(this.listView,"after:render",(()=>{e&&this.onCheck(this.listView.getCheckedIds()),e=!0})),this.listenTo(this.listView,"check",(()=>this.onCheck(this.listView.getCheckedIds())))}getColor(){let e=null;if(null!=this.model.attributes.color){e=(this.getHelper().themeManager.getParam("chartColorList")||[])[this.model.attributes.color]}return e}async actionRefresh(){Espo.Ui.notify(" ... "),await this.collection.fetch(),Espo.Ui.notify(!1)}async actionEditGroup(){const e=new a.default({entityType:"ProjectGroup",id:this.model.id,fullFormDisabled:!0});Espo.Ui.notify(" ... "),await this.assignView("dialog",e),e.getRecordView().hideField("project"),this.listenTo(e,"after:save",(e=>{this.afterSaveGroup(e)})),await e.render(),Espo.Ui.notify(!1)}async afterSaveGroup(e){this.model.setMultiple(e.attributes);const t=this.getView("dialog");this.unchainView("dialog"),await this.reRender(),this.setView("dialog",t),this.collection&&this.collection.parentModel&&this.collection.parentModel.attributes.activeGroupId===e.id&&this.collection.parentModel.set("activeGroupName",e.attributes.name)}async actionRemoveGroup(){await this.confirm(this.translate("confirmation","messages")),Espo.Ui.notify(" ... "),await Espo.Ajax.deleteRequest(`ProjectGroup/${this.model.id}`),Espo.Ui.notify(!1),this.afterGroupRemove()}async actionToggleCollapse(e){if(this.isCollapsed=e,this.onToggleCollapse(e),e)return this.listView.uncheckAll(),this.collection.reset(),void await this.reRender();this.isLoading=!0,await this.reRender(),Espo.Ui.notify(" ... "),await this.collection.fetch({noRebuild:!0}),Espo.Ui.notify(!1),this.isLoading=!1,await this.reRender(),this.listView.buildRows((()=>this.listView.reRender()))}async actionViewList(){const e=new i.default({url:this.collection.url,entityType:"ProjectTask",defaultOrderBy:"order",defaultOrder:"asc",filter:"planParent",layoutName:"listSmallForProject",createDisabled:!0,selectDisabled:!0,massUnlinkDisabled:!0,title:this.model.attributes.name,defs:{rowActionList:["complete","changeColumn"]},filterList:["all","planParent",{name:"completedParent",style:"success"}],noDefaultFilters:!0});await this.assignView("dialog",e),e.collection.parentModel=this.collection.parentModel,await e.render()}}e.default=r})),define("modules/project/views/project/record/plan/buttons",["exports","view","modules/project/views/project/record/plan/total-task-count","views/record/list/settings"],(function(e,t,s,a){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=i(t),s=i(s),a=i(a);class n extends t.default{templateContent='\n        <div class="pull-right">\n            <div class="btn-group pull-right">\n                <button class="btn btn-text dropdown-toggle" data-toggle="dropdown">\n                    <span class="fas fa-ellipsis-h fa-sm" style="font-size: 100%"></span>\n                </button>\n                <ul class="dropdown-menu pull-left">\n                    <li>\n                        <a role="button" data-action="toggleShowCompleted">\n                            {{#if showCompleted}}<span class="fas fa-check check-icon pull-right"></span>{{/if}}\n                            <div>{{translate \'Show Completed\' scope=\'Project\'}}</div>\n                        </a>\n                    </li>\n                </ul>\n            </div>\n        </div>\n        <div\n            class="settings-container pull-right margin-left-sm"\n            style="margin-right: var(--1px);"\n        >{{{settings}}}</div>\n        <div\n            class="text-muted total-count pull-right margin-right"\n            data-role="totalTaskCount"\n        >{{{totalTaskCount}}}</div>\n        <div class="btn-group">\n            {{#if hasCreateTask}}\n                <button\n                    class="btn btn-default"\n                    data-action="createTask"\n                >\n                    <span class="fas fa-plus fa-sm"></span>\n                    <span>{{translate \'Create ProjectTask\' scope=\'ProjectTask\'}}</span>\n                </button>\n            {{/if}}\n            {{#if hasDropdown}}\n                <button\n                    class="btn btn-default dropdown-toggle"\n                    data-toggle="dropdown"\n                ><span class="fas fa-ellipsis-h"></span></button>\n                <ul class="dropdown-menu pull-left">\n                    {{#if hasCreateTask}}\n                        <li>\n                            <a\n                                role="button"\n                                tabindex="0"\n                                data-action="createMilestone"\n                            >{{translate \'Create Milestone\' scope=\'ProjectTask\'}}</a>\n                        </li>\n                    {{/if}}\n                    {{#if hasEditAccess}}\n                        <li class="divider"></li>\n                        <li>\n                            <a\n                                role="button"\n                                tabindex="0"\n                                data-action="createGroup"\n                            >{{translate \'Create ProjectGroup\' scope=\'ProjectGroup\'}}</a>\n                        </li>\n                        <li>\n                            <a\n                                role="button"\n                                tabindex="0"\n                                data-action="reorderGroups"\n                            >{{translate \'Reorder Groups\' scope=\'ProjectGroup\'}}</a>\n                        </li>\n                    {{/if}}\n                </ul>\n            {{/if}}\n        </div>\n    ';constructor(e){super(e),this.state=e.state,this.onSettingsChange=e.onSettingsChange,this.listSettingsHelper=e.listSettingsHelper}data(){return{hasDropdown:this.state.hasCreateTaskAccess||this.state.hasEditAccess,hasCreateTask:this.state.hasCreateTaskAccess,hasEditAccess:this.state.hasEditAccess,showCompleted:this.state.showCompleted}}setup(){this.setupCountView(),this.setupSettingsView()}setupCountView(){const e=new s.default({state:this.state});this.assignView("totalTaskCount",e,'[data-role="totalTaskCount"]')}setupSettingsView(){const e=new a.default({layoutProvider:()=>this.state.taskListLayout,helper:this.listSettingsHelper,entityType:"ProjectTask",onChange:e=>{this.reRender(),this.onSettingsChange(e)},columnResize:!0});this.assignView("settings",e,".settings-container")}}e.default=n})),define("modules/project/views/project/modals/reorder-groups",["exports","views/modal","views/record/edit-for-modal","model","views/fields/array"],(function(e,t,s,a,i){"use strict";function n(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=n(t),s=n(s),a=n(a),i=n(i);class o extends t.default{templateContent='\n        <div class="record no-side-margin">{{{record}}}</div>\n    ';constructor(e){super(e),this.groups=e.groups,this.onOrderApply=e.onOrderApply}setup(){this.headerText=this.translate("Reorder Groups","labels","ProjectGroup"),this.buttonList.push({name:"apply",label:"Apply",style:"danger",onClick:()=>this.actionApply()}),this.buttonList.push({name:"cancel",label:"Cancel",onClick:()=>this.actionClose()}),this.model=new a.default({ids:this.groups.map((e=>e.id))});const e=this.groups.reduce(((e,t)=>({...e,[t.id]:t.attributes.name})),{});this.recordView=new s.default({model:this.model,detailLayout:[{rows:[[{view:new i.default({name:"ids",params:{options:this.model.attributes.ids,keepItems:!0,translatedOptions:e},labelText:this.translate("groups","links","Project")})}]]}]}),this.assignView("record",this.recordView,".record")}actionApply(){this.recordView.validate()||(this.onOrderApply(this.model.attributes.ids),this.close())}}e.default=o})),define("modules/project/views/project-task/modals/select-column",["exports","views/modal"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{templateContent='\n        <div class="list-group list-group-panel no-side-margin">\n            {{#each dataList}}\n                <li class="list-group-item">\n                    <a role="button" data-action="selectColumn" data-id="{{id}}">{{name}}</a>\n                </li>\n            {{/each}}\n        </div>\n    ';backdrop=!0;constructor(e){super(e),this.columns=e.columns,this.onSelectColumn=e.onSelect}data(){return{dataList:this.columns}}setup(){this.headerText=this.translate("changeColumn","actions","ProjectTask")+" · "+this.model.attributes.name,this.addActionHandler("selectColumn",((e,t)=>{this.onSelectColumn(t.dataset.id),this.close()}))}}e.default=a})),define("modules/project/views/project-task/fields/assigned-user",["exports","views/fields/user-with-avatar"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{getOnEmptyAutocomplete(){if(!this.params.autocompleteOnEmpty&&(null!==this.model.attributes.memberRoleData||this.model.isNew())&&(!this.recordHelper||!1!==this.recordHelper.getFieldStateParam("memberRoleData","isMember")))return Promise.resolve([{id:this.getUser().id,name:this.getUser().attributes.name}])}}e.default=a})),define("modules/project/views/project/record/plan",["exports","view","helpers/list/select-provider","views/modals/edit","modules/project/views/project/record/group","modules/project/views/project/record/plan/buttons","view-record-helper","modules/project/views/project/modals/reorder-groups","helpers/list/settings","draggable-project"],(function(e,t,s,a,i,n,o,r,l,d){"use strict";function c(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=c(t),s=c(s),a=c(a),i=c(i),n=c(n),o=c(o),r=c(r),l=c(l);class u extends t.default{templateContent='\n        <div class="button-container list-buttons-container clearfix" data-role="buttons" tabindex="-1">{{{buttons}}}</div>\n        {{#each ids}}\n            <div\n                data-id="{{this}}"\n                data-role="group"\n                style="user-select: none;"\n            >{{{var this ../this}}}</div>\n        {{/each}}\n    ';primaryFilter;layoutName="listForProject";items;taskCollection;groupModel;taskSelect;maxSize;draggable;showCompletedStorageKey;blockDraggable=!1;constructor(e){super(e),this.state={taskListLayout:void 0,totalTaskCount:void 0,hasCreateTaskAccess:void 0,hasEditAccess:void 0,taskAssign:void 0,taskAssignPermission:void 0,showCompleted:void 0}}data(){return{ids:this.items.map((e=>e.group.id))}}setup(){this.maxSize=this.getConfig().get("recordsPerPage"),this.controlAccess(),this.getHelper().isXsScreen()&&(this.layoutName="listSmallForProject"),this.setupFilter(),this.setPrimaryFilter(),this.setupListSettingsHelper(),this.setupButtonsView(),this.wait(this.loadGroups()),this.addActionHandler("createGroup",(()=>this.actionCreateGroup())),this.addActionHandler("createTask",(()=>this.actionCreateTask())),this.addActionHandler("createMilestone",(()=>this.actionCreateMilestone())),this.addActionHandler("reorderGroups",(()=>this.actionReorderGroups())),this.addActionHandler("toggleShowCompleted",(()=>this.toggleShowCompleted())),this.addHandler("keydown.project","",(e=>this.onKeyDown(e)))}setupFilter(){this.showCompletedStorageKey=`projectPlanShowCompleted-${this.model.id}`,this.state.showCompleted=!0,this.getStorage().has("state",this.showCompletedStorageKey)&&(this.state.showCompleted=this.getStorage().get("state",this.showCompletedStorageKey))}setPrimaryFilter(){this.primaryFilter=this.state.showCompleted?"planOrCompletedParent":"planParent"}controlAccess(){if(this.state.hasCreateTaskAccess=!1,this.state.hasEditAccess=!1,this.state.taskAssignmentPermission="own",this.getAcl().checkModel(this.model,"edit"))return this.state.hasCreateTaskAccess=!0,this.state.hasEditAccess=!0,void(this.state.taskAssignmentPermission="all");if(void 0===this.model.attributes.memberRoleData)return void this.listenToOnce(this.model,"sync",(async()=>{this.controlAccess(),await this.buttonsView.whenReady(),await this.buttonsView.reRender()}));const e=this.model.attributes.memberRoleData;if(e){if("Owner"===e.role||"Editor"===e.role)return this.state.hasCreateTaskAccess=!0,this.state.hasEditAccess=!0,void(this.state.taskAssignmentPermission="all");this.state.taskAssignmentPermission=e.permissions.taskAssignment,"yes"===e.permissions.taskCreate&&(this.state.hasCreateTaskAccess=!0)}}setupListSettingsHelper(){this.listSettingsHelper=new l.default("ProjectTask",this.layoutName+this.model.id,this.getUser().id,this.getStorage());const e=()=>{this.items.forEach((e=>{this.getGroupView(e.group.id).listView.reRender()}))};this.listSettingsHelper.subscribeToColumnWidthChange&&(this.listSettingsHelper.subscribeToColumnWidthChange(e),this.on("remove",(()=>this.listSettingsHelper.unsubscribeFromColumnWidthChange(e))))}setupButtonsView(){this.buttonsView=new n.default({state:this.state,listSettingsHelper:this.listSettingsHelper,onSettingsChange:async e=>{if(e&&"toggleColumn"===e.action&&!this.listSettingsHelper.getHiddenColumnMap()[e.column]){new(await Espo.loader.requirePromise("helpers/record/list/column-width-control"))({helper:this.listSettingsHelper,layoutProvider:()=>this.state.taskListLayout}).adjust({tableWidth:this.getGroupView(this.items[0].group.id).element.clientWidth,staticWidth:100})}this.items.filter((e=>!e.isCollapsed)).forEach((e=>{const t=this.getGroupView(e.group.id).listView;t.rebuild().then((()=>t.reRender()))}))}}),this.assignView("buttons",this.buttonsView,'[data-role="buttons"]')}async loadGroups(e=!1){this.items=[],this.taskSelect=await this.loadTaskSelect(),this.state.taskListLayout=await this.loadTaskListLayout(),this.taskCollection=await this.getCollectionFactory().create("ProjectTask"),this.groupModel=await this.getModelFactory().create("ProjectGroup");const t=await Espo.Ajax.getRequest(`Project/${this.model.id}/plan`,{maxSize:this.maxSize,select:this.taskSelect.join(","),primaryFilter:this.primaryFilter,collapsedGroupIds:this.getCollapsedGroupIds().join(",")}),s=[];t.groups.forEach((e=>{const t={group:this.prepareGroupModel(e.group),tasks:e.tasks.list?this.prepareTasksCollection(e.group.id,e.tasks.list,e.tasks.total):this.prepareTasksCollection(e.group.id,[],e.tasks.total),isCollapsed:this.isGroupCollapsed(e.group.id)};this.items.push(t);const a=this.createGroupView(t);s.push(a)})),this.controlTotalTaskCount(),e&&await Promise.all(s)}async loadTaskSelect(){const e=new s.default(this.getHelper().layoutManager,this.getHelper().metadata,this.getHelper().fieldManager);return[...await e.get("ProjectTask",this.layoutName),"boardId"]}prepareGroupModel(e){const t=this.groupModel.clone();return t.set(e),t.url=`ProjectGroup/${e.id}`,t}prepareTasksCollection(e,t,s=0){const a=this.taskCollection.clone();return t.forEach((e=>a.add(e))),a.url=`ProjectGroup/${e}/tasks`,a.parentModel=this.model,a.maxSize=this.maxSize,a.total=s,a.data.select=this.taskSelect.join(","),a.data.primaryFilter=this.primaryFilter,a.orderBy="order",a.order="asc",a.defaultOrderBy=a.orderBy,a.defaultOrder=a.order,this.listenTo(a,"update update-total",(()=>this.controlTotalTaskCount())),this.listenTo(a,"change:groupId",((t,s,a)=>{a.sync&&t.attributes.groupId!==e&&this.afterMoveBetweenGroups(e,t.attributes.groupId)})),this.listenTo(a,"change:status",(e=>{this.onTaskStatusChange(e)})),this.listenTo(this.model,"update-all",(()=>a.fetch())),a}onTaskStatusChange(e){this.items.forEach((t=>{t.tasks.forEach((t=>{const s=Espo.Utils.cloneDeep(t.attributes.fromTasksColumns);s&&s[e.id]&&(s[e.id].status=e.attributes.status,t.set("fromTasksColumns",s))}))}))}createGroupView(e){const t=new i.default({model:e.group,collection:e.tasks,isCollapsed:e.isCollapsed,state:this.state,onTaskCreate:()=>this.createTask(e.group.id),onMilestoneCreate:()=>this.createTask(e.group.id,!0),afterGroupRemove:()=>this.removeGroup(e.group.id),onToggleCollapse:t=>this.setGroupCollapse(e.group.id,t),onCheck:t=>this.controlCheck(e,t.length>0),listSettingsHelper:this.listSettingsHelper});return this.assignView(e.group.id,t,`[data-id="${e.group.id}"][data-role="group"]`)}getGroupView(e){return this.getView(e)}controlCheck(e,t){this.items.filter((t=>t.group.id!==e.group.id)).forEach((e=>{const s=this.getGroupView(e.group.id).listView;t?s.disableCheckboxes():s.enableCheckboxes()}))}getCheckedTasks(){const e=[];return this.items.forEach((t=>{const s=this.getGroupView(t.group.id).listView;s.getCheckedIds().forEach((t=>{e.push(s.collection.get(t))}))})),e}checkTasks(e){this.items.filter((e=>!e.isCollapsed)).forEach((t=>{const s=this.getGroupView(t.group.id).listView;s.checkboxesAreDisabled&&s.checkboxesAreDisabled()||e.forEach((e=>s.checkRecord(e)))}))}removeGroup(e){const t=this.items.findIndex((t=>t.group.id===e));-1!==t&&(this.items.splice(t,1),this.clearView(e))}async actionCreateGroup(){const e=new a.default({entityType:"ProjectGroup",attributes:{projectId:this.model.attributes.id,projectName:this.model.attributes.name},fullFormDisabled:!0});Espo.Ui.notify(" ... "),await this.assignView("dialog",e),e.getRecordView().hideField("project",!0),this.listenTo(e,"after:save",((e,t)=>{this.afterSaveGroup(e,t.bypassClose)})),await e.render(),Espo.Ui.notify(!1)}getItem(e){return this.items.find((t=>t.group.id===e))}getItems(){return this.items}async afterSaveGroup(e,t){if(this.getItem(e.id)){const t=this.getItem(e.id);return void(t&&(t.group.setMultiple(e.attributes),await this.getView(e.id).reRender()))}const s={group:this.prepareGroupModel(e.attributes),tasks:this.prepareTasksCollection(e.id,[]),isCollapsed:!1};if(this.items.push(s),await this.createGroupView(s),t){const e=this.getView("dialog");return this.unchainView("dialog"),await this.reRender(),void this.setView("dialog",e)}await this.reRender()}actionCreateTask(){this.createTask(this.model.attributes.activeGroupId)}async createTask(e,t=!1){let s=null;const i=this.getItem(e);i&&(s=i.group.attributes.name);const n=new o.default;n.setFieldStateParam("column","options",this.model.attributes.columns),this.state.hasEditAccess||"own"!==this.state.taskAssignmentPermission||(n.setFieldStateParam("owner","readOnly",!0),n.setFieldStateParam("owner","readOnlyLocked",!0)),n.setFieldStateParam("memberRoleData","isMember",!!this.model.attributes.memberRoleData);const r=new a.default({entityType:"ProjectTask",attributes:{assignedUserId:null,assignedUserName:null,projectId:this.model.attributes.id,projectName:this.model.attributes.name,groupId:e,groupName:s,columnId:this.model.attributes.firstColumnId,columnName:this.model.attributes.firstColumnName,memberRoleData:this.state.hasEditAccess?{role:"Owner",permissions:{}}:this.model.attributes.memberRoleData,type:t?"Milestone":"Task"},recordHelper:n,headerText:t?this.translate("Create Milestone","labels","ProjectTask"):void 0,focusForCreate:!0});await this.assignView("dialog",r),r.getRecordView().hideField("project",!0),r.getRecordView().hideField("owner",!0),await r.render(),this.listenTo(r,"after:save",(e=>{this.afterSaveTask(e)}))}afterSaveTask(e){const t=e.attributes.groupId,s=this.getItem(t);s&&(s.tasks.get(e.id)?s.tasks.get(e.id).fetch():s.tasks.fetch())}actionCreateMilestone(){this.createTask(this.model.attributes.activeGroupId,!0)}async loadTaskListLayout(){return(await new Promise((e=>{this.getHelper().layoutManager.get("ProjectTask",this.layoutName,e)}))).map((e=>({...e,notSortable:!0}))).map((e=>("assignedUser"===e.name&&(e.view="modules/project/views/project-task/fields/assigned-user-short"),e)))}async actionReorderGroups(){const e=new r.default({groups:this.items.map((e=>e.group)),onOrderApply:e=>{this.reorderGroups(e)}});Espo.Ui.notify(" ... "),await this.assignView("dialog",e),await e.render(),Espo.Ui.notify(!1)}async reorderGroups(e){const t=this.items.map((e=>e.group.id)),s=(e,t,s)=>e.findIndex((e=>e===t.group.id))-e.findIndex((e=>e===s.group.id));this.items=this.items.sort(((t,a)=>s(e,t,a))),Espo.Ui.notify(" ... "),await this.reRender();try{await Espo.Ajax.postRequest(`Project/${this.model.id}/reorderGroups`,{ids:e}),Espo.Ui.success(this.translate("Done"))}catch(e){this.items=this.items.sort(((e,a)=>s(t,e,a))),await this.reRender()}}isGroupCollapsed(e){return this.getCollapsedGroupIds().includes(e)}async setGroupCollapse(e,t){const s=this.getItem(e);s.isCollapsed=t,t&&this.controlCheck(s,!1);const a=this.items.filter((e=>e.isCollapsed)).map((e=>e.group.id));this.getStorage().set("state",`projectCollapsedGroups-${this.model.id}`,a),this.initDraggable()}getCollapsedGroupIds(){const e=this.getStorage().get("state",`projectCollapsedGroups-${this.model.id}`)||[];return Array.isArray(e)?e:[]}controlTotalTaskCount(){this.state.totalTaskCount=this.items.reduce(((e,t)=>e+t.tasks.total),0),this.buttonsView.isRendered()&&this.buttonsView.reRender()}async afterMoveBetweenGroups(e,t){const s=this.getItem(e),a=this.getItem(t);await Promise.all([s?s.tasks.fetch():Promise.resolve(),a?a.tasks.fetch():Promise.resolve()])}afterRender(){this.initDraggable(),this.element.querySelector(".button-container").focus({preventScroll:!0})}async moveToGroup(e,t,s){Espo.Ui.notify(" ... ");const a=this.getItem(s).tasks;e.forEach((e=>{a.remove(e),a.total>0&&a.total--}));const i=this.getGroupView(s).listView;i.rebuild().then((()=>i.reRender()));try{await Espo.Ajax.postRequest(`ProjectGroup/${t}/tasks`,{ids:e})}catch(e){await Promise.all([this.getItem(t).tasks.fetch(),this.getItem(s).tasks.fetch()])}await Promise.all([this.getItem(t).tasks.fetch(),this.getItem(s).tasks.fetch()]),Espo.Ui.success(this.translate("Moved to Group","labels","ProjectTask"))}async placeTasks(e,t,s,a){const i=[],n=this.getItem(a);for(const a of n.tasks.models){if(a.id===t){s&&i.push(a);break}e.includes(a.id)||i.push(a)}e.forEach((e=>{i.push(n.tasks.get(e))})),n.tasks.forEach((e=>{i.find((t=>t.id===e.id))||i.push(e)})),n.tasks.remove(i),n.tasks.add(i);const o=this.getGroupView(a).listView;o.rebuild().then((()=>o.reRender())),Espo.Ui.notify(" ... ");try{await Espo.Ajax.postRequest(`ProjectGroup/${a}/taskReOrder`,{ids:e,targetId:t,isAfter:s})}catch(e){return void await this.getItem(a).tasks.fetch()}await this.getItem(a).tasks.fetch(),Espo.Ui.success(this.translate("Moved","labels","ProjectTask"))}initDraggable(){const e=this.items.filter((e=>!e.isCollapsed)).map((e=>this.getGroupView(e.group.id))).map((e=>e.element)).filter((e=>e));this.draggable&&this.draggable.destroy();const t=d.Draggable.Sensors.TouchSensor,s=new d.Draggable(e,{distance:8,draggable:"tr.list-row",mirror:{cursorOffsetX:5,cursorOffsetY:5,appendTo:"body"},exclude:{sensors:[t]}});this.draggable=s;const a=[],i=[];let n=null,o=null,r=null,l=null,c=!1,u=[];s.on("mirror:created",(e=>{const t=e.mirror,s=e.source,a=e.originalSource;a.dataset.wasActive=a.classList.contains("active")?"true":"",a.classList.add("active"),a.style.display="",s.style.display="none",t.innerText=this.translate("Moving","labels","ProjectTask"),u.length>1&&(t.innerText+=" · "+u.length.toString()),t.style.display="block",t.style.cursor="grabbing",t.classList.add("draggable-helper"),t.style.pointerEvents="auto"})),s.on("mirror:move",(e=>{e.mirror.style.pointerEvents="auto"})),s.on("drag:start",(e=>{if(this.state.hasEditAccess&&!this.blockDraggable){n=e.sourceContainer.dataset.id,r=e.source.dataset.id,u=[r],this.getGroupView(n).listView.getCheckedIds().includes(r)&&(u=this.getGroupView(n).listView.getCheckedIds().sort(((e,t)=>{const s=this.getItem(n).tasks;return s.models.findIndex((t=>t.id===e))-s.models.findIndex((e=>e.id===t))}))),e.sourceContainer.querySelectorAll("tr.list-row").forEach((t=>{t!==e.source&&a.push({id:t instanceof HTMLElement?t.dataset.id:void 0,element:t})}));for(const e of this.items){const t=this.getGroupView(e.group.id).element;i.push({id:e.group.id,element:t,panelElement:t.querySelector(".panel")})}}else e.cancel()})),s.on("drag:move",(e=>{o=null,c=!1,l=null;for(const t of i){const s=t.element.getBoundingClientRect();s.left<e.sensorEvent.clientX&&s.right>e.sensorEvent.clientX&&s.top<e.sensorEvent.clientY&&s.bottom>e.sensorEvent.clientY?(o=t.id,o!==n&&t.panelElement.classList.add("highlighted")):t.panelElement.classList.remove("highlighted")}for(const t of a){const s=t.element.getBoundingClientRect();r!==t.id&&s.left<e.sensorEvent.clientX&&s.right>e.sensorEvent.clientX&&s.top<e.sensorEvent.clientY&&s.bottom>e.sensorEvent.clientY?(l=t.id,e.sensorEvent.clientY-s.top<s.bottom-e.sensorEvent.clientY?(t.element.classList.add("border-top-highlighted"),t.element.classList.remove("border-bottom-highlighted")):(t.element.classList.add("border-bottom-highlighted"),t.element.classList.remove("border-top-highlighted"),c=!0)):(t.element.classList.remove("border-top-highlighted"),t.element.classList.remove("border-bottom-highlighted"))}})),s.on("drag:stop",(e=>{a.forEach((e=>{e.element.classList.remove("border-bottom-highlighted"),e.element.classList.remove("border-top-highlighted")})),a.splice(0,a.length),i.forEach((e=>e.panelElement.classList.remove("highlighted"))),i.splice(0,i.length);const t=e.originalSource;"true"!==t.dataset.wasActive&&t.classList.remove("active"),o&&(n===o?l&&(this.blockDraggable=!0,this.placeTasks(u,l,c,n).then((()=>this.blockDraggable=!1))):(this.blockDraggable=!0,this.moveToGroup(u,o,n).then((()=>this.blockDraggable=!1)))),o=null,r=null,n=null,l=null,c=!1,u=[]}))}onKeyDown(e){"Control+Space"===Espo.Utils.getKeyFromKeyEvent(e)&&(e.stopPropagation(),e.preventDefault(),this.actionCreateTask())}async toggleShowCompleted(){this.state.showCompleted=!this.state.showCompleted,this.getStorage().set("state",this.showCompletedStorageKey,this.state.showCompleted),this.setPrimaryFilter(),Espo.Ui.notify(" ... "),await this.loadGroups(!0),await this.reRender(),Espo.Ui.notify(!1)}}e.default=u})),define("modules/project/views/project/record/gantt/buttons",["exports","view"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{templateContent='\n        <div class="btn-group pull-left">\n            {{#if hasCreateTask}}\n                <button\n                    class="btn btn-default"\n                    data-action="createTask"\n                >\n                    <span class="fas fa-plus fa-sm{{#if oneSelected}} text-warning{{/if}}"></span>\n                    <span>{{translate \'Create ProjectTask\' scope=\'ProjectTask\'}}</span>\n                </button>\n            {{/if}}\n            {{#if hasDropdown}}\n                <button\n                    class="btn btn-default dropdown-toggle margin-right"\n                    data-toggle="dropdown"\n                ><span class="fas fa-ellipsis-h"></span></button>\n                <ul class="dropdown-menu pull-left">\n                    {{#if hasCreateTask}}\n                        <li>\n                            <a\n                                role="button"\n                                tabindex="0"\n                                data-action="createMilestone"\n                            >{{translate \'Create Milestone\' scope=\'ProjectTask\'}}</a>\n                        </li>\n                    {{/if}}\n                </ul>\n            {{/if}}\n        </div>\n        {{#ifEqual selectionAction \'link\'}}\n            <div class="btn-group pull-left">\n                <button\n                    class="btn btn-default"\n                    data-action="addDependency"\n                >\n                    <span class="fas fa-plus fa-sm"></span>\n                    <span>{{translate \'Add Dependency\' scope=\'ProjectTask\'}}</span>\n                </button>\n            </div>\n        {{/ifEqual}}\n        {{#ifEqual selectionAction \'unlink\'}}\n            <div class="btn-group pull-left">\n                <button\n                    class="btn btn-default"\n                    data-action="removeDependency"\n                >\n                    <span class="fas fa-minus fa-sm"></span>\n                    <span>{{translate \'Remove Dependency\' scope=\'ProjectTask\'}}</span>\n                </button>\n                <button\n                    class="btn btn-default dropdown-toggle"\n                    data-toggle="dropdown"\n                ><span class="fas fa-ellipsis-h"></span></button>\n                <ul class="dropdown-menu">\n                    <li class="dropdown-header"\n                    >{{translate \'dependencyTaskType\' category=\'fields\' scope=\'ProjectTask\'}}</li>\n                    {{#each dependencyTypeDataList}}\n                        <li>\n                            <a\n                                role="button"\n                                data-name="{{type}}"\n                                data-action="setDependencyType"\n                            >\n                                {{#if selected}}\n                                    <span class="fas fa-check check-icon pull-right"></span>\n                                {{/if}}\n                                <div>{{label}}</div>\n                            </a>\n                        </li>\n                    {{/each}}\n                </ul>\n            </div>\n        {{/ifEqual}}\n        {{#if rangeData}}\n            <div\n                data-role="range-data-text"\n                class="pull-left hidden-xs pull-left input-text-block text-soft nowrap"\n            >\n                <span data-object="from">{{rangeData.from}}</span>\n                <span data-object="arrow"><span class="fas fa-long-arrow-alt-right fa-sm"></span></span>\n                <span data-object="to">{{rangeData.to}}</span>\n            </div>\n        {{/if}}\n        {{#if hintString}}\n            <div\n                class="pull-left hidden-xs pull-left input-text-block text-muted"\n                style="max-width: 40%; text-overflow: ellipsis; overflow: hidden; user-select: none;"\n            >{{hintString}}</div>\n        {{/if}}\n\n        <div class="btn-group pull-right">\n            <button\n                class="btn btn-default dropdown-toggle btn-wide"\n                data-toggle="dropdown"\n            >\n                {{scaleLabel}}\n                <span class="caret"></span>\n            </button>\n            <ul class="dropdown-menu">\n                {{#each scaleDataList}}\n                    <li>\n                        <a\n                            role="button"\n                            data-name="{{name}}"\n                            data-action="selectScale"\n                        >\n                            {{#if selected}}\n                                <span class="fas fa-check check-icon pull-right"></span>\n                            {{/if}}\n                            <div>{{label}}</div>\n                        </a>\n                    </li>\n                {{/each}}\n            </ul>\n        </div>\n    ';constructor(e){super(e),this.state=e.state,this.onScaleChange=e.onScaleChange,this.onDependencyTypeChange=e.onDependencyTypeChange,this.getTask=e.getTask,this.scales=["week","twoWeeks","month","twoMonths","sixMonths","year"]}data(){return{hasCreateTask:this.state.hasCreateTaskAccess,hasDropdown:this.state.hasCreateTaskAccess,scaleLabel:this.translate(this.state.scale,"ganttScales","Project"),scaleDataList:this.scales.map((e=>({name:e,selected:this.state.scale===e,label:this.translate(e,"ganttScales","Project")}))),selectionAction:this.state.selectionAction,dependencyTypeDataList:this.getDependencyTypeDataList(),rangeData:this.getRangeData(),hintString:this.getHintString(),oneSelected:1===this.state.selectedIds.length}}setup(){this.addActionHandler("selectScale",((e,t)=>this.selectScale(t.dataset.name))),this.addActionHandler("setDependencyType",((e,t)=>this.setDependencyType(t.dataset.name||null)))}getHintString(){if(1!==this.state.selectedIds.length)return null;let e=this.translate("holdCtrlToSelectMultiple","messages","Project");return window.navigator.userAgent.includes("Mac")&&(e=e.replace("CTRL","CMD")),e}getRangeData(){return this.state.selectionAction?2!==this.state.selectedIds.length?null:{from:this.getTask(this.state.selectedIds[0]).attributes.name,to:this.getTask(this.state.selectedIds[1]).attributes.name}:null}getDependencyTypeDataList(){return(this.getMetadata().get("entityDefs.ProjectTask.fields.dependencyTaskType.options")||[]).map((e=>{const t=""===e?this.translate("None"):this.getLanguage().translateOption(e,"dependencyTaskType","ProjectTask");return{type:e,selected:(e||null)===this.state.selectionDependencyType,label:t}}))}selectScale(e){this.onScaleChange(e)}setDependencyType(e){this.onDependencyTypeChange(e)}}e.default=a})),define("modules/project/views/project/record/board/buttons",["exports","view","views/record/list/settings","modules/project/views/project/record/plan/total-task-count"],(function(e,t,s,a){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=i(t),s=i(s),a=i(a);class n extends t.default{templateContent='\n        <div class="pull-right">\n            <div class="btn-group pull-right">\n                <button class="btn btn-text dropdown-toggle" data-toggle="dropdown">\n                    <span class="fas fa-ellipsis-h fa-sm" style="font-size: 100%"></span>\n                </button>\n                <ul class="dropdown-menu pull-left">\n                    <li>\n                        <a role="button" data-action="toggleShowCompleted">\n                            {{#if showCompleted}}<span class="fas fa-check check-icon pull-right"></span>{{/if}}\n                            <div>{{translate \'Show Completed\' scope=\'Project\'}}</div>\n                        </a>\n                    </li>\n                </ul>\n            </div>\n        </div>\n        <div\n            class="settings-container pull-right {{#unless hasSettings}} hidden {{/unless}} margin-left-sm"\n        >{{{settings}}}</div>\n        <div\n            class="text-muted total-count pull-right margin-right"\n            data-role="totalTaskCount"\n        >{{{totalTaskCount}}}</div>\n        <div class="btn-group margin-right">\n            {{#if hasCreateTask}}\n                <button\n                    class="btn btn-default"\n                    data-action="createTask"\n                >\n                    <span class="fas fa-plus fa-sm"></span>\n                    <span>{{translate \'Create ProjectTask\' scope=\'ProjectTask\'}}</span>\n                </button>\n            {{/if}}\n            {{#if hasDropdown}}\n                <button\n                    class="btn btn-default dropdown-toggle margin-right"\n                    data-toggle="dropdown"\n                ><span class="fas fa-ellipsis-h"></span></button>\n                <ul class="dropdown-menu pull-left">\n                    {{#if hasCreateTask}}\n                        <li>\n                            <a\n                                role="button"\n                                tabindex="0"\n                                data-action="createMilestone"\n                            >{{translate \'Create Milestone\' scope=\'ProjectTask\'}}</a>\n                        </li>\n                    {{/if}}\n                </ul>\n            {{/if}}\n        </div><div class="btn-group">\n            <button\n                class="btn btn-text dropdown-toggle btn-s-wide"\n                data-toggle="dropdown"\n                title="{{translate "group" category="fields" scope="ProjectTask"}}"\n            >\n                {{~#if color~}}\n                    <span\n                        class="color-icon fas fa-square"\n                        style="color: {{color}}"\n                    ></span>\n                {{/if}}\n                {{groupName}}\n                <span class="caret"></span>\n            </button>\n            <ul class="dropdown-menu">\n                {{#each groups}}\n                    <li>\n                        <a\n                            role="button"\n                            data-id="{{id}}"\n                            data-action="selectGroup"\n                        >\n\n                            {{#if selected}}\n                                <span class="fas fa-check check-icon pull-right"></span>\n                            {{/if}}\n                            <div class="{{#if active}}text-primary{{/if}}">\n                                {{~#if itemColor~}}\n                                    <span\n                                        class="color-icon fas fa-square"\n                                        style="color: {{itemColor}}"\n                                    ></span>\n                                {{/if}}\n                                {{name}}\n                            </div>\n                        </a>\n                    </li>\n                {{/each}}\n            </ul>\n        </div>\n    ';constructor(e){super(e),this.state=e.state,this.onGroupChange=e.onGroupChange,this.listSettingsHelper=e.listSettingsHelper,this.onSettingsChange=e.onSettingsChange}data(){return{color:this.getGroupColor(this.state.groupId),groupName:this.state.groupName,groups:this.state.groups.map((e=>({itemColor:this.getGroupColor(e.id)||"transparent",...e,selected:this.state.groupId===e.id,active:this.model.attributes.activeGroupId===e.id}))),hasCreateTask:this.state.hasCreateTaskAccess&&this.state.groupId,hasSettings:void 0!==this.state.totalTaskCount,hasDropdown:this.state.hasCreateTaskAccess&&this.state.groupId,showCompleted:this.state.showCompleted}}setup(){this.addActionHandler("selectGroup",((e,t)=>this.selectGroup(t.dataset.id))),this.setupSettingsView(),this.setupCountView()}setupCountView(){const e=new a.default({state:this.state});this.assignView("totalTaskCount",e,'[data-role="totalTaskCount"]')}getGroupColor(e){let t=null,s=this.state.groups.find((t=>t.id===e))?.color;if(null==s&&e===this.model.attributes.activeGroupId&&null!==this.model.attributes.activeGroupColor&&(s=this.model.attributes.activeGroupColor),null!=s){t=(this.getHelper().themeManager.getParam("chartColorList")||[])[s]}return t}selectGroup(e){this.state.groupId!==e&&this.onGroupChange(e)}setupSettingsView(){const e=new s.default({layoutProvider:()=>this.state.kanbanLayout,helper:this.listSettingsHelper,entityType:"ProjectTask",onChange:()=>{this.reRender(),this.onSettingsChange()}});this.assignView("settings",e,".settings-container")}}e.default=n})),define("modules/project/views/project/modals/settings",["exports","views/modal","views/record/edit-for-modal","views/fields/bool"],(function(e,t,s,a){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=i(t),s=i(s),a=i(a);class n extends t.default{templateContent='\n        <div class="record no-side-margin">{{{record}}}</div>\n    ';constructor(e){super(e),this.afterSave=e.afterSave}setup(){this.headerText=this.translate("Settings","labels","Project")+" · "+this.model.attributes.name,this.buttonList.push({name:"save",label:"Save",style:"danger",onClick:()=>this.actionSave()}),this.buttonList.push({name:"cancel",label:"Cancel",onClick:()=>this.actionClose()}),this.recordView=new s.default({model:this.model,detailLayout:[{rows:[[{view:new a.default({name:"ganttView",labelText:this.translate("ganttView","fields","Project")})}]]}]}),this.assignView("record",this.recordView,".record")}async actionSave(){if(!this.recordView.validate()){this.disableButton("save");try{await this.recordView.save()}catch(e){this.enableButton("save")}this.afterSave({ganttView:this.model.attributes.ganttView}),this.close()}}}e.default=n})),define("modules/project/views/project/modals/select-role",["exports","views/modal","model","views/record/edit-for-modal","views/fields/enum","views/fields/multi-enum"],(function(e,t,s,a,i,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=o(t),s=o(s),a=o(a),i=o(i),n=o(n);class r extends t.default{templateContent='\n        <div class="record no-side-margin">{{{record}}}</div>\n    ';constructor(e){super(e),this.members=e.members,this.onSelect=e.onSelect,this.currentRole=e.role}setup(){this.headerText=this.translate("Select Role","labels","Project"),this.buttonList.push({name:"apply",label:"Apply",style:"danger",onClick:()=>this.actionApply()}),this.buttonList.push({name:"cancel",label:"Cancel",onClick:()=>this.actionClose()}),this.model=new s.default({role:this.currentRole||null,members:this.members.map((e=>e.attributes.name))});const e=this.getHelper().getAppParam("projectRoles")||[],t=["",...e.map((e=>e.id)),"Editor","Owner"],o=t.reduce(((e,t)=>({...e,[t]:this.getLanguage().translateOption(t,"projectRole","User")})),{});e.forEach((e=>o[e.id]=e.name)),this.recordView=new a.default({model:this.model,detailLayout:[{rows:[[{view:new i.default({name:"role",params:{options:t,translatedOptions:o},labelText:this.translate("role","otherFields","Project")})},{view:new n.default({name:"members",labelText:this.translate("members","links","Project"),params:{readOnly:!0,displayAsList:!0}})}]]}]}),this.assignView("record",this.recordView,".record")}actionApply(){this.recordView.validate()||(this.onSelect(this.model.attributes.role),this.close())}}e.default=r})),define("modules/project/views/project/modals/clone",["exports","views/modal","views/record/edit-for-modal","views/fields/bool","views/fields/varchar","views/fields/date","model"],(function(e,t,s,a,i,n,o){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=r(t),s=r(s),a=r(a),i=r(i),n=r(n),o=r(o);class l extends t.default{templateContent='\n        <div class="record no-side-margin">{{{record}}}</div>\n    ';formModel;constructor(e){super(e),this.noDateStart=!e.model.attributes.dateStart}setup(){this.headerText=this.translate("Clone","labels","Project")+" · "+this.model.attributes.name,this.buttonList.push({name:"clone",text:this.translate("Clone","labels","Project"),style:"danger",onClick:()=>this.actionClone()}),this.buttonList.push({name:"cancel",label:"Cancel",onClick:()=>this.actionClose()}),this.formModel=new o.default({name:null,dateStart:null,withMembers:!0,withTasks:!1,withOwners:!1,withAssignees:!1,withAttachments:!1}),this.recordView=new s.default({model:this.formModel,dynamicLogicDefs:{fields:{dateStart:{required:{conditionGroup:[{type:"isTrue",attribute:"withTasks"}]}},withOwners:{visible:{conditionGroup:[{type:"isTrue",attribute:"withMembers"},{type:"isTrue",attribute:"withTasks"}]}},withAssignees:{visible:{conditionGroup:[{type:"isTrue",attribute:"withMembers"},{type:"isTrue",attribute:"withTasks"}]}},withAttachments:{visible:{conditionGroup:[{type:"isTrue",attribute:"withTasks"}]}}}},detailLayout:[{rows:[[{view:new i.default({name:"name",labelText:this.translate("name","fields","Project"),params:{required:!0}})},{view:new n.default({name:"dateStart",labelText:this.translate("dateStart","fields","Project")})}]]},{customLabel:this.translate("include","otherPanels","Project"),rows:[[{view:new a.default({name:"withMembers",labelText:this.translate("withMembers","otherFields","Project")})}],[{view:new a.default({name:"withTasks",labelText:this.translate("withTasks","otherFields","Project")})}],[{view:new a.default({name:"withOwners",labelText:this.translate("withOwners","otherFields","Project")})}],[{view:new a.default({name:"withAssignees",labelText:this.translate("withAssignees","otherFields","Project")})}],[{view:new a.default({name:"withAttachments",labelText:this.translate("withAttachments","otherFields","Project")})}]]}]}),this.assignView("record",this.recordView,".record"),this.noDateStart&&(this.formModel.setMultiple({withTasks:!1,withOwners:!1,withAssignees:!1,withAttachments:!1,dateStart:null}),this.recordView.setFieldReadOnly("withTasks",!0),this.recordView.setFieldReadOnly("withOwners",!0),this.recordView.setFieldReadOnly("withAssignees",!0),this.recordView.setFieldReadOnly("withAttachments",!0),this.recordView.setFieldReadOnly("dateStart",!0),this.recordView.hideField("withTasks",!0),this.recordView.hideField("withOwners",!0),this.recordView.hideField("withAssignees",!0),this.recordView.hideField("withAttachments",!0),this.recordView.hideField("dateStart",!0))}async actionClone(){if(this.recordView.validate())return;let e;this.disableButton("clone"),Espo.Ui.notify(" ... ");try{e=await Espo.Ajax.postRequest(`Project/${this.model.id}/clone`,{name:this.formModel.attributes.name,dateStart:this.formModel.attributes.dateStart,withMembers:this.formModel.attributes.withMembers,withTasks:this.formModel.attributes.withTasks,withOwners:this.formModel.attributes.withOwners,withAssignees:this.formModel.attributes.withAssignees,withAttachments:this.formModel.attributes.withAttachments})}catch(e){this.enableButton("clone")}const t=this.translate("cloned","messages","Project").replace("{name}",this.formModel.attributes.name).replace("{link}",`#Project/view/${e.id}`);Espo.Ui.notify(t,"success",0,{closeButton:!0,suppress:!0}),this.close()}}e.default=l})),define("modules/project/helpers/member-task-access",["exports","model"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};e.default=class{constructor(e){this.user=e}checkEdit(e){const t=this.getParentTask(e);if(t&&this.checkEdit(t))return!0;if(this.user.isAdmin())return!0;const s=this.getMemberRoleData(e);if(void 0===s)return null;if(null===s)return!1;if("Owner"===s.role||"Editor"===s.role)return!0;const a=s.permissions.taskEdit;return"all"===a||("own"===a&&e.attributes.ownerId===this.user.id||"assigned"===a&&(e.attributes.assignedUserId===this.user.id||e.attributes.ownerId===this.user.id))}checkStream(e){const t=this.getParentTask(e);if(t&&this.checkStream(t))return!0;if(this.user.isAdmin())return!0;const s=this.getMemberRoleData(e);if(void 0===s)return null;if(null===s)return!1;if("Owner"===s.role||"Editor"===s.role)return!0;const a=s.permissions.taskStream;return"all"===a||"own"===a&&(e.attributes.assignedUserId===this.user.id||e.attributes.ownerId===this.user.id)}checkDelete(e){const t=this.getParentTask(e);if(t&&this.checkEdit(t))return!0;if(this.user.isAdmin())return!0;const s=this.getMemberRoleData(e);if(void 0===s)return null;if(null===s)return!1;if("Owner"===s.role||"Editor"===s.role)return!0;const a=s.permissions.taskDelete;return"all"===a||("assigned"===a&&(e.attributes.assignedUserId===this.user.id||e.attributes.ownerId===this.user.id)||"own"===a&&e.attributes.ownerId===this.user.id)}checkColumnEdit(e){const t=this.getParentTask(e);if(t&&this.checkColumnEdit(t))return!0;if(this.checkEdit(e))return!0;const s=this.getMemberRoleData(e);if(void 0===s)return null;if(null===s)return!1;if("Owner"===s.role||"Editor"===s.role)return!0;const a=s.permissions.taskColumnEdit;return"all"===a||("assigned"===a?e.attributes.assignedUserId===this.user.id||e.attributes.ownerId===this.user.id:"own"===a&&e.attributes.ownerId===this.user.id)}getMemberRoleData(e){return e.collection&&e.collection.parentModel?e.collection.parentModel.attributes.memberRoleData:e.attributes.memberRoleData}getParentTask(e){return e.collection&&e.collection.parentModel&&"ProjectTask"===e.collection.parentModel.entityType?e.collection.parentModel:e.attributes.parentTaskAttributes?new t.default(e.attributes.parentTaskAttributes,{entityType:"ParentTask"}):void 0}}})),define("modules/project/views/user/fields/project-role",["exports","views/fields/enum"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{listTemplateContent='\n        {{#if stringValue}}\n            <span\n                class="text-{{style}}"\n                title="{{stringValue}}"\n            >{{stringValue}}</span>\n        {{/if}}\n    ';getAttributeList(){return["projectRole","projectRoleId"]}data(){if(this.isListMode()){let e="default";return["Owner","Editor"].includes(this.model.attributes.projectRole)&&(e="primary"),{stringValue:this.getStringValue(),style:e}}return super.data}getStringValue(){const e=this.model.attributes.projectRole,t=this.model.attributes.projectRoleId;if(void 0===e)return;if(!t)return this.getLanguage().translateOption(e||"","projectRole","User");const s=this.getHelper().getAppParam("projectRoles").find((e=>e.id===t));return s?s.name:t}}e.default=a})),define("modules/project/views/project-task/fields/timeline",["exports","views/fields/base","model","views/fields/date","moment"],(function(e,t,s,a,i){"use strict";function n(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=n(t),s=n(s),a=n(a),i=n(i);class o extends t.default{listTemplateContent='\n        {{~#if isNotEmpty}}\n            <span class="text-{{style}}">\n            {{#if onlyStart}}\n                {{#if isMilestone}}\n                    <span\n                        class="far fa-square text-info"\n                        style="transform: rotate(45deg)"\n                        title="{{translateOption \'Milestone\' field=\'type\' scope=\'ProjectTask\'}}"\n                    ></span>\n                    <span style="user-select: none">&nbsp;</span>\n                {{/if}}\n                <span data-sub-field="dateStart">{{{dateStartField}}}</span>\n                {{~#unless isMilestone}} <span class="text-muted">→</span> ∞{{else}}{{/unless}}\n            {{~/if}}\n            {{#if onlyEnd}}\n                <span data-sub-field="dateEnd">{{{dateEndField}}}</span>\n            {{/if}}\n            {{#if both}}\n                <span data-sub-field="dateStart">{{{dateStartField}}}</span> <span class="text-muted">→</span>\n                <span data-sub-field="dateEnd">{{{dateEndField}}}</span>\n            {{/if}}\n            </span>\n        {{else~}}\n            {{~#if isMilestone}}\n                <span\n                    class="far fa-square text-info"\n                    style="transform: rotate(45deg)"\n                    title="{{translateOption \'Milestone\' field=\'type\' scope=\'ProjectTask\'}}"\n                ></span>\n                <span style="user-select: none">&nbsp;</span>\n            {{/if}}\n        {{~/if~}}\n    ';detailTemplateContent='\n        {{#if isSet}}\n            {{#if isNotEmpty}}\n                <span class="text-{{style}}">\n                {{#if onlyStart}}\n                    {{#if isMilestone}}\n                        <span\n                            class="far fa-square text-info"\n                            style="transform: rotate(45deg)"\n                            title="{{translateOption \'Milestone\' field=\'type\' scope=\'ProjectTask\'}}"\n                        ></span>\n                        <span style="user-select: none">&nbsp;</span>\n                    {{/if}}\n                    <span data-sub-field="dateStart">{{{dateStartField}}}</span>\n                    {{#unless isMilestone}} <span class="text-muted">→</span> ∞{{else}}{{/unless}}\n                {{~/if}}\n                {{#if onlyEnd}}\n                    <span data-sub-field="dateEnd">{{{dateEndField}}}</span>\n                {{/if}}\n                {{#if both}}\n                    <span data-sub-field="dateStart">{{{dateStartField}}}</span> <span class="text-muted">→</span>\n                    <span data-sub-field="dateEnd">{{{dateEndField}}}</span>\n                {{/if}}\n                <span class="text-{{style}}">\n            {{else}}\n                {{#if isMilestone}}\n                    <span\n                        class="far fa-square text-info"\n                        style="transform: rotate(45deg)"\n                        title="{{translateOption \'Milestone\' field=\'type\' scope=\'ProjectTask\'}}"\n                    ></span>\n                    <span style="user-select: none">&nbsp;</span>\n                {{else}}\n                    <span class="none-value">{{translate \'None\'}}</span>\n                {{/if}}\n            {{/if}}\n        {{else}}\n            <span class="loading-value"></span>\n        {{/if}}\n    ';editTemplateContent='\n        {{#unless isMilestone}}\n            <div class="row">\n                <div class="col-sm-5 col-xs-5" data-sub-field="dateStart">{{{dateStartField}}}</div>\n                <div class="col-sm-2 col-xs-2 center-align text-soft">\n                    <span class="input-text-block">\n                        <span class="fas fa-arrow-right"></span>\n                    </span>\n                </div>\n                <div class="col-sm-5 col-xs-5" data-sub-field="dateEnd">{{{dateEndField}}}</div>\n            </div>\n        {{else}}\n            <div class="row">\n                <div class="col-sm-5 col-xs-5" data-sub-field="dateStart">{{{dateStartField}}}</div>\n                <div class="col-sm-1 col-xs-1 center-align text-soft">\n                    <span class="input-text-block">\n                        <span\n                            class="far fa-square text-info"\n                            style="transform: rotate(45deg)"\n                            title="{{translateOption \'Milestone\' field=\'type\' scope=\'ProjectTask\'}}"\n                        ></span>\n                    </span>\n                </div>\n            </div>\n\n        {{/unless}}\n    ';getAttributeList(){return["dateStart","dateEnd","type","status"]}data(){const e=this.model.attributes.dateStart,t=this.model.attributes.dateEnd,s=!e&&t||t===e;return{isSet:this.model.has("dateStart")&&this.model.has("dateEnd"),isNotEmpty:e||t,onlyStart:e&&!t,onlyEnd:s,both:!s&&e&&t,isMilestone:"Milestone"===this.model.attributes.type,style:this.getStyle()||"default"}}setup(){this.validations=[],this.validations.push((()=>this.validateSub())),this.validations.push((()=>this.validateAfter())),this.validations.push((()=>this.validateRequired())),this.setupSub()}setupSub(){this.subModel=new s.default({},{entityType:"ProjectTask"});const e=()=>{this.subModel.set({dateStart:this.model.attributes.dateStart,dateEnd:this.model.attributes.dateEnd})};e(),this.listenTo(this.model,"change:dateStart change:dateEnd",((t,s,a)=>{(!a.ui||a.fromView&&a.fromView!==this)&&e()})),this.listenTo(this.subModel,"change",((e,t)=>t.ui?this.trigger("change"):null))}prepare(){return this.dateStartView=new a.default({name:"dateStart",model:this.subModel,mode:this.mode,labelText:this.translate("dateStart","fields","ProjectTask"),inlineEditDisabled:!0}),this.dateEndView=new a.default({name:"dateEnd",model:this.subModel,mode:this.mode,labelText:this.translate("dateEnd","fields","ProjectTask"),inlineEditDisabled:!0,params:{after:"dateStart",afterOrEqual:!0}}),Promise.all([this.assignView("dateStartField",this.dateStartView,'[data-sub-field="dateStart"]'),this.assignView("dateEndField",this.dateEndView,'[data-sub-field="dateEnd"]')])}fetch(){return{dateStart:this.subModel.attributes.dateStart,dateEnd:this.subModel.attributes.dateEnd}}validateSub(){let e=!1;return e=this.dateStartView.validate()||e,e=this.dateEndView.validate()||e,e}validateAfter(){const e=this.model.attributes.dateStart,t=this.model.attributes.dateEnd;if(e&&t&&e!==t&&Date.parse(e)>Date.parse(t)){const e=this.translate("fieldShouldAfter","messages").replace("{field}",this.translate("dateEnd","fields",this.entityType)).replace("{otherField}",this.translate("dateStart","fields",this.entityType));return this.showValidationMessage(e,this.dateEndView.element.querySelector(".main-element")),!0}return!1}validateRequired(){if(!this.params.required)return!1;if("Milestone"===this.model.attributes.type){if(this.model.attributes.dateStart)return!1;const e=this.translate("fieldIsRequired","messages").replace("{field}",this.translate("dateStart","fields",this.entityType));return this.dateStartView.showValidationMessage(e,this.dateStartView.element.querySelector(".main-element")),!0}if(!this.model.attributes.dateStart){const e=this.translate("fieldIsRequired","messages").replace("{field}",this.translate("dateStart","fields",this.entityType));this.dateStartView.showValidationMessage(e,this.dateStartView.element.querySelector(".main-element"))}if(!this.model.attributes.dateEnd){const e=this.translate("fieldIsRequired","messages").replace("{field}",this.translate("dateEnd","fields",this.entityType));this.dateStartView.showValidationMessage(e,this.dateEndView.element.querySelector(".main-element"))}return!this.model.attributes.dateStart||!this.model.attributes.dateEnd}getStyle(){const e=this.model.attributes.status;if(void 0===e||"Completed"===e||"Canceled"===e)return null;const t=this.model.attributes.dateStart,s=this.model.attributes.dateEnd;if(!t&&!s)return null;const a=(e,t)=>{const s=this.model.attributes[e];if(!s)return!1;const a=t?`${s} 00:00`:`${s} 23:59`,n=i.default.tz(a,this.getDateTime().getTimeZone()),o=this.getDateTime().getNowMoment();return n.unix()<o.unix()};return t||!a("dateEnd",!0)||a("dateEnd")?"Milestone"===this.model.attributes.type&&a("dateStart")||a("dateEnd")?"danger":a("dateStart",!0)?"warning":null:"warning"}}e.default=o})),define("modules/project/views/project-task/fields/name",["exports","views/fields/varchar"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{listLinkTemplateContent='\n        {{#if isSubTask}}\n            <span class="list-icon-container pull-right">\n                <span\n                    class="fas fa-chevron-circle-left small text-muted"\n                    title="{{translate \'Sub-Task\' scope=\'ProjectTask\'}}"\n                ></span>\n            </span>\n        {{else}}\n            {{#if actualSubTaskCount}}\n                <span\n                    class="list-icon-container pull-right"\n                    style="user-select: none;"\n                    title="{{translate \'hasSubTasks\' category=\'strings\' scope=\'ProjectTask\'}}"\n                >\n                    <span\n                        class="small text-muted"\n                    >{{actualSubTaskCount}}</span>\n                    <span\n                        class="far fa-list-alt small text-muted"\n                    ></span>\n                </span>\n            {{/if}}\n\n        {{/if}}\n        <a\n            href="{{link}}"\n            class="link"\n            data-id="{{id}}"\n            title="{{value}}"\n        >{{#if value}}{{value}}{{else}}{{translate \'None\'}}{{/if}}</a>\n    ';getAttributeList(){return[...super.getAttributeList(),"actualSubTaskCount"]}data(){return this.mode===this.MODE_LIST_LINK?{link:`#${this.model.entityType}/view/${this.model.id}`,entityType:this.model.entityType,id:this.model.id,value:this.model.attributes[this.name],isSubTask:!(!this.model.attributes.parentTaskId||this.model.collection&&this.model.collection.parentModel),actualSubTaskCount:this.model.attributes.actualSubTaskCount}:super.data()}}e.default=a})),define("modules/project/views/project-task/fields/group",["exports","views/fields/link"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{listTemplateContent='\n        {{#if id}}\n            {{#if color}}<span class="color-icon fas fa-square" style="color: {{color}}"></span>{{/if}}\n            {{name}}\n        {{/if}}\n    ';detailTemplateContent='\n        {{#if id}}\n            {{#if color}}<span class="color-icon fas fa-square" style="color: {{color}}"></span>{{/if}}\n            {{name}}\n        {{else}}\n            {{#if valueIsSet}}\n                <span class="none-value">{{translate \'None\'}}</span>\n            {{else}}\n                <span class="loading-value"></span>\n            {{/if}}\n        {{/if}}\n    ';getAttributeList(){return[...super.getAttributeList(),this.name+"Color"]}data(){if(this.isReadMode()){const e=this.getHelper().themeManager.getParam("chartColorList")||[],t=null!=this.model.attributes[this.name+"Color"]?e[this.model.attributes[this.name+"Color"]]:null;return{valueIsSet:void 0!==this.model.attributes[this.name+"Id"],id:this.model.attributes[this.name+"Id"],name:this.model.attributes[this.name+"Name"],color:t}}return super.data()}}e.default=a})),define("modules/project/views/project-task/fields/from-tasks",["exports","views/fields/link-multiple-with-columns"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{detailTemplateContent='\n        {{#if isNotEmpty}}\n            {{#each dataList}}\n                <div class="link-multiple-item">\n                    {{#if typeString}}\n                        <span\n                            class="label label-sm label-state label-{{style}}"\n                            style="user-select: none;"\n                            title="{{title}}"\n                        >{{typeString}}</span>\n                    {{/if}}\n                    <a href="{{url}}" data-id="{{id}}" class="text-default">{{name}}</a>\n                </div>\n            {{/each}}\n        {{else}}\n            {{#if valueIsSet}}\n                <span class="none-value">{{translate \'None\'}}</span>\n            {{else}}\n                <span class="loading-value"></span>\n            {{/if}}\n        {{/if}}\n    ';listTemplateContent='\n        {{~#each dataList}}\n            <div class="link-multiple-item">\n                {{#if typeString}}\n                    <span\n                        class="label label-sm label-state label-{{style}}"\n                        style="user-select: none;"\n                        title="{{title}}"\n                    >{{typeString}}</span>\n                {{/if}}\n                <a href="{{url}}" data-id="{{id}}" class="text-default" title="{{name}}">{{name}}</a>\n            </div>\n        {{/each~}}\n    ';data(){if(this.isReadMode()){const e=this.model.attributes.fromTasksIds||[],t=this.model.attributes.fromTasksNames||{};return{dataList:e.map((e=>{const s=this.getColumnValue(e,"type"),a=this.getColumnValue(e,"status"),i=a?this.getLanguage().translateOption(a,"status","ProjectTask"):"",n=this.getLanguage().translateOption(s,"dependencyTaskTypeShort","ProjectTask");let o=i;return s&&(o+=" · "+this.getLanguage().translateOption(s,"dependencyTaskType","ProjectTask")),{id:e,name:t[e]||e,url:`#ProjectTask/view/${e}`,typeString:s?n:"‎ ‎ ‎",style:this.styleMap[a]||"default",title:o}})),isNotEmpty:e.length>0,valueIsSet:void 0!==this.model.attributes.fromTasksIds}}return super.data()}setup(){super.setup(),this.columnList=["type"],this.styleMap=this.getMetadata().get("entityDefs.ProjectTask.fields.status.style")||{}}}e.default=a})),define("modules/project/views/project-task/fields/column",["exports","views/fields/link","model","views/fields/enum"],(function(e,t,s,a){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=i(t),s=i(s),a=i(a);class n extends t.default{listTemplateContent='\n        {{#if stringValue}}\n            <span\n                class="{{#if isText}}text-{{style}}{{else}}label label-md label-state label-{{style}}{{/if}}"\n                title="{{stringValue}}"\n            >{{stringValue}}</span>\n        {{/if}}\n    ';detailTemplateContent='\n        {{#if stringValue}}\n            <span\n                class="{{#if isText}}text-{{style}}{{else}}label label-md label-state label-{{style}}{{/if}}"\n            >{{stringValue}}</span>\n        {{else}}\n            {{#if valueIsSet}}\n                <span class="none-value">{{translate \'None\'}}</span>\n            {{else}}\n                <span class="loading-value"></span>\n            {{/if}}\n        {{/if}}\n    ';editTemplateContent='\n        <div data-sub-field="column">{{{columnField}}}</div>\n    ';columns;getAttributeList(){return["columnId","columnName","status"]}data(){const e=super.data();e.stringValue=e.nameValue,e.style="default";const t=this.model.attributes.columnId,s=this.model.attributes.status;return this.isReadMode()&&this.styleMap&&t&&(e.style=this.styleMap[t]||"default"),e.valueIsSet&&!t&&(e.stringValue=this.getLanguage().translateOption(s,"status","ProjectTask"),e.isText=!0,e.style=this.statusStyleMap[s]||"default"),e}setupOptions(){this.subParams={},this.subParams.options=[],this.translatedOptions={},this.columns=null;const e=this.getMetadata().get("entityDefs.ProjectTask.fields.status.options")||[];this.statusTranslatedOptions=e.reduce(((e,t)=>({...e,[t]:this.getLanguage().translateOption(t,"status","ProjectTask")})),{});const t=this.model.attributes.columnId;t&&(this.subParams.options.push(t),this.translatedOptions[t]=this.model.attributes.columnName||t),null===t&&(this.subParams.options=[""]),this.recordHelper&&(this.columns=this.recordHelper.getFieldStateParam("column","options")),this.setupSubParams()}setup(){super.setup(),this.statusStyleMap=this.getMetadata().get("entityDefs.ProjectTask.fields.status.style")||{},this.setupOptions(),this.setupSub()}setupSubParams(){const e=this.model.attributes.boardId,t=this.model.attributes.columnId,s=this.model.attributes.status;if(!this.columns&&e){const t=this.getHelper().getAppParam("projectBoards")||{};this.columns=(t[e]||{}).columns}this.columns?(this.subParams.options=this.columns.map((e=>e[0])),this.translatedOptions=this.columns.reduce(((e,t)=>({...e,[t[0]]:t[1]})),{}),this.styleMap=this.subParams.style=this.columns.reduce(((e,t)=>({...e,[t[0]]:this.statusStyleMap[t[2]]})),{}),t||(this.subParams.options.push(""),s&&(this.translatedOptions[""]=this.statusTranslatedOptions[s],this.styleMap[""]=this.statusStyleMap[s]))):this.subParams.options=[""]}setupSub(){this.subModel=new s.default;const e=()=>this.subModel.set({column:this.model.attributes.columnId});e(),this.listenTo(this.model,"change:columnId",((t,s,a)=>{(!a.ui||a.fromView&&a.fromView!==this)&&e()})),this.listenTo(this.subModel,"change",((e,t)=>t.ui?this.trigger("change"):null)),this.listenTo(this.model,"change:boardId change:status",(()=>{this.columns=null,this.setupSubParams(),this.onEditModeSet().then((()=>this.reRender()))}))}onEditModeSet(){return this.enumView=new a.default({name:"column",model:this.subModel,mode:"edit",params:this.subParams,translatedOptions:this.translatedOptions}),this.assignView("columnField",this.enumView,'[data-sub-field="column"]')}fetch(){const e=this.subModel.attributes.column;return{columnId:e,columnName:e?this.translatedOptions[e]:null}}}e.default=n})),define("modules/project/views/project-task/fields/assigned-user-short",["exports","modules/project/views/project-task/fields/assigned-user"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{listTemplateContent='\n        <span title="{{name}}">{{{avatar}}}</span>\n    ';data(){const e=super.data();return this.mode===this.MODE_LIST&&(e.avatar=this.getHelper().getAvatarHtml(this.model.get(this.idName),"small",20,"avatar-link"),e.isOwn=this.model.get(this.idName)===this.getUser().id,e.name=this.model.get(this.nameName)),e}}e.default=a})),define("modules/project/views/project-role/fields/permission",["exports","views/fields/enum"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{setup(){this.params.style={yes:"success",all:"success",assigned:"info",own:"warning",no:"danger"},super.setup()}}e.default=a})),define("modules/project/views/project-group/fields/color",["exports","views/fields/base"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{listTemplateContent='\n        {{#if isNotNull}}\n            <span class="fas fa-square" style="color: {{color}}"></span>\n        {{/if}}\n    ';detailTemplateContent='\n        {{#if isNotNull}}\n            <span class="fas fa-square" style="color: {{color}}"></span>\n        {{else}}\n            {{#if valueIsSet}}\n                <span class="none-value">{{translate \'None\'}}</span>\n            {{else}}\n                <span class="loading-value""></span>\n            {{/if}}\n        {{/if}}\n    ';editTemplateContent='\n        <div class="btn-group">\n            <button class="btn btn-default dropdown-toggle" data-toggle="dropdown">\n                <span class="fas fa-square" style="color: {{color}}"></span>\n            </button>\n            <ul class="dropdown-menu">\n                <li>\n                    <ul\n                        style="\n                            display: grid;\n                            grid-template-columns: 52px 52px 52px;\n                            padding-left: 0;\n                        "\n                    >\n                        {{#each colors}}\n                            <li style="list-style: none;">\n                                <a\n                                    style="\n                                        width: 100%;\n                                        display: inline-block;\n                                        text-align: center;\n                                        padding: 2px;\n                                    "\n                                    class="dropdown-item"\n                                    role="button"\n                                    tabindex="0"\n                                    data-action="selectColor{{#if selected}} active{{/if}}"\n                                    data-value="{{value}}"\n                                ><span class="fas fa-square" style="color: {{color}}"></span></a>\n                            </li>\n                        {{/each}}\n                    </ul>\n                </li>\n                <li class="divider"></li>\n                <li>\n                    <a\n                        class="dropdown-item"\n                        role="button"\n                        tabindex="0"\n                        data-action="selectColor{{#if isNull}} active{{/if}}"\n                        data-value=""\n                        style="text-align: center;"\n                    >{{translate \'None\'}}</a>\n                </li>\n            </ul>\n        </div>\n    ';data(){const e=this.model.attributes[this.name];if(this.isEditMode()){const t=[];let s="transparent";for(let a=0;a<9;a++)t.push({color:this.colors[a],selected:a===e,value:a}),a===e&&(s=this.colors[a]);return{colors:t,color:s,isNull:null===e}}return this.isReadMode()?{valueIsSet:void 0!==e,isNotNull:null!==e,color:null!=e?this.colors[e]:"transparent"}:super.data()}setup(){this.colors=this.getHelper().themeManager.getParam("chartColorList")||[],this.addActionHandler("selectColor",((e,t)=>{const s=""!==t.dataset.value?parseInt(t.dataset.value):null;this.model.set(this.name,s,{ui:!0}),this.reRender()}))}}e.default=a})),define("modules/project/views/project/record/gantt",["exports","view","moment","modules/project/views/project/record/gantt/buttons","views/modals/detail","views/modals/edit","view-record-helper"],(function(e,t,s,a,i,n,o){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}let l,d;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=r(t),s=r(s),a=r(a),i=r(i),n=r(n),o=r(o);class c extends t.default{templateContent='\n        <link href="{{basePath}}client/custom/modules/project/css/vis.css?r={{cacheTimestamp}}" rel="stylesheet">\n\n        <div\n            class="button-container list-buttons-container clearfix"\n            data-role="buttons"\n            tabindex="-1"\n        >{{{buttons}}}</div>\n        <div class="panel gantt-panel">\n            <div class="panel-body">\n                <div class="timeline"></div>\n            </div>\n        </div>\n    ';items;taskCollection;groupModel;rowDataSet;itemDataSet;timeline;bgColor;taskColor;minStart;maxEnd;startFetched;endFetched;start;end;taskDependencies;svg;dependencyPaths;nonWorkingRanges;lastFetchNonWorkingRangesPromise;lastFetchNonWorkingRangesRange;constructor(e){super(e),this.state={totalTaskCount:void 0,hasCreateTaskAccess:!1,hasEditAccess:!1,scale:void 0,selectedIds:[],selectionAction:null,selectionDependencyType:void 0},this.resizeHandler=this.onResize.bind(this)}data(){return{cacheTimestamp:this.getConfig().get("cacheTimestamp")}}setup(){this.setupColor(),this.state.scale=this.getStorage().get("state",`projectGanttScale-${this.model.id}`)||"week",this.wait(this.loadVisAndGantt()),this.wait(this.controlAccess()),this.setupEventHandlers(),this.setupButtonsView(),this.listenTo(this.model,"update-all",(()=>this.refresh()))}async loadVisAndGantt(){await this.loadVisTimeline(),await this.loadGantt()}setupButtonsView(){this.buttonsView=new a.default({state:this.state,onScaleChange:e=>this.onScaleChange(e),onDependencyTypeChange:e=>this.onDependencyTypeChange(e),getTask:e=>this.getTask(e)}),this.assignView("buttons",this.buttonsView,'[data-role="buttons"]')}async onScaleChange(e){this.state.scale=e,this.getStorage().set("state",`projectGanttScale-${this.model.id}`,e),this.buttonsView.reRender().then((()=>{})),this.prepareRange(this.getAxisMiddle()),this.timeline.setWindow(this.start,this.end)}getAxisMiddle(){const e=this.timeline.getWindow(),t=Math.floor((0,s.default)(e.end).diff((0,s.default)(e.start),"day")/2);return(0,s.default)(e.start).add(t,"day")}async onDependencyTypeChange(e){const t=this.state.selectedIds;if(!t[1])return;const s=this.getTask(t[1]);if(!s)return;const a={...s.attributes.fromTasksColumns};a[t[0]]={type:e},Espo.Ui.notify(" ... "),await s.save({fromTasksColumns:a},{patch:!0}),await this.refresh(),Espo.Ui.notify(!1),this.timeline.setSelection(t),this.onSelectItems(t),await this.buttonsView.reRender()}setupEventHandlers(){this.addHandler("click",".vis-label.vis-nesting-group",((e,t)=>{this.onNestingGroupClick(e,t)})),this.addActionHandler("viewTask",((e,t)=>{e.preventDefault(),this.viewTask(t.dataset.id)})),this.addActionHandler("createTask",(()=>this.createTask())),this.addActionHandler("createMilestone",(()=>this.createTask(!0))),this.addActionHandler("addDependency",(()=>this.addDependency())),this.addActionHandler("removeDependency",(()=>this.removeDependency())),this.addHandler("keydown.project","",(e=>this.onKeyDown(e)))}async createTask(e=!1){let t=this.model.attributes.activeGroupId,s=this.model.attributes.activeGroupName,a=this.model.attributes.activeGroupColor,i=null,r=null;const l=[],d={};if(1===this.state.selectedIds.length){const n=this.getTask(this.state.selectedIds[0]);if(n){t=n.attributes.groupId,s=null,a=void 0;const o=this.getItem(t);o&&(s=o.group.attributes.name,a=o.group.attributes.color),l.push(n.id),d[n.id]=n.attributes.name;let c=n.attributes.dateEnd||n.attributes.dateStart;n.attributes.dateEnd&&(c=this.getDateTime().toMomentDate(c).add(1,"days").format(this.getDateTime().internalDateFormat)),c&&(i=c,e||(r=c))}}const c=new o.default;c.setFieldStateParam("memberRoleData","isMember",!!this.model.attributes.memberRoleData);const u=new n.default({entityType:"ProjectTask",attributes:{assignedUserId:null,assignedUserName:null,projectId:this.model.attributes.id,projectName:this.model.attributes.name,boardId:this.model.attributes.boardId,groupId:t,groupName:s,groupColor:a,columnId:this.model.attributes.firstColumnId,columnName:this.model.attributes.firstColumnName,memberRoleData:this.state.hasEditAccess?{role:"Owner",permissions:{}}:this.model.attributes.memberRoleData,type:e?"Milestone":"Task",fromTasksIds:l,fromTasksNames:d,dateStart:i,dateEnd:r},headerText:e?this.translate("Create Milestone","labels","ProjectTask"):void 0,focusForCreate:!0,recordHelper:c});await this.assignView("dialog",u),u.getRecordView().hideField("project",!0),u.getRecordView().hideField("owner",!0),u.getRecordView().setFieldRequired("timeline"),await u.render(),this.listenTo(u,"after:save",(()=>this.refresh()))}onNestingGroupClick(e,t){const s=t.getBoundingClientRect();if(e.clientX<s.left+10||e.clientX>s.left+18||e.clientY<s.top+10||e.clientY>s.top+27)return;const a=t.querySelector("[data-group-id]");if(!(a instanceof HTMLElement))return;const i=a.dataset.groupId,n=!this.getItem(i).isCollapsed;this.setGroupCollapse(i,n),this.prepareDataSets(),this.timeline.setGroups(this.rowDataSet),this.renderDependencies()}async controlAccess(){if(this.state.hasCreateTaskAccess=!1,this.state.hasEditAccess=!1,this.getAcl().checkModel(this.model,"edit"))return this.state.hasCreateTaskAccess=!0,void(this.state.hasEditAccess=!0);if(void 0===this.model.attributes.memberRoleData)return new Promise((e=>{this.listenToOnce(this.model,"sync",(async()=>{await this.controlAccess(),e(),await this.buttonsView.whenReady(),await this.buttonsView.reRender()}))}));const e=this.model.attributes.memberRoleData;return e?"Owner"===e.role||"Editor"===e.role?(this.state.hasCreateTaskAccess=!0,void(this.state.hasEditAccess=!0)):void("yes"===e.permissions.taskCreate&&(this.state.hasCreateTaskAccess=!0)):void 0}setupColor(){const e={...this.getMetadata().get("clientDefs.Calendar.colors"),...this.getHelper().themeManager.getParam("calendarColors")};this.bgColor=e.bg,this.taskColor=e.ProjectTask}async loadVisTimeline(){const e=await Espo.loader.requirePromise("vis-data-project"),t=await Espo.loader.requirePromise("vis-timeline-project");d=e.DataSet,l=t.Timeline}async loadGantt(){const e=this.getScaleData();let t;try{t=await Espo.Ajax.getRequest(`Project/${this.model.id}/gantt`,{collapsedGroupIds:this.getCollapsedGroupIds().join(","),scaleUnit:e[1],scale:e[0]})}catch(e){return}this.nonWorkingRanges=t.nonWorkingRanges,this.taskCollection=await this.getCollectionFactory().create("ProjectTask"),this.groupModel=await this.getModelFactory().create("ProjectGroup"),this.items=[],t.groups.forEach((e=>{const t={group:this.prepareGroupModel(e.group),tasks:e.tasks.list?this.prepareTasksCollection(e.group.id,e.tasks.list,e.tasks.total):this.prepareTasksCollection(e.group.id,[],e.tasks.total),isCollapsed:this.isGroupCollapsed(e.group.id),isFetched:null!=e.tasks.list};this.items.push(t)})),this.prepareDataSets(),this.controlTotalTaskCount(),this.start||(this.prepareRange(),this.start=s.default.utc(t.range[0]),this.end=s.default.utc(t.range[1]),this.startFetched=this.start.clone(),this.endFetched=this.end.clone(),"year"===this.state.scale&&(this.startFetched=s.default.utc(),this.endFetched=s.default.utc()))}getScaleData(){const e={week:[1,"week"],twoWeeks:[2,"week"],month:[1,"month"],twoMonths:[2,"month"],sixMonths:[6,"month"],year:[12,"month"]};return e[this.state.scale]||e.week}prepareRange(e=void 0){const t=this.getScaleData();this.start=(e||s.default.utc()).startOf("day"),this.end=this.start.clone().add(t[0],t[1]);const a=this.end.diff(this.start,"day");this.start.subtract(Math.floor(a/2),"day"),this.end.subtract(Math.floor(a/2),"day"),this.minStart&&(0,s.default)().isBefore(this.minStart)&&(this.start=this.minStart.clone(),this.end=this.start.clone().add(t[0],t[1])),this.maxEnd&&(0,s.default)().isAfter(this.maxEnd)&&(this.end=this.maxEnd.clone(),this.start=this.end.clone().subtract(t[0],t[1]))}prepareDataSets(){const e=new d({}),t=new d({});let s,a;this.items.forEach((t=>{0===t.tasks.length&&t.isFetched||e.add({id:"group-"+t.group.id,nestedGroups:t.tasks.models.map((e=>"task-"+e.id)),content:this.getGroupContent(t.group),showNested:!t.isCollapsed,className:"group-row"})}));const i=[];this.items.map((n=>{n.tasks.forEach((o=>{e.add({id:"task-"+o.id,content:this.getTaskRowContent(o)});const r=this.prepareEvent(o,n.group.id);t.add(r),r.start.isBefore(s)&&(s=r.start.clone()),r.end&&r.end.isAfter(a)&&(a=r.end.clone());const l=o.attributes.fromTasksIds,d=o.attributes.fromTasksColumns||{};l&&l.forEach((e=>{const t=(d[e]||{}).type||null;i.push([e,o.id,t])}))}))})),this.nonWorkingRanges.forEach((e=>{t.add(this.prepareBackgroundEvent(e))})),this.minStart=s,this.maxEnd=a,this.rowDataSet=e,this.itemDataSet=t,this.taskDependencies=i}prepareBackgroundEvent(e){const[t,a]=[s.default.utc(e[0]),s.default.utc(e[1])];return{id:`${e[0]}-${e[1]}`,className:"non-working",type:"background",start:t,end:a,style:`background-color: ${this.bgColor}`}}prepareEvent(e,t){const a="Milestone"===e.attributes.type,i=e.attributes.dateStart||e.attributes.dateEnd,n=s.default.utc(i),o=a?void 0:s.default.utc(e.attributes.dateEnd).add(1,"days"),r=a?"point":"range",l=a?void 0:this.getHelper().escapeString(e.attributes.name),d={id:e.id,type:r,group:"task-"+e.id,content:l,start:n,end:o,status:e.attributes.status,groupId:t};return a&&(d.className="milestone",d.isMilestone=!0,d.style="width: 0;height: 0;"),this.fillColor(d),d}fillColor(e){let t=this.taskColor;"non-working"===e.className&&(t=this.bgColor),e.status&&["Completed","Canceled"].includes(e.status)&&(t=this.shadeColor(t,.4)),"Canceled"===e.status&&(e.className||(e.className=""),e.className+=" event-canceled"),e.style=e.style||"",e.style+=`background-color: ${t};`,e.style+=`border-color: ${t};`}shadeColor(e,t){if("transparent"===e)return e;this.getThemeManager().getParam("isDark")&&(t*=-1);const s=e.substring(7),a=parseInt(e.slice(1,7),16),i=t<0?0:255,n=t<0?-1*t:t,o=a>>16,r=a>>8&255,l=255&a;return"#"+(16777216+65536*(Math.round((i-o)*n)+o)+256*(Math.round((i-r)*n)+r)+(Math.round((i-l)*n)+l)).toString(16).slice(1)+s}getTaskRowContent(e){const t=this.getHelper().escapeString(e.attributes.name),s=this.getHelper().escapeString(e.id),a=this.getHelper().escapeString(this.translate("View"));let i="";if(e.attributes.assignedUserId){const t=this.getHelper().getAvatarHtml(e.attributes.assignedUserId,"medium",18);i=`<div class="pull-right" title="${this.getHelper().escapeString(e.attributes.assignedUserName)}">${t}</div>`}return`${`\n            <span\n                class="pull-left fas fa-check-double action icon"\n                style="cursor: pointer"\n                data-action="viewTask"\n                data-id="${s}"\n                title="${a}"\n            ></span>`}<div class="pull-left overflow" style="max-width: calc(100% - 25px); overflow: hidden; text-overflow: ellipsis;" title="${t}">${`\n            <a role="button"\n            class="${"Milestone"===e.attributes.type?"text-info":"text-default"}"\n            data-action="viewTask"\n            data-id="${s}"\n            href="${`#ProjectTask/view/${s}`}"\n        >${t}</a>`}</div>${i}`}getGroupContent(e){const t=`<span class="color-icon fas fa-square" style="color: ${this.getGroupColor(e)}"></span><span class="user-select: none">&nbsp;</span>`,s=this.getHelper().escapeString(e.attributes.name);return`${t} <span class="text-bold text-soft" data-group-id="${this.getHelper().escapeString(e.id)}">${s}</span>`}getGroupColor(e){let t=null;if(null!=e.attributes.color){t=(this.getHelper().themeManager.getParam("chartColorList")||[])[e.attributes.color]}return t||"var(--gray-soft)"}afterRender(){const e=setInterval((()=>{for(const t of document.styleSheets)if(t.href&&t.href.includes("/vis.css"))try{if(t.cssRules,clearInterval(e),this.isRemoved())return;this.initTimeline();break}catch(e){}}),50);this.element.querySelector(".button-container").focus({preventScroll:!0})}initTimeline(){const e=this.element.querySelector(".timeline");this.timeline=new l(e,this.itemDataSet,this.rowDataSet,{start:this.start,end:this.end,dataAttributes:"all",rollingMode:{follow:!1},maxHeight:this.getHelper().calculateContentContainerHeight(e),orientation:"top",verticalScroll:!0,snap:e=>(0,s.default)(e).utc().startOf("day"),locales:{myLocale:{current:this.translate("current","labels","Calendar"),time:this.translate("time","labels","Calendar")}},locale:"myLocale",margin:{item:{vertical:12},axis:6},zoomable:!1,xss:{filterOptions:{onTag:(e,t)=>t}},moment:e=>(0,s.default)(e).utc(),multiselect:!0,editable:{add:!1,updateTime:this.state.hasEditAccess,updateGroup:!1,remove:!1},onMove:async(e,t)=>{if(e.end&&e.start.getTime()===e.end.getTime())return void t(null);const a=(0,s.default)(e.start).format(this.getDateTime().internalDateFormat),i=e.end?(0,s.default)(e.end).subtract(1,"day").format(this.getDateTime().internalDateFormat):null;try{await this.updateEventDates(e.id,a,i);const t=this.getTask(e.id).attributes.groupId;this.orderGroupTasks(t)}catch(e){return void t(null)}t(e)},onInitialDrawComplete:()=>{this.renderSvg(),this.renderDependencies()}}),this.timeline.on("changed",(()=>this.renderDependencies())),this.timeline.on("rangechanged",(()=>this.controlNonWorkingRangesFetch())),this.timeline.on("select",(e=>this.onSelectItems([...e.items]))),this.timeline.itemSet.toggleGroupShowNested=function(){},window.addEventListener("resize",this.resizeHandler)}onSelectItems(e){if(this.state.selectedIds=e,2!==e.length)return this.setSelectionAction(null),void this.renderDependencies();const t=this.taskDependencies.find((t=>t[0]===e[0]&&t[1]===e[1])),s=this.getTask(e[0]),a=this.getTask(e[1]);if(!s||!a)return this.setSelectionAction(null),void this.renderDependencies();if(!this.getAcl().checkModel(a,"edit"))return this.setSelectionAction(null),void this.renderDependencies();const i=t?t[2]:void 0;this.setSelectionAction(t?"unlink":"link",i),this.renderDependencies()}setSelectionAction(e,t=void 0){this.state.selectionAction=e,this.state.selectionDependencyType=t,this.buttonsView.reRender()}renderSvg(){this.svg&&this.svg.parentNode&&this.svg.parentNode.removeChild(this.svg);const e=this.svg=document.createElementNS("http://www.w3.org/2000/svg","svg");e.style.position="absolute",e.style.top="0px",e.style.height="100%",e.style.width="100%",e.style.display="block",e.style.zIndex="0";const t=e=>{const t=document.createElementNS("http://www.w3.org/2000/svg","marker");return t.setAttribute("id",e),t.setAttribute("viewBox","-10 -5 10 10"),t.setAttribute("refX","-7"),t.setAttribute("refY","0"),t.setAttribute("markerUnits","strokeWidth"),t.setAttribute("markerWidth","3"),t.setAttribute("markerHeight","3"),t.setAttribute("orient","auto"),t},s=t("arrow-head"),a=t("arrow-head-selected"),i=document.createElementNS("http://www.w3.org/2000/svg","path");i.setAttribute("d","M 0 0 L -10 -5 L -7.5 0 L -10 5 z"),i.style.fill="var(--gray-light)";const n=i.cloneNode();n.style.fill="var(--brand-warning)",s.appendChild(i),a.appendChild(n),this.svg.appendChild(s),this.svg.appendChild(a),this.element.querySelector(".vis-content").appendChild(this.svg)}renderDependencies(){if(!this.svg)return;this.dependencyPaths&&this.dependencyPaths.forEach((e=>{e.parentNode.removeChild(e)})),this.dependencyPaths=[];const e=e=>{let t=e.left,s=e.width,a=e.height;if(null==e.left)return null;let i=e.parent.top+e.parent.height-e.top-a;e.data.isMilestone&&(t-=4,s=23,a=20,i-=23);let n=t+s;return{midX:Math.round((t+n)/2),midY:Math.round(i+a/2),left:Math.round(t),right:Math.round(n),top:Math.round(i),bottom:Math.round(i+a)}};for(const t of this.taskDependencies){const s=document.createElementNS("http://www.w3.org/2000/svg","path"),a=2===this.state.selectedIds.length&&this.state.selectedIds[0]===t[0]&&this.state.selectedIds[1]===t[1];s.setAttribute("d","M 0 0"),s.setAttribute("marker-end",a?"url(#arrow-head-selected)":"url(#arrow-head)"),s.setAttribute("shape-rendering","optimizeQuality"),s.style.stroke=a?"var(--brand-warning)":"var(--gray-light)",s.style.strokeWidth="2px",s.style.fill="none",s.dataset.pair=`${t[0]}-${t[1]}`;const i=this.timeline.itemSet.items[t[0]],n=this.timeline.itemSet.items[t[1]],o=t[2];if(!i||!n)continue;const r=i.data.groupId,l=n.data.groupId;if(!this.getItem(r)||!this.getItem(l)||this.getItem(r).isCollapsed||this.getItem(l).isCollapsed)continue;const d=this.timeline.getVisibleItems();if(d.indexOf(t[0])<0&&d.indexOf(t[1])<0)continue;const c=e(i),u=e(n);if(null===c||null===u)continue;if(Number.isNaN(c.midY)||Number.isNaN(u.midY))continue;const h=i.data.isMilestone,p=n.data.isMilestone,m=4,f=4,g=12;let w=19;p||(w-=m);const b="sf"===o||"ff"===o,v=null==o||"fs"===o||"ff"===o?c.right:c.left,y=b?u.right+f:u.left-f;let k=c.midY;h||(k+=m);const T=p?u.midY:u.midY-m;let C;if("fs"===o||null==o)C=v>=y-g?`M ${v} ${k} H ${v+g} V ${T-w} H ${y-g+f} V ${T} L ${y} ${T}`:`M ${v} ${k} H ${v+g} V ${T} L ${y} ${T}`;else if("ss"===o)C=v>=y-g?`M ${v} ${k} H ${v-g} V ${T-w} H ${y-g+f} V ${T} L ${y} ${T}`:`M ${v} ${k} H ${v-g} V ${T} L ${y} ${T}`;else if("ff"===o)C=v<=y?`M ${v} ${k} H ${y+g-f} V ${T} L ${y} ${T}`:`M ${v} ${k} H ${v+g} V ${T-w} H ${y+g-f} V ${T} L ${y} ${T}`;else{if("sf"!==o)continue;C=`M ${v} ${k} H ${v-g} V ${T-w} H ${y+g-f} V ${T} L ${y} ${T}`}s.setAttribute("d",C),s.onclick=()=>this.onDependencyClick(t[0],t[1]),this.dependencyPaths.push(s),this.svg.appendChild(s)}}onRemove(){this.timeline&&(this.timeline.destroy(),this.timeline=void 0),window.removeEventListener("resize",this.resizeHandler)}prepareGroupModel(e){const t=this.groupModel.clone();return t.set(e),t.url=`ProjectGroup/${e.id}`,t}prepareTasksCollection(e,t,s=0){const a=this.taskCollection.clone();return t.forEach((e=>a.add(e))),a.url=`ProjectGroup/${e}/ganttTasks`,a.parentModel=this.model,a.total=s,a.orderBy="order",a.order="asc",a.defaultOrderBy=a.orderBy,a.defaultOrder=a.order,a.maxSize=void 0,a.forEach((t=>t.attributes.groupId=e)),this.listenTo(a,"update update-total",(()=>this.controlTotalTaskCount())),a}controlTotalTaskCount(){this.state.totalTaskCount=this.items.reduce(((e,t)=>e+t.tasks.total),0),this.buttonsView.isRendered()&&this.buttonsView.reRender()}isGroupCollapsed(e){return this.getCollapsedGroupIds().includes(e)}async setGroupCollapse(e,t){const s=this.getItem(e);s.isCollapsed=t,t||s.isFetched||this.fetchGroupTasks(e).then((()=>{}));const a=this.items.filter((e=>e.isCollapsed)).map((e=>e.group.id));this.getStorage().set("state",`projectGanttCollapsedGroups-${this.model.id}`,a)}async fetchGroupTasks(e){const t=this.getItem(e);Espo.Ui.notify(" ... "),await t.tasks.fetch(),t.isFetched=!0,Espo.Ui.notify(!1),this.prepareDataSets(),this.updateDataSets()}getItem(e){return this.items.find((t=>t.group.id===e))}getCollapsedGroupIds(){const e=this.getStorage().get("state",`projectGanttCollapsedGroups-${this.model.id}`)||[];return Array.isArray(e)?e:[]}async updateEventDates(e,t,s){let a=null;for(const t of this.items)if(a=t.tasks.get(e),a)break;if(!a)throw new Error;Espo.Ui.notify(" ... "),await a.save({dateStart:t,dateEnd:s},{patch:!0}),Espo.Ui.success(this.translate("Saved"))}onResize(){if(!this.timeline||!this.element)return;const e=this.element.querySelector(".timeline");if(!e)return;const t=this.getHelper().calculateContentContainerHeight(e);this.timeline.setOptions({maxHeight:t})}async viewTask(e){const t=new i.default({entityType:"ProjectTask",id:e});Espo.Ui.notify(" ... "),await this.assignView("dialog",t),await t.render();const s=async()=>{const s=t.model,a=this.getTask(e);a&&(a.attributes.groupId===s.attributes.groupId?(a.setMultiple(s.attributes),this.orderGroupTasks(a.attributes.groupId),this.prepareDataSets(),this.updateDataSets()):await this.refresh())};Espo.Ui.notify(!1),this.listenTo(t.model,"sync",(async()=>s())),this.listenTo(t,"after:save",(async()=>s())),this.listenTo(t,"after:destroy",(async()=>{const t=this.getTask(e);t&&this.getItem(t.attributes.groupId).tasks.remove(e),this.prepareDataSets(),this.updateDataSets()}))}async refresh(){await this.loadGantt(),this.updateDataSets(),this.renderDependencies(),await this.controlNonWorkingRangesFetch()}updateDataSets(){this.timeline.setGroups(this.rowDataSet),this.timeline.setItems(this.itemDataSet)}getTask(e){let t=null;for(const s of this.items)if(t=s.tasks.get(e),t)break;return t}async controlNonWorkingRangesFetch(){if("year"===this.state.scale)return;const e=s.default.utc(this.timeline.getWindow().start).startOf("day"),t=s.default.utc(this.timeline.getWindow().end).subtract(1,"second").endOf("day").add(1,"second"),a=e.isBefore(this.startFetched),i=t.isAfter(this.endFetched);if(!a&&!i)return;let n=e,o=t;a&&!i?o=this.startFetched:!a&&i&&(n=this.endFetched),this.lastFetchNonWorkingRangesPromise&&this.lastFetchNonWorkingRangesPromise.abort(),this.lastFetchNonWorkingRangesRange&&(n=n.isBefore(this.lastFetchNonWorkingRangesRange[0])?n:this.lastFetchNonWorkingRangesRange[0],o=o.isAfter(this.lastFetchNonWorkingRangesRange[1])?o:this.lastFetchNonWorkingRangesRange[1]),this.lastFetchNonWorkingRangesRange=[n,o],this.lastFetchNonWorkingRangesPromise=Espo.Ajax.getRequest(`Project/${this.model.id}/ganttNonWorkingRanges`,{from:n.format(this.getDateTime().internalDateFormat),to:o.format(this.getDateTime().internalDateFormat)}).then((e=>{this.lastFetchNonWorkingRangesPromise=void 0,this.lastFetchNonWorkingRangesRange=void 0,a&&!i?this.startFetched=n:(!a&&i||(this.startFetched=n),this.endFetched=o);const t=e.filter((e=>!this.nonWorkingRanges.find((t=>t[0]===e[0]&&t[1]===e[1]))));this.nonWorkingRanges.forEach((e=>{this.timeline.itemsData.remove(`${e[0]}-${e[1]}`)})),t.forEach((e=>this.nonWorkingRanges.push(e)));const r=[],l=[];for(let e=0;e<this.nonWorkingRanges.length-1;e++){const t=this.nonWorkingRanges[e],a=s.default.utc(t[0]),i=s.default.utc(t[1]);for(let n=e+1;n<this.nonWorkingRanges.length;n++){if(l.includes(n))continue;const o=this.nonWorkingRanges[n],d=s.default.utc(o[0]),c=s.default.utc(o[1]);a.isSame(d)&&i.isSame(c)?(l.push(e,n),r.push([t[0],t[1]])):i.isAfter(d)&&i.isSameOrBefore(c)?(r.push([t[0],o[1]]),l.push(e,n)):c.isAfter(a)&&c.isSameOrBefore(i)?(r.push([o[0],t[1]]),l.push(e,n)):a.isBefore(d)&&i.isAfter(c)?(r.push([t[0],t[1]]),l.push(e,n)):d.isBefore(a)&&c.isAfter(i)&&(r.push([o[0],o[1]]),l.push(e,n))}}this.nonWorkingRanges=this.nonWorkingRanges.filter(((e,t)=>!l.includes(t))),r.forEach((e=>this.nonWorkingRanges.push(e))),this.nonWorkingRanges=this.nonWorkingRanges.filter(((e,t)=>!this.nonWorkingRanges.find(((s,a)=>t!==a&&e[0]===s[0]&&e[1]===s[1])))),this.nonWorkingRanges.forEach((e=>{this.timeline.itemsData.add(this.prepareBackgroundEvent(e))}))}))}async addDependency(){const e=this.state.selectedIds;if(!e[1])return;const t=this.getTask(e[1]);if(!t)return;const s=[...t.attributes.fromTasksIds||[]],a={...t.attributes.fromTasksColumns};if(!s.includes(e[0])){s.push(e[0]);const t=this.getMetadata().get("entityDefs.ProjectTask.fields.dependencyTaskType.default");a[e[0]]={type:t}}Espo.Ui.notify(" ... "),await t.save({fromTasksIds:s,fromTasksColumns:a},{patch:!0}),await this.refresh(),Espo.Ui.notify(!1),this.timeline.setSelection(e),this.onSelectItems(e)}async removeDependency(){const e=this.state.selectedIds;if(!e[1])return;const t=e[0],s=e[1],a=this.getTask(t),i=this.getTask(s);if(!a||!i)return;const n=async(t,s)=>{const a=[...t.attributes.fromTasksIds||[]],i=a.findIndex((e=>e===s));~i&&a.splice(i,1),Espo.Ui.notify(" ... "),await t.save({fromTasksIds:a},{patch:!0}),await this.refresh(),Espo.Ui.notify(!1),this.timeline.setSelection(e),this.onSelectItems(e)};(i.attributes.fromTasksIds||[]).includes(t)?await n(i,t):(a.attributes.fromTasksIds||[]).includes(s)&&await n(a,s)}onKeyDown(e){"Control+Space"===Espo.Utils.getKeyFromKeyEvent(e)&&(e.stopPropagation(),e.preventDefault(),this.createTask())}onDependencyClick(e,t){this.timeline.setSelection([e,t]),this.onSelectItems([e,t])}orderGroupTasks(e,t=!1){const s=this.getItem(e),a=s.tasks.models.map((e=>e.id));if(s.tasks.models.sort(((e,t)=>{const s=e.attributes.dateStart,a=t.attributes.dateStart;if(!s||!a)return s&&a?0:s?1:0;const i=this.getDateTime().toMomentDate(s),n=this.getDateTime().toMomentDate(a);return i.unix()===n.unix()?e.attributes.order-t.attributes.order:i.unix()-n.unix()})),t)return;let i=!1;for(const[e,t]of a.entries())if(t!==s.tasks.models[e].id){i=!0;break}i&&(this.prepareDataSets(),this.updateDataSets(),this.timeline.setSelection(this.state.selectedIds))}}e.default=c})),define("modules/project/views/project/record/board",["exports","view","views/record/kanban","modules/project/views/project/record/board/buttons","helpers/list/select-provider","views/modals/edit","helpers/list/settings","view-record-helper"],(function(e,t,s,a,i,n,o,r){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=l(t),s=l(s),a=l(a),i=l(i),n=l(n),o=l(o),r=l(r);class d extends t.default{templateContent='\n        <div\n            class="button-container list-buttons-container clearfix"\n            data-role="buttons"\n            tabindex="-1"\n        >{{{buttons}}}</div>\n        <div class="board-record">{{{record}}}</div>\n    ';primaryFilter="actualParent";collection;buttonsView;kanbanView;taskSelect;storageKey;groupsLoaded=!1;showCompletedStorageKey;constructor(e){super(e),this.state={groupId:this.model.attributes.activeGroupId,groupName:this.model.attributes.activeGroupName,groups:this.model.attributes.activeGroupId?[{id:this.model.attributes.activeGroupId,name:this.model.attributes.activeGroupName}]:[],hasCreateTaskAccess:!1,hasEditAccess:!1,kanbanLayout:void 0,totalTaskCount:void 0,showCompleted:void 0}}setup(){this.setupStored(),this.controlAccess(),this.setupFilter(),this.setPrimaryFilter(),this.setupListSettingsHelper(),this.wait(this.setupBoard()),this.setupButtonsView(),this.loadGroups(),this.addActionHandler("createTask",(()=>this.createTask())),this.addActionHandler("createMilestone",(()=>this.createTask(!0))),this.addActionHandler("toggleShowCompleted",(()=>this.toggleShowCompleted())),this.addHandler("keydown.project","",(e=>this.onKeyDown(e))),this.listenTo(this.model,"update-all",(()=>this.collection.fetch()))}setupFilter(){this.showCompletedStorageKey=`projectBoardShowCompleted-${this.model.id}`,this.state.showCompleted=!1,this.getStorage().has("state",this.showCompletedStorageKey)&&(this.state.showCompleted=this.getStorage().get("state",this.showCompletedStorageKey))}setPrimaryFilter(){this.primaryFilter=this.state.showCompleted?"actualOrCompletedParent":"actualParent"}async controlTotalTaskCount(){this.state.totalTaskCount=this.collection.total,await this.buttonsView.whenReady(),await this.buttonsView.reRender()}setupStored(){if(this.storageKey=`projectBoardGroup-${this.model.id}`,!this.getStorage().has("state",this.storageKey))return;const e=this.getStorage().get("state",this.storageKey);if(!Array.isArray(e))return;this.state.groupId=e[0],this.state.groupName=e[1];const t=e[2];this.state.groups.length&&this.state.groups.find((e=>e.id===this.state.groupId))||this.state.groups.push({id:this.state.groupId,name:this.state.groupName,color:t})}controlAccess(){if(this.state.hasCreateTaskAccess=!1,this.state.hasEditAccess=!1,this.getAcl().checkModel(this.model,"edit"))return this.state.hasCreateTaskAccess=!0,void(this.state.hasEditAccess=!0);if(void 0===this.model.attributes.memberRoleData)return void this.listenToOnce(this.model,"sync",(async()=>{this.controlAccess(),await this.buttonsView.whenReady(),await this.buttonsView.reRender(),await this.kanbanView.whenReady(),this.kanbanView.setCanCreate(this.state.hasCreateTaskAccess),this.kanbanView.setCanReOrder(this.state.hasEditAccess)}));const e=this.model.attributes.memberRoleData;return e?"Owner"===e.role||"Editor"===e.role?(this.state.hasCreateTaskAccess=!0,void(this.state.hasEditAccess=!0)):void("yes"===e.permissions.taskCreate&&(this.state.hasCreateTaskAccess=!0)):void 0}async setupBoard(){await this.loadKanbanLayout(),await this.loadTaskSelect(),this.state.groupId||(await this.loadGroups(),this.state.groupId=this.state.groups[0].id,this.state.groupName=this.state.groups[0].name),await this.setupCollection(),await this.setupKanbanView()}async loadKanbanLayout(){this.state.kanbanLayout=await new Promise((e=>{this.getHelper().layoutManager.get("ProjectTask","kanbanForProject",e)}))}afterRender(){this.collection.lastSyncPromise||this.processFetch(),this.element.querySelector(".button-container").focus({preventScroll:!0})}setupListSettingsHelper(){this.listSettingsHelper=new o.default("ProjectTask","kanbanForProject",this.getUser().id,this.getStorage())}async processFetch(){Espo.Ui.notify(" ... "),await this.collection.fetch(),Espo.Ui.notify(!1)}setupButtonsView(){this.buttonsView=new a.default({state:this.state,onGroupChange:e=>this.changeGroup(e),model:this.model,listSettingsHelper:this.listSettingsHelper,onSettingsChange:async()=>{await this.kanbanView.rebuild(),await this.kanbanView.reRender()}}),this.assignView("buttons",this.buttonsView,'[data-role="buttons"]')}async loadTaskSelect(){const e=new i.default(this.getHelper().layoutManager,this.getHelper().metadata,this.getHelper().fieldManager);this.taskSelect=await e.get("ProjectTask","kanbanForProject")}async loadGroups(){const e=await Espo.Ajax.getRequest(`Project/${this.model.id}/groups`);if(this.state.groups=e.list.map((e=>({id:e.id,name:e.name,color:e.color}))),this.groupsLoaded=!0,!this.buttonsView)return;(async()=>{await this.buttonsView.whenReady(),await this.buttonsView.reRender()})().then((()=>{}))}async setupCollection(){this.collection=await this.getCollectionFactory().create("ProjectTask"),this.collection.url=`ProjectGroup/${this.state.groupId}/board`,this.collection.maxSize=this.getConfig().get("recordsPerPageKanban"),this.collection.data.select=this.taskSelect.join(","),this.collection.data.primaryFilter=this.primaryFilter,this.collection.defaultOrderBy="boardOrder",this.collection.defaultOrder="asc",this.collection.orderBy=this.collection.defaultOrderBy,this.collection.order=this.collection.defaultOrder,this.collection.parentModel=this.model,this.listenTo(this.collection,"sync update-total",(()=>this.controlTotalTaskCount()))}async setupKanbanView(){const e=new s.default({collection:this.collection,layoutName:"kanbanForProject",canChangeGroup:!0,canCreate:this.state.hasCreateTaskAccess,canReOrder:this.state.hasEditAccess,moveOverRowAction:!1,statusField:"columnId",skipBuildRows:!0,groupChangeSaveHandler:async e=>{const t=await Espo.Ajax.putRequest(`ProjectTask/${e.id}/column`,{columnId:e.attributes.columnId});e.set(t),e.trigger("sync")},onGroupOrder:(e,t)=>this.groupOrder(e,t),createActionHandler:e=>this.createInColumn(e),settingsHelper:this.listSettingsHelper,settingsEnabled:!0,topBarDisabled:!0,keepCurrentRootUrl:!0,additionalRowActionList:["selfAssign"]});await this.assignView("record",e,".board-record"),this.kanbanView=e}async createTask(e=!1){const t=new r.default;t.setFieldStateParam("memberRoleData","isMember",!!this.model.attributes.memberRoleData);const s=new n.default({entityType:"ProjectTask",attributes:{assignedUserId:null,assignedUserName:null,projectId:this.model.attributes.id,projectName:this.model.attributes.name,boardId:this.model.attributes.boardId,groupId:this.state.groupId,groupName:this.state.groupName,groupColor:this.state.groups.find((e=>e.id===this.state.groupId))?.color,columnId:this.model.attributes.firstColumnId,columnName:this.model.attributes.firstColumnName,memberRoleData:this.state.hasEditAccess?{role:"Owner",permissions:{}}:this.model.attributes.memberRoleData,type:e?"Milestone":"Task"},recordHelper:t,headerText:e?this.translate("Create Milestone","labels","ProjectTask"):void 0,focusForCreate:!0});await this.assignView("dialog",s),s.getRecordView().hideField("project",!0),s.getRecordView().hideField("owner",!0),s.getRecordView().setFieldReadOnly("group",!0),await s.render(),this.listenTo(s,"after:save",(async e=>{await this.kanbanView.storeGroupOrder(e.attributes.columnId,e.id),await this.collection.fetch({maxSize:this.collection.maxSize})}))}async createInColumn(e){const t=new r.default;t.setFieldStateParam("memberRoleData","isMember",!!this.model.attributes.memberRoleData);const s=new n.default({entityType:"ProjectTask",attributes:{columnId:e,projectId:this.model.id,projectName:this.model.attributes.name,boardId:this.model.attributes.boardId,groupId:this.state.groupId,groupName:this.state.groupName,groupColor:this.state.groups.find((e=>e.id===this.state.groupId))?.color,assignedUserId:null,assignedUserName:null,memberRoleData:this.state.hasEditAccess?{role:"Owner",permissions:{}}:this.model.attributes.memberRoleData},focusForCreate:!0,recordHelper:t});Espo.Ui.notify(" ... "),await this.assignView("dialog",s),s.getRecordView().hideField("project",!0),s.getRecordView().hideField("owner",!0),s.getRecordView().setFieldReadOnly("group",!0),await s.render(),Espo.Ui.notify(!1),this.listenTo(s,"after:save",(async t=>{await this.kanbanView.storeGroupOrder(e,t.id),await this.collection.fetch({maxSize:this.collection.maxSize})}))}async groupOrder(e,t){Espo.Ui.notify(" ... "),await Espo.Ajax.postRequest(`ProjectGroup/${this.state.groupId}/boardOrder`,{columnId:e,ids:t}),Espo.Ui.notify(!1)}async changeGroup(e){this.state.groupId=e,this.state.groupName=this.state.groups.find((t=>t.id===e)).name;const t=this.state.groups.find((t=>t.id===e))?.color;this.getStorage().set("state",this.storageKey,[e,this.state.groupName,t]),await this.buttonsView.reRender(),await this.setupCollection(),await this.setupKanbanView(),await this.processFetch()}onKeyDown(e){"Control+Space"===Espo.Utils.getKeyFromKeyEvent(e)&&(e.stopPropagation(),e.preventDefault(),this.createTask())}async toggleShowCompleted(){this.state.showCompleted=!this.state.showCompleted,this.getStorage().set("state",this.showCompletedStorageKey,this.state.showCompleted),this.setPrimaryFilter(),this.collection.data.primaryFilter=this.primaryFilter,Espo.Ui.notify(" ... "),await this.buttonsView.reRender(),await this.collection.fetch(),await this.kanbanView.rebuild(),await this.kanbanView.reRender(),Espo.Ui.notify(!1)}}e.default=d})),define("modules/project/views/dashlets/project-tasks",["exports","views/dashlets/abstract/record-list"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{listView="views/record/list-expanded";additionalRowActionList=["complete"];getSearchData(){const e=Espo.Utils.cloneDeep(super.getSearchData());e.advanced={};const t=this.getOption("futureDays");let s;return s=null!=t?{type:"or",value:[{type:"nextXDays",attribute:"dateStart",value:t},{type:"isNull",attribute:"dateStart"},{type:"past",attribute:"dateStart"}]}:{type:"or",value:[{type:"today",field:"dateStart"},{type:"past",field:"dateStart"},{type:"isNull",field:"dateStart"}]},e.advanced.dateStart=s,this.getOption("includeOwn")&&(e.bool||(e.bool={}),e.bool.own=!0),e}}e.default=a})),define("modules/project/handlers/user/change-project-role-row-action",["exports","handlers/row-action","modules/project/views/project/modals/select-role"],(function(e,t,s){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=a(t),s=a(s);class i extends t.default{async process(e,t){if(!e.collection||!e.collection.parentModel)return void console.error("Project model cannot be obtained.");const a=e.collection.parentModel,i=new s.default({members:[e],role:e.attributes.projectRoleId||e.attributes.projectRole,onSelect:async t=>{Espo.Ui.notify(" ... "),await Espo.Ajax.postRequest(`Project/${a.id}/members`,{ids:[e.id],role:t}),Espo.Ui.success(this.view.translate("Done")),await this.collection.fetch()}});await this.view.assignView("dialog",i),await i.render()}isAvailable(e,t){return!(!e.collection||!e.collection.parentModel)&&this.view.getAcl().checkModel(e.collection.parentModel,"edit")}}e.default=i})),define("modules/project/handlers/project-task/select-project",["exports"],(function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;e.default=class{async getAttributes(e){return{boardId:e.attributes.boardId,groupId:null,groupName:null,columnId:e.attributes.firstColumnId,columnName:e.attributes.firstColumnName,fromTasksIds:[],fromTasksNames:{},fromTasksColumns:{}}}async getClearAttributes(){return{boardId:null,groupId:null,groupName:null,columnId:null,columnName:null,fromTasksIds:[],fromTasksNames:{},fromTasksColumns:{}}}}})),define("modules/project/handlers/project-task/select-owner",["exports"],(function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;e.default=class{constructor(e){this.viewHelper=e,this.user=e.user}async getFilters(e){const t=e.attributes.memberRoleData;return t&&e.attributes.projectId?!this.user.isAdmin()&&t.permissions&&"own"===t.permissions.taskAssignment?{bool:["onlyMe"]}:{advanced:{projects:{type:"linkedWith",attribute:"projects",value:[e.attributes.projectId],data:{type:"anyOf",nameHash:{[e.attributes.projectId]:e.attributes.projectName}}}}}:{}}}})),define("modules/project/handlers/project-task/select-group",["exports"],(function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;e.default=class{async getFilters(e){return e.attributes.projectId?{advanced:{project:{attribute:"projectId",type:"equals",value:e.attributes.projectId,data:{type:"is",nameValue:e.attributes.projectName}}}}:{}}}})),define("modules/project/handlers/project-task/select-from-tasks",["exports"],(function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;e.default=class{async getFilters(e){if(!e.attributes.projectId)return{};const t={project:{attribute:"projectId",type:"equals",value:e.attributes.projectId,data:{type:"is",nameValue:e.attributes.projectName}}};return e.isNew()||(t.id={attribute:"id",type:"notEquals",value:e.attributes.id}),e.attributes.parentTaskId?t.parentTask={attribute:"parentTaskId",type:"equals",value:e.attributes.parentTaskId,data:{type:"is",nameValue:e.attributes.parentTaskName}}:t.parentTask={attribute:"parentTaskId",type:"isNull",data:{type:"isEmpty"}},{advanced:t}}}})),define("modules/project/handlers/project-task/row-action-self-assign",["exports","handlers/row-action","modules/project/helpers/member-task-access"],(function(e,t,s){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=a(t),s=a(s);class i extends t.default{isAvailable(e,t){return null===e.attributes.assignedUserId&&("Completed"!==e.attributes.status&&"Canceled"!==e.attributes.status&&(!(null===e.attributes.memberRoleData||e.collection&&e.collection.parentModel&&null===e.collection.parentModel.attributes.memberRoleData)&&!!new s.default(this.view.getUser()).checkEdit(e)))}async process(e,t){Espo.Ui.notify(" ... ");try{await e.save({assignedUserId:this.view.getUser().id,assignedUserName:this.view.getUser().attributes.name})}catch(t){e.setMultiple({assignedUserId:null,assignedUserName:null})}Espo.Ui.success(this.view.translate("Self-Assigned"))}}e.default=i})),define("modules/project/handlers/project-task/row-action-move",["exports","handlers/row-action"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{isAvailable(e,t){if(!this.hasAccess(e))return!1;const s=e.collection;return!!s&&(("moveToTop"!==t||0!==s.models.findIndex((t=>t===e)))&&("moveToBottom"!==t||s.models.findIndex((t=>t===e))!==s.models.length-1))}async process(e,t){Espo.Ui.notify(" ... "),await Espo.Ajax.postRequest(`ProjectTask/${e.id}/moveInGroup`,{placement:"moveToBottom"===t?"bottom":"top"}),await e.collection.fetch();const s="moveToBottom"===t?"movedToBottom":"movedToTop";Espo.Ui.success(this.view.getLanguage().translate(s,"messages","ProjectTask"))}hasAccess(e){if(e.collection&&e.collection.parentModel&&this.view.getAcl().checkModel(e.collection.parentModel,"edit"))return!0;const t=this.getMemberRoleData(e);return!(!t||!["Owner","Editor"].includes(t.role))}getMemberRoleData(e){let t;return e.collection&&e.collection.parentModel&&(t=e.collection.parentModel.attributes.memberRoleData),t}}e.default=a})),define("modules/project/handlers/project-task/row-action-complete",["exports","handlers/row-action","modules/project/helpers/member-task-access"],(function(e,t,s){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=a(t),s=a(s);class i extends t.default{isAvailable(e,t){return"Completed"!==e.attributes.status&&"Canceled"!==e.attributes.status&&(!e.collection||!e.collection.parentModel&&!e.attributes.memberRoleData||!!new s.default(this.view.getUser()).checkColumnEdit(e))}async process(e,t){Espo.Ui.notify(" ... ");const s=await Espo.Ajax.postRequest(`ProjectTask/${e.id}/complete`);e.set(s),Espo.Ui.success(this.view.getLanguage().translateOption("Completed","status","ProjectTask"))}}e.default=i})),define("modules/project/handlers/project-task/row-action-change-column",["exports","handlers/row-action","modules/project/helpers/member-task-access","modules/project/views/project-task/modals/select-column"],(function(e,t,s,a){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=i(t),s=i(s),a=i(a);class n extends t.default{isAvailable(e,t){return!!e.attributes.columnId&&(!e.collection||!e.collection.parentModel&&!e.attributes.memberRoleData||!!new s.default(this.view.getUser()).checkColumnEdit(e))}async process(e,t){const s=e.attributes.boardId;if(!s)throw new Error("No boardId.");const i=this.view.getHelper().getAppParam("projectBoards")||{};if(!i[s])throw new Error(`No data for board ${s}.`);const n=new a.default({model:e,columns:i[s].columns.map((e=>({id:e[0],name:e[1]}))),onSelect:async t=>{Espo.Ui.notify(" ... ");const s=await Espo.Ajax.putRequest(`ProjectTask/${e.id}/column`,{columnId:t});e.set(s),Espo.Ui.success(this.view.translate("Done"))}});await this.view.assignView("dialog",n),await n.render()}}e.default=n})),define("modules/project/handlers/project-task/record",["exports"],(function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;e.default=class{constructor(e){this.view=e,this.model=e.model}process(){void 0!==this.model.attributes.memberRoleData?this.controlMember():this.view.listenToOnce(this.model,"sync",(()=>this.controlMember())),this.model.isNew()&&this.model.attributes.projectId&&this.model.attributes.parentTaskId&&(this.view.hideField("project",!0),this.view.setFieldReadOnly("group",!0)),this.view.listenTo(this.model,"after:relate:subTasks after:unrelate:subTasks after:related-change:subTasks",(()=>this.model.fetch()))}controlMember(){const e=this.model.attributes.memberRoleData;e&&e.permissions&&"own"===e.permissions.taskAssignment&&this.view.setFieldReadOnly("owner",!0)}}})),define("modules/project/handlers/project-task/record-list",["exports","draggable-project"],(function(e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;e.default=class{draggable;blockDraggable=!1;constructor(e){this.view=e,this.collection=e.collection,this.acl=e.getAcl()}process(){this.collection.parentModel&&"ProjectTask"===this.collection.parentModel.entityType&&this.view.whenRendered().then((()=>this.initDraggable()))}initDraggable(){this.draggable&&this.draggable.destroy();this.view.element.style.userSelect="none";const e=t.Draggable.Sensors.TouchSensor,s=new t.Draggable(this.view.element,{distance:8,draggable:"tr.list-row",mirror:{cursorOffsetX:5,cursorOffsetY:5,appendTo:"body"},exclude:{sensors:[e]}});this.draggable=s;const a=[];let i=null,n=null,o=!1,r=[];s.on("mirror:created",(e=>{const t=e.mirror,s=e.source,a=e.originalSource;a.dataset.wasActive=a.classList.contains("active")?"true":"",a.classList.add("active"),a.style.display="",s.style.display="none",t.innerText=this.view.translate("Moving","labels","ProjectTask"),r.length>1&&(t.innerText+=" · "+r.length.toString()),t.style.display="block",t.style.cursor="grabbing",t.classList.add("draggable-helper"),t.style.pointerEvents="auto"})),s.on("mirror:move",(e=>{e.mirror.style.pointerEvents="auto"})),s.on("drag:start",(e=>{!this.blockDraggable&&this.acl.checkModel(this.collection.parentModel,"edit")&&"order"===this.collection.orderBy&&"asc"===this.collection.order?(i=e.source.dataset.id,r=[i],this.view.getCheckedIds().includes(i)&&(r=this.view.getCheckedIds().sort(((e,t)=>this.collection.models.findIndex((t=>t.id===e))-this.collection.models.findIndex((e=>e.id===t))))),e.sourceContainer.querySelectorAll("tr.list-row").forEach((t=>{t!==e.source&&a.push({id:t instanceof HTMLElement?t.dataset.id:void 0,element:t})}))):e.cancel()})),s.on("drag:move",(e=>{o=!1,n=null;for(const t of a){const s=t.element.getBoundingClientRect();i!==t.id&&s.left<e.sensorEvent.clientX&&s.right>e.sensorEvent.clientX&&s.top<e.sensorEvent.clientY&&s.bottom>e.sensorEvent.clientY?(n=t.id,e.sensorEvent.clientY-s.top<s.bottom-e.sensorEvent.clientY?(t.element.classList.add("border-top-highlighted"),t.element.classList.remove("border-bottom-highlighted")):(t.element.classList.add("border-bottom-highlighted"),t.element.classList.remove("border-top-highlighted"),o=!0)):(t.element.classList.remove("border-top-highlighted"),t.element.classList.remove("border-bottom-highlighted"))}})),s.on("drag:stop",(e=>{a.forEach((e=>{e.element.classList.remove("border-bottom-highlighted"),e.element.classList.remove("border-top-highlighted")})),a.splice(0,a.length);const t=e.originalSource;"true"!==t.dataset.wasActive&&t.classList.remove("active"),n&&(this.blockDraggable=!0,this.placeTasks(r,n,o).then((()=>this.blockDraggable=!1))),i=null,n=null,o=!1,r=[]}))}async placeTasks(e,t,s){const a=[];for(const i of this.collection.models){if(i.id===t){s&&a.push(i);break}e.includes(i.id)||a.push(i)}e.forEach((e=>{a.push(this.collection.get(e))})),this.collection.models.forEach((e=>{a.find((t=>t.id===e.id))||a.push(e)})),this.collection.remove(a),this.collection.add(a),this.view.rebuild().then((()=>this.view.reRender())),Espo.Ui.notify(" ... ");try{await Espo.Ajax.postRequest(`ProjectTask/${this.collection.parentModel.id}/subTaskReOrder`,{ids:e,targetId:t,isAfter:s})}catch(e){return void await this.collection.fetch()}this.collection.parentModel.trigger("update-all"),Espo.Ui.success(this.view.translate("Moved","labels","ProjectTask"))}}})),define("modules/project/handlers/project-task/record-action",["exports","action-handler","modules/project/helpers/member-task-access","modules/project/views/project-task/modals/select-column"],(function(e,t,s,a){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=i(t),s=i(s),a=i(a);class n extends t.default{hasComplete(){const e=this.view.model;return"Completed"!==e.attributes.status&&"Canceled"!==e.attributes.status&&!!new s.default(this.view.getUser()).checkColumnEdit(e)}hasCancel(){const e=this.view.model;return"Completed"!==e.attributes.status&&"Canceled"!==e.attributes.status&&!!new s.default(this.view.getUser()).checkEdit(e)}hasChangeColumn(){const e=this.view.model;return!!e.attributes.columnId&&(!e.collection||!e.collection.parentModel&&!e.attributes.memberRoleData||!!new s.default(this.view.getUser()).checkColumnEdit(e))}async complete(){const e=this.view.model;Espo.Ui.notify(" ... ");const t=await Espo.Ajax.postRequest(`ProjectTask/${e.id}/complete`);e.set(t),e.trigger("sync"),Espo.Ui.success(this.view.getLanguage().translateOption("Completed","status","ProjectTask"))}async cancel(){const e=this.view.model;await this.view.confirm(this.view.translate("cancelConfirmation","messages","ProjectTask")),Espo.Ui.notify(" ... ");const t=await Espo.Ajax.postRequest(`ProjectTask/${e.id}/cancel`);e.set(t),e.trigger("sync"),Espo.Ui.info(this.view.getLanguage().translateOption("Canceled","status","ProjectTask"))}async changeColumn(){const e=this.view.model,t=e.attributes.boardId;if(!t)throw new Error("No boardId.");const s=this.view.getHelper().getAppParam("projectBoards")||{};if(!s[t])throw new Error(`No data for board ${t}.`);const i=new a.default({model:e,columns:s[t].columns.map((e=>({id:e[0],name:e[1]}))),onSelect:async t=>{Espo.Ui.notify(" ... ");const s=await Espo.Ajax.putRequest(`ProjectTask/${e.id}/column`,{columnId:t});e.set(s),e.trigger("sync"),Espo.Ui.success(this.view.translate("Done"))}});await this.view.assignView("dialog",i),await i.render()}async selfAssign(){const e=this.view.model;Espo.Ui.notify(" ... ");try{await e.save({assignedUserId:this.view.getUser().id,assignedUserName:this.view.getUser().attributes.name})}catch(t){e.setMultiple({assignedUserId:null,assignedUserName:null})}Espo.Ui.success(this.view.translate("Self-Assigned"))}hasSelfAssign(){const e=this.view.model;return null===e.attributes.assignedUserId&&(null!==e.attributes.memberRoleData&&("Completed"!==e.attributes.status&&"Canceled"!==e.attributes.status&&!!new s.default(this.view.getUser()).checkEdit(e)))}}e.default=n})),define("modules/project/handlers/project-task/mass-action",["exports"],(function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;e.default=class{constructor(e){this.view=e}async complete(e){await this.view.confirm(this.view.translate("massCompleteConfirmation","messages","ProjectTask")),Espo.Ui.notify(" ... ");const t=await Espo.Ajax.postRequest("MassAction",{entityType:"ProjectTask",action:"complete",params:e.params});if(0===t.count)return void Espo.Ui.warning(this.view.translate("noRecordsUpdated","messages"));await this.view.collection.fetch();const s=e.params.ids;s&&s.forEach((e=>this.view.checkRecord(e)));const a=this.view.translate("massCompleteDone","messages","ProjectTask").replace("{count}",t.count.toString());Espo.Ui.success(a)}}})),define("modules/project/handlers/project-task/defaults-preparator",["exports","handlers/model/defaults-preparator","model"],(function(e,t,s){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=a(t),s=a(s);class i extends t.default{prepare(e){return Promise.resolve({ownerId:this.viewHelper.user.id,ownerName:this.viewHelper.user.attributes.name})}}e.default=i})),define("modules/project/handlers/project-task/create-sub-task",["exports"],(function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;e.default=class{constructor(e){this.viewHelper=e}async getAttributes(e){let t=null,s=null;if(e.attributes.boardId){const a=this.viewHelper.getAppParam("projectBoards")||{};if(a[e.attributes.boardId]){const i=a[e.attributes.boardId].columns;i.length&&(t=i[0][0],s=i[0][1])}}return{assignedUserId:null,assignedUserName:null,boardId:e.attributes.boardId,groupId:e.attributes.groupId,groupName:e.attributes.groupName,groupColor:e.attributes.groupColor,columnId:t,columnName:s,fromTasksIds:[],fromTasksNames:{},fromTasksColumns:{}}}}})),define("modules/project/handlers/project-role/setup-record-edit",["exports"],(function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;e.default=class{constructor(e){this.view=e,this.model=e.model}process(){this.model.id||this.view.on("after:save",(()=>{this.view.getHelper().appParams&&this.view.getHelper().appParams.load&&(this.view.getHelper().appParams.load(),this.view.getHelper().broadcastChannel.postMessage("update:appParams"))}))}}})),define("modules/project/handlers/project-column/row-actions/move-up",["exports","handlers/row-action"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{process(e,t){Espo.Ui.notify(" ... "),Espo.Ajax.postRequest(`ProjectColumn/${e.id}/moveUp`).then((()=>{this.collection.fetch().then((()=>Espo.Ui.success(this.view.translate("Done"))))}))}isAvailable(e,t){const s=this.collection.models.findIndex((t=>t===e));if(s<0||0===s)return!1;if("Deferred"===e.attributes.mappedStatus)return!0;const a=this.collection.at(s-1);return!(!a||a.attributes.mappedStatus!==e.attributes.mappedStatus)}}e.default=a})),define("modules/project/handlers/project-column/row-actions/move-down",["exports","handlers/row-action"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{process(e,t){Espo.Ui.notify(" ... "),Espo.Ajax.postRequest(`ProjectColumn/${e.id}/moveDown`).then((()=>{this.collection.fetch().then((()=>Espo.Ui.success(this.view.translate("Done"))))}))}isAvailable(e,t){const s=this.collection.models.findIndex((t=>t===e));if(s<0)return!1;if(s===this.collection.total-1)return!1;if("Deferred"===e.attributes.mappedStatus)return!0;const a=this.collection.at(s+1);return!a||a.attributes.mappedStatus===e.attributes.mappedStatus}}e.default=a})),define("modules/project/handlers/project/select-members",["exports"],(function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;e.default=class{constructor(e){this.viewHelper=e}async getFilters(e){const t=this.viewHelper.acl.getPermissionLevel("assignment");return"team"===t?Promise.resolve({bool:["onlyMyTeam"]}):"no"===t?Promise.resolve({bool:["onlyMe"]}):{}}}})),define("modules/project/handlers/project/select-members-action",["exports","views/modals/select-records","modules/project/views/project/modals/select-role"],(function(e,t,s){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=a(t),s=a(s);e.default=class{constructor(e){this.view=e,this.model=e.model,this.collection=e.collection}async select(){const e=this.view.getAcl().getPermissionLevel("assignment"),a=[];"team"===e&&a.push("onlyMyTeam"),"no"===e&&a.push("onlyMe");const i=new t.default({entityType:"User",multiple:!0,createButton:!1,boolFilterList:a,filters:{projects:{type:"notLinkedWith",attribute:"projects",value:[this.model.id],data:{type:"noneOf",nameHash:{[this.model.id]:this.model.attributes.name}}}}});this.view.listenToOnce(i,"select",(async e=>{const t=new s.default({members:e,onSelect:async t=>{Espo.Ui.notify(" ... "),await Espo.Ajax.postRequest(`Project/${this.model.id}/members`,{ids:e.map((e=>e.attributes.id)),role:t}),await this.collection.fetch(),Espo.Ui.success(this.view.translate("Done")),this.model.trigger("after:relate"),this.model.trigger("after:relate:members")}});await this.view.assignView("dialog",t),await t.render()})),await this.view.assignView("dialog",i),await i.render()}}})),define("modules/project/handlers/project/detail",["exports","modules/project/views/project/record/plan","modules/project/helpers/member-task-access"],(function(e,t,s){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=a(t),s=a(s);e.default=class{constructor(e){this.view=e,this.model=e.model}process(){this.model.attributes.ganttView||this.view.hideViewMode("gantt"),this.view.listenTo(this.model,"change:ganttView",((e,t,s)=>{s.syncSettings&&(this.model.attributes.ganttView?this.view.showViewMode("gantt"):this.view.hideViewMode("gantt"))})),this.view.shortcutKeys||(this.view.shortcutKeys={}),this.view.shortcutKeys["Control+Backspace"]=e=>{this.onShortcutControlBackspace(e)}}onShortcutControlBackspace(e){const s=this.view.getRecordView();if(s instanceof t.default){let t=s.getCheckedTasks();if(!t.length)return;if(e.target instanceof HTMLTextAreaElement||e.target instanceof HTMLInputElement&&"checkbox"!==e.target.type)return;if(e.preventDefault(),e.stopPropagation(),t=this.filterTasksForComplete(t),!t.length)return;this.massComplete(t,s)}}filterTasksForComplete(e){const t=new s.default(this.view.getUser());return e.filter((e=>e.attributes.status&&!["Completed","Canceled"].includes(e.attributes.status)&&t.checkColumnEdit(e)))}async massComplete(e,t){Espo.Ui.notify(" ... ");const s=e.map((e=>e.id)),a=await Espo.Ajax.postRequest("MassAction",{entityType:"ProjectTask",action:"complete",params:{ids:s}});if(0===a.count)return void Espo.Ui.warning(this.view.translate("noRecordsUpdated","messages"));for(const e of t.getItems())if(s.find((t=>e.tasks.get(t)))){await e.tasks.fetch();break}t.checkTasks(s);let i=this.view.translate("massCompleteDone","messages","ProjectTask").replace("{count}",a.count.toString());1===s.length&&(i=this.view.translate("Completed","labels","ProjectTask")),Espo.Ui.success(i)}}})),define("modules/project/handlers/project/detail-action",["exports","action-handler","modules/project/views/project/modals/settings","modules/project/views/project/modals/clone"],(function(e,t,s,a){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=i(t),s=i(s),a=i(a);class n extends t.default{async viewSettings(){const e=this.view.model.clone(),t=new s.default({model:e,afterSave:e=>{this.view.model.setMultiple(e,{syncSettings:!0})}});await this.view.assignView("dialog",t),await t.render()}async clone(){const e=this.view.model.clone(),t=new a.default({model:e});await this.view.assignView("dialog",t),await t.render()}hasClone(){const e=this.view.model;return!!this.view.getAcl().checkScope("Project","create")&&this.view.getAcl().checkModel(e,"edit")}}e.default=n})),define("modules/project/handlers/project/relationships/select-active-group",["exports"],(function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;e.default=class{getFilters(e){return Promise.resolve({advanced:{project:{type:"equals",attribute:"projectId",value:e.id,data:{type:"is",nameValue:e.attributes.name}}}})}}})),define("modules/project/acl/project",["exports","acl"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{checkIsOwner(e){return!0}checkScope(e,t,s,a){return"read"===t||"stream"===t?super.checkScope("Project","read"):super.checkScope(e,t,s,a)}checkModel(e,t,s,a){if("edit"===s){if(t&&"all"===t.edit)return!0;const s=e.attributes.memberRoleData;return null==s?null:"Owner"===s.role||"Editor"===s.role}if("stream"===s){if(this.user.isAdmin())return!0;const t=e.attributes.memberRoleData;return null==t?null:"Owner"===t.role||"Editor"===t.role}return super.checkModel(e,t,s,a)}}e.default=a})),define("modules/project/acl/project-task",["exports","acl","modules/project/helpers/member-task-access"],(function(e,t,s){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=a(t),s=a(s);class i extends t.default{checkModel(e,t,a,i){if("edit"===a||"stream"===a||"delete"===a){const t=new s.default(this.user);return"edit"===a?t.checkEdit(e):"stream"===a?t.checkStream(e):"delete"===a&&t.checkDelete(e)}return super.checkModel(e,t,a,i)}}e.default=i})),define("modules/project/acl/project-group",["exports","acl"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{checkIsOwner(e){return!0}checkInTeam(e){return!0}checkScope(e,t,s,a){return!("create"!==t||!this.checkScope(e,"edit"))||super.checkScope(e,t,s,a)}checkModelDelete(e,t,s){return!!this.checkScope(t,"edit")||super.checkModelDelete(e,t,s)}}e.default=a})),define("modules/project/acl/project-column",["exports","acl"],(function(e,t){"use strict";var s;Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,t=(s=t)&&s.__esModule?s:{default:s};class a extends t.default{checkIsOwner(e){return!0}checkInTeam(e){return!0}checkScope(e,t,s,a){return!("create"!==t||!this.checkScope(e,"edit"))||super.checkScope(e,t,s,a)}checkModelDelete(e,t,s){return!!this.checkScope(t,"edit")||super.checkModelDelete(e,t,s)}}e.default=a}));