* Add holiday and fix project and product menu.

This commit is contained in:
Yagami
2020-08-19 10:58:29 +08:00
parent bc65843452
commit a86cb31895
32 changed files with 967 additions and 104 deletions

View File

@@ -131,8 +131,8 @@ $filter->product->default->cookie['preProductID'] = 'int';
$filter->product->index->cookie['preBranch'] = 'int';
$filter->product->export->cookie['checkedItem'] = 'reg::checked';
$filter->program->index->cookie['programType'] = 'code';
$filter->program->index->cookie['mine'] = 'code';
$filter->program->browse->cookie['programType'] = 'code';
$filter->program->browse->cookie['mine'] = 'code';
$filter->program->export->cookie['checkedItem'] = 'reg::checked';
$filter->project->default->cookie['lastProject'] = 'int';

View File

@@ -197,6 +197,7 @@ if(!defined('TABLE_PROJECTSPEC')) define('TABLE_PROJECTSPEC', '`' . $conf
if(!defined('TABLE_WORKESTIMATION')) define('TABLE_WORKESTIMATION', '`' . $config->db->prefix . 'workestimation`');
if(!defined('TABLE_DURATIONESTIMATION')) define('TABLE_DURATIONESTIMATION', '`' . $config->db->prefix . 'durationestimation`');
if(!defined('TABLE_BUDGET')) define('TABLE_BUDGET', '`' . $config->db->prefix . 'budget`');
if(!defined('TABLE_HOLIDAY')) define('TABLE_HOLIDAY', '`' . $config->db->prefix . 'holiday`');
$config->objectTables['product'] = TABLE_PRODUCT;
$config->objectTables['story'] = TABLE_STORY;

View File

@@ -234,3 +234,38 @@ CREATE TABLE `zt_workestimation` (
`dayHour` float(5,2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `zt_holiday` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL DEFAULT '',
`type` enum('holiday', 'working') NOT NULL DEFAULT 'holiday',
`desc` text NOT NULL,
`year` char(4) NOT NULL,
`begin` date NOT NULL,
`end` date NOT NULL,
PRIMARY KEY (`id`),
KEY `year` (`year`),
KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
ALTER TABLE `zt_task`
ADD `design` mediumint(8) unsigned NOT NULL AFTER `story`,
ADD `version` smallint(6) NOT NULL AFTER `desc`,
ADD `activatedDate` date NOT NULL AFTER `lastEditedDate`,
ADD `planDuration` int(11) NOT NULL AFTER `closedDate`,
ADD `realDuration` int(11) NOT NULL AFTER `closedDate`,
ADD `designVersion` smallint(6) unsigned NOT NULL AFTER `storyVersion`;
ALTER TABLE `zt_burn`
ADD `storyPoint` float NOT NULL AFTER `consumed`,
ADD `product` mediumint(8) unsigned NOT NULL DEFAULT '0' AFTER `project`;
-- DROP TABLE IF EXISTS `zt_taskspec`;
CREATE TABLE `zt_taskspec` (
`task` mediumint(8) NOT NULL,
`version` smallint(6) NOT NULL,
`name` varchar(255) NOT NULL,
`estStarted` date NOT NULL,
`deadline` date NOT NULL,
UNIQUE KEY `task` (`task`,`version`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

View File

@@ -120,7 +120,7 @@ $lang->common->common = '公有模块';
/* 主导航菜单。*/
$lang->mainNav = new stdclass();
$lang->mainNav->my = '<i class="icon icon-menu-my"></i> 地盘|my|index|';
$lang->mainNav->program = '<i class="icon icon-menu-project"></i> 项目|program|index|';
$lang->mainNav->program = '<i class="icon icon-menu-project"></i> 项目|program|browse|';
//$lang->mainNav->reporting = '<i class="icon icon-menu-report"></i> 报表|report|index|';
//$lang->mainNav->attend = '<i class="icon icon-file"></i> 办公|attend|personal|';
$lang->mainNav->system = '<i class="icon icon-menu-users"></i> 组织|custom|estimate|';
@@ -170,7 +170,7 @@ if($this->cookie->systemModel == 'scrum')
$lang->system->menu->custom = array('link' => '自定义|custom|concept|');
$lang->system->subMenu->setmodel->cmmi ='cmmi|custom|setcmmi|';
$lang->mainNav->system = '<i class="icon icon-menu-users"></i> 组织|measurement|settips|';
$lang->mainNav->system = '<i class="icon icon-menu-users"></i> 组织|subject|browse|';
unset($lang->system->dividerMenu);
}

View File

@@ -0,0 +1,5 @@
<?php
if(!isset($config->holiday)) $config->holiday = new stdclass();
$config->holiday->require = new stdclass();
$config->holiday->require->create = 'name,begin,end,year';
$config->holiday->require->edit = 'name,begin,end,year';

100
module/holiday/control.php Normal file
View File

@@ -0,0 +1,100 @@
<?php
/**
* The control file of holiday of Ranzhi.
*
* @copyright Copyright 2009-2018 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author chujilu <chujilu@cnezsoft.com>
* @package holiday
* @version $Id$
* @link http://www.ranzhi.org
*/
class holiday extends control
{
/**
* index
*
* @access public
* @return void
*/
public function index()
{
$this->locate(inlink('browse'));
}
/**
* browse holidays.
*
* @param string $year
* @access public
* @return void
*/
public function browse($year = '')
{
if($year == '') $year = date('Y');
$holidays = $this->holiday->getList($year);
$yearList = $this->holiday->getYearPairs();
$this->view->title = $this->lang->holiday->browse;
$this->view->holidays = $holidays;
$this->view->yearList = $yearList;
$this->view->currentYear = $year;
$this->display();
}
/**
* Create a holiday.
*
* @access public
* @return void
*/
public function create()
{
if($_POST)
{
$holidayID = $this->holiday->create();
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
$actionID = $this->loadModel('action')->create('holiday', $holidayID, 'created');
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$this->view->title = $this->lang->holiday->create;
$this->display();
}
/**
* Edit holiday.
*
* @param int $id
* @access public
* @return void
*/
public function edit($id)
{
$holiday = $this->holiday->getById($id);
if($_POST)
{
$this->holiday->update($id);
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$this->view->title = $this->lang->holiday->edit;
$this->view->holiday = $holiday;
$this->display();
}
/**
* Delete holiday.
*
* @param int $id
* @access public
* @return void
*/
public function delete($id)
{
$result = $this->holiday->delete($id);
if(!$result) $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->send(array('result' => 'success'));
}
}

View File

@@ -0,0 +1,3 @@
.tree .active{font-weight: bold;}
.with-side .side {position: absolute; width: 130px;}
.with-side .main {padding-left: 145px; float: left;}

View File

@@ -0,0 +1,19 @@
<?php
if(!isset($lang->holiday)) $lang->holiday = new stdclass();
$lang->holiday->common = 'Holiday';
$lang->holiday->browse = 'Browse';
$lang->holiday->create = 'Create';
$lang->holiday->edit = 'Edit';
$lang->holiday->delete = 'Delete';
$lang->holiday->id = 'ID';
$lang->holiday->name = 'Name';
$lang->holiday->desc = 'Description';
$lang->holiday->type = 'Type';
$lang->holiday->begin = 'Begin';
$lang->holiday->end = 'End';
$lang->holiday->holiday = 'Holiday';
$lang->holiday->typeList['holiday'] = 'Holiday';
$lang->holiday->typeList['working'] = 'Working Day';

View File

@@ -0,0 +1,19 @@
<?php
if(!isset($lang->holiday)) $lang->holiday = new stdclass();
$lang->holiday->common = 'Holiday';
$lang->holiday->browse = 'Browse';
$lang->holiday->create = 'Create';
$lang->holiday->edit = 'Edit';
$lang->holiday->delete = 'Delete';
$lang->holiday->id = 'ID';
$lang->holiday->name = 'Name';
$lang->holiday->desc = 'Description';
$lang->holiday->type = 'Type';
$lang->holiday->begin = 'Begin';
$lang->holiday->end = 'End';
$lang->holiday->holiday = 'Holiday';
$lang->holiday->typeList['holiday'] = 'Holiday';
$lang->holiday->typeList['working'] = 'Working Day';

View File

@@ -0,0 +1,19 @@
<?php
if(!isset($lang->holiday)) $lang->holiday = new stdclass();
$lang->holiday->common = 'Holiday';
$lang->holiday->browse = 'Browse';
$lang->holiday->create = 'Create';
$lang->holiday->edit = 'Edit';
$lang->holiday->delete = 'Delete';
$lang->holiday->id = 'ID';
$lang->holiday->name = 'Name';
$lang->holiday->desc = 'Description';
$lang->holiday->type = 'Type';
$lang->holiday->begin = 'Begin';
$lang->holiday->end = 'End';
$lang->holiday->holiday = 'Holiday';
$lang->holiday->typeList['holiday'] = 'Holiday';
$lang->holiday->typeList['working'] = 'Working Day';

View File

@@ -0,0 +1,19 @@
<?php
if(!isset($lang->holiday)) $lang->holiday = new stdclass();
$lang->holiday->common = 'Ngày lễ';
$lang->holiday->browse = 'Browse';
$lang->holiday->create = 'Tạo';
$lang->holiday->edit = 'Sửa';
$lang->holiday->delete = 'Xóa';
$lang->holiday->id = 'ID';
$lang->holiday->name = 'Tên';
$lang->holiday->desc = 'Mô tả';
$lang->holiday->type = 'Loại';
$lang->holiday->begin = 'Bắt đầu';
$lang->holiday->end = 'Kết thúc';
$lang->holiday->holiday = 'Ngày lễ';
$lang->holiday->typeList['holiday'] = 'Ngày lễ';
$lang->holiday->typeList['working'] = 'Ngày làm việc';

View File

@@ -0,0 +1,26 @@
<?php
if(!isset($lang->holiday)) $lang->holiday = new stdclass();
$lang->holiday->common = '节假日';
$lang->holiday->browse = '浏览';
$lang->holiday->create = '新建';
$lang->holiday->edit = '编辑';
$lang->holiday->delete = '删除';
$lang->holiday->createAction = '创建节假日';
$lang->holiday->editAction = '编辑节假日';
$lang->holiday->deleteAction = '删除节假日';
$lang->holiday->id = '编号';
$lang->holiday->name = '名称';
$lang->holiday->desc = '描述';
$lang->holiday->type = '类型';
$lang->holiday->begin = '开始日期';
$lang->holiday->end = '结束日期';
$lang->holiday->all = '所有';
$lang->holiday->holiday = '假期';
$lang->holiday->typeList['holiday'] = '假期';
$lang->holiday->typeList['working'] = '补班';
$lang->holiday->emptyTip = '暂时没有节假日。';

View File

@@ -0,0 +1,19 @@
<?php
if(!isset($lang->holiday)) $lang->holiday = new stdclass();
$lang->holiday->common = '節假日';
$lang->holiday->browse = '瀏覽';
$lang->holiday->create = '新建';
$lang->holiday->edit = '編輯';
$lang->holiday->delete = '刪除';
$lang->holiday->id = '編號';
$lang->holiday->name = '名稱';
$lang->holiday->desc = '描述';
$lang->holiday->type = '類型';
$lang->holiday->begin = '開始日期';
$lang->holiday->end = '結束日期';
$lang->holiday->holiday = '假期';
$lang->holiday->typeList['holiday'] = '假期';
$lang->holiday->typeList['working'] = '補班';

443
module/holiday/model.php Normal file
View File

@@ -0,0 +1,443 @@
<?php
/**
* The model file of holiday module of ranzhi.
*
* @copyright Copyright 2009-2018 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author chujilu <chujilu@cnezsoft.com>
* @package holiday
* @version $Id$
* @link http://www.ranzhi.org
*/
class holidayModel extends model
{
/**
* Get holiday by id.
*
* @param int $id
* @access public
* @return object
*/
public function getById($id)
{
return $this->dao->select('*')->from(TABLE_HOLIDAY)->where('id')->eq($id)->fetch();
}
/**
* Get holiday list.
*
* @param string $year
* @access public
* @return array
*/
public function getList($year = '', $type = 'all')
{
return $this->dao->select('*')->from(TABLE_HOLIDAY)
->where('1')
->beginIf($year != '')
->andWhere('year', true)->eq($year)
->orWhere('begin')->like("$year-%")
->orWhere('end')->like("$year-%")
->markright(1)
->fi()
->beginIf($type != 'all' && $type)->andWhere('type')->eq($type)->fi()
->fetchAll('id');
}
/**
* Get year pairs.
*
* @access public
* @return array
*/
public function getYearPairs()
{
return $this->dao->select('year,year')->from(TABLE_HOLIDAY)->groupBy('year')->orderBy('year_desc')->fetchPairs();
}
/**
* create a holiday.
*
* @access public
* @return bool
*/
public function create()
{
$holiday = fixer::input('post')->get();
$holiday->year = substr($holiday->begin, 0, 4);
$this->dao->insert(TABLE_HOLIDAY)
->data($holiday)
->autoCheck()
->batchCheck($this->config->holiday->require->create, 'notempty')
->check('end', 'ge', $holiday->begin)
->exec();
if(!dao::isError())
{
$beginDate = $this->post->begin;
$endDate = $this->post->end;
/* Update project. */
$this->updateProjectPlanDuration($beginDate, $endDate);
$this->updateProjectRealDuration($beginDate, $endDate);
/* Update task. */
$this->updateTaskPlanDuration($beginDate, $endDate);
$this->updateTaskRealDuration($beginDate, $endDate);
}
return $this->dao->lastInsertID();
}
/**
* Edit holiday.
*
* @access public
* @return bool
*/
public function update($id)
{
$holiday = fixer::input('post')->get();
$holiday->year = substr($holiday->begin, 0, 4);
$this->dao->update(TABLE_HOLIDAY)
->data($holiday)
->autoCheck()
->batchCheck($this->config->holiday->require->edit, 'notempty')
->check('end', 'ge', $holiday->begin)
->where('id')->eq($id)
->exec();
if(!dao::isError())
{
$beginDate = $this->post->begin;
$endDate = $this->post->end;
/* Update project. */
$this->updateProjectPlanDuration($beginDate, $endDate);
$this->updateProjectRealDuration($beginDate, $endDate);
/* Update task. */
$this->updateTaskPlanDuration($beginDate, $endDate);
$this->updateTaskRealDuration($beginDate, $endDate);
}
return !dao::isError();
}
/**
* Delete a holiday
*
* @param int $id
* @param null $null
* @access public
* @return bool
*/
public function delete($id, $null = null)
{
$holidayInformation = $this->dao->select('begin, end')->from(TABLE_HOLIDAY)->where('id')->eq($id)->fetch();
$this->dao->delete()->from(TABLE_HOLIDAY)->where('id')->eq($id)->exec();
/* Update project. */
$this->updateProjectPlanDuration($holidayInformation->begin, $holidayInformation->end);
$this->updateProjectRealDuration($holidayInformation->begin, $holidayInformation->end);
/* Update task. */
$this->updateTaskPlanDuration($holidayInformation->begin, $holidayInformation->end);
$this->updateTaskRealDuration($holidayInformation->begin, $holidayInformation->end);
return !dao::isError();
}
/**
* Get holidays by begin and end.
*
* @param varchar $begin
* @param varchar $end
* @access public
* @return bool
*/
public function getHolidays($begin, $end)
{
$records = $this->dao->select('*')->from(TABLE_HOLIDAY)
->where('type')->eq('holiday')
->andWhere('begin')->le($end)
->andWhere('end')->ge($begin)
->fetchAll('id');
$naturalDays = $this->getDaysBetween($begin, $end);
$holidays = array();
foreach($records as $record)
{
$dates = $this->getDaysBetween($record->begin, $record->end);
$holidays = array_merge($holidays, $dates);
}
return array_intersect($naturalDays, $holidays);
}
/**
* Get working days.
*
* @param varchar $begin
* @param varchar $end
* @access public
* @return bool
*/
public function getWorkingDays($begin = '', $end = '')
{
$records = $this->dao->select('*')->from(TABLE_HOLIDAY)
->where('type')->eq('working')
->andWhere('begin')->le($end)
->andWhere('end')->ge($begin)
->fetchAll('id');
$workingDays = array();
foreach($records as $record)
{
$dates = $this->getDaysBetween($record->begin, $record->end);
$workingDays = array_merge($workingDays, $dates);
}
return $workingDays;
}
/**
* Get actual working days.
*
* @param varchar $begin
* @param varchar $end
* @access public
* @return bool
*/
public function getActualWorkingDays($begin, $end)
{
if(empty($begin) or empty($end) or $begin == '0000-00-00' or $end == '0000-00-00') return array();
$actualDays = array();
$currentDay = $begin;
$holidays = $this->getHolidays($begin, $end);
$workingDays = $this->getWorkingDays($begin, $end);
$weekend = isset($this->config->project->weekend) ? $this->config->project->weekend : 2;
/* When the start date and end date are the same. */
if($begin == $end)
{
if(in_array($begin, $workingDays)) return $actualDays[] = $begin;
if(in_array($begin, $holidays)) return $actualDays;
$w = date('w', strtotime($begin));
if($weekend == 2)
{
if($w == 0 or $w == 6) return $actualDays;
}
else
{
if($w == 0) return $actualDays;
}
$actualDays[] = $begin;
return $actualDays;
}
for($i = 0; $currentDay < $end; $i ++)
{
$currentDay = date('Y-m-d', strtotime("$begin + $i days"));
$w = date('w', strtotime($currentDay));
if(in_array($currentDay, $workingDays))
{
$actualDays[] = $currentDay;
continue;
}
if(in_array($currentDay, $holidays)) continue;
if($weekend == 2)
{
if($w == 0 or $w == 6) continue;
}
else
{
if($w == 0) continue;
}
$actualDays[] = $currentDay;
}
return $actualDays;
}
/**
* Get diff days.
*
* @param varchar $begin
* @param varchar $end
* @access public
* @return bool
*/
public function getDaysBetween($begin, $end)
{
$beginTime = strtotime($begin);
$endTime = strtotime($end);
$days = ($endTime - $beginTime) / 86400;
$dateList = array();
for($i = 0; $i <= $days; $i ++) $dateList[] = date('Y-m-d', strtotime("+$i days", $beginTime));
return $dateList;
}
/**
* Judge if is holiday.
*
* @param varchar $date
* @access public
* @return bool
*/
public function isHoliday($date)
{
$record = $this->dao->select('*')->from(TABLE_HOLIDAY)
->where('type')->eq('holiday')
->andWhere('begin')->le($date)
->andWhere('end')->ge($date)
->fetch();
return !empty($record);
}
/**
* Judge if is working days.
*
* @param varchar $date
* @access public
* @return bool
*/
public function isWorkingDay($date)
{
$record = $this->dao->select('*')->from(TABLE_HOLIDAY)
->where('type')->eq('working')
->andWhere('begin')->le($date)
->andWhere('end')->ge($date)
->fetch();
return !empty($record);
}
/**
* Update project plan duration.
*
* @param varchar $beginDate
* @param varchar $endDate
* @access public
* @return bool
*/
public function updateProjectPlanDuration($beginDate, $endDate)
{
$updateProjectList = $this->dao->select('id, begin, end')
->from(TABLE_PROJECT)
->where('begin')->between($beginDate, $endDate)
->orWhere('end')->between($beginDate, $endDate)
->orWhere("(begin < '$beginDate' AND end > '$endDate')")
->andWhere('status')->ne('done')
->fetchAll();
foreach($updateProjectList as $project)
{
$realDuration = $this->getActualWorkingDays($project->begin, $project->end);
$realDuration = count($realDuration);
$this->dao->update(TABLE_PROJECT)
->set('planDuration')->eq($realDuration)
->where('id')->eq($project->id)
->exec();
}
}
/**
* Update project real duration.
*
* @param varchar $beginDate
* @param varchar $endDate
* @access public
* @return bool
*/
public function updateProjectRealDuration($beginDate, $endDate)
{
$updateProjectList = $this->dao->select('id, realStarted, realFinished')
->from(TABLE_PROJECT)
->where('realStarted')->between($beginDate, $endDate)
->orWhere('realFinished')->between($beginDate, $endDate)
->orWhere("(realStarted < '$beginDate' AND realFinished > '$endDate')")
->andWhere('status')->ne('done')
->fetchAll();
foreach($updateProjectList as $project)
{
$realDuration = $this->getActualWorkingDays($project->realStarted, $project->realFinished);
$realDuration = count($realDuration);
$this->dao->update(TABLE_PROJECT)
->set('realDuration')->eq($realDuration)
->where('id')->eq($project->id)
->exec();
}
}
/**
* Update task plan duration.
*
* @param varchar $beginDate
* @param varchar $endDate
* @access public
* @return bool
*/
public function updateTaskPlanDuration($beginDate, $endDate)
{
$updateTaskList = $this->dao->select('id, estStarted, deadline')
->from(TABLE_TASK)
->where('estStarted')->between($beginDate, $endDate)
->orWhere('deadline')->between($beginDate, $endDate)
->orWhere("(estStarted < '$beginDate' AND deadline > '$endDate')")
->andWhere('status') ->ne('done')
->fetchAll();
foreach($updateTaskList as $task)
{
$planduration = $this->getActualWorkingDays($task->estStarted, $task->deadline);
$planduration = count($planduration);
$this->dao->update(TABLE_TASK)
->set('planduration')->eq($planduration)
->where('id')->eq($task->id)
->exec();
}
}
/**
* Update task real duration.
*
* @param varchar $beginDate
* @param varchar $endDate
* @access public
* @return bool
*/
public function updateTaskRealDuration($beginDate, $endDate)
{
$updateTaskList = $this->dao->select('id, realStarted, finishedDate')
->from(TABLE_TASK)
->where('realStarted')->between($beginDate, $endDate)
->orWhere("date_format(finishedDate,'%Y-%m-%d')")->between($beginDate, $endDate)
->orWhere("(realStarted < '$beginDate' AND date_format(finishedDate,'%Y-%m-%d') > '$endDate')")
->andWhere('status')->ne('done')
->fetchAll();
foreach($updateTaskList as $task)
{
$realDuration = $this->getActualWorkingDays($task->realStarted, date('Y-m-d',strtotime($task->finishedDate)));
$realDuration = count($realDuration);
$this->dao->update(TABLE_TASK)
->set('realDuration')->eq($realDuration)
->where('id')->eq($task->id)
->exec();
}
}
}

View File

@@ -0,0 +1,74 @@
<?php
/**
* The browse view file of holiday module of Ranzhi.
*
* @copyright Copyright 2009-2018 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author chujilu <chujilu@cnezsoft.com>
* @package holiday
* @version $Id$
* @link http://www.ranzhi.org
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='mainMenu' class='clearfix'>
<div class='pull-left btn-toolbar'>
<?php
echo html::a($this->createLink('holiday', 'browse'), '<span class="text">' . $lang->holiday->all . '</span>', '', "class='btn btn-link btn-active-text'");
?>
</div>
<div class='pull-right'>
<?php common::printLink('holiday', 'create', "", "<i class='icon icon-plus'> </i>" . $lang->holiday->create, '', "class='btn btn-primary iframe'", '', true)?>
</div>
</div>
<div id='mainContent' class='main-row fade in'>
<div class='side-col'>
<div class='panel panel-sm'>
<div class='panel-body'>
<ul class='tree' data-ride='tree' data-collapsed='true'>
<?php foreach($yearList as $year):?>
<li class='<?php echo $year == $currentYear ? 'active' : ''?>'>
<?php common::printLink('holiday', 'browse', "year=$year", $year);?>
</li>
<?php endforeach;?>
</ul>
</div>
</div>
</div>
<div class='main-col main-table'>
<?php if($holidays):?>
<table class='table text-center'>
<thead>
<tr class='text-center'>
<th class='w-150px'><?php echo $lang->holiday->name;?></th>
<th class='w-200px'><?php echo $lang->holiday->holiday;?></th>
<th class='w-80px'><?php echo $lang->holiday->type;?></th>
<th><?php echo $lang->holiday->desc;?></th>
<th class='w-100px'><?php echo $lang->actions;?></th>
</tr>
</thead>
<?php foreach($holidays as $holiday):?>
<tr>
<td><?php echo $holiday->name;?></td>
<td><?php echo formatTime($holiday->begin, DT_DATE1) . ' ~ ' . formatTime($holiday->end, DT_DATE1);?></td>
<td><?php echo zget($lang->holiday->typeList, $holiday->type);?></td>
<td><?php echo $holiday->desc;?></td>
<td>
<?php common::printLink('holiday', 'edit', "id=$holiday->id", $lang->edit, '', "class='iframe'", '', true);?>
<?php common::printLink('holiday', 'delete', "id=$holiday->id", $lang->delete);?>
</td>
</tr>
<?php endforeach;?>
</table>
<?php if(!$holidays):?>
<?php endif;?>
</div>
<?php else:?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->holiday->emptyTip;?></span>
</p>
</div>
<?php endif;?>
</div>
<?php include '../../common/view/footer.html.php';?>

View File

@@ -0,0 +1,53 @@
<?php
/**
* The create view file of holiday module of ZenTaoPMS.
*
* @copyright Copyright 2009-2018 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author chujilu <chujilu@cnezsoft.com>
* @package attend
* @version $Id$
* @link http://www.ranzhi.org
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2>
<?php echo $lang->holiday->create;?>
</h2>
</div>
<form class='form-ajax' method='post'>
<table class='table table-form table-condensed'>
<tr>
<th class='w-80px'><?php echo $lang->holiday->type;?></th>
<td><?php echo html::radio('type', $lang->holiday->typeList, 'holiday');?></td>
<td></td>
</tr>
<tr>
<th class='w-80px'><?php echo $lang->holiday->name;?></th>
<td><?php echo html::input('name', '', "class='form-control'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->holiday->begin;?></th>
<td><?php echo html::input('begin', '', "class='form-control form-date'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->holiday->end;?></th>
<td><?php echo html::input('end', '', "class='form-control form-date'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->holiday->desc?></th>
<td><?php echo html::textarea('desc', '', "class='form-control'")?></td>
<td></td>
</tr>
<tr><th></th><td clospan='2'><?php echo baseHTML::submitButton();?></td></tr>
</table>
</form>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>

View File

@@ -0,0 +1,53 @@
<?php
/**
* The create view file of holiday module of ZenTaoPMS.
*
* @copyright Copyright 2009-2018 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author chujilu <chujilu@cnezsoft.com>
* @package attend
* @version $Id$
* @link http://www.ranzhi.org
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2>
<?php echo $lang->holiday->edit;?>
</h2>
</div>
<form class='form-ajax' method='post'>
<table class='table table-form table-condensed'>
<tr>
<th class='w-80px'><?php echo $lang->holiday->type;?></th>
<td><?php echo html::radio('type', $lang->holiday->typeList, $holiday->type);?></td>
<td></td>
</tr>
<tr>
<th class='w-80px'><?php echo $lang->holiday->name?></th>
<td><?php echo html::input('name', $holiday->name, "class='form-control'")?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->holiday->begin?></th>
<td><?php echo html::input('begin', $holiday->begin, "class='form-control form-date'")?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->holiday->end?></th>
<td><?php echo html::input('end', $holiday->end, "class='form-control form-date'")?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->holiday->desc?></th>
<td><?php echo html::textarea('desc', $holiday->desc, "class='form-control'")?></td>
<td></td>
</tr>
<tr><th></th><td clospan='2'><?php echo baseHTML::submitButton();?></td></tr>
</table>
</form>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>

View File

@@ -81,7 +81,6 @@ class productModel extends model
}
if($currentMethod == 'report') $currentMethod = 'browse';
$selectHtml = $this->select($products, $product->id, $currentModule, $currentMethod, $extra, $branch, $module, $moduleType);
$pageNav = '';
@@ -93,17 +92,15 @@ class productModel extends model
}
else
{
if(isset($project->category) and $project->category == 'multiple' || $project->template == 'scrum') $pageNav = $selectHtml;
}
$label = $this->lang->product->index;
$pageNav = '<div class="btn-group angle-btn' . ($currentMethod == 'index' ? ' active' : '') . '"><div class="btn-group"><button data-toggle="dropdown" type="button" class="btn">' . $label . ' <span class="caret"></span></button>';
$pageNav .= '<ul class="dropdown-menu">';
if($this->config->global->flow == 'full' && common::hasPriv('product', 'index')) $pageNav .= '<li>' . html::a(helper::createLink('product', 'index', 'locate=no'), '<i class="icon icon-home"></i> ' . $this->lang->product->index) . '</li>';
if(common::hasPriv('product', 'all')) $pageNav .= '<li>' . html::a(helper::createLink('product', 'all'), '<i class="icon icon-cards-view"></i> ' . $this->lang->product->all) . '</li>';
if(common::hasPriv('product', 'create')) $pageNav .= '<li>' . html::a(helper::createLink('product', 'create'), '<i class="icon icon-plus"></i> ' . $this->lang->product->create) . '</li>';
$pageActions = '';
if($this->config->global->flow != 'full')
{
if($currentMethod == 'build' && common::hasPriv('build', 'create'))
{
$this->app->loadLang('build');
$pageActions .= html::a(helper::createLink('build', 'create', "productID=$productID"), "<i class='icon icon-plus'></i> {$this->lang->build->create}", '', "class='btn btn-primary'");
}
$pageNav .= '</ul></div></div>';
$pageNav .= $selectHtml;
}
return $pageNav;
@@ -160,22 +157,6 @@ class productModel extends model
}
}
if($this->config->global->flow == 'onlyTest' and $moduleType)
{
if($module) $module = $this->loadModel('tree')->getById($module);
$moduleName = $module ? $module->name : $this->lang->tree->all;
if(!$isMobile)
{
$dropMenuLink = helper::createLink('tree', 'ajaxGetDropMenu', "objectID=$productID&module=$currentModule&method=$currentMethod&extra=$extra");
$output .= "<div class='btn-group'><button id='currentModule' data-toggle='dropdown' type='button' class='btn btn-limit'>{$moduleName} <span class='caret'></span></button><div id='dropMenu' class='dropdown-menu search-list' data-ride='searchList' data-url='$dropMenuLink'>";
$output .= '<div class="input-control search-box has-icon-left has-icon-right search-example"><input type="search" class="form-control search-input" /><label class="input-control-icon-left search-icon"><i class="icon icon-search"></i></label><a class="input-control-icon-right search-clear-btn"><i class="icon icon-close icon-sm"></i></a></div>';
$output .= "</div></div>";
}
else
{
$output .= "<a id='currentModule' href=\"javascript:showSearchMenu('tree', '$productID', '$currentModule', '$currentMethod', '$extra')\">{$moduleName} <span class='icon-caret-down'></span></a><div id='currentBranchDropMenu' class='hidden affix enter-from-bottom layer'></div>";
}
}
if(!$isMobile) $output .= '</div>';
return $output;

View File

@@ -12,12 +12,6 @@
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/sortable.html.php';?>
<div id="mainMenu" class="clearfix">
<div id="sidebarHeader">
<div class="title">
<?php echo $line ? zget($lines, $line) : $lang->product->line;?>
<?php if($line) echo html::a(inlink('all', "productID={$productID}&line=&status={$status}"), "<i class='icon icon-sm icon-close'></i>", '', "class='text-muted'");?>
</div>
</div>
<div class="btn-toolbar pull-left">
<?php
foreach($lang->product->featureBar['all'] as $key => $label)
@@ -42,16 +36,6 @@
</div>
</div>
<div id="mainContent" class="main-row fade">
<div class="side-col" id="sidebar">
<div class="sidebar-toggle"><i class="icon icon-angle-left"></i></div>
<div class="cell">
<?php echo $lineTree;?>
<div class="text-center">
<?php common::printLink('tree', 'browse', "rootID=$productID&view=line", $lang->tree->manageLine, '', "class='btn btn-info btn-wide'");?>
<hr class="space-sm" />
</div>
</div>
</div>
<div class="main-col">
<form class="main-table table-product" data-ride="table" method="post" id='productsForm' action='<?php echo inLink('batchEdit', "productID=$productID");?>'>
<?php $canOrder = (common::hasPriv('product', 'updateOrder'))?>

View File

@@ -29,16 +29,6 @@
<th><?php echo $lang->product->code;?></th>
<td><?php echo html::input('code', '', "class='form-control input-product-code' required");?></td><td></td>
</tr>
<tr>
<th><?php echo $lang->product->line;?></th>
<td>
<div class='input-group' id='lineIdBox'>
<?php echo html::select('line', $lines, '', "class='form-control chosen'");?>
<span class='input-group-addon'><?php echo html::a($this->createLink('tree', 'browse', "rootID=$rootID&view=line", '', true), $lang->tree->manageLine, '', "class='text-primary' data-toggle='modal' data-type='iframe' data-width='95%'");?></span>
</div>
<div class='hidden'><?php echo html::a("javascript:void(0)", $lang->refresh, '', "class='refresh' onclick='loadProductLines($rootID)'");?></div>
</td>
</tr>
<tr>
<th><?php echo $lang->product->PO;?></th>
<td><?php echo html::select('PO', $poUsers, $this->app->user->account, "class='form-control chosen'");?></td><td></td>

View File

@@ -33,11 +33,6 @@
<th><?php echo $lang->product->code;?></th>
<td><?php echo html::input('code', $product->code, "class='form-control' required");?></td><td></td>
</tr>
<tr>
<th><?php echo $lang->product->line;?></th>
<td><?php echo html::select('line', $lines, $product->line, "class='form-control chosen'");?></td>
<td><?php if(!$lines) common::printLink('tree', 'browse', 'rootID=&view=line', $lang->tree->manageLine);?></td>
</tr>
<tr>
<th><?php echo $lang->product->PO;?></th>
<td><?php echo html::select('PO', $poUsers, $product->PO, "class='form-control chosen'");?></td><td></td>

View File

@@ -9,7 +9,7 @@ class program extends control
$this->programs = $this->program->getPairs();
}
public function index($status = 'doing', $orderBy = 'order_desc', $recTotal = 0, $recPerPage = 10, $pageID = 1)
public function browse($status = 'doing', $orderBy = 'order_desc', $recTotal = 0, $recPerPage = 10, $pageID = 1)
{
if(common::hasPriv('program', 'createGuide')) $this->lang->pageActions = html::a($this->createLink('program', 'createGuide'), "<i class='icon icon-sm icon-plus'></i> " . $this->lang->program->create, '', "class='btn btn-primary' data-toggle=modal");
@@ -36,8 +36,8 @@ class program extends control
$this->view->orderBy = $orderBy;
$this->view->pager = $pager;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->title = $this->lang->program->index;
$this->view->position[] = $this->lang->program->index;
$this->view->title = $this->lang->program->browse;
$this->view->position[] = $this->lang->program->browse;
$this->view->programType = $programType;
$this->display();
}
@@ -57,7 +57,7 @@ class program extends control
$this->send(array('result' => 'fail', 'message' => $this->processErrors(dao::getError())));
}
$this->loadModel('action')->create('project', $projectID, 'opened');
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('index', array('status' => 'wait', 'orderBy' => 'order_desc'))));
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse', array('status' => 'wait', 'orderBy' => 'order_desc'))));
}
$name = '';
@@ -329,7 +329,7 @@ class program extends control
$actionID = $this->loadModel('action')->create('project', $projectID, 'edited');
$this->action->logHistory($actionID, $changes);
}
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('index')));
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
}
$this->view->pmUsers = $this->loadModel('user')->getPairs('noclosed|nodeleted|pmfirst', $project->PM);
@@ -346,7 +346,7 @@ class program extends control
if(!empty($_POST))
{
$this->project->manageMembers($projectID);
die(js::locate($this->createLink('program', 'index'), 'parent'));
die(js::locate($this->createLink('program', 'browse'), 'parent'));
}
/* Load model. */
@@ -419,7 +419,7 @@ class program extends control
else
{
$this->project->delete(TABLE_PROJECT, $projectID);
die(js::locate(inlink('index'), 'parent'));
die(js::locate(inlink('browse'), 'parent'));
}
}

View File

@@ -1,5 +1,6 @@
<?php
$lang->program->index = '项目主页';
$lang->program->browse = '项目列表';
$lang->program->common = '项目';
$lang->program->stage = '阶段';
$lang->program->name = '项目名称';

View File

@@ -50,10 +50,10 @@ class programModel extends model
{
echo(js::alert($this->lang->program->accessDenied));
if(!$this->server->http_referer) die(js::locate(helper::createLink('program', 'index')));
if(!$this->server->http_referer) die(js::locate(helper::createLink('program', 'browse')));
$loginLink = $this->config->requestType == 'GET' ? "?{$this->config->moduleVar}=user&{$this->config->methodVar}=login" : "user{$this->config->requestFix}login";
if(strpos($this->server->http_referer, $loginLink) !== false) die(js::locate(helper::createLink('program', 'index')));
if(strpos($this->server->http_referer, $loginLink) !== false) die(js::locate(helper::createLink('program', 'browse')));
die(js::locate('back'));
}
@@ -160,7 +160,7 @@ class programModel extends model
$currentProgram = $this->project->getById($programID);
$currentProgramName = $currentProgram->name;
}
if($currentModule == 'program' && $currentMethod == 'index') $currentProgramName = $this->lang->program->all;
if($currentModule == 'program' && $currentMethod == 'browse') $currentProgramName = $this->lang->program->all;
$dropMenuLink = helper::createLink('program', 'ajaxGetDropMenu', "objectID=$programID&module=$currentModule&method=$currentMethod&extra=$extra");
$output = "<div class='btn-group' id='swapper'><button data-toggle='dropdown' type='button' class='btn btn-limit' id='currentItem' title='{$currentProgramName}'>{$currentProgramName} <i class='icon icon-swap'></i></button><div id='dropMenu' class='dropdown-menu search-list' data-ride='searchList' data-url='$dropMenuLink'>";

View File

@@ -51,7 +51,7 @@ foreach($programs as $program)
<div class="col-footer">
<?php echo html::a(helper::createLink('program', 'createGuide'), '<i class="icon icon-plus"></i>' . $lang->program->create, '', 'class="not-list-item text-primary" data-toggle=modal'); ?>
<div class='pull-right'>
<?php echo html::a(helper::createLink('program', 'index', 'status=all'), '<i class="icon icon-cards-view muted"></i> ' . $lang->project->all, '', 'class="not-list-item"'); ?>
<?php echo html::a(helper::createLink('program', 'browse', 'status=all'), '<i class="icon icon-cards-view muted"></i> ' . $lang->project->all, '', 'class="not-list-item"'); ?>
<span class='text-muted muted'> &nbsp; | &nbsp; </span>
<a class='toggle-right-col not-list-item'><?php echo $lang->project->doneProjects?><i class='icon icon-angle-right'></i></a>
</div>

View File

@@ -24,7 +24,7 @@
<?php $active = $status == $key ? 'btn-active-text' : '';?>
<?php $label = "<span class='text'>$label</span>";?>
<?php if($status == $key) $label .= " <span class='label label-light label-badge'>{$pager->recTotal}</span>";?>
<?php echo html::a(inlink('index', "status=$key&orderBy=$orderBy"), $label, '', "class='btn btn-link $active'");?>
<?php echo html::a(inlink('browse', "status=$key&orderBy=$orderBy"), $label, '', "class='btn btn-link $active'");?>
<?php endforeach;?>
<?php echo html::checkbox('mine', array('1' => $lang->program->mine), '', $this->cookie->mine ? 'checked=checked' : '');?>
</div>
@@ -40,7 +40,7 @@
<div id='mainContent' class='main-row'>
<?php if(empty($projectList)):?>
<div class="table-empty-tip">
<p><span class="text-muted"><?php echo $lang->program->noProgram;?></span> <?php common::printLink('program', 'createguide', '', "<i class='icon icon-plus'></i> " . $lang->program->create, '', "class='btn btn-info'");?></p>
<p><span class="text-muted"><?php echo $lang->program->noProgram;?></span> <?php common::printLink('program', 'createguide', '', "<i class='icon icon-plus'></i> " . $lang->program->create, '', "class='btn btn-info' data-toggle=modal");?></p>
</div>
<?php else:?>
<div class='main-col'>

View File

@@ -16,7 +16,7 @@ function fixScroll()
if($tfoot.size() > 0) scrollOffset += $tfoot.height();
if($('div.datatable.head-fixed').size() == 0) scrollOffset -= '29';
var windowH = $(window).height();
$scrollwrapper.css({'position': 'fixed', 'bottom': 50 + 'px'});
if(scrollOffset > windowH + $(window).scrollTop()) $scrollwrapper.css({'position': 'fixed', 'bottom': 50 + 'px'});
$(window).scroll(function()
{
newBottom = $tfoot.hasClass('fixedTfootAction') ? 50 + $tfoot.height() : 50;

View File

@@ -2243,16 +2243,15 @@ class project extends control
*/
public function ajaxGetDropMenu($projectID, $module, $method, $extra)
{
$project = $this->project->getByID($projectID);
$program = $this->project->getByID($project->program);
$this->view->link = $this->project->getProjectLink($module, $method, $extra);
$this->view->projectID = $projectID;
$this->view->module = $module;
$this->view->method = $method;
$this->view->extra = $extra;
$projects = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->in(array_keys($this->projects))->orderBy('order desc')->fetchAll();
$projectPairs = array();
foreach($projects as $project) $projectPairs[$project->id] = $project->name;
$this->view->projects = $projects;
$this->view->projects = $this->project->getProjectsByProgram($program);
$this->display();
}

View File

@@ -122,7 +122,18 @@ class projectModel extends model
$this->cookie->projectMode = 'all';
}
if(!isset($this->lang->modulePageNav)) $this->lang->modulePageNav = $this->getModuleNav($projectID, $extra);
/* Set project module page nav. */
$label = $this->lang->project->index;
$projectIndex = '<div class="btn-group angle-btn' . ($methodName == 'index' ? ' active' : '') . '"><div class="btn-group"><button data-toggle="dropdown" type="button" class="btn">' . $label . ' <span class="caret"></span></button>';
$projectIndex .= '<ul class="dropdown-menu">';
if(common::hasPriv('project', 'index')) $projectIndex .= '<li>' . html::a(helper::createLink('project', 'index', 'locate=no'), '<i class="icon icon-home"></i> ' . $this->lang->project->index) . '</li>';
if(common::hasPriv('project', 'all')) $projectIndex .= '<li>' . html::a(helper::createLink('project', 'all', 'status=all'), '<i class="icon icon-cards-view"></i> ' . $this->lang->project->allProjects) . '</li>';
if(common::hasPriv('project', 'create')) $projectIndex .= '<li>' . html::a(helper::createLink('project', 'create'), '<i class="icon icon-plus"></i> ' . $this->lang->project->create) . '</li>';
$projectIndex .= '</ul></div></div>';
$projectIndex .= $this->select(null, $projectID, null, $moduleName, $methodName, $extra);
$this->lang->modulePageNav = $projectIndex;
foreach($this->lang->project->menu as $key => $menu)
{
common::setMenuVars($this->lang->project->menu, $key, $projectID);
@@ -154,24 +165,6 @@ class projectModel extends model
return true;
}
/**
* Set module page nav.
*
* @param int $activeID
* @param string $extra
* @access public
* @return string
*/
public function getModuleNav($projectID, $extra = '')
{
$moduleName = $this->app->getModuleName();
$methodName = $this->app->getMethodName();
$selectHtml = $this->select(null, $projectID, null, $moduleName, $methodName, $extra);
return $selectHtml; //暂时先隐藏掉迭代主页、单个创建迭代和所有迭代列表页面,统一使用计划阶段来管理
}
/**
* Create the select code of projects.
*
@@ -195,8 +188,7 @@ class projectModel extends model
if(isset($currentProject->type) and $currentProject->type == 'program') return;
if(isset($currentProject->program))
$program = $this->getByID($currentProject->program);
if(isset($currentProject->program)) $program = $this->getByID($currentProject->program);
if(isset($program->category) and $program->category == 'multiple')
{
@@ -847,6 +839,40 @@ class projectModel extends model
}
}
/**
* Get projects by program.
*
* @param int $program
* @access public
* @return array
*/
public function getProjectsByProgram($program)
{
$projects = $this->dao->select('t1.*, t3.name as productName')->from(TABLE_PROJECT)->alias('t1')
->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id = t2.project')
->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t2.product = t3.id')
->where('t1.program')->eq((int)$program->id)
->andWhere('t1.template')->eq('')
->andWhere('t1.deleted')->eq('0')
->orderBy('t1.order desc')
->fetchAll('id');
if($program->template == 'cmmi')
{
foreach($projects as $projectID => $project)
{
if($project->parent and isset($projects[$project->id]) and isset($projects[$project->parent])) $projects[$project->id]->name = $projects[$project->parent]->name . '/' . $project->name;
}
if($program->category == 'multiple')
{
foreach($projects as $projectID => $project) $projects[$projectID]->name = $project->productName . '/' . $project->name;
}
foreach($projects as $projectID => $project) unset($projects[$project->parent]);
}
return $projects;
}
/**
* Get projects lists grouped by product.
*

View File

@@ -22,7 +22,6 @@
</div>
<div class='btn-toolbar pull-right'>
<?php common::printLink('project', 'export', "status=$status&productID=$productID&orderBy=$orderBy", "<i class='icon-export muted'> </i>" . $lang->export, '', "class='btn btn-link export'")?>
<?php common::printLink('program', 'createguide', '', "<i class='icon-plus'></i> " . $lang->project->create, '', "class='btn btn-primary' data-toggle='modal' data-type='ajax'")?>
</div>
</div>
<div id='mainContent'>