diff --git a/api/v1/entries/product.php b/api/v1/entries/product.php
index 34089f3221..ae8f4e374b 100644
--- a/api/v1/entries/product.php
+++ b/api/v1/entries/product.php
@@ -58,7 +58,9 @@ class productEntry extends Entry
$product->bugStatistic = $this->loadModel('bug')->getStatistic($productID);
break;
case 'moduleoptionmenu':
- $product->moduleOptionMenu = $this->loadModel('tree')->getOptionMenu($productID, 'story', 0, '0');
+ $modules = $this->loadModel('tree')->getOptionMenu($productID, $this->param('moduleType', 'story'));
+ $product->moduleOptionMenu = array();
+ foreach($modules as $id => $name) $product->moduleOptionMenu[] = array('id' => $id, 'name' => $name);
break;
case 'parentstories':
$product->parentstories= $this->loadModel('story')->getParentStoryPairs($productID);
diff --git a/lib/base/filter/filter.class.php b/lib/base/filter/filter.class.php
index 8db2523369..fda784c2a2 100644
--- a/lib/base/filter/filter.class.php
+++ b/lib/base/filter/filter.class.php
@@ -661,11 +661,11 @@ class baseValidater
global $config;
if(empty($config->framework->filterXSS)) return $var;
- if(stripos($var, '
+
diff --git a/module/story/model.php b/module/story/model.php
index 40de139460..fc3646beb3 100644
--- a/module/story/model.php
+++ b/module/story/model.php
@@ -2437,6 +2437,7 @@ class storyModel extends model
* Get stories by assignedTo.
*
* @param int $productID
+ * @param string $branch
* @param string $account
* @param string $type requirement|story
* @param string $orderBy
@@ -2453,6 +2454,8 @@ class storyModel extends model
* Get stories by openedBy.
*
* @param int $productID
+ * @param int $branch
+ * @param string $modules
* @param string $account
* @param string $type requirement|story
* @param string $orderBy
@@ -2469,6 +2472,8 @@ class storyModel extends model
* Get stories by reviewedBy.
*
* @param int $productID
+ * @param int $branch
+ * @param string $modules
* @param string $account
* @param string $type requirement|story
* @param string $orderBy
@@ -2503,6 +2508,8 @@ class storyModel extends model
* Get stories by closedBy.
*
* @param int $productID
+ * @param int $branch
+ * @param string $modules
* @param string $account
* @param string $type requirement|story
* @param string $orderBy
@@ -2518,6 +2525,8 @@ class storyModel extends model
* Get stories by status.
*
* @param int $productID
+ * @param int $branch
+ * @param string $modules
* @param string $status
* @param string $type requirement|story
* @param string $orderBy
@@ -2533,14 +2542,15 @@ class storyModel extends model
/**
* Get stories by plan.
*
- * @param int $productID
- * @param int $branch
- * @param array $modules
- * @param int $plan
- * @param string $type requirement|story
- * @param string $orderBy
- * @param object $pager
+ * @param int $productID
+ * @param int $branch
+ * @param array $modules
+ * @param int $plan
+ * @param string $type requirement|story
+ * @param string $orderBy
+ * @param object $pager
*
+ * @access public
* @return array
*/
public function getByPlan($productID, $branch, $modules, $plan, $type = 'story', $orderBy = '', $pager = null)
@@ -2548,6 +2558,24 @@ class storyModel extends model
return $this->getByField($productID, $branch, $modules, 'plan', $plan, $type, $orderBy, $pager);
}
+ /**
+ * Get stories by assignedBy.
+ *
+ * @param int $productID
+ * @param int $branch
+ * @param string $modules
+ * @param string $account
+ * @param string $type requirement|story
+ * @param string $orderBy
+ * @param object $pager
+ * @access public
+ * @return array
+ */
+ public function getByAssignedBy($productID, $branch, $modules, $account, $type = 'story', $orderBy = '', $pager = null)
+ {
+ return $this->getByField($productID, $branch, $modules, 'assignedBy', $account, $type, $orderBy, $pager);
+ }
+
/**
* Get stories by a field.
*
@@ -2565,7 +2593,10 @@ class storyModel extends model
*/
public function getByField($productID, $branch, $modules, $fieldName, $fieldValue, $type = 'story', $orderBy = '', $pager = null, $operator = 'equal')
{
- if(!$this->loadModel('common')->checkField(TABLE_STORY, $fieldName) and $fieldName != 'reviewBy') return array();
+ if(!$this->loadModel('common')->checkField(TABLE_STORY, $fieldName) and $fieldName != 'reviewBy' and $fieldName != 'assignedBy') return array();
+
+ $actionIDList = array();
+ if($fieldName == 'assignedBy') $actionIDList = $this->dao->select('objectID')->from(TABLE_ACTION)->where('objectType')->eq('story')->andWhere('action')->eq('assigned')->andWhere('actor')->eq($fieldValue)->fetchPairs('objectID', 'objectID');
$sql = $this->dao->select('t1.*')->from(TABLE_STORY)->alias('t1');
if($fieldName == 'reviewBy') $sql = $sql->leftJoin(TABLE_STORYREVIEW)->alias('t2')->on('t1.id = t2.story and t1.version = t2.version');
@@ -2575,13 +2606,14 @@ class storyModel extends model
->andWhere('t1.type')->eq($type)
->beginIF($branch != 'all')->andWhere("t1.branch")->eq($branch)->fi()
->beginIF($modules)->andWhere("t1.module")->in($modules)->fi()
- ->beginIF($operator == 'equal' and $fieldName != 'reviewBy')->andWhere('t1.' . $fieldName)->eq($fieldValue)->fi()
- ->beginIF($operator == 'include' and $fieldName != 'reviewBy')->andWhere('t1.' . $fieldName)->like("%$fieldValue%")->fi()
+ ->beginIF($operator == 'equal' and $fieldName != 'reviewBy' and $fieldName != 'assignedBy')->andWhere('t1.' . $fieldName)->eq($fieldValue)->fi()
+ ->beginIF($operator == 'include' and $fieldName != 'reviewBy' and $fieldName != 'assignedBy')->andWhere('t1.' . $fieldName)->like("%$fieldValue%")->fi()
->beginIF($fieldName == 'reviewBy')
->andWhere('t2.reviewer')->eq($this->app->user->account)
->andWhere('t2.result')->eq('')
->andWhere('t1.status')->in('draft,changed')
->fi()
+ ->beginIF($fieldName == 'assignedBy')->andWhere('t1.id')->in($actionIDList)->andWhere('t1.status')->ne('closed')->fi()
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
@@ -2592,6 +2624,8 @@ class storyModel extends model
* Get to be closed stories.
*
* @param int $productID
+ * @param int $branch
+ * @param string $modules
* @param string $type requirement|story
* @param string $orderBy
* @param object $pager
@@ -4319,7 +4353,30 @@ class storyModel extends model
public function checkForceReview()
{
$forceReview = false;
- if(!empty($this->config->story->forceReview)) $forceReview = strpos(",{$this->config->story->forceReview},", ",{$this->app->user->account},") !== false;
+
+ if(isset($this->config->story->forceReviewAll) and $this->config->story->forceReviewAll) return true;
+
+ $forceUsers = '';
+ if(!empty($this->config->story->forceReview)) $forceUsers = $this->config->story->forceReview;
+
+ if(!empty($this->config->story->forceReviewRoles) or !empty($this->config->story->forceReviewDepts))
+ {
+ $users = $this->dao->select('account')->from(TABLE_USER)
+ ->where('deleted')->eq(0)
+ ->andWhere(true, true)
+ ->beginIF(!empty($this->config->story->forceReviewRoles))
+ ->andWhere('role', true)->in($this->config->story->forceReviewRoles)
+ ->andWhere('role')->ne('')
+ ->markRight(1)
+ ->fi()
+ ->beginIF(!empty($this->config->story->forceReviewDepts))->orWhere('dept')->in($this->config->story->forceReviewDepts)->fi()
+ ->markRight(1)
+ ->fetchAll('account');
+
+ $forceUsers .= "," . implode(',', array_keys($users));
+ }
+
+ $forceReview = strpos(",{$forceUsers},", ",{$this->app->user->account},") !== false;
return $forceReview;
}
diff --git a/module/task/js/recordestimate.js b/module/task/js/recordestimate.js
index 1237816baf..e64667d31d 100644
--- a/module/task/js/recordestimate.js
+++ b/module/task/js/recordestimate.js
@@ -8,7 +8,15 @@ $(function()
{
if($(this).val() !== '') left = $(this).val();
});
- if(left === '0') return confirm(confirmRecord);
+ if(left == '0')
+ {
+ var confirmMsg = confirm(confirmRecord);
+ if(confirmMsg == false)
+ {
+ $('#submit').attr("disabled", false);
+ return false;
+ }
+ }
});
$('#recordForm .showinonlybody').each(function()
diff --git a/module/task/model.php b/module/task/model.php
index f04071e1dc..806a919512 100644
--- a/module/task/model.php
+++ b/module/task/model.php
@@ -2186,6 +2186,10 @@ class taskModel extends model
if(is_string($type)) $type = strtolower($type);
$fields = 'DISTINCT t1.*, t2.id AS storyID, t2.title AS storyTitle, t2.product, t2.branch, t2.version AS latestStoryVersion, t2.status AS storyStatus, t3.realname AS assignedToRealName';
$this->config->edition == 'max' && $fields .= ', t6.name as designName, t6.version as latestDesignVersion';
+
+ $actionIDList = array();
+ if($type == 'assignedbyme') $actionIDList = $this->dao->select('objectID')->from(TABLE_ACTION)->where('objectType')->eq('task')->andWhere('action')->eq('assigned')->andWhere('actor')->eq($this->app->user->account)->fetchPairs('objectID', 'objectID');
+
$tasks = $this->dao->select($fields)
->from(TABLE_TASK)->alias('t1')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id')
@@ -2207,8 +2211,9 @@ class taskModel extends model
->markRight(1)
->fi()
->beginIF($type == 'delayed')->andWhere('t1.deadline')->gt('1970-1-1')->andWhere('t1.deadline')->lt(date(DT_DATE1))->andWhere('t1.status')->in('wait,doing')->fi()
- ->beginIF(is_array($type) or strpos(',all,undone,needconfirm,assignedtome,delayed,finishedbyme,myinvolved,', ",$type,") === false)->andWhere('t1.status')->in($type)->fi()
+ ->beginIF(is_array($type) or strpos(',all,undone,needconfirm,assignedtome,delayed,finishedbyme,myinvolved,assignedbyme,', ",$type,") === false)->andWhere('t1.status')->in($type)->fi()
->beginIF($modules)->andWhere('t1.module')->in($modules)->fi()
+ ->beginIF($type == 'assignedbyme')->andWhere('t1.id')->in($actionIDList)->andWhere('t1.status')->ne('closed')->fi()
->andWhere('t1.deleted')->eq(0)
->orderBy($orderBy)
->page($pager, 't1.id')
diff --git a/module/user/model.php b/module/user/model.php
index 0426609ed0..52cc9b3269 100644
--- a/module/user/model.php
+++ b/module/user/model.php
@@ -2769,6 +2769,53 @@ class userModel extends model
return $visionList;
}
+ /**
+ * Get users who have authority to create stories.
+ *
+ * @access public
+ * @return array
+ */
+ public function getCanCreateStoryUsers()
+ {
+ $users = $this->getPairs('noclosed|nodeleted');
+ $groupList = $this->dao->select('*')->from(TABLE_USERGROUP)
+ ->where('account')->in(array_keys($users))
+ ->fetchGroup('account', 'group');
+
+ $hasPrivGroups = $this->dao->select('*')->from(TABLE_GROUPPRIV)
+ ->where('module')->eq('story')
+ ->andWhere('(method')->eq('create')
+ ->orWhere('method')->eq('batchCreate')
+ ->markRight(1)
+ ->fetchAll('group');
+
+ foreach($users as $account => $user)
+ {
+ if(empty($user) or strpos($this->app->company->admins, ",{$account},") !== false) continue;
+
+ if(!isset($groupList[$account]))
+ {
+ unset($users[$account]);
+ continue;
+ }
+
+ $groups = $groupList[$account];
+ $hasPriv = false;
+ foreach($groups as $groupID => $group)
+ {
+ if(isset($hasPrivGroups[$groupID]))
+ {
+ $hasPriv = true;
+ break;
+ }
+ }
+
+ if(!$hasPriv) unset($users[$account]);
+ }
+
+ return $users;
+ }
+
/**
* Switch admin of ZenTao.
*
diff --git a/module/webhook/model.php b/module/webhook/model.php
index c518eacce2..209f021344 100644
--- a/module/webhook/model.php
+++ b/module/webhook/model.php
@@ -417,7 +417,7 @@ class webhookModel extends model
$object = $this->dao->select('*')->from($this->config->objectTables[$objectType])->where('id')->eq($objectID)->fetch();
$field = $this->config->action->objectNameFields[$objectType];
$host = empty($webhook->domain) ? common::getSysURL() : $webhook->domain;
- $viewLink = $this->getViewLink($objectType, $objectID);
+ $viewLink = $this->getViewLink($objectType == 'kanbancard' ? 'kanban' : $objectType, $objectType == 'kanbancard' ? $object->kanban : $objectID);
$objectTypeName = ($objectType == 'story' and $object->type == 'requirement') ? $this->lang->action->objectTypes['requirement'] : $this->lang->action->objectTypes[$objectType];
$title = $this->app->user->realname . $this->lang->action->label->$actionType . $objectTypeName;
$text = $title . ' ' . "[#{$objectID}::{$object->$field}](" . $host . $viewLink . ")";
diff --git a/test/class/project.class.php b/test/class/project.class.php
index dae625653c..8abf7d2773 100644
--- a/test/class/project.class.php
+++ b/test/class/project.class.php
@@ -16,7 +16,7 @@ class Project
}
/**
- * Test start a project.
+ * Test start a project.
*
* @param int $projectID
* @access public
@@ -35,8 +35,8 @@ class Project
/**
* Test create project.
- *
- * @param array $params
+ *
+ * @param array $params
* @access public
* @return void
*/
@@ -88,4 +88,19 @@ class Project
return $this->project->getByIdList($data['projectIdList']);
}
+
+ /**
+ * Test get all the projects under the program set to which an project belongs
+ *
+ * @param object $project
+ * @access public
+ * @return void
+ */
+ public function getBrotherProjectsTest($project)
+ {
+ $projectIds = $this->project->getBrotherProjects($project);
+
+ if(dao::isError()) return array('message' => dao::getError());
+ return $projectIds;
+ }
}
diff --git a/test/model/program/update.php b/test/model/program/update.php
index 15dc691661..15103dbf8e 100755
--- a/test/model/program/update.php
+++ b/test/model/program/update.php
@@ -11,11 +11,12 @@ cid=1
pid=1
更新id为10的项目集信息 >> 测试更新项目集十
+更新项目集名称为空时 >> 『项目集名称』不能为空。
当计划开始为空时更新项目集信息 >> 『计划开始』不能为空。
当计划完成为空时更新项目集信息 >> 『计划完成』不能为空。
-当计划完成小于计划开始时 >> 『计划完成』应当大于『2020-10-10』。
-项目集名称已经存在时 >> 『项目集名称』已经有『项目集1』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。
-项目集开始时间小于父项目集时 >> 父项目集的开始日期:2019-09-09,开始日期不能小于父项目集的开始日期;父项目集的完成日期:2019-09-09,完成日期不能大于父项目集的完成日期
+父项目集的开始日期大于子项目集的开始日期时 >> 子项目集的最小开始日期:2022-03-26,父项目集的开始日期不能大于子项目集的最小开始日期
+项目集开始时间小于父项目集时 >> 父项目集的开始日期:2022-03-26,开始日期不能小于父项目集的开始日期;父项目集的完成日期:2022-06-02,完成日期不能大于父项目集的完成日期
+更新未开始的项目集实际开始时间 >> doing
*/
@@ -25,7 +26,7 @@ $data = array(
'parent' => '0',
'name' => '测试更新项目集十',
'begin' => '2020-10-10',
- 'end' => '2022-06-03',
+ 'end' => '2022-09-03',
'acl' => 'private',
'budget' => '100',
'budgetUnit' => 'CNY',
@@ -52,10 +53,14 @@ $beginLtParentProgram = $data;
$beginLtParentProgram['parent'] = '9';
$beginLtParentProgram['begin'] = '2019-01-01';
+$realBeganProgram = $data;
+$realBeganProgram['realBegan'] = '2020-11-10';
+
r($program->update(10, $normalProgram)) && p('name') && e('测试更新项目集十'); // 正常更新项目集的情况
r($program->update(10, $emptyTitleProgram)) && p('message[name]:0') && e('『项目集名称』不能为空。'); // 更新项目集名称为空时
-r($program->update(10, $emptyBeginProgram)) && p('message[begin]:0') && e('『计划开始』不能为空。'); // 当计划完成为空时更新项目集信息
-r($program->update(10, $emptyEndProgram)) && p('message:end') && e('子项目的最大完成日期:2022-05-27,父项目的完成日期不能小于子项目的最大完成日期'); //当计划完成小于计划开始时
+r($program->update(10, $emptyBeginProgram)) && p('message[begin]:0') && e('『计划开始』不能为空。'); // 当计划开始为空时更新项目集信息
+r($program->update(10, $emptyEndProgram)) && p('message:end') && e('『计划完成』不能为空。'); // 当计划完成为空时更新项目集信息
r($program->update(10, $beginGtEndProgram)) && p('message:begin') && e('子项目集的最小开始日期:2022-02-01,父项目集的开始日期不能大于子项目集的最小开始日期'); // 父项目集的开始日期大于子项目集的开始日期时
-r($program->update(10, $beginLtParentProgram)) && p('message:begin;message:end') && e('父项目集的开始日期:2022-02-09,开始日期不能小于父项目集的开始日期;父项目集的完成日期:2022-04-16,完成日期不能大于父项目集的完成日期'); // 项目集开始、结束日期和子项目不符的情况
+r($program->update(10, $beginLtParentProgram)) && p('message:begin;message:end') && e('父项目集的开始日期:2022-03-26,开始日期不能小于父项目集的开始日期;父项目集的完成日期:2022-06-02,完成日期不能大于父项目集的完成日期'); // 项目集开始、结束日期和子项目不符的情况
+r($program->update(10, $realBeganProgram)) && p('status') && e('doing'); // 更新未开始的项目集实际开始时间
system("./ztest init");
diff --git a/test/model/project/getbrotherprojects.php b/test/model/project/getbrotherprojects.php
new file mode 100644
index 0000000000..cf77573f70
--- /dev/null
+++ b/test/model/project/getbrotherprojects.php
@@ -0,0 +1,28 @@
+#!/usr/bin/env php
+getBrotherProjects();
+cid=1
+pid=1
+
+获取项目id为11同一个项目集下的所有项目个数 >> 9
+获取id为731的顶级项目兄弟项目个数 >> 1
+
+*/
+
+global $tester;
+$tester->app->loadConfig('execution');
+$project = new Project();
+
+$projectInst = $project->project->getById(11);
+$programProjects = $project->getBrotherProjectsTest($projectInst);
+$projectInst = $project->project->getById(731);
+$depProjects = $project->getBrotherProjectsTest($projectInst);
+
+r(count($programProjects)) && p() && e('9'); // 获取项目id为11同一个项目集下的所有项目个数
+r(count($depProjects)) && p() && e('1'); // 获取id为731的顶级项目兄弟项目个数
diff --git a/www/js/my.full.js b/www/js/my.full.js
index 858f1b43ed..011203b28d 100644
--- a/www/js/my.full.js
+++ b/www/js/my.full.js
@@ -91,8 +91,6 @@
if(config.debug > 2)
{
- console.log(document.title || location.href, 'tid', _tid);
-
$(function()
{
$('#tid').prepend('localtid=' + _tid + '');
diff --git a/www/js/zui/kanban/min.css b/www/js/zui/kanban/min.css
index 032844f1ff..52876d016c 100644
--- a/www/js/zui/kanban/min.css
+++ b/www/js/zui/kanban/min.css
@@ -1,6 +1,6 @@
/*!
- * ZUI: ZUI Kanban View - v1.10.0 - 2022-03-24
+ * ZUI: ZUI Kanban View - v1.10.0 - 2022-05-19
* http://openzui.com
* GitHub: https://github.com/easysoft/zui.git
* Copyright (c) 2022 cnezsoft.com; Licensed MIT
- */.kanban{min-height:300px}.kanban-header{position:relative;z-index:1;background-color:rgba(0,0,0,.07)}.use-flex .kanban-cols{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-width:0;flex-direction:row;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-flex:1;-webkit-flex:auto;-ms-flex:auto;flex:auto}.kanban-col{min-width:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.no-flex .kanban-col{position:absolute;top:0;bottom:0}.kanban-col+.kanban-col{border-left:2px solid #fff}.kanban-header-cols{position:absolute;top:0;right:0;bottom:0;left:auto}.kanban-header-col{position:relative}.kanban-header-col>.title>.icon{display:inline-block;vertical-align:middle}.kanban-header-col>.title>.text{display:inline-block;margin:0 5px;overflow:hidden;font-weight:700;text-overflow:clip;white-space:nowrap;vertical-align:middle}.kanban-header-col>.title>.count{position:relative;top:1px;display:inline-block;color:#8b91a2;vertical-align:middle}.kanban-affixed .kanban-header-col>.title>.count{color:#ededed}.use-flex .kanban-header-col{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-width:0;min-height:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0 30px;flex-direction:row;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row}.use-flex .kanban-header-col>.title{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;max-width:100%;flex-direction:row;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;-webkit-box-flex:1;-webkit-flex:auto;-ms-flex:auto;flex:auto;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.no-flex .kanban-header-col>.title{position:absolute;top:50%;right:30px;left:30px;margin-top:-10px;line-height:20px;text-align:center;white-space:nowrap}.kanban-header-col>.actions{position:absolute;top:0;right:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.kanban-header-col>.actions>.btn,.kanban-header-col>.actions>a{min-width:20px;padding:5px;border-radius:0}.kanban-header-col>.actions>.btn>.icon,.kanban-header-col>.actions>a>.icon{opacity:.5}.kanban-affixed .kanban-header-col>.actions>.btn,.kanban-affixed .kanban-header-col>.actions>.btn>.icon,.kanban-affixed .kanban-header-col>.actions>a,.kanban-affixed .kanban-header-col>.actions>a>.icon{color:#fff}.kanban-header-parent-col>.kanban-header-col,.kanban-header-parent-col>.kanban-header-sub-cols{height:50%}.use-flex .kanban-header-parent-col{padding:0;flex-direction:column;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch}.kanban-header-sub-cols{position:relative;margin-top:-1px;margin-left:-2px;border-top:2px solid #fff;border-right:none}.use-flex .kanban-header-sub-cols{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;flex-direction:row;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row}.use-flex .kanban-header-sub-cols>.kanban-col{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.kanban-col:first-child>.kanban-header-sub-cols{margin-left:0}.kanban-lane,.kanban-sub-lane{position:relative;background-color:#f1f3f5}.use-flex .kanban-lane,.use-flex .kanban-sub-lane{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-height:0;flex-direction:row;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.kanban-lane+.kanban-lane{margin-top:2px}.kanban-lane>*{opacity:1;-webkit-transition:opacity .1s;-o-transition:opacity .1s;transition:opacity .1s}.kanban-lane.virtual-pending>*{opacity:0}.kanban-lane .has-sub-lane{background:0 0}.no-flex .kanban-lane-cols{position:absolute;top:0;right:0;bottom:0}.no-flex .kanban-sub-lane-cols{position:absolute;top:0;right:0;bottom:0;left:0}.kanban-sub-lane{-webkit-box-flex:1;-webkit-flex:auto;-ms-flex:auto;flex:auto}.kanban-lane-name{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:20px;overflow:hidden;color:#fff;text-align:center;background-color:#3dc6fd;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none}.kanban-lane-name>.text{position:absolute;top:5px;bottom:5px;left:0;display:block;overflow:hidden;line-height:20px;text-align:center;white-space:nowrap;-webkit-writing-mode:tb-rl;-ms-writing-mode:tb-rl;writing-mode:tb-rl;-webkit-writing-mode:vertical-rl;writing-mode:vertical-rl}.no-flex .kanban-lane-name{position:absolute;top:0;bottom:0;left:0}.kanban-sub-lanes{min-width:0}.use-flex .kanban-sub-lanes{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;flex-direction:column;-webkit-box-flex:1;-webkit-flex:auto;-ms-flex:auto;flex:auto;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-pack:stretch;-webkit-justify-content:stretch;-ms-flex-pack:stretch;justify-content:stretch;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column}.no-flex .kanban-sub-lanes{position:absolute;top:0;right:0;bottom:0}.kanban-sub-lanes.no-sub-lane{background-color:#f1f3f5}.kanban-dragging .kanban-lane-col{-webkit-transition:-webkit-box-shadow .1s;-o-transition:box-shadow .1s;transition:-webkit-box-shadow .1s;transition:box-shadow .1s;transition:box-shadow .1s,-webkit-box-shadow .1s}.kanban-lane-col.drop-target{-webkit-box-shadow:inset 0 0 0 3px rgba(255,152,0,.25);box-shadow:inset 0 0 0 3px rgba(255,152,0,.25)}.kanban-lane-col.drop-to{-webkit-box-shadow:inset 0 0 1px 4px rgba(255,152,0,.75);box-shadow:inset 0 0 1px 4px rgba(255,152,0,.75)}.kanban-lane-col.drop-to .kanban-lane-actions>.btn{background-color:rgba(255,152,0,.25);border:1px dotted #ff9800}.kanban-lane-col.drop-to .kanban-lane-actions>.btn>span{opacity:0}.kanban-lane-col[data-type=EMPTY]{background-color:#fff}.kanban-lane-items{height:100%;overflow:auto;overflow:overlay!important}.kanban-lane-actions{padding:10px 15px}.use-flex .kanban-items-grid{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-align-content:flex-start;-ms-flex-line-pack:start;align-content:flex-start}.kanban-card{position:relative;padding:8px 10px;background:#fff;border:1px solid #fff;border-radius:4px;-webkit-box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06);box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06);-webkit-transition:-webkit-box-shadow .2s,-webkit-transform .2s;-o-transition:box-shadow .2s,-o-transform .2s;transition:-webkit-box-shadow .2s,-webkit-transform .2s;transition:box-shadow .2s,transform .2s;transition:box-shadow .2s,transform .2s,-webkit-box-shadow .2s,-webkit-transform .2s,-o-transform .2s}.dragging>.kanban-card{background-color:#aaa;opacity:.2}.kanban-card:hover{border-color:rgba(0,0,0,.1);-webkit-box-shadow:0 4px 10px 0 rgba(0,0,0,.09);box-shadow:0 4px 10px 0 rgba(0,0,0,.09)}.drag-shadow>.kanban-card{z-index:10;border-color:rgba(0,0,0,.2);-webkit-box-shadow:0 4px 10px 0 rgba(0,0,0,.05),0 4px 20px 0 rgba(0,0,0,.3);box-shadow:0 4px 10px 0 rgba(0,0,0,.05),0 4px 20px 0 rgba(0,0,0,.3);opacity:1!important;-webkit-transition:-webkit-box-shadow .2s,-webkit-transform .4s!important;-o-transition:box-shadow .2s,-o-transform .4s!important;transition:-webkit-box-shadow .2s,-webkit-transform .4s!important;transition:box-shadow .2s,transform .4s!important;transition:box-shadow .2s,transform .4s,-webkit-box-shadow .2s,-webkit-transform .4s,-o-transform .4s!important}.drag-shadow>.kanban-card.in{-webkit-transform:scale(1.1) rotate(5deg);-ms-transform:scale(1.1) rotate(5deg);-o-transform:scale(1.1) rotate(5deg);transform:scale(1.1) rotate(5deg)}.drag-shadow>.kanban-card a{pointer-events:none}.kanban-dragging{cursor:move}
\ No newline at end of file
+ */.kanban{min-height:300px}.kanban-header{position:relative;z-index:1;background-color:rgba(0,0,0,.07)}.use-flex .kanban-cols{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-width:0;flex-direction:row;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-flex:1;-webkit-flex:auto;-ms-flex:auto;flex:auto}.kanban-col{min-width:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.no-flex .kanban-col{position:absolute;top:0;bottom:0}.kanban-col+.kanban-col{border-left:2px solid #fff}.kanban-header-cols{position:absolute;top:0;right:0;bottom:0;left:auto}.kanban-header-col{position:relative}.kanban-header-col>.title>.icon{display:inline-block;vertical-align:middle}.kanban-header-col>.title>.text{display:inline-block;margin:0 5px;overflow:hidden;font-weight:700;text-overflow:clip;white-space:nowrap;vertical-align:middle}.kanban-header-col>.title>.count{position:relative;top:1px;display:inline-block;color:#8b91a2;vertical-align:middle}.kanban-affixed .kanban-header-col>.title>.count{color:#ededed}.use-flex .kanban-header-col{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-width:0;min-height:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0 30px;flex-direction:row;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row}.use-flex .kanban-header-col>.title{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;max-width:100%;flex-direction:row;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;-webkit-box-flex:1;-webkit-flex:auto;-ms-flex:auto;flex:auto;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.no-flex .kanban-header-col>.title{position:absolute;top:50%;right:30px;left:30px;margin-top:-10px;line-height:20px;text-align:center;white-space:nowrap}.kanban-header-col>.actions{position:absolute;top:0;right:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.kanban-header-col>.actions>.btn,.kanban-header-col>.actions>a{min-width:20px;padding:5px;border-radius:0}.kanban-header-col>.actions>.btn>.icon,.kanban-header-col>.actions>a>.icon{opacity:.5}.kanban-affixed .kanban-header-col>.actions>.btn,.kanban-affixed .kanban-header-col>.actions>.btn>.icon,.kanban-affixed .kanban-header-col>.actions>a,.kanban-affixed .kanban-header-col>.actions>a>.icon{color:#fff}.kanban-header-parent-col>.kanban-header-col,.kanban-header-parent-col>.kanban-header-sub-cols{height:50%}.use-flex .kanban-header-parent-col{padding:0;flex-direction:column;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch}.kanban-header-sub-cols{position:relative;margin-top:-1px;margin-left:-2px;border-top:2px solid #fff;border-right:none}.use-flex .kanban-header-sub-cols{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;flex-direction:row;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row}.use-flex .kanban-header-sub-cols>.kanban-col{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.kanban-col:first-child>.kanban-header-sub-cols{margin-left:0}.kanban-lane,.kanban-sub-lane{position:relative;background-color:#f1f3f5}.use-flex .kanban-lane,.use-flex .kanban-sub-lane{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-height:0;flex-direction:row;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.kanban-lane+.kanban-lane{margin-top:2px}.kanban-lane>*{opacity:1;-webkit-transition:opacity .1s;-o-transition:opacity .1s;transition:opacity .1s}.kanban-lane.virtual-pending>*{opacity:0}.kanban-lane .has-sub-lane{background:0 0}.no-flex .kanban-lane-cols{position:absolute;top:0;right:0;bottom:0}.no-flex .kanban-sub-lane-cols{position:absolute;top:0;right:0;bottom:0;left:0}.kanban-sub-lane{-webkit-box-flex:1;-webkit-flex:auto;-ms-flex:auto;flex:auto}.kanban-lane-name{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:20px;overflow:hidden;color:#fff;text-align:center;background-color:#3dc6fd;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none}.kanban-lane-name>.text{position:absolute;top:5px;bottom:5px;left:0;display:block;overflow:hidden;line-height:20px;text-align:center;white-space:nowrap;-webkit-writing-mode:tb-rl;-ms-writing-mode:tb-rl;writing-mode:tb-rl;-webkit-writing-mode:vertical-rl;writing-mode:vertical-rl}.no-flex .kanban-lane-name{position:absolute;top:0;bottom:0;left:0}.kanban-sub-lanes{min-width:0}.use-flex .kanban-sub-lanes{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;flex-direction:column;-webkit-box-flex:1;-webkit-flex:auto;-ms-flex:auto;flex:auto;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-pack:stretch;-webkit-justify-content:stretch;-ms-flex-pack:stretch;justify-content:stretch;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column}.no-flex .kanban-sub-lanes{position:absolute;top:0;right:0;bottom:0}.kanban-sub-lanes.no-sub-lane{background-color:#f1f3f5}.kanban-dragging .kanban-lane-col{-webkit-transition:-webkit-box-shadow .1s;-o-transition:box-shadow .1s;transition:-webkit-box-shadow .1s;transition:box-shadow .1s;transition:box-shadow .1s,-webkit-box-shadow .1s}.kanban-lane-col.drop-target{-webkit-box-shadow:inset 0 0 0 3px rgba(255,152,0,.25);box-shadow:inset 0 0 0 3px rgba(255,152,0,.25)}.kanban-lane-col.drop-to{-webkit-box-shadow:inset 0 0 1px 4px rgba(255,152,0,.75);box-shadow:inset 0 0 1px 4px rgba(255,152,0,.75)}.kanban-lane-col.drop-to .kanban-lane-actions>.btn{background-color:rgba(255,152,0,.25);border:1px dotted #ff9800}.kanban-lane-col.drop-to .kanban-lane-actions>.btn>span{opacity:0}.kanban-lane-col[data-type=EMPTY]{background-color:#fff}.kanban-lane-items{height:100%;overflow:auto;overflow:overlay!important}.kanban-lane-actions{padding:10px 15px}.use-flex .kanban-items-grid{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-align-content:flex-start;-ms-flex-line-pack:start;align-content:flex-start}.kanban-card{position:relative;padding:8px 10px;background:#fff;border:1px solid #fff;border-radius:4px;-webkit-box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06);box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06);-webkit-transition:-webkit-box-shadow .2s,-webkit-transform .2s;-o-transition:box-shadow .2s,-o-transform .2s;transition:-webkit-box-shadow .2s,-webkit-transform .2s;transition:box-shadow .2s,transform .2s;transition:box-shadow .2s,transform .2s,-webkit-box-shadow .2s,-webkit-transform .2s,-o-transform .2s}.dragging>.kanban-card{opacity:.2}.kanban-card:hover{border-color:rgba(0,0,0,.1);-webkit-box-shadow:0 4px 10px 0 rgba(0,0,0,.09);box-shadow:0 4px 10px 0 rgba(0,0,0,.09)}.drag-shadow>.kanban-card{z-index:10;border-color:rgba(0,0,0,.2);-webkit-box-shadow:0 4px 10px 0 rgba(0,0,0,.05),0 4px 20px 0 rgba(0,0,0,.3);box-shadow:0 4px 10px 0 rgba(0,0,0,.05),0 4px 20px 0 rgba(0,0,0,.3);opacity:1!important;-webkit-transition:-webkit-box-shadow .2s,-webkit-transform .4s!important;-o-transition:box-shadow .2s,-o-transform .4s!important;transition:-webkit-box-shadow .2s,-webkit-transform .4s!important;transition:box-shadow .2s,transform .4s!important;transition:box-shadow .2s,transform .4s,-webkit-box-shadow .2s,-webkit-transform .4s,-o-transform .4s!important}.drag-shadow>.kanban-card.in{-webkit-transform:scale(1.1) rotate(5deg);-ms-transform:scale(1.1) rotate(5deg);-o-transform:scale(1.1) rotate(5deg);transform:scale(1.1) rotate(5deg)}.drag-shadow>.kanban-card a{pointer-events:none}.kanban-dragging{cursor:move}
\ No newline at end of file
diff --git a/www/js/zui/kanban/min.js b/www/js/zui/kanban/min.js
index 6552dc91c3..d590eebc89 100644
--- a/www/js/zui/kanban/min.js
+++ b/www/js/zui/kanban/min.js
@@ -1,7 +1,7 @@
/*!
- * ZUI: ZUI Kanban View - v1.10.0 - 2022-04-21
+ * ZUI: ZUI Kanban View - v1.10.0 - 2022-05-19
* http://openzui.com
- * GitHub: https://github.com/easysoft/zui.git
+ * GitHub: https://github.com/easysoft/zui.git
* Copyright (c) 2022 cnezsoft.com; Licensed MIT
*/
-!function(){"use strict";function a(a,e){return n&&!e?requestAnimationFrame(a):setTimeout(a,e||0)}function e(a){return n?cancelAnimationFrame(a):void clearTimeout(a)}var n="function"==typeof window.requestAnimationFrame;$.zui({asap:a,clearAsap:e})}(),function(a){"use strict";function e(e,n){"string"==typeof e&&(e=a(e)),e instanceof a&&(e=e[0]);var t=e.getBoundingClientRect(),r=window.innerHeight||document.documentElement.clientHeight,d=window.innerWidth||document.documentElement.clientWidth;if(n)return t.left>=0&&t.top>=0&&t.left+t.width<=d&&t.top+t.height<=r;var i=t.top<=r&&t.top+t.height>=0,o=t.left<=d&&t.left+t.width>=0;return i&&o}var n="zui.virtualRender",t=function(e,r){"function"==typeof r&&(r={render:r});var d=this;d.name=n,d.$=a(e),d.options=r=a.extend({},t.DEFAULTS,this.$.data(),r),d.rendered=!1;var i=r.container;"function"==typeof i&&(i=i(d));var o=a(i?i:window);d.tryRender()||(d.$container=o,d.scrollListener=d.tryRender.bind(d),r.pendingClass&&d.$.addClass(r.pendingClass),o.on("scroll",d.scrollListener))};t.prototype.tryRender=function(){var n=this;return!(n.rendered||!e(n.$))&&(n.renderTaskID&&a.zui.clearAsap(n.renderTaskID),n.renderTaskID=a.zui.asap(function(){n.renderTaskID=null;var a=n.options.render(n.$);a!==!1&&(n.rendered=!0,n.destroy())},n.options.delay),!0)},t.prototype.destroy=function(){var e=this;e.renderTaskID&&a.zui.clearAsap(e.renderTaskID),e.scrollListener&&(e.$container.off("scroll",e.scrollListener),e.scrollListener=null);var t=e.options.pendingClass;t&&e.$.removeClass(t),e.$.removeData(n)},t.DEFAULTS={pendingClass:"virtual-pending"},a.fn.virtualRender=function(e){return this.each(function(){var r=a(this),d=r.data(n);if(d){if("string"==typeof e)return d[e]();d.destroy()}r.data(n,d=new t(this,e))})},a.zui.isElementInViewport=e}(jQuery),function(a){"use strict";var e="zui.kanban",n="object"==typeof CSS&&CSS.supports("display","flex"),t=function(n,r){var d=this;if(d.name=e,d.$=a(n).addClass("kanban"),r=d.setOptions(a.extend({},t.DEFAULTS,this.$.data(),r)),r.onAction){var i=function(e){var n=a(this);r.onAction(n.data("action"),n,e,d)};d.$.on("click",".action",i).on("dblclick",".action-dbc",i)}var o=r.droppable;if("auto"===o&&(o=!r.readonly),o){var s=r.sortable;"function"==typeof s?s={finish:s}:s&&"object"!=typeof s&&(s={});var l=0;"function"==typeof o?o={drop:o}:"object"!=typeof o&&(o={});var c=a.extend({dropOnMouseleave:!0,selector:".kanban-item",target:".kanban-lane-col:not(.kanban-col-sorting)",mouseButton:"left"},o,{before:function(e){if(o.before){var n=o.before(e);if(n===!1)return n}if(s){var t=e.element.closest(".kanban-lane-items");t.closest(".kanban-col").addClass("kanban-col-sorting"),d._sortResult=null,d._$sortItems=t;var r=t.data("zui.sortable");r||t.sortable(a.extend({},s,{selector:".kanban-item",trigger:".kanban-card",dragCssClass:"kanban-item-sorting",noShadow:!0,finish:function(a){a.changed&&a.list.length>1&&(d._sortResult=a)}})).triggerHandler(e.event)}},drop:function(a){o.drop&&o.drop(a),r.onAction&&r.onAction("dropItem",a.element,a,d)},start:function(e){d.$.addClass("kanban-dragging"),l&&clearTimeout(l),l=setTimeout(function(){a(e.shadowElement).addClass("in"),l=0},50),o.start&&o.start(e)},always:function(a){d.$.removeClass("kanban-dragging"),l&&(clearTimeout(l),l=0),s&&(d._$sortItems.sortable("destroy").closest(".kanban-col").removeClass("kanban-col-sorting"),a.target[0]===a.element.closest(".kanban-lane-col")[0]&&d._sortResult&&s.finish&&s.finish(d._sortResult)),o.always&&o.always(a)}});d.$.droppable(c)}r.onCreate&&r.onCreate(d)};t.prototype.setOptions=function(e){var t=this,r=a.extend({},t.options,{data:t.data},e);t.options=r,r.useFlex&&!n&&(r.useFlex=!1),t.$.toggleClass("no-flex",!r.useFlex).toggleClass("use-flex",!!r.useFlex);var d=!!a.fn.virtualRender&&r.virtualize;return d&&("object"!=typeof d&&(d={lane:!0}),t.virtualize=a.extend({},d)),t.data=r.data||[],t.render(t.data),r},t.prototype.render=function(a){var e=this;a&&(e.data=a),e.data&&!Array.isArray(e.data)&&(e.data=[e.data]);var n=e.options,t=e.data||[];n.beforeRender&&n.beforeRender(e,t),e.$.toggleClass("kanban-readonly",!!n.readonly).toggleClass("kanban-no-lane-name",!!n.noLaneName),e.$.children(".kanban-board").addClass("kanban-expired"),e.maxKanbanBoardWidth=0;for(var r=0;r1&&e.$.children(".kanban-board").css("min-width",e.maxKanbanBoardWidth),n.onRender&&n.onRender(e)},t.prototype.layoutKanban=function(a,e){for(var n=this,t=n.options,r=t.noLaneName?0:t.laneNameWidth,d=0,i={},o=!1,s=[],l=0;l0&&t.subLaneSpace&&(k.$height+=t.subLaneSpace)}}else for(var y=k.items||k.cards||{},C=0;C-1){var r=n.data[t];e=a.extend(r,e),n.data[t]=e}else n.data.push(e)}e.id||(e.id=a.zui.uuid());var d=e.id,i=n.options,o=n.$,s=o.children('.kanban-board[data-id="'+d+'"]');s.length?s.removeClass("kanban-expired"):s=a('').appendTo(o),n.layoutKanban(e,s),n.renderKanbanHeader(e,s),s.children(".kanban-lane").addClass("kanban-expired");for(var l=e.lanes||[],c=0;c