* Finish task#9005.

This commit is contained in:
leiyong
2021-01-19 11:13:23 +08:00
parent 36bc9e9d02
commit 66ef1c6fa3
36 changed files with 1693 additions and 121 deletions
+3
View File
@@ -284,3 +284,6 @@ $filter->repo->ajaxsynccommit->cookie['syncBranch'] = 'reg::any';
$filter->webhook->bind->get['selectedDepts'] = 'reg::checked';
$filter->webhook->bind->cookie['selectedDepts'] = 'reg::checked';
$filter->search->index->get['words'] = 'reg::any';
$filter->search->index->get['type'] = 'code';
+3
View File
@@ -174,6 +174,9 @@ if(!defined('TABLE_BUDGET')) define('TABLE_BUDGET', '`' . $config->d
if(!defined('TABLE_HOLIDAY')) define('TABLE_HOLIDAY', '`' . $config->db->prefix . 'holiday`');
if(!defined('TABLE_WEEKLYREPORT')) define('TABLE_WEEKLYREPORT', '`' . $config->db->prefix . 'weeklyreport`');
if(!defined('TABLE_SEARCHINDEX')) define('TABLE_SEARCHINDEX', $config->db->prefix . 'searchindex');
if(!defined('TABLE_SEARCHDICT')) define('TABLE_SEARCHDICT', $config->db->prefix . 'searchdict');
$config->objectTables['product'] = TABLE_PRODUCT;
$config->objectTables['story'] = TABLE_STORY;
$config->objectTables['productplan'] = TABLE_PRODUCTPLAN;
+36
View File
@@ -18,3 +18,39 @@ ALTER TABLE `zt_project` DROP `storyConcept`;
ALTER TABLE `zt_product` DROP `storyConcept`;
ALTER TABLE `zt_user` CHANGE `avatar` `avatar` text NOT NULL AFTER `commiter`;
-- DROP TABLE IF EXISTS `zt_searchindex`;
CREATE TABLE IF NOT EXISTS `zt_searchindex` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`objectType` char(20) NOT NULL,
`objectID` mediumint(9) NOT NULL,
`title` text NOT NULL,
`content` text NOT NULL,
`addedDate` datetime NOT NULL,
`editedDate` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `object` (`objectType`,`objectID`),
KEY `addedDate` (`addedDate`),
FULLTEXT KEY `content` (`content`),
FULLTEXT KEY `title` (`title`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_searchdict`;
CREATE TABLE IF NOT EXISTS `zt_searchdict` (
`key` smallint(5) unsigned NOT NULL,
`value` char(3) NOT NULL,
PRIMARY KEY (`key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
REPLACE INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(1, 'search', 'index'),
(2, 'search', 'index'),
(3, 'search', 'index'),
(4, 'search', 'index'),
(5, 'search', 'index'),
(6, 'search', 'index'),
(7, 'search', 'index'),
(8, 'search', 'index'),
(9, 'search', 'index'),
(10, 'search', 'index'),
(1, 'search', 'buildIndex');
+36
View File
@@ -1,3 +1,26 @@
-- DROP TABLE IF EXISTS `zt_searchindex`;
CREATE TABLE IF NOT EXISTS `zt_searchindex` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`objectType` char(20) NOT NULL,
`objectID` mediumint(9) NOT NULL,
`title` text NOT NULL,
`content` text NOT NULL,
`addedDate` datetime NOT NULL,
`editedDate` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `object` (`objectType`,`objectID`),
KEY `addedDate` (`addedDate`),
FULLTEXT KEY `content` (`content`),
FULLTEXT KEY `title` (`title`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_searchdict`;
CREATE TABLE IF NOT EXISTS `zt_searchdict` (
`key` smallint(5) unsigned NOT NULL,
`value` char(3) NOT NULL,
PRIMARY KEY (`key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_acl`;
CREATE TABLE IF NOT EXISTS `zt_acl` (
`id` mediumint(9) NOT NULL AUTO_INCREMENT,
@@ -1481,6 +1504,19 @@ INSERT INTO `zt_group` (`id`, `name`, `role`, `desc`) VALUES
(12, 'LIMITED', 'limited', 'For limited user'),
(13, '项目管理员', 'PRJAdmin', '项目管理员可以维护项目的权限');
INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(1, 'search', 'index'),
(2, 'search', 'index'),
(3, 'search', 'index'),
(4, 'search', 'index'),
(5, 'search', 'index'),
(6, 'search', 'index'),
(7, 'search', 'index'),
(8, 'search', 'index'),
(9, 'search', 'index'),
(10, 'search', 'index'),
(1, 'search', 'buildIndex');
INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(1, 'action', 'editComment'),
(1, 'action', 'hideAll'),
+124
View File
@@ -0,0 +1,124 @@
<?php
/**
* The spliter class file of chanzhiEPS.
*
* @copyright Copyright 2013-2014 青岛息壤网络信息有限公司 (QingDao XiRang Network Infomation Co,LTD www.xirangit.com)
* @license LGPL
* @author Xiying Guan <guanxiying@xirangit.com>
* @package spliter
* @version $Id$
* @link http://www.chanzhi.org
* @see http://www.cnblogs.com/chenwenbiao/archive/2011/08/11/2134503.html
* @see http://stackoverflow.com/questions/9361303/can-i-get-the-unicode-value-of-a-character-or-vise-versa-with-php
*/
class spliter
{
/**
* Split a utf-8 string into words, computing unicode for every word.
*
* @param string $string
* @access public
* @return array
*/
public function utf8Split($string)
{
$string = strtolower($string);
$i = 0;
$length = strlen($string);
$dict = array();
$words = '';
$offset = 0;
while($i <= $length)
{
$letter = substr($string, $i, 1);
$ord = ord($letter);
/* The first letter is ascii, try to get a word. */
if($ord >= 0 && $ord <= 191)
{
$i ++;
if($this->isLetter($letter))
{
$word = $letter;
while($i <= $length)
{
$letter = substr($string, $i, 1);
if(!$this->isLetter($letter)) break;
$word .= $letter;
$i++;
}
/* Process intigers. */
if(is_numeric($word) and (strpos($word, '.') === false)) $word = "|" . $word . "|";
$word = str_pad(strtolower($word), 5, '_');
$words .= ' ' . $word;
}
continue;
}
if($ord >= 192 && $ord <= 223) $offset = 2;
if($ord >= 224 && $ord <= 239) $offset = 3;
if($ord >= 240 && $ord <= 247) $offset = 4;
if($ord >= 248 && $ord <= 251) $offset = 5;
if($ord >= 252 && $ord <= 253) $offset = 6;
if($offset >= 2)
{
$letter = substr($string, $i, $offset);
$unicode = $this->unicode($letter);
if(strlen($unicode) == 5)
{
$dict[$unicode] = $letter;
$words .= ' ' . $unicode;
}
else
{
$words .= ' ' . $letter;
}
$i += $offset;
}
}
return array('dict' => $dict, 'words' => $words);
}
/**
* Return unicode value for a char.
*
* @param string $c
* @access public
* @return int
*/
public function unicode($c)
{
if(ord($c{0}) >= 0 && ord($c{0}) <= 127) return ord($c{0});
if(ord($c{0}) >= 192 && ord($c{0}) <= 223) return (ord($c{0}) - 192) * 64 + (ord($c{1}) - 128);
if(ord($c{0}) >= 224 && ord($c{0}) <= 239) return (ord($c{0}) - 224) * 4096 + (ord($c{1}) - 128) * 64 + (ord($c{2}) - 128);
if(ord($c{0}) >= 240 && ord($c{0}) <= 247) return (ord($c{0}) - 240) * 262144 + (ord($c{1}) - 128) * 4096 + (ord($c{2}) - 128) * 64 + (ord($c{3}) - 128);
if(ord($c{0}) >= 248 && ord($c{0}) <= 251) return (ord($c{0}) - 248) * 16777216 + (ord($c{1}) - 128) * 262144 + (ord($c{2}) - 128) * 4096 + (ord($c{3}) - 128) * 64 + (ord($c{4}) - 128);
if(ord($c{0}) >= 252 && ord($c{0}) <= 253) return (ord($c{0}) - 252) * 1073741824 + (ord($c{1}) - 128) * 16777216 + (ord($c{2}) - 128) * 262144 + (ord($c{3}) - 128) * 4096 + (ord($c{4}) - 128) * 64 + (ord($c{5}) - 128);
if(ord($c{0}) >= 254 && ord($c{0}) <= 255) return false;
return false;
}
/**
* Judge a char is Letter or not.
*
* @param string $letter
* @access public
* @return bool
*/
public function isLetter($letter)
{
$ord = ord($letter);
if($ord >= ord('a') and $ord <= ord('z')) return true;
if($ord >= ord('A') and $ord <= ord('Z')) return true;
if($ord >= ord(0) and $ord <= ord(9)) return true;
if($letter and strpos('._/->:<?&', $letter) !== false) return true;
return false;
}
}
+53
View File
@@ -69,6 +69,8 @@ class actionModel extends model
$this->loadModel('message')->send($objectType, $objectID, $actionType, $actionID, $actor);
$this->saveIndex($objectType, $objectID, $actionType);
return $actionID;
}
@@ -1185,4 +1187,55 @@ class actionModel extends model
->fetch('count');
return $count > 0;
}
/**
* Save global search object index information.
*
* @param string $objectType
* @param int $objectID
* @param string $actionType
* @access public
* @return bool
*/
public function saveIndex($objectType, $objectID, $actionType)
{
$this->loadModel('search');
$actionType = strtolower($actionType);
if(!isset($this->config->search->fields->$objectType)) return true;
if(strpos($this->config->search->buildAction, ",{$actionType},") === false and empty($_POST['comment'])) return true;
if($actionType == 'deleted' or $actionType == 'erased') return $this->search->deleteIndex($objectType, $objectID);
$field = $this->config->search->fields->$objectType;
$query = $this->search->buildIndexQuery($objectType, $testDeleted = false);
$data = $query->andWhere('t1.' . $field->id)->eq($objectID)->fetch();
if(empty($data)) return true;
$data->comment = '';
if($objectType == 'effort' and $data->objectType == 'task') return true;
if($objectType == 'case')
{
$caseStep = $this->dao->select('*')->from(TABLE_CASESTEP)->where('`case`')->eq($objectID)->andWhere('version')->eq($data->version)->fetchAll();
$data->desc = '';
$data->expect = '';
foreach($caseStep as $step)
{
$data->desc .= $step->desc . "\n";
$data->expect .= $step->expect . "\n";
}
}
$actions = $this->dao->select('*')->from(TABLE_ACTION)
->where('objectType')->eq($objectType)
->andWhere('objectID')->eq($objectID)
->orderBy('id asc')
->fetchAll();
foreach($actions as $action)
{
if($action->action == 'opened') $data->{$field->addedDate} = $action->date;
$data->{$field->editedDate} = $action->date;
if(!empty($action->comment)) $data->comment .= $action->comment . "\n";
}
$this->search->saveIndex($objectType, $data);
}
}
+27 -13
View File
@@ -131,6 +131,11 @@ $lang->typeAB = 'Typ';
$lang->common = new stdclass();
$lang->common->common = 'Standard Module';
global $config;
list($programModule, $programMethod) = explode('-', $config->programLink);
list($productModule, $productMethod) = explode('-', $config->productLink);
list($projectModule, $projectMethod) = explode('-', $config->projectLink);
/* Main menu. */
$lang->mainNav = new stdclass();
$lang->mainNav->my = '<i class="icon icon-menu-my"></i> My|my|index|';
@@ -220,7 +225,11 @@ $lang->holiday->menu = $lang->subject->menu;
$lang->measurement = new stdclass();
$lang->measurement->menu = new stdclass();
$lang->searchTips = '';
$lang->searchAB = 'Search';
/* Object list in search form. */
$lang->searchObjects['all'] = 'All';
$lang->searchObjects['bug'] = 'Bug';
$lang->searchObjects['story'] = 'Story';
$lang->searchObjects['task'] = 'Aufgaben';
@@ -236,6 +245,7 @@ $lang->searchObjects['testreport'] = 'Test-Bericht';
$lang->searchObjects['program'] = 'Program';
$lang->searchObjects['project'] = 'Project';
$lang->searchObjects['execution'] = $lang->sprintCommon;
$lang->searchObjects['user'] = 'User';
$lang->searchTips = 'ID (strg+g)';
/* Code formats for import. */
@@ -338,18 +348,18 @@ $lang->story->menu = $lang->product->menu;
$lang->project = new stdclass();
$lang->project->menu = new stdclass();
$lang->project->menu->task = array('link' => 'Aufgabenliste|project|task|projectID=%s', 'subModule' => 'task,grouptask,tree', 'alias' => 'grouptask,importtask,importbug,tree', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->kanban = array('link' => 'Kanban|project|kanban|projectID=%s');
$lang->project->menu->burn = array('link' => 'Burn|project|burn|projectID=%s');
$lang->project->menu->view = array('link' => 'View|project|grouptask|projectID=%s', 'alias' => 'grouptask,tree', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->story = array('link' => 'Story|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory,storykanban');
$lang->project->menu->bug = array('link' => 'Bug|project|bug|projectID=%s');
$lang->project->menu->build = array('link' => 'Build|project|build|projectID=%s', 'subModule' => 'build');
$lang->project->menu->testtask = array('link' => 'Test Aufgabe|project|testtask|projectID=%s', 'subModule' => 'testreport,testtask');
$lang->project->menu->doc = array('link' => 'Dok|doc|objectLibs|type=project&objectID=%s&from=project', 'subModule' => 'doc');
$lang->project->menu->product = $lang->productCommon . '|project|manageproducts|projectID=%s';
$lang->project->menu->team = array('link' => 'Team|project|team|projectID=%s', 'alias' => 'managemembers');
$lang->project->menu->more = array('link' => 'More|project|whitelist|projectID=%s', 'subModule' => 'personnel', 'alias' => 'edit', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->task = array('link' => 'Aufgabenliste|project|task|projectID=%s', 'subModule' => 'task,grouptask,tree', 'alias' => 'grouptask,importtask,importbug,tree', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->kanban = array('link' => 'Kanban|project|kanban|projectID=%s');
$lang->project->menu->burn = array('link' => 'Burn|project|burn|projectID=%s');
$lang->project->menu->view = array('link' => 'View|project|grouptask|projectID=%s', 'alias' => 'grouptask,tree', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->story = array('link' => 'Story|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory,storykanban');
$lang->project->menu->bug = array('link' => 'Bug|project|bug|projectID=%s');
$lang->project->menu->build = array('link' => 'Build|project|build|projectID=%s', 'subModule' => 'build');
$lang->project->menu->testtask = array('link' => 'Test Aufgabe|project|testtask|projectID=%s', 'subModule' => 'testreport,testtask');
$lang->project->menu->doc = array('link' => 'Dok|doc|objectLibs|type=project&objectID=%s&from=project', 'subModule' => 'doc');
$lang->project->menu->product = $lang->productCommon . '|project|manageproducts|projectID=%s';
$lang->project->menu->team = array('link' => 'Team|project|team|projectID=%s', 'alias' => 'managemembers');
$lang->project->menu->more = array('link' => 'More|project|whitelist|projectID=%s', 'subModule' => 'personnel', 'alias' => 'edit', 'class' => 'dropdown dropdown-hover');
$lang->project->subMenu = new stdclass();
$lang->project->subMenu->view = new stdclass();
@@ -560,6 +570,9 @@ $lang->admin->subMenu->system = new stdclass();
$lang->admin->subMenu->system->cron = array('link' => 'Cron|cron|index', 'subModule' => 'cron');
$lang->admin->subMenu->system->timezone = array('link' => 'Timezone|custom|timezone', 'subModule' => 'custom');
$lang->admin->subMenu->system->buildIndex = array('link' => 'Full Text Search|search|buildindex|');
$lang->admin->subMenuOrder->system[15] = 'buildIndex';
$lang->convert = new stdclass();
$lang->upgrade = new stdclass();
$lang->action = new stdclass();
@@ -619,6 +632,7 @@ $lang->navGroup = new stdclass();
$lang->navGroup->my = 'my';
$lang->navGroup->todo = 'my';
$lang->navGroup->effort = 'my';
$lang->navGroup->score = 'my';
$lang->navGroup->personnel = 'program';
@@ -999,6 +1013,6 @@ $lang->projectstory->menu->story = array('link' => "{$lang->SRCommon}|projectsto
$lang->projectstory->menu->track = array('link' => 'Track|projectstory|track', 'subModule' => '');
$lang->nc->menu = $lang->auditplan->menu;
$lang->noMenuModule = array('my', 'todo', 'effort', 'program', 'product', 'productplan', 'projectbuild', 'projectrelease', 'story', 'job', 'jenkins', 'branch', 'release', 'attend', 'leave', 'makeup', 'overtime', 'lieu', 'custom', 'admin', 'mail', 'extension', 'dev', 'backup', 'action', 'cron', 'issue', 'risk', 'pssp', 'sms', 'message', 'webhook', 'search', 'stage');
$lang->noMenuModule = array('my', 'todo', 'effort', 'program', 'product', 'productplan', 'projectbuild', 'projectrelease', 'story', 'branch', 'release', 'attend', 'leave', 'makeup', 'overtime', 'lieu', 'custom', 'admin', 'mail', 'extension', 'dev', 'backup', 'action', 'cron', 'issue', 'risk', 'pssp', 'sms', 'message', 'webhook', 'search', 'score', 'stage');
include (dirname(__FILE__) . '/menuOrder.php');
+27 -13
View File
@@ -131,6 +131,11 @@ $lang->typeAB = 'Type';
$lang->common = new stdclass();
$lang->common->common = 'Common Module';
global $config;
list($programModule, $programMethod) = explode('-', $config->programLink);
list($productModule, $productMethod) = explode('-', $config->productLink);
list($projectModule, $projectMethod) = explode('-', $config->projectLink);
/* Main menu. */
$lang->mainNav = new stdclass();
$lang->mainNav->my = '<i class="icon icon-menu-my"></i> My|my|index|';
@@ -220,7 +225,11 @@ $lang->holiday->menu = $lang->subject->menu;
$lang->measurement = new stdclass();
$lang->measurement->menu = new stdclass();
$lang->searchTips = '';
$lang->searchAB = 'Search';
/* Object list in search form. */
$lang->searchObjects['all'] = 'All';
$lang->searchObjects['bug'] = 'Bug';
$lang->searchObjects['story'] = 'Story';
$lang->searchObjects['task'] = 'Task';
@@ -236,6 +245,7 @@ $lang->searchObjects['testreport'] = 'Test Report';
$lang->searchObjects['program'] = 'Program';
$lang->searchObjects['project'] = 'Project';
$lang->searchObjects['execution'] = $lang->sprintCommon;
$lang->searchObjects['user'] = 'User';
$lang->searchTips = 'ID (ctrl+g)';
/* Code formats for import. */
@@ -338,18 +348,18 @@ $lang->story->menu = $lang->product->menu;
$lang->project = new stdclass();
$lang->project->menu = new stdclass();
$lang->project->menu->task = array('link' => 'Task|project|task|projectID=%s', 'subModule' => 'task,tree', 'alias' => 'importtask,importbug');
$lang->project->menu->kanban = array('link' => 'Kanban|project|kanban|projectID=%s');
$lang->project->menu->burn = array('link' => 'Burndown|project|burn|projectID=%s');
$lang->project->menu->view = array('link' => 'View|project|grouptask|projectID=%s', 'alias' => 'grouptask,tree', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->story = array('link' => 'Story|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory,storykanban');
$lang->project->menu->bug = array('link' => 'Bug|project|bug|projectID=%s');
$lang->project->menu->build = array('link' => 'Build|project|build|projectID=%s', 'subModule' => 'build');
$lang->project->menu->testtask = array('link' => 'Request|project|testtask|projectID=%s', 'subModule' => 'testreport,testtask');
$lang->project->menu->doc = array('link' => 'Doc|doc|objectLibs|type=project&objectID=%s&from=project', 'subModule' => 'doc');
$lang->project->menu->product = $lang->productCommon . '|project|manageproducts|projectID=%s';
$lang->project->menu->team = array('link' => 'Team|project|team|projectID=%s', 'alias' => 'managemembers');
$lang->project->menu->more = array('link' => 'More|project|whitelist|projectID=%s', 'subModule' => 'personnel', 'alias' => 'edit', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->task = array('link' => 'Task|project|task|projectID=%s', 'subModule' => 'task,tree', 'alias' => 'importtask,importbug');
$lang->project->menu->kanban = array('link' => 'Kanban|project|kanban|projectID=%s');
$lang->project->menu->burn = array('link' => 'Burndown|project|burn|projectID=%s');
$lang->project->menu->view = array('link' => 'View|project|grouptask|projectID=%s', 'alias' => 'grouptask,tree', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->story = array('link' => 'Story|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory,storykanban');
$lang->project->menu->bug = array('link' => 'Bug|project|bug|projectID=%s');
$lang->project->menu->build = array('link' => 'Build|project|build|projectID=%s', 'subModule' => 'build');
$lang->project->menu->testtask = array('link' => 'Request|project|testtask|projectID=%s', 'subModule' => 'testreport,testtask');
$lang->project->menu->doc = array('link' => 'Doc|doc|objectLibs|type=project&objectID=%s&from=project', 'subModule' => 'doc');
$lang->project->menu->product = $lang->productCommon . '|project|manageproducts|projectID=%s';
$lang->project->menu->team = array('link' => 'Team|project|team|projectID=%s', 'alias' => 'managemembers');
$lang->project->menu->more = array('link' => 'More|project|whitelist|projectID=%s', 'subModule' => 'personnel', 'alias' => 'edit', 'class' => 'dropdown dropdown-hover');
$lang->project->subMenu = new stdclass();
$lang->project->subMenu->view = new stdclass();
@@ -560,6 +570,9 @@ $lang->admin->subMenu->system = new stdclass();
$lang->admin->subMenu->system->cron = array('link' => 'Cron|cron|index', 'subModule' => 'cron');
$lang->admin->subMenu->system->timezone = array('link' => 'Timezone|custom|timezone', 'subModule' => 'custom');
$lang->admin->subMenu->system->buildIndex = array('link' => 'Full Text Search|search|buildindex|');
$lang->admin->subMenuOrder->system[15] = 'buildIndex';
$lang->convert = new stdclass();
$lang->upgrade = new stdclass();
$lang->action = new stdclass();
@@ -619,6 +632,7 @@ $lang->navGroup = new stdclass();
$lang->navGroup->my = 'my';
$lang->navGroup->todo = 'my';
$lang->navGroup->effort = 'my';
$lang->navGroup->score = 'my';
$lang->navGroup->personnel = 'program';
@@ -999,6 +1013,6 @@ $lang->projectstory->menu->story = array('link' => "{$lang->SRCommon}|projectsto
$lang->projectstory->menu->track = array('link' => 'Track|projectstory|track', 'subModule' => '');
$lang->nc->menu = $lang->auditplan->menu;
$lang->noMenuModule = array('my', 'todo', 'effort', 'program', 'product', 'productplan', 'projectbuild', 'projectrelease', 'story', 'job', 'jenkins', 'branch', 'release', 'attend', 'leave', 'makeup', 'overtime', 'lieu', 'custom', 'admin', 'mail', 'extension', 'dev', 'backup', 'action', 'cron', 'issue', 'risk', 'pssp', 'sms', 'message', 'webhook', 'search', 'stage');
$lang->noMenuModule = array('my', 'todo', 'effort', 'program', 'product', 'productplan', 'projectbuild', 'projectrelease', 'story', 'branch', 'release', 'attend', 'leave', 'makeup', 'overtime', 'lieu', 'custom', 'admin', 'mail', 'extension', 'dev', 'backup', 'action', 'cron', 'issue', 'risk', 'pssp', 'sms', 'message', 'webhook', 'search', 'score', 'stage');
include (dirname(__FILE__) . '/menuOrder.php');
+27 -16
View File
@@ -131,6 +131,11 @@ $lang->typeAB = 'Type';
$lang->common = new stdclass();
$lang->common->common = 'Module Commun';
global $config;
list($programModule, $programMethod) = explode('-', $config->programLink);
list($productModule, $productMethod) = explode('-', $config->productLink);
list($projectModule, $projectMethod) = explode('-', $config->projectLink);
/* Main menu. */
$lang->mainNav = new stdclass();
$lang->mainNav->my = '<i class="icon icon-menu-my"></i> My|my|index|';
@@ -220,7 +225,11 @@ $lang->holiday->menu = $lang->subject->menu;
$lang->measurement = new stdclass();
$lang->measurement->menu = new stdclass();
$lang->searchTips = '';
$lang->searchAB = 'Search';
/* Object list in search form. */
$lang->searchObjects['all'] = 'All';
$lang->searchObjects['bug'] = 'Bug';
$lang->searchObjects['story'] = 'Story';
$lang->searchObjects['task'] = 'Tâche';
@@ -236,6 +245,7 @@ $lang->searchObjects['testreport'] = 'CR de Test';
$lang->searchObjects['program'] = 'Program';
$lang->searchObjects['project'] = 'Project';
$lang->searchObjects['execution'] = $lang->sprintCommon;
$lang->searchObjects['user'] = 'User';
$lang->searchTips = 'ID (ctrl+g)';
/* Code formats for import. */
@@ -338,21 +348,18 @@ $lang->story->menu = $lang->product->menu;
$lang->project = new stdclass();
$lang->project->menu = new stdclass();
$lang->project->menu->task = array('link' => 'Tâche|project|task|projectID=%s', 'subModule' => 'task,tree', 'alias' => 'importtask,importbug');
$lang->project->menu->kanban = array('link' => 'Kanban|project|kanban|projectID=%s');
$lang->project->menu->burn = array('link' => 'Atterrissage|project|burn|projectID=%s');
$lang->project->menu->view = array('link' => 'View|project|grouptask|projectID=%s', 'alias' => 'grouptask,tree', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->story = array('link' => 'Story|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory,storykanban');
$lang->project->menu->bug = array('link' => 'Bug|project|bug|projectID=%s');
$lang->project->menu->build = array('link' => 'Build|project|build|projectID=%s', 'subModule' => 'build');
$lang->project->menu->testtask = array('link' => 'Recette|project|testtask|projectID=%s', 'subModule' => 'testreport,testtask');
$lang->project->menu->doc = array('link' => 'Doc|doc|objectLibs|type=project&objectID=%s&from=project', 'subModule' => 'doc');
$lang->project->menu->product = $lang->productCommon . '|project|manageproducts|projectID=%s';
$lang->project->menu->team = array('link' => 'Equipe|project|team|projectID=%s', 'alias' => 'managemembers');
$lang->project->menu->more = array('link' => 'More|project|whitelist|projectID=%s', 'subModule' => 'personnel', 'alias' => 'edit', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->action = array('link' => 'Historique|project|dynamic|projectID=%s', 'subModule' => 'dynamic', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->view = array('link' => "Vue d'ensemble|project|view|projectID=%s", 'alias' => 'edit,start,suspend,putoff,close');
$lang->project->menu->whitelist = array('link' => 'Whitelist|project|whitelist|projectID=%s', 'alias' => 'addwhitelist', 'subModule' => 'personnel');
$lang->project->menu->task = array('link' => 'Tâche|project|task|projectID=%s', 'subModule' => 'task,tree', 'alias' => 'importtask,importbug');
$lang->project->menu->kanban = array('link' => 'Kanban|project|kanban|projectID=%s');
$lang->project->menu->burn = array('link' => 'Atterrissage|project|burn|projectID=%s');
$lang->project->menu->view = array('link' => 'View|project|grouptask|projectID=%s', 'alias' => 'grouptask,tree', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->story = array('link' => "Story|project|story|projectID=%s", 'subModule' => 'story', 'alias' => 'linkstory,storykanban');
$lang->project->menu->bug = array('link' => 'Bug|project|bug|projectID=%s');
$lang->project->menu->build = array('link' => 'Build|project|build|projectID=%s', 'subModule' => 'build');
$lang->project->menu->testtask = array('link' => 'Recette|project|testtask|projectID=%s', 'subModule' => 'testreport,testtask');
$lang->project->menu->doc = array('link' => 'Doc|doc|objectLibs|type=project&objectID=%s&from=project', 'subModule' => 'doc');
$lang->project->menu->product = $lang->productCommon . '|project|manageproducts|projectID=%s';
$lang->project->menu->team = array('link' => 'Equipe|project|team|projectID=%s', 'alias' => 'managemembers');
$lang->project->menu->more = array('link' => 'More|project|whitelist|projectID=%s', 'subModule' => 'personnel', 'alias' => 'edit', 'class' => 'dropdown dropdown-hover');
$lang->project->subMenu = new stdclass();
$lang->project->subMenu->view = new stdclass();
@@ -563,6 +570,9 @@ $lang->admin->subMenu->system = new stdclass();
$lang->admin->subMenu->system->cron = array('link' => 'Cron|cron|index', 'subModule' => 'cron');
$lang->admin->subMenu->system->timezone = array('link' => 'Timezone|custom|timezone', 'subModule' => 'custom');
$lang->admin->subMenu->system->buildIndex = array('link' => 'Full Text Search|search|buildindex|');
$lang->admin->subMenuOrder->system[15] = 'buildIndex';
$lang->convert = new stdclass();
$lang->upgrade = new stdclass();
$lang->action = new stdclass();
@@ -622,6 +632,7 @@ $lang->navGroup = new stdclass();
$lang->navGroup->my = 'my';
$lang->navGroup->todo = 'my';
$lang->navGroup->effort = 'my';
$lang->navGroup->score = 'my';
$lang->navGroup->personnel = 'program';
@@ -1002,6 +1013,6 @@ $lang->projectstory->menu->story = array('link' => "{$lang->SRCommon}|projectsto
$lang->projectstory->menu->track = array('link' => 'Track|projectstory|track', 'subModule' => '');
$lang->nc->menu = $lang->auditplan->menu;
$lang->noMenuModule = array('my', 'todo', 'effort', 'program', 'product', 'productplan', 'projectbuild', 'projectrelease', 'story', 'job', 'jenkins', 'branch', 'release', 'attend', 'leave', 'makeup', 'overtime', 'lieu', 'custom', 'admin', 'mail', 'extension', 'dev', 'backup', 'action', 'cron', 'issue', 'risk', 'pssp', 'sms', 'message', 'webhook', 'search', 'stage');
$lang->noMenuModule = array('my', 'todo', 'effort', 'program', 'product', 'productplan', 'projectbuild', 'projectrelease', 'story', 'branch', 'release', 'attend', 'leave', 'makeup', 'overtime', 'lieu', 'custom', 'admin', 'mail', 'extension', 'dev', 'backup', 'action', 'cron', 'issue', 'risk', 'pssp', 'sms', 'message', 'webhook', 'search', 'score', 'stage');
include (dirname(__FILE__) . '/menuOrder.php');
+27 -16
View File
@@ -131,6 +131,11 @@ $lang->typeAB = 'Loại';
$lang->common = new stdclass();
$lang->common->common = 'Module chung';
global $config;
list($programModule, $programMethod) = explode('-', $config->programLink);
list($productModule, $productMethod) = explode('-', $config->productLink);
list($projectModule, $projectMethod) = explode('-', $config->projectLink);
/* Main menu. */
$lang->mainNav = new stdclass();
$lang->mainNav->my = '<i class="icon icon-menu-my"></i> My|my|index|';
@@ -220,7 +225,11 @@ $lang->holiday->menu = $lang->subject->menu;
$lang->measurement = new stdclass();
$lang->measurement->menu = new stdclass();
$lang->searchTips = '';
$lang->searchAB = 'Tìm ki?m';
/* Object list in search form. */
$lang->searchObjects['all'] = 'T?t c?';
$lang->searchObjects['bug'] = 'Bug';
$lang->searchObjects['story'] = 'Câu chuyện';
$lang->searchObjects['task'] = 'Nhiệm vụ';
@@ -236,6 +245,7 @@ $lang->searchObjects['testreport'] = 'Test báo cáo';
$lang->searchObjects['program'] = 'Program';
$lang->searchObjects['project'] = 'Project';
$lang->searchObjects['execution'] = $lang->sprintCommon;
$lang->searchObjects['user'] = 'User';
$lang->searchTips = 'ID (ctrl+g)';
/* Code formats for import. */
@@ -338,21 +348,18 @@ $lang->story->menu = $lang->product->menu;
$lang->project = new stdclass();
$lang->project->menu = new stdclass();
$lang->project->menu->task = array('link' => 'Nhiệm vụ|project|task|projectID=%s', 'subModule' => 'task,tree', 'alias' => 'importtask,importbug');
$lang->project->menu->kanban = array('link' => 'Kanban|project|kanban|projectID=%s');
$lang->project->menu->burn = array('link' => 'Burndown|project|burn|projectID=%s');
$lang->project->menu->view = array('link' => 'View|project|grouptask|projectID=%s', 'alias' => 'grouptask,tree', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->story = array('link' => 'Câu chuyện|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory,storykanban');
$lang->project->menu->bug = array('link' => 'Bug|project|bug|projectID=%s');
$lang->project->menu->build = array('link' => 'Bản dựng|project|build|projectID=%s', 'subModule' => 'build');
$lang->project->menu->testtask = array('link' => 'Yêu cầu|project|testtask|projectID=%s', 'subModule' => 'testreport,testtask');
$lang->project->menu->doc = array('link' => 'Tài liệu|doc|objectLibs|type=project&objectID=%s&from=project', 'subModule' => 'doc');
$lang->project->menu->product = $lang->productCommon . '|project|manageproducts|projectID=%s';
$lang->project->menu->team = array('link' => 'Đội nhóm|project|team|projectID=%s', 'alias' => 'managemembers');
$lang->project->menu->more = array('link' => 'More|project|whitelist|projectID=%s', 'subModule' => 'personnel', 'alias' => 'edit', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->action = array('link' => 'Lịch sử|project|dynamic|projectID=%s', 'subModule' => 'dynamic', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->view = array('link' => 'Tổng quan|project|view|projectID=%s', 'alias' => 'edit,start,suspend,putoff,close');
$lang->project->menu->whitelist = array('link' => 'Whitelist|project|whitelist|projectID=%s', 'alias' => 'addwhitelist', 'subModule' => 'personnel');
$lang->project->menu->task = array('link' => 'Nhiệm vụ|project|task|projectID=%s', 'subModule' => 'task,tree', 'alias' => 'importtask,importbug');
$lang->project->menu->kanban = array('link' => 'Kanban|project|kanban|projectID=%s');
$lang->project->menu->burn = array('link' => 'Burndown|project|burn|projectID=%s');
$lang->project->menu->view = array('link' => 'View|project|grouptask|projectID=%s', 'alias' => 'grouptask,tree', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->story = array('link' => "Câu chuyện|project|story|projectID=%s", 'subModule' => 'story', 'alias' => 'linkstory,storykanban');
$lang->project->menu->bug = array('link' => 'Bug|project|bug|projectID=%s');
$lang->project->menu->build = array('link' => 'Bản dựng|project|build|projectID=%s', 'subModule' => 'build');
$lang->project->menu->testtask = array('link' => 'Yêu cầu|project|testtask|projectID=%s', 'subModule' => 'testreport,testtask');
$lang->project->menu->doc = array('link' => 'Tài liệu|doc|objectLibs|type=project&objectID=%s&from=project', 'subModule' => 'doc');
$lang->project->menu->product = $lang->productCommon . '|project|manageproducts|projectID=%s';
$lang->project->menu->team = array('link' => 'Đội nhóm|project|team|projectID=%s', 'alias' => 'managemembers');
$lang->project->menu->more = array('link' => 'More|project|whitelist|projectID=%s', 'subModule' => 'personnel', 'alias' => 'edit', 'class' => 'dropdown dropdown-hover');
$lang->project->subMenu = new stdclass();
$lang->project->subMenu->view = new stdclass();
@@ -563,6 +570,9 @@ $lang->admin->subMenu->system = new stdclass();
$lang->admin->subMenu->system->cron = array('link' => 'Cron|cron|index', 'subModule' => 'cron');
$lang->admin->subMenu->system->timezone = array('link' => 'Timezone|custom|timezone', 'subModule' => 'custom');
$lang->admin->subMenu->system->buildIndex = array('link' => 'Full Text Search|search|buildindex|');
$lang->admin->subMenuOrder->system[15] = 'buildIndex';
$lang->convert = new stdclass();
$lang->upgrade = new stdclass();
$lang->action = new stdclass();
@@ -622,6 +632,7 @@ $lang->navGroup = new stdclass();
$lang->navGroup->my = 'my';
$lang->navGroup->todo = 'my';
$lang->navGroup->effort = 'my';
$lang->navGroup->score = 'my';
$lang->navGroup->personnel = 'program';
@@ -1002,6 +1013,6 @@ $lang->projectstory->menu->story = array('link' => "{$lang->SRCommon}|projectsto
$lang->projectstory->menu->track = array('link' => 'Track|projectstory|track', 'subModule' => '');
$lang->nc->menu = $lang->auditplan->menu;
$lang->noMenuModule = array('my', 'todo', 'effort', 'program', 'product', 'productplan', 'projectbuild', 'projectrelease', 'story', 'job', 'jenkins', 'branch', 'release', 'attend', 'leave', 'makeup', 'overtime', 'lieu', 'custom', 'admin', 'mail', 'extension', 'dev', 'backup', 'action', 'cron', 'issue', 'risk', 'pssp', 'sms', 'message', 'webhook', 'search', 'stage');
$lang->noMenuModule = array('my', 'todo', 'effort', 'program', 'product', 'productplan', 'projectbuild', 'projectrelease', 'story', 'branch', 'release', 'attend', 'leave', 'makeup', 'overtime', 'lieu', 'custom', 'admin', 'mail', 'extension', 'dev', 'backup', 'action', 'cron', 'issue', 'risk', 'pssp', 'sms', 'message', 'webhook', 'search', 'score', 'stage');
include (dirname(__FILE__) . '/menuOrder.php');
+21 -13
View File
@@ -225,7 +225,11 @@ $lang->holiday->menu = $lang->subject->menu;
$lang->measurement = new stdclass();
$lang->measurement->menu = new stdclass();
/* 查询条中可以选择的对象列表。*/
$lang->searchTips = '';
$lang->searchAB = '搜索';
/* 查询中可以选择的对象列表。*/
$lang->searchObjects['all'] = '全部';
$lang->searchObjects['bug'] = 'Bug';
$lang->searchObjects['story'] = "{$lang->SRCommon}";
$lang->searchObjects['task'] = '任务';
@@ -241,6 +245,7 @@ $lang->searchObjects['testreport'] = '测试报告';
$lang->searchObjects['program'] = '项目集';
$lang->searchObjects['project'] = '项目';
$lang->searchObjects['execution'] = $lang->sprintCommon;
$lang->searchObjects['user'] = '用户';
$lang->searchTips = '编号(ctrl+g)';
/* 导入支持的编码格式。*/
@@ -343,18 +348,18 @@ $lang->story->menu = $lang->product->menu;
$lang->project = new stdclass();
$lang->project->menu = new stdclass();
$lang->project->menu->task = array('link' => '任务|project|task|projectID=%s', 'subModule' => 'task,tree', 'alias' => 'importtask,importbug');
$lang->project->menu->kanban = array('link' => '看板|project|kanban|projectID=%s');
$lang->project->menu->burn = array('link' => '燃尽图|project|burn|projectID=%s');
$lang->project->menu->view = array('link' => '视图|project|grouptask|projectID=%s', 'alias' => 'grouptask,tree', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->story = array('link' => "{$lang->SRCommon}|project|story|projectID=%s", 'subModule' => 'story', 'alias' => 'linkstory,storykanban');
$lang->project->menu->bug = array('link' => 'Bug|project|bug|projectID=%s');
$lang->project->menu->build = array('link' => '版本|project|build|projectID=%s', 'subModule' => 'build');
$lang->project->menu->testtask = array('link' => '测试单|project|testtask|projectID=%s', 'subModule' => 'testreport,testtask');
$lang->project->menu->doc = array('link' => '文档|doc|objectLibs|type=project&objectID=%s&from=project', 'subModule' => 'doc');
$lang->project->menu->product = $lang->productCommon . '|project|manageproducts|projectID=%s';
$lang->project->menu->team = array('link' => '团队|project|team|projectID=%s', 'alias' => 'managemembers');
$lang->project->menu->more = array('link' => '更多|project|whitelist|projectID=%s', 'subModule' => 'personnel', 'alias' => 'edit', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->task = array('link' => '任务|project|task|projectID=%s', 'subModule' => 'task,tree', 'alias' => 'importtask,importbug');
$lang->project->menu->kanban = array('link' => '看板|project|kanban|projectID=%s');
$lang->project->menu->burn = array('link' => '燃尽图|project|burn|projectID=%s');
$lang->project->menu->view = array('link' => '视图|project|grouptask|projectID=%s', 'alias' => 'grouptask,tree', 'class' => 'dropdown dropdown-hover');
$lang->project->menu->story = array('link' => "{$lang->SRCommon}|project|story|projectID=%s", 'subModule' => 'story', 'alias' => 'linkstory,storykanban');
$lang->project->menu->bug = array('link' => 'Bug|project|bug|projectID=%s');
$lang->project->menu->build = array('link' => '版本|project|build|projectID=%s', 'subModule' => 'build');
$lang->project->menu->testtask = array('link' => '测试单|project|testtask|projectID=%s', 'subModule' => 'testreport,testtask');
$lang->project->menu->doc = array('link' => '文档|doc|objectLibs|type=project&objectID=%s&from=project', 'subModule' => 'doc');
$lang->project->menu->product = $lang->productCommon . '|project|manageproducts|projectID=%s';
$lang->project->menu->team = array('link' => '团队|project|team|projectID=%s', 'alias' => 'managemembers');
$lang->project->menu->more = array('link' => '更多|project|whitelist|projectID=%s', 'subModule' => 'personnel', 'alias' => 'edit', 'class' => 'dropdown dropdown-hover');
$lang->project->subMenu = new stdclass();
$lang->project->subMenu->view = new stdclass();
@@ -565,6 +570,9 @@ $lang->admin->subMenu->system = new stdclass();
$lang->admin->subMenu->system->cron = array('link' => '定时|cron|index', 'subModule' => 'cron');
$lang->admin->subMenu->system->timezone = array('link' => '时区|custom|timezone', 'subModule' => 'custom');
$lang->admin->subMenu->system->buildIndex = array('link' => '重建索引|search|buildindex|');
$lang->admin->subMenuOrder->system[15] = 'buildIndex';
$lang->convert = new stdclass();
$lang->upgrade = new stdclass();
$lang->action = new stdclass();
+5 -29
View File
@@ -748,45 +748,21 @@ class commonModel extends model
*/
public static function printSearchBox()
{
global $app, $config, $lang;
$moduleName = $app->getModuleName();
$methodName = $app->getMethodName();
$searchObject = $moduleName;
if($moduleName == 'product')
{
if($methodName == 'browse') $searchObject = 'story';
}
elseif($moduleName == 'project')
{
if(strpos('task|story|bug|build', $methodName) !== false) $searchObject = $methodName;
}
elseif($moduleName == 'my' or $moduleName == 'user')
{
$searchObject = $methodName;
if($methodName == 'execution') $searchObject = 'project';
}
if(empty($lang->searchObjects[$searchObject])) $searchObject = 'bug';
echo "<div id='searchbox'>";
echo "<div class='input-group'>";
global $lang;
$searchObject = 'bug';
echo "<div class='input-group-btn'>";
echo "<a data-toggle='dropdown' class='btn btn-link'><span id='searchTypeName'>" . $lang->searchObjects[$searchObject] . "</span> <span class='caret'></span></a>";
echo html::hidden('searchType', $searchObject);
echo "<ul id='searchTypeMenu' class='dropdown-menu'>";
foreach ($lang->searchObjects as $key => $value)
{
$class = $key == $searchObject ? "class='selected'" : '';
if($key == 'program') $key = 'program-pgmproduct';
if($key == 'project') $key = 'program-index';
if($key == 'program') $key = 'program-pgmproduct';
if($key == 'project') $key = 'program-index';
if($key == 'execution') $key = 'project-view';
echo "<li $class><a href='javascript:$.setSearchType(\"$key\");' data-value='{$key}'>{$value}</a></li>";
}
echo '</ul></div>';
echo "<input id='searchInput' class='form-control search-input' type='search' onclick='this.value=\"\"' onkeydown='if(event.keyCode==13) $.gotoObject();' placeholder='" . $lang->searchTips . "'/>";
echo '</div>';
echo "<a href='javascript:$.gotoObject();' class='btn btn-link' id='searchGo'>GO!</a>";
echo "</div>\n";
}
/**
+3
View File
@@ -83,6 +83,8 @@ $config->dev->group['repo'] = 'repo';
$config->dev->group['repofiles'] = 'repo';
$config->dev->group['repohistory'] = 'repo';
$config->dev->group['repobranch'] = 'repo';
$config->dev->group['searchindex'] = 'search';
$config->dev->group['searchdict'] = 'search';
$config->dev->tableMap['storyspec'] = 'story';
$config->dev->tableMap['storystage'] = 'story';
@@ -110,6 +112,7 @@ $config->dev->tableMap['suitecase'] = 'testcase';
$config->dev->tableMap['repofiles'] = 'repo';
$config->dev->tableMap['repohistory'] = 'repo';
$config->dev->tableMap['repobranch'] = 'repo';
$config->dev->tableMap['searchindex'] = 'search';
$config->dev->postParams['story']['create']['product'] = 'int';
$config->dev->postParams['story']['create']['title'] = 'string';
+3
View File
@@ -114,6 +114,8 @@ $lang->dev->tableList['ci'] = 'CI';
$lang->dev->tableList['compile'] = 'Compile';
$lang->dev->tableList['jenkins'] = 'Jenkins';
$lang->dev->tableList['job'] = 'Job';
$lang->dev->tableList['searchdict'] = 'Search dict';
$lang->dev->tableList['searchindex'] = 'Search index';
$lang->dev->groupList['my'] = 'Dashboard';
$lang->dev->groupList['product'] = $lang->productCommon;
@@ -125,6 +127,7 @@ $lang->dev->groupList['company'] = 'Unternehmen';
$lang->dev->groupList['repo'] = 'CI';
$lang->dev->groupList['api'] = 'API';
$lang->dev->groupList['message'] = 'Message';
$lang->dev->groupList['search'] = 'Search';
$lang->dev->endGroupList['admin'] = 'Admin';
$lang->dev->endGroupList['system'] = 'System';
+3
View File
@@ -114,6 +114,8 @@ $lang->dev->tableList['ci'] = 'CI';
$lang->dev->tableList['compile'] = 'Compile';
$lang->dev->tableList['jenkins'] = 'Jenkins';
$lang->dev->tableList['job'] = 'Job';
$lang->dev->tableList['searchdict'] = 'Search dict';
$lang->dev->tableList['searchindex'] = 'Search index';
$lang->dev->groupList['my'] = 'Dashboard';
$lang->dev->groupList['product'] = $lang->productCommon;
@@ -125,6 +127,7 @@ $lang->dev->groupList['company'] = 'Company';
$lang->dev->groupList['repo'] = 'CI';
$lang->dev->groupList['api'] = 'API';
$lang->dev->groupList['message'] = 'Message';
$lang->dev->groupList['search'] = 'Search';
$lang->dev->endGroupList['admin'] = 'Admin';
$lang->dev->endGroupList['system'] = 'System';
+3
View File
@@ -114,6 +114,8 @@ $lang->dev->tableList['ci'] = 'CI';
$lang->dev->tableList['compile'] = 'Compile';
$lang->dev->tableList['jenkins'] = 'Jenkins';
$lang->dev->tableList['job'] = 'Job';
$lang->dev->tableList['searchdict'] = 'Search dict';
$lang->dev->tableList['searchindex'] = 'Search index';
$lang->dev->groupList['my'] = 'Dashboard';
$lang->dev->groupList['product'] = $lang->productCommon;
@@ -125,6 +127,7 @@ $lang->dev->groupList['company'] = 'Entreprise';
$lang->dev->groupList['repo'] = 'CI';
$lang->dev->groupList['api'] = 'API';
$lang->dev->groupList['message'] = 'Message';
$lang->dev->groupList['search'] = 'Search';
$lang->dev->endGroupList['admin'] = 'Admin';
$lang->dev->endGroupList['system'] = 'Système';
+3
View File
@@ -114,6 +114,8 @@ $lang->dev->tableList['ci'] = 'CI';
$lang->dev->tableList['compile'] = 'Compile';
$lang->dev->tableList['jenkins'] = 'Jenkins';
$lang->dev->tableList['job'] = 'Job';
$lang->dev->tableList['searchdict'] = 'Search dict';
$lang->dev->tableList['searchindex'] = 'Search index';
$lang->dev->groupList['my'] = 'Dashboard';
$lang->dev->groupList['product'] = $lang->productCommon;
@@ -125,6 +127,7 @@ $lang->dev->groupList['company'] = 'Doanh nghiệp';
$lang->dev->groupList['repo'] = 'CI';
$lang->dev->groupList['api'] = 'API';
$lang->dev->groupList['message'] = 'Tin nhắn';
$lang->dev->groupList['search'] = 'Tìm kiếm';
$lang->dev->endGroupList['admin'] = 'Quản trị';
$lang->dev->endGroupList['system'] = 'Hệ thống';
+3
View File
@@ -114,6 +114,8 @@ $lang->dev->tableList['ci'] = '持续集成';
$lang->dev->tableList['compile'] = '构建';
$lang->dev->tableList['jenkins'] = 'Jenkins';
$lang->dev->tableList['job'] = '构建任务';
$lang->dev->tableList['searchdict'] = '搜索字典';
$lang->dev->tableList['searchindex'] = '搜索索引';
$lang->dev->groupList['my'] = '我的地盘';
$lang->dev->groupList['product'] = $lang->productCommon;
@@ -125,6 +127,7 @@ $lang->dev->groupList['company'] = '组织';
$lang->dev->groupList['repo'] = '持续集成';
$lang->dev->groupList['api'] = 'API';
$lang->dev->groupList['message'] = '消息';
$lang->dev->groupList['search'] = '搜索';
$lang->dev->endGroupList['admin'] = '后台';
$lang->dev->endGroupList['system'] = '系统';
+9 -5
View File
@@ -1370,17 +1370,21 @@ $lang->report->methodOrder[20] = 'workload';
/* Search. */
$lang->resource->search = new stdclass();
$lang->resource->search->buildForm = 'buildForm';
$lang->resource->search->buildQuery = 'buildQuery';
$lang->resource->search->saveQuery = 'saveQuery';
$lang->resource->search->deleteQuery = 'deleteQuery';
$lang->resource->search->select = 'select';
$lang->resource->search->buildForm = 'buildForm';
$lang->resource->search->buildQuery = 'buildQuery';
$lang->resource->search->saveQuery = 'saveQuery';
$lang->resource->search->deleteQuery = 'deleteQuery';
$lang->resource->search->select = 'select';
$lang->resource->search->index = 'index';
$lang->resource->search->buildIndex = 'buildIndex';
$lang->search->methodOrder[5] = 'buildForm';
$lang->search->methodOrder[10] = 'buildQuery';
$lang->search->methodOrder[15] = 'saveQuery';
$lang->search->methodOrder[20] = 'deleteQuery';
$lang->search->methodOrder[25] = 'select';
$lang->search->methodOrder[30] = 'index';
$lang->search->methodOrder[35] = 'buildIndex';
/* Admin. */
$lang->resource->admin = new stdclass();
+18
View File
@@ -62,6 +62,10 @@ body.menu-hide {padding-left: 0;}
#poweredBy{width: 55%; position: absolute; top: 4px; right: 0; padding: 0;}
#globalSearchDiv{width:50%; float: right; margin-right: 4px;}
@media screen and (max-height: 768px)
{
#globalSearchDiv{width:60%;}
}
#globalSearchDiv .input-group{width: 70%; float: right; margin-top: 2px;}
#globalSearchInput{height: 28px; padding-left: 10px;}
#globalSearchButton{height: 28px;}
@@ -70,3 +74,17 @@ body.menu-hide {padding-left: 0;}
#globalBarLogo a:first-child{margin-right: 10px;}
#globalBarLogo a{float: right; margin: 0px 2px;}
#globalBarLogo a .icon{font-size: 24px; color: #16a8f8;}
#searchbox a {float: left; width: 100%;}
#searchbox a:hover {color:white}
#searchbox {width: 100%;}
#searchbox .dropdown-menu {margin-top: 0px; left: 1px; position: absolute; top: -50px;}
#searchbox .dropdown-menu > li > a {padding: 5px 8px}
#searchbox .dropdown-menu > li {display: none}
#searchbox .dropdown-menu > li.search-type-all {width: 100%; display: block;}
#searchbox .dropdown-menu > li:hover {position: relative;}
#searchbox .dropdown-menu.show-quick-go.with-active {position: absolute; top: -358px; max-height: 355px; padding-top: 30px;}
#searchbox .dropdown-menu.show-quick-go > li {display: block;}
#searchbox .dropdown-menu.show-quick-go > li.active {width: 100%; position: absolute; top: 0; left: 0; right: 0;}
#searchbox .dropdown-menu>li.active>a, #searchbox .dropdown-menu>li.selected>a { position: relative; color: #fff; background-color: #16a8f8;}
#searchbox .dropdown-menu>li.selected>a:after {position: absolute; top: 2px; right: 4px; display: block; font-family: ZentaoIcon; font-size: 18px; font-size: 14px; font-style: normal; font-weight: 400; font-variant: normal; line-height: 1; line-height: 20px; text-transform: none; content: "\e5ca"; speak: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;}
+131
View File
@@ -499,3 +499,134 @@ function getExecutions()
})
}
}
$.extend({
gotoObject:function()
{
objectType = $('#searchType').attr('value');
objectValue = $('input#globalSearchInput').attr('value');
if(objectType && objectValue)
{
var reg = /[^0-9]/;
if(reg.test(objectValue) || objectType == 'all')
{
location.href = createLink('search', 'index') + (config.requestType == 'PATH_INFO' ? '?' : '&') + 'words=' + objectValue;
}
else
{
var types = objectType.split('-');
var searchModule = types[0];
var searchMethod = typeof(types[1]) == 'undefined' ? 'view' : types[1];
location.href = createLink(searchModule, searchMethod, "id=" + objectValue);
}
}
}
});
/* Initialize global search. */
$(function()
{
var reg = /[^0-9]/;
var $searchbox = $('#searchbox');
var $typeSelector = $searchbox.find('.input-group-btn');
var $dropmenu = $typeSelector.children('.dropdown-menu');
var $searchQuery = $('#globalSearchInput');
var searchType = $('#searchType').val();
var toggleMenu = function(show)
{
$searchbox.toggleClass('open', show);
$dropmenu.toggleClass('show', show).toggleClass('in', show);
if(show) $dropmenu.show();
else $dropmenu.hide();
};
var hideMenu = function(){toggleMenu(false);};
var refreshMenu = function()
{
var val = $searchQuery.val();
var searchType = changeSearchObject();
if(val !== null && val !== "")
{
var isQuickGo = !reg.test(val);
$dropmenu.toggleClass('show-quick-go', isQuickGo);
var $typeAll = $dropmenu.find('li.search-type-all > a');
$typeAll.html(searchAB + ' <span>"' + val + '"</span>');
if(isQuickGo)
{
$typeAll.closest('li').removeClass('active');
$dropmenu.removeClass('with-active').find('li:not(.search-type-all) > a').each(function()
{
var $this = $(this);
var isActiveType = $this.data('value') === searchType && searchType !== 'all';
$this.closest('li').toggleClass('selected active', isActiveType);
$this.html($this.data('name') + ' <span>#' + (val.length > 4 ? (val.substr(0, 4) + '...') : val) + "</span>");
if(isActiveType) $dropmenu.addClass('with-active');
});
}
else
{
$dropmenu.find('li.active').removeClass('active');
$typeAll.closest('li').addClass('active');
}
toggleMenu(true);
}
else
{
hideMenu();
}
};
$dropmenu = $dropmenu.appendTo($searchbox);
$dropmenu.on('click', 'a', function(e)
{
$('#searchType').val($(this).data('value'));
$.gotoObject();
e.stopPropagation();
}).find('li > a').each(function()
{
var $this = $(this);
$this.attr('data-name', $this.text());
});
var $allItem = $dropmenu.find('li > a[data-value="all"]');
if($allItem.length)
{
$allItem.closest('li').addClass('search-type-all').prependTo($dropmenu);
}
$searchQuery.on('change keyup paste input propertychange', refreshMenu).on('focus', function()
{
setTimeout(refreshMenu, 300);
});
$(document).on('click', hideMenu);
});
/* Change the search object according to the module and method. */
function changeSearchObject()
{
var tabInfo = $.tabs.getLastTab();
var tabPageModuleName = tabInfo.$iframe[0].contentWindow.config.currentModule;
var tabPageMethodName = tabInfo.$iframe[0].contentWindow.config.currentMethod;
var searchType = tabPageModuleName;
if(tabPageModuleName == 'product' && tabPageMethodName == 'browse') var searchType = 'story';
var projectMethod = 'task|story|bug|build';
if(tabPageModuleName == 'project' && projectMethod.indexOf(tabPageMethodName) != -1) var searchType = tabPageMethodName;
if(tabPageModuleName == 'my' || tabPageModuleName == 'user') var searchType = tabPageMethodName;
if(searchObjectList.indexOf(searchType) == -1) var searchType = 'bug';
if(searchType == 'program') var searchType = 'program-pgmproduct';
if(searchType == 'project') var searchType = 'program-index';
if(searchType == 'execution') var searchType = 'project-view';
$("#searchType").val(searchType);
return searchType;
}
+8 -3
View File
@@ -56,10 +56,13 @@ js::set('defaultOpen', $open);
<!--<a href='javascript:void(0)' class="btn btn-sm btn-link" type="button"><i class="icon icon-message"></i></a>-->
<div id="globalSearchDiv">
<div class="input-group">
<div class="input-control search-box search-box-circle has-icon-left has-icon-right search-example" id="searchboxExample">
<input id="globalSearchInput" type="search" class="form-control search-input" placeholder="<?php echo $lang->index->search;?>">
<div id='searchbox'>
<?php echo common::printSearchBox();?>
</div>
<span class="input-group-btn">
<div class="input-control search-box search-box-circle has-icon-left has-icon-right search-example" id="searchboxExample">
<input id="globalSearchInput" type="search" onclick="this.value=''" onkeydown="if(event.keyCode==13) $.gotoObject();" class="form-control search-input" placeholder="<?php echo $lang->index->search;?>" autocomplete="off">
</div>
<span class="input-group-btn" onclick="javascript:$.gotoObject();">
<button id="globalSearchButton" class="btn btn-secondary" type="button"><i class="icon icon-search"></i></button>
</span>
</div>
@@ -67,4 +70,6 @@ js::set('defaultOpen', $open);
</div>
</div>
</div>
<?php js::set('searchAB', $lang->searchAB);?>
<?php js::set('searchObjectList', implode(',', array_keys($lang->searchObjects)));?>
<?php include '../../common/view/footer.lite.html.php';?>
+3 -1
View File
@@ -12,6 +12,7 @@
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/sortable.html.php';?>
<div id="mainMenu" class="clearfix">
<?php if(!isonlybody()):?>
<div class="btn-toolbar pull-left">
<?php foreach($lang->product->featureBar['all'] as $key => $label):?>
<?php $active = $key == $browseType ? 'btn-active-text' : '';?>
@@ -22,6 +23,7 @@
<div class="btn-toolbar pull-right">
<?php common::printLink('product', 'create', "programID=$program->id", '<i class="icon icon-plus"></i>' . $lang->product->create, '', 'class="btn btn-primary"');?>
</div>
<?php endif;?>
</div>
<div id="mainContent" class="main-row fade">
<?php if(empty($products)):?>
@@ -33,7 +35,7 @@
<form class="main-table table-product" data-ride="table" id="productListForm" method="post" action='<?php echo $this->createLink('product', 'batchEdit', "programID=$program->id");?>'>
<?php $canOrder = common::hasPriv('product', 'updateOrder');?>
<?php $canBatchEdit = common::hasPriv('product', 'batchEdit');?>
<table id="productList" class="table has-sort-head table-fixed">
<table id="productList" class="table has-sort-head table-bordered table-fixed">
<?php $vars = "programID=$program->id&browseType=$browseType&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";?>
<thead>
<tr class="text-center">
+135
View File
@@ -8,3 +8,138 @@ $config->search->dynamic['$lastWeek'] = '$lastWeek';
$config->search->dynamic['$thisWeek'] = '$thisWeek';
$config->search->dynamic['$yesterday'] = '$yesterday';
$config->search->dynamic['$today'] = '$today';
$config->search->buildAction = ',created,opened,changed,edited,deleted,undeleted,erased,';
$config->search->fields = new stdclass();
$config->search->fields->bug = new stdclass();
$config->search->fields->bug->id = 'id';
$config->search->fields->bug->title = 'title';
$config->search->fields->bug->content = 'steps,keywords,resolvedBuild';
$config->search->fields->bug->addedDate = 'openedDate';
$config->search->fields->bug->editedDate = 'lastEditedDate';
$config->search->fields->build = new stdclass();
$config->search->fields->build->id = 'id';
$config->search->fields->build->title = 'name';
$config->search->fields->build->content = 'desc,filePath,scmPath';
$config->search->fields->build->addedDate = 'date';
$config->search->fields->build->editedDate = 'lastEditedDate';
$config->search->fields->case = new stdclass();
$config->search->fields->case->id = 'id';
$config->search->fields->case->title = 'title';
$config->search->fields->case->content = 'precondition,desc,expect';
$config->search->fields->case->addedDate = 'openedDate';
$config->search->fields->case->editedDate = 'lastEditedDate';
$config->search->fields->doc = new stdclass();
$config->search->fields->doc->id = 'id';
$config->search->fields->doc->title = 'title';
$config->search->fields->doc->content = 'digest,keywords,content';
$config->search->fields->doc->addedDate = 'addedDate';
$config->search->fields->doc->editedDate = 'editedDate';
$config->search->fields->product = new stdclass();
$config->search->fields->product->id = 'id';
$config->search->fields->product->title = 'name';
$config->search->fields->product->content = 'code,desc';
$config->search->fields->product->addedDate = 'createdDate';
$config->search->fields->product->editedDate = 'lastEditedDate';
$config->search->fields->productplan = new stdclass();
$config->search->fields->productplan->id = 'id';
$config->search->fields->productplan->title = 'title';
$config->search->fields->productplan->content = 'desc';
$config->search->fields->productplan->addedDate = 'addedDate';
$config->search->fields->productplan->editedDate = 'lastEditedDate';
$config->search->fields->project = new stdclass();
$config->search->fields->project->id = 'id';
$config->search->fields->project->title = 'name';
$config->search->fields->project->content = 'code,desc';
$config->search->fields->project->addedDate = 'openedDate';
$config->search->fields->project->editedDate = 'lastEditedDate';
$config->search->fields->release = new stdclass();
$config->search->fields->release->id = 'id';
$config->search->fields->release->title = 'name';
$config->search->fields->release->content = 'desc';
$config->search->fields->release->addedDate = 'addedDate';
$config->search->fields->release->editedDate = 'lastEditedDate';
$config->search->fields->story = new stdclass();
$config->search->fields->story->id = 'id';
$config->search->fields->story->title = 'title';
$config->search->fields->story->content = 'keywords,spec,verify';
$config->search->fields->story->addedDate = 'openedDate';
$config->search->fields->story->editedDate = 'lastEditedDate';
$config->search->fields->task = new stdclass();
$config->search->fields->task->id = 'id';
$config->search->fields->task->title = 'name';
$config->search->fields->task->content = 'desc';
$config->search->fields->task->addedDate = 'openedDate';
$config->search->fields->task->editedDate = 'lastEditedDate';
$config->search->fields->testtask = new stdclass();
$config->search->fields->testtask->id = 'id';
$config->search->fields->testtask->title = 'name';
$config->search->fields->testtask->content = 'desc,report';
$config->search->fields->testtask->addedDate = 'addedDate';
$config->search->fields->testtask->editedDate = 'lastEditedDate';
$config->search->fields->todo = new stdclass();
$config->search->fields->todo->id = 'id';
$config->search->fields->todo->title = 'name';
$config->search->fields->todo->content = 'desc';
$config->search->fields->todo->addedDate = 'date';
$config->search->fields->todo->editedDate = 'lastEditedDate';
$config->search->fields->effort = new stdclass();
$config->search->fields->effort->id = 'id';
$config->search->fields->effort->title = 'work';
$config->search->fields->effort->content = '';
$config->search->fields->effort->addedDate = 'date';
$config->search->fields->effort->editedDate = 'date';
$config->search->fields->testsuite = new stdclass();
$config->search->fields->testsuite->id = 'id';
$config->search->fields->testsuite->title = 'name';
$config->search->fields->testsuite->content = 'desc';
$config->search->fields->testsuite->addedDate = 'addedDate';
$config->search->fields->testsuite->editedDate = 'lastEditedDate';
$config->search->fields->caselib = new stdclass();
$config->search->fields->caselib->id = 'id';
$config->search->fields->caselib->title = 'name';
$config->search->fields->caselib->content = 'desc';
$config->search->fields->caselib->addedDate = 'addedDate';
$config->search->fields->caselib->editedDate = 'lastEditedDate';
$config->search->fields->testreport = new stdclass();
$config->search->fields->testreport->id = 'id';
$config->search->fields->testreport->title = 'title';
$config->search->fields->testreport->content = 'report';
$config->search->fields->testreport->addedDate = 'createdDate';
$config->search->fields->testreport->editedDate = 'createdDate';
$config->search->fields->program = new stdclass();
$config->search->fields->program->id = 'id';
$config->search->fields->program->title = 'name';
$config->search->fields->program->content = 'code,desc';
$config->search->fields->program->addedDate = 'openedDate';
$config->search->fields->program->editedDate = 'lastEditedDate';
$config->search->fields->execution = new stdclass();
$config->search->fields->execution->id = 'id';
$config->search->fields->execution->title = 'name';
$config->search->fields->execution->content = 'code,desc';
$config->search->fields->execution->addedDate = 'openedDate';
$config->search->fields->execution->editedDate = 'lastEditedDate';
/* Set the recPerPage of search. */
$config->search->recPerPage = 10;
/* Set the length of summary of search results. */
$config->search->summaryLength = 120;
+95
View File
@@ -130,4 +130,99 @@ class search extends control
{
$this->dao->update(TABLE_USERQUERY)->set('shortcut')->eq(0)->where('id')->eq($queryID)->exec();
}
/**
* Build All index.
*
* @access public
* @return void
*/
public function buildIndex($type = '', $lastID = 0)
{
if(helper::isAjaxRequest())
{
$result = $this->search->buildAllIndex($type, $lastID);
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
if(isset($result['finished']) and $result['finished'])
{
$this->send(array('result' => 'finished', 'message' => $this->lang->search->buildSuccessfully));
}
else
{
$this->send(array('result' => 'unfinished', 'message' => sprintf($this->lang->search->buildResult, zget($this->lang->searchObjects, ($result['type'] == 'case' ? 'testcase' : $result['type']), $result['type']), $result['count']),'next' => inlink('buildIndex', "type={$result['type']}&lastID={$result['lastID']}") ));
}
}
$this->lang->search->menu = $this->lang->admin->menu;
$this->lang->menugroup->search = 'admin';
$this->view->title = $this->lang->search->buildIndex;
$this->display();
}
/**
* index
*
* @param int $recTotal
* @param int $pageID
*
* @access public
* @return void
*/
public function index($recTotal = 0, $pageID = 1)
{
$this->lang->admin->menu->search = "{$this->lang->search->common}|search|index";
if(empty($words)) $words = $this->get->words;
if(empty($words)) $words = $this->post->words;
if(empty($words) and ($recTotal != 0 or $pageID != 1)) $words = $this->session->searchIngWord;
$words = strip_tags(strtolower($words));
if(empty($type)) $type = $this->get->type;
if(empty($type)) $type = $this->post->type;
if(empty($type) and ($recTotal != 0 or $pageID != 1)) $type = $this->session->searchIngType;
$type = (empty($type) or $type[0] == 'all') ? 'all' : $type;
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $this->config->search->recPerPage, $pageID);
/* Set session. */
$uri = inlink('index', "recTotal=$recTotal&pageID=$pageID");
$uri .= strpos($uri, '?') === false ? '?' : '&';
$uri .= 'words=' . $words;
$this->session->set('bugList', $uri);
$this->session->set('buildList', $uri);
$this->session->set('caseList', $uri);
$this->session->set('docList', $uri);
$this->session->set('productList', $uri);
$this->session->set('productPlanList', $uri);
$this->session->set('projectList', $uri);
$this->session->set('releaseList', $uri);
$this->session->set('storyList', $uri);
$this->session->set('taskList', $uri);
$this->session->set('testtaskList', $uri);
$this->session->set('todoList', $uri);
$this->session->set('effortList', $uri);
$this->session->set('reportList', $uri);
$this->session->set('testsuiteList', $uri);
$this->session->set('searchIngWord', $words);
$this->session->set('searchIngType', $type);
$begin = time();
$this->view->results = $this->search->getList($words, $pager, $type);
if(strpos($this->server->http_referer, 'search') === false)
{
$this->session->set('referer', $this->server->http_referer);
}
$this->view->consumed = time() - $begin;
$this->view->title = $this->lang->search->index;
$this->view->type = $type;
$this->view->pager = $pager;
$this->view->words = $words;
$this->view->referer = $this->session->referer;
$this->display();
}
}
+39
View File
@@ -0,0 +1,39 @@
.execute-info{position:relative; top:5px;}
#type_chosen .chosen-drop{width:150px;}
.table-footer .pager{margin:0px; height:30px; padding-top:10px;}
.table-footer .pager .icon-play.icon-flip-horizontal:before{content:"\e314";}
.table-footer .pager .icon-play:before{content:"\e315";}
.modal.with-titlebar .modal-header{margin-bottom:10px;}
.modal.with-titlebar .modal-header .modal-title{display:block;}
.list {color: #333; background-color: #fff; border: solid #DDD 1px; border-radius: 3px;}
.list > header
{
padding: 8px 15px;
border-bottom: solid #DDD 1px;
font-weight: inherit;
font-size: inherit;
background-color: #F5F5F5;
color: #333;
background-image: -moz-linear-gradient(top,#fbfbfb 0%,#f2f2f2 100%);
background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0%,#fbfbfb),color-stop(100%,#f2f2f2));
background-image: -webkit-linear-gradient(top,#fbfbfb 0%,#f2f2f2 100%);
background-image: -o-linear-gradient(top,#fbfbfb 0%,#f2f2f2 100%);
background-image: linear-gradient(top,#fbfbfb 0%,#f2f2f2 100%);
}
.list > header h2 {font-size: 14px; font-weight: bold; margin: 0; padding: 0; line-height: 20px;}
.list-condensed > .items > .item {padding: 10px 15px; border-bottom: 1px solid #e5e5e5; transition: all .5s cubic-bezier(.175,.885,.32,1);}
.items .item .text-muted{color: #757575;}
.items .item-heading h4{margin-top: 5px; font-size:14px; line-height:1.5; font-weight:normal}
.item:hover{background-color:#f5f5f5}
.modal-iframe .modal-content .modal-header{margin:0px;}
.modal-iframe .modal-content .modal-header .modal-title{position:absolute; right:45px; background:#F8FAFE; height:45px; padding:8px 0px; width:200px; text-align:right;}
.modal-iframe .modal-content .modal-header .modal-title .icon-eye-open{display:none}
.modal-iframe .modal-content .modal-header .modal-title a.btn{border-color: transparent; background:none; padding: 0px; border-radius: 2px; color: #036; padding:4px 7px;;}
.modal-iframe .modal-content .modal-header .modal-title a.btn .icon-eye-open{display:inline;}
.input-group-btn.goback{padding-left:10px;}
.input-group-btn.select{min-width:60px;margin-left:-2px;}
.input-group .chosen-container {min-width: 250px; }
#words {border-right-width: 0px}
#submit {border: 0px;}
+23
View File
@@ -0,0 +1,23 @@
$(document).ready(function()
{
$('#execButton').click(function()
{
$('#execButton').hide();
$.getJSON($(this).attr('href'), function(response)
{
if(response.result == 'finished')
{
$('#resultBox').append("<li class='text-success'>" + response.message + "</li>");
return false;
}
else
{
$('#execButton').attr('href', response.next);
$('#resultBox').append("<li class='text-success'>" + response.message + "</li>");
return $('#execButton').click();
}
});
return false;
});
})
+38
View File
@@ -51,3 +51,41 @@ $lang->search->null = 'Null';
$lang->userquery = new stdclass();
$lang->userquery->title = 'Title';
$lang->searchObjects['todo'] = 'Todo';
$lang->searchObjects['effort'] = 'Effort';
$lang->searchObjects['testsuite'] = 'Test Suite';
$lang->search->objectType = 'Object Type';
$lang->search->objectID = 'Object ID';
$lang->search->content = 'Content';
$lang->search->addedDate = 'Added';
$lang->search->index = 'Full Text Search';
$lang->search->buildIndex = 'Rebuild Index';
$lang->search->preview = 'Preview';
$lang->search->result = 'Search Results';
$lang->search->buildSuccessfully = 'Search index initialized.';
$lang->search->executeInfo = '%s search results for you in %s seconds.';
$lang->search->buildResult = 'Created index %s and added %s records.';
$lang->search->modules['all'] = 'All';
$lang->search->modules['task'] = 'Task';
$lang->search->modules['bug'] = 'Bug';
$lang->search->modules['case'] = 'Case';
$lang->search->modules['doc'] = 'Doc';
$lang->search->modules['todo'] = 'Todo';
$lang->search->modules['build'] = 'Build';
$lang->search->modules['effort'] = 'Effort';
$lang->search->modules['caselib'] = 'CaseLib';
$lang->search->modules['product'] = $lang->productCommon;
$lang->search->modules['release'] = 'Release';
$lang->search->modules['testtask'] = 'Test Request';
$lang->search->modules['testsuite'] = 'Test Suite';
$lang->search->modules['testreport'] = 'Testing Report';
$lang->search->modules['productplan'] = 'Plan';
$lang->search->modules['program'] = 'Program';
$lang->search->modules['project'] = 'Project';
$lang->search->modules['execution'] = 'Iteration/Phase';
$lang->search->modules['story'] = 'US/SR';
+38
View File
@@ -51,3 +51,41 @@ $lang->search->null = 'Null';
$lang->userquery = new stdclass();
$lang->userquery->title = 'Title';
$lang->searchObjects['todo'] = 'Todo';
$lang->searchObjects['effort'] = 'Effort';
$lang->searchObjects['testsuite'] = 'Test Suite';
$lang->search->objectType = 'Object Type';
$lang->search->objectID = 'Object ID';
$lang->search->content = 'Content';
$lang->search->addedDate = 'Added';
$lang->search->index = 'Full Text Search';
$lang->search->buildIndex = 'Rebuild Index';
$lang->search->preview = 'Preview';
$lang->search->result = 'Search Results';
$lang->search->buildSuccessfully = 'Search index initialized.';
$lang->search->executeInfo = '%s search results for you in %s seconds.';
$lang->search->buildResult = 'Created index %s and added %s records.';
$lang->search->modules['all'] = 'All';
$lang->search->modules['task'] = 'Task';
$lang->search->modules['bug'] = 'Bug';
$lang->search->modules['case'] = 'Case';
$lang->search->modules['doc'] = 'Doc';
$lang->search->modules['todo'] = 'Todo';
$lang->search->modules['build'] = 'Build';
$lang->search->modules['effort'] = 'Effort';
$lang->search->modules['caselib'] = 'CaseLib';
$lang->search->modules['product'] = $lang->productCommon;
$lang->search->modules['release'] = 'Release';
$lang->search->modules['testtask'] = 'Test Request';
$lang->search->modules['testsuite'] = 'Test Suite';
$lang->search->modules['testreport'] = 'Testing Report';
$lang->search->modules['productplan'] = 'Plan';
$lang->search->modules['program'] = 'Program';
$lang->search->modules['project'] = 'Project';
$lang->search->modules['execution'] = 'Iteration/Phase';
$lang->search->modules['story'] = 'US/SR';
+38
View File
@@ -51,3 +51,41 @@ $lang->search->null = 'Null';
$lang->userquery = new stdclass();
$lang->userquery->title = 'Title';
$lang->searchObjects['todo'] = 'Todo';
$lang->searchObjects['effort'] = 'Effort';
$lang->searchObjects['testsuite'] = 'Test Suite';
$lang->search->objectType = 'Object Type';
$lang->search->objectID = 'Object ID';
$lang->search->content = 'Content';
$lang->search->addedDate = 'Added';
$lang->search->index = 'Full Text Search';
$lang->search->buildIndex = 'Rebuild Index';
$lang->search->preview = 'Preview';
$lang->search->result = 'Search Results';
$lang->search->buildSuccessfully = 'Search index initialized.';
$lang->search->executeInfo = '%s search results for you in %s seconds.';
$lang->search->buildResult = 'Created index %s and added %s records.';
$lang->search->modules['all'] = 'All';
$lang->search->modules['task'] = 'Task';
$lang->search->modules['bug'] = 'Bug';
$lang->search->modules['case'] = 'Case';
$lang->search->modules['doc'] = 'Doc';
$lang->search->modules['todo'] = 'Todo';
$lang->search->modules['build'] = 'Build';
$lang->search->modules['effort'] = 'Effort';
$lang->search->modules['caselib'] = 'CaseLib';
$lang->search->modules['product'] = $lang->productCommon;
$lang->search->modules['release'] = 'Release';
$lang->search->modules['testtask'] = 'Test Request';
$lang->search->modules['testsuite'] = 'Test Suite';
$lang->search->modules['testreport'] = 'Testing Report';
$lang->search->modules['productplan'] = 'Plan';
$lang->search->modules['program'] = 'Program';
$lang->search->modules['project'] = 'Project';
$lang->search->modules['execution'] = 'Iteration/Phase';
$lang->search->modules['story'] = 'US/SR';
+38
View File
@@ -51,3 +51,41 @@ $lang->search->null = 'Null';
$lang->userquery = new stdclass();
$lang->userquery->title = 'Title';
$lang->searchObjects['todo'] = 'Việc làm';
$lang->searchObjects['effort'] = 'Chấm công';
$lang->searchObjects['testsuite'] = 'Test Suite';
$lang->search->objectType = 'Loại đối tượng';
$lang->search->objectID = 'ID đối tượng';
$lang->search->content = 'Nội dung';
$lang->search->addedDate = 'Ngày thêm';
$lang->search->index = 'Full Text Search';
$lang->search->buildIndex = 'Rebuild Index';
$lang->search->preview = 'Preview';
$lang->search->result = 'Kết quả tìm kiếm';
$lang->search->buildSuccessfully = 'Tìm kiếm khởi tạo chỉ mục.';
$lang->search->executeInfo = '%s kết quả tìm kiếm trong %s giây';
$lang->search->buildResult = 'Chỉ mục được tao %s và được thêm %s mục';
$lang->search->modules['all'] = 'Tất cả';
$lang->search->modules['task'] = 'Nhiệm vụ';
$lang->search->modules['bug'] = 'Bug';
$lang->search->modules['case'] = 'Tình huống';
$lang->search->modules['doc'] = 'Tài liệu';
$lang->search->modules['todo'] = 'Việc làm';
$lang->search->modules['build'] = 'Bản dựng';
$lang->search->modules['effort'] = 'Chấm công';
$lang->search->modules['caselib'] = 'CaseLib';
$lang->search->modules['product'] = $lang->productCommon;
$lang->search->modules['release'] = 'Phát hành';
$lang->search->modules['testtask'] = 'Yêu cầu Test';
$lang->search->modules['testsuite'] = 'Test Suite';
$lang->search->modules['testreport'] = 'Báo cáo Test';
$lang->search->modules['productplan'] = 'Kế hoạch';
$lang->search->modules['program'] = 'Program';
$lang->search->modules['project'] = 'Project';
$lang->search->modules['execution'] = 'Iteration/Phase';
$lang->search->modules['story'] = 'US/SR';
+38
View File
@@ -51,3 +51,41 @@ $lang->search->null = '空';
$lang->userquery = new stdclass();
$lang->userquery->title = '标题';
$lang->searchObjects['todo'] = '待办';
$lang->searchObjects['effort'] = '日志';
$lang->searchObjects['testsuite'] = '套件';
$lang->search->objectType = '对象类型';
$lang->search->objectID = '对象编号';
$lang->search->content = '内容';
$lang->search->addedDate = '添加时间';
$lang->search->index = '全文检索';
$lang->search->buildIndex = '重建索引';
$lang->search->preview = '预览';
$lang->search->result = '搜索结果';
$lang->search->buildSuccessfully = '初始化搜索索引成功';
$lang->search->executeInfo = '为您找到相关结果%s个,耗时%s秒';
$lang->search->buildResult = '创建 %s 索引, 新增 %s 条记录;';
$lang->search->modules['all'] = '全部';
$lang->search->modules['task'] = '任务';
$lang->search->modules['bug'] = 'Bug';
$lang->search->modules['case'] = '用例';
$lang->search->modules['doc'] = '文档';
$lang->search->modules['todo'] = '待办';
$lang->search->modules['build'] = 'Build';
$lang->search->modules['effort'] = '日志';
$lang->search->modules['caselib'] = '测试库';
$lang->search->modules['product'] = $lang->productCommon;
$lang->search->modules['release'] = '发布';
$lang->search->modules['testtask'] = '测试单';
$lang->search->modules['testsuite'] = '测试套件';
$lang->search->modules['testreport'] = '报告';
$lang->search->modules['productplan'] = '计划';
$lang->search->modules['program'] = '项目集';
$lang->search->modules['project'] = '项目';
$lang->search->modules['execution'] = '迭代/阶段';
$lang->search->modules['story'] = '用需/软需';
+542
View File
@@ -491,4 +491,546 @@ class searchModel extends model
}
return $query;
}
/**
* get search results of keywords.
*
* @param string $keywords
* @param object $pager
* @param string $type
* @access public
* @return array
*/
public function getList($keywords, $pager, $type)
{
$spliter = $this->app->loadClass('spliter');
$words = explode(' ', self::unify($keywords, ' '));
$against = '';
$againstCond = '';
$likeCondition = '';
foreach($words as $word)
{
$splitedWords = $spliter->utf8Split($word);
$trimedWord = trim($splitedWords['words']);
$against .= '"' . $trimedWord . '" ';
$againstCond .= '+"' . $trimedWord . '" ';
if(is_numeric($word) and strlen($word) == 5) $againstCond .= "-\" $word \" ";
$likeWord = is_numeric($word) ? $word : $trimedWord;
if(is_numeric($word) and strlen($word) < 5) $likeWord = str_pad("|$likeWord|", 5, '_');
$condition = "OR title like '%{$likeWord}%' OR content like '%{$likeWord}%'";
if(is_numeric($word) and strlen($word) == 5) $condition = "OR title REGEXP '[^ ]{$likeWord}[^ ]' OR content REGEXP '[^ ]{$likeWord}[^ ]'";
$likeCondition .= $condition;
}
$words = str_replace('"', '', $against);
$words = str_pad($words, 5, '_');
$allowedObject = array();
if($type != 'all')
{
foreach($type as $module) $allowedObject[] = $module;
}
else
{
foreach($this->config->search->fields as $objectType => $fields)
{
$module = $objectType;
if($module == 'case') $module = 'testcase';
if(common::hasPriv($module, 'view')) $allowedObject[] = $objectType;
if($module == 'caselib' and common::hasPriv('caselib', 'view')) $allowedObject[] = $objectType;
}
}
$scoreColumn = "((1 * (MATCH(title) AGAINST('{$against}' IN BOOLEAN MODE))) + (0.6 * (MATCH(content) AGAINST('{$against}' IN BOOLEAN MODE))) )";
$results = $this->dao->select("*, {$scoreColumn} as score")
->from(TABLE_SEARCHINDEX)
->where("(MATCH(title) AGAINST('{$againstCond}' IN BOOLEAN MODE) >= 1 or MATCH(content) AGAINST('{$againstCond}' IN BOOLEAN MODE) >= 1 $likeCondition)")
->andWhere('objectType')->in($allowedObject)
->andWhere('addedDate')->le(helper::now())
->orderBy('score_desc, editedDate_desc')
->page($pager)
->fetchAll('id');
foreach($results as $record)
{
$record->title = str_replace('</span> ', '</span>', $this->decode($this->markKeywords($record->title, $words)));
$record->title = str_replace('_', '', $record->title);
$record->summary = str_replace('</span> ', '</span>', $this->getSummary($record->content, $words));
$record->summary = str_replace('_', '', $record->summary);
$module = $record->objectType == 'case' ? 'testcase' : $record->objectType;
$method = 'view';
if($module == 'deploystep')
{
$module = 'deploy';
$method = 'viewstep';
}
$record->url = helper::createLink($module, $method, "id={$record->objectID}");
}
foreach($results as $object)
{
if($object->objectType == 'program') $object->url = str_replace('m=program&f=view&', 'm=program&f=view&', $object->url);
if($object->objectType == 'project') $object->url = str_replace('m=project&f=view&', 'm=program&f=index&', $object->url);
if($object->objectType == 'execution') $object->url = str_replace('m=execution&f=view&', 'm=project&f=view&', $object->url);
}
return $this->checkPriv($results, $pager);
}
/**
* Save an index item.
*
* @param string $objectType article|blog|page|product|thread|reply|
* @param int $objectID
* @access public
* @return void
*/
public function saveIndex($objectType, $object)
{
$fields = $this->config->search->fields->{$objectType};
if(empty($fields)) return true;
$index = new stdclass();
$index->objectID = $object->{$fields->id};
$index->objectType = $objectType;
$index->title = $object->{$fields->title};
$index->addedDate = isset($object->{$fields->addedDate}) ? $object->{$fields->addedDate} : '0000-00-00 00:00:00';
$index->editedDate = isset($object->{$fields->editedDate}) ? $object->{$fields->editedDate} : '0000-00-00 00:00:00';
$index->content = '';
$contentFields = explode(',', $fields->content . ',comment');
foreach($contentFields as $field)
{
if(empty($field)) continue;
$index->content .= $object->$field;
}
$spliter = $this->app->loadClass('spliter');
$titleSplited = $spliter->utf8Split($index->title);
$index->title = $titleSplited['words'];
$contentSplited = $spliter->utf8Split(strip_tags($index->content));
$index->content = $contentSplited['words'];
$this->saveDict($titleSplited['dict'] + $contentSplited['dict']);
$this->dao->replace(TABLE_SEARCHINDEX)->data($index)->exec();
return true;
}
/**
* Save dict info.
*
* @param array $words
* @access public
* @return void
*/
public function saveDict($dict)
{
foreach($dict as $key => $value)
{
if(!is_numeric($key) or empty($value) or strlen($key) != 5) continue;
$this->dao->replace(TABLE_SEARCHDICT)->data(array('key' => $key, 'value' => $value))->exec();
}
}
/**
* Transfer unicode to words.
*
* @param string $string
* @access public
* @return void
*/
public function decode($string)
{
static $dict;
if(empty($dict))
{
$dict = $this->dao->select("concat(`key`, ' ') as `key`, value")->from(TABLE_SEARCHDICT)->fetchPairs();
$dict['|'] = '';
}
if(strpos($string, ' ') === false) return zget($dict, $string . ' ');
return trim(str_replace(array_keys($dict), array_values($dict), $string . ' '));
}
/**
* Get summary of results.
*
* @param string $content
* @param string $words
* @access public
* @return string
*/
public function getSummary($content, $words)
{
$length = $this->config->search->summaryLength;
if(strlen($content) <= $length) return $this->decode($this->markKeywords($content, $words));
$content = $this->markKeywords($content, $words);
preg_match_all("/\<span class='text-danger'\>.*\<\/span\>/U", $content, $matches);
if(empty($matches[0])) return $this->decode($this->markKeywords(substr($content, 0, $length), $words));
$matches = $matches[0];
$score = 0;
$needle = '';
foreach($matches as $matched)
{
if(strlen($matched) > $score)
{
$content = str_replace($needle, strip_tags($needle), $content);
$needle = $matched;
$score = strlen($matched);
}
}
$content = str_replace('<span class', ' <spanclass', $content);
$content = explode(' ', $content);
$pos = array_search(str_replace('<span class', '<spanclass', $needle), $content);
$start = max(0, $pos - ($length / 2));
$summary = join(' ', array_slice($content, $start, $length));
$summary = str_replace(' <spanclass', '<span class', $summary);
return $this->decode($summary);
}
/**
* Check product and project priv.
*
* @param array $results
* @access public
* @return array
*/
public function checkPriv($results, $pager = null)
{
$this->loadModel('doc');
$products = $this->app->user->view->products;
$projects = $this->app->user->view->projects;
$objectPairs = array();
$noPrivNum = 0;
foreach($results as $record) $objectPairs[$record->objectType][$record->objectID] = $record->id;
foreach($objectPairs as $objectType => $objectIdList)
{
$objectProducts = array();
$objectProjects = array();
if(!isset($this->config->objectTables[$objectType])) continue;
$table = $this->config->objectTables[$objectType];
if(strpos(',bug,case,productplan,release,story,testtask,', ",$objectType,") !== false)
{
$objectProducts = $this->dao->select('id,product')->from($table)->where('id')->in(array_keys($objectIdList))->fetchGroup('product', 'id');
}
elseif(strpos(',build,task,testreport,', ",$objectType,") !== false)
{
$objectProjects = $this->dao->select('id,project')->from($table)->where('id')->in(array_keys($objectIdList))->fetchGroup('project', 'id');
}
elseif($objectType == 'effort')
{
$efforts = $this->dao->select('id,product,project')->from($table)->where('id')->in(array_keys($objectIdList))->fetchAll();
foreach($efforts as $effort)
{
$objectProjects[$effort->project][$effort->id] = $effort;
$effortProducts = explode(',', trim($effort->product, ','));
foreach($effortProducts as $effortProduct) $objectProducts[$effortProduct][$effort->id] = $effort;
}
}
elseif($objectType == 'product')
{
foreach($objectIdList as $productID => $recordID)
{
if(strpos(",$products,", ",$productID,") === false)
{
unset($results[$recordID]);
$noPrivNum++;
}
}
}
elseif($objectType == 'project')
{
foreach($objectIdList as $projectID => $recordID)
{
if(strpos(",$projects,", ",$projectID,") === false)
{
unset($results[$recordID]);
$noPrivNum++;
}
}
}
elseif($objectType == 'doc')
{
$objectDocs = $this->dao->select('*')->from($table)->where('id')->in(array_keys($objectIdList))
->andWhere('deleted')->eq(0)
->fetchAll('id');
$privLibs = array();
foreach($objectIdList as $docID => $recordID)
{
if(!isset($objectDocs[$docID]) or !$this->doc->checkPrivDoc($objectDocs[$docID]))
{
unset($results[$recordID]);
$noPrivNum++;
continue;
}
$objectDoc = $objectDocs[$docID];
$privLibs[$objectDoc->lib] = $objectDoc->lib;
}
$libs = $this->doc->getLibs('all');
$objectDocLibs = $this->dao->select('id')->from(TABLE_DOCLIB)->where('id')->in($privLibs)
->andWhere('id')->in(array_keys($libs))
->andWhere('deleted')->eq(0)
->fetchPairs('id', 'id');
foreach($objectDocs as $docID => $doc)
{
$libID = $doc->lib;
if(!isset($objectDocLibs[$libID]))
{
$recordID = $objectIdList[$docID];
unset($results[$recordID]);
$noPrivNum++;
}
}
}
elseif($objectType == 'todo')
{
$objectTodos = $this->dao->select('id')->from($table)->where('id')->in(array_keys($objectIdList))->andWhere("private")->eq(1)->fetchPairs('id', 'id');
foreach($objectTodos as $todoID)
{
if(isset($objectIdList[$todoID]))
{
$recordID = $objectIdList[$todoID];
unset($results[$recordID]);
$noPrivNum++;
}
}
}
elseif($objectType == 'testsuite')
{
$objectSuites = $this->dao->select('id')->from($table)->where('id')->in(array_keys($objectIdList))
->andWhere("type")->eq('private')
->andWhere('deleted')->eq(0)
->fetchPairs('id', 'id');
foreach($objectSuites as $suiteID)
{
if(isset($objectIdList[$suiteID]))
{
$recordID = $objectIdList[$suiteID];
unset($results[$recordID]);
$noPrivNum++;
}
}
}
foreach($objectProducts as $productID => $idList)
{
if(empty($productID)) continue;
if(strpos(",$products,", ",$productID,") === false)
{
foreach($idList as $object)
{
$recordID = $objectIdList[$object->id];
unset($results[$recordID]);
$noPrivNum++;
}
}
}
foreach($objectProjects as $projectID => $idList)
{
if(empty($projectID)) continue;
if(strpos(",$projects,", ",$projectID,") === false)
{
foreach($idList as $object)
{
$recordID = $objectIdList[$object->id];
unset($results[$recordID]);
$noPrivNum++;
}
}
}
}
if($noPrivNum > 0) $pager->recTotal = $pager->recTotal - $noPrivNum;
return $results;
}
/**
* Mark keywords in content.
*
* @param string $content
* @param string $keywords
* @access public
* @return void
*/
public function markKeywords($content, $keywords)
{
$words = explode(' ', trim($keywords, ' '));
$markedWords = array();
foreach($words as $key => $word)
{
if(preg_match('/^\|[0-9]+\|$/', $word))
{
$words[$key] = trim($word, '|');
}
elseif(is_numeric($word))
{
$words[$key] = $word . ' ';
}
else
{
$words[$key] = strlen($word) == 5 ? str_replace('_', '', $word) : $word;
}
$markedWords[] = "<span class='text-danger'>" . $this->decode($word) . "</span > ";
}
$content = str_replace($words, $markedWords, $content . ' ');
$content = str_replace("</span > <span class='text-danger'>", '', $content);
$content = str_replace("</span >", '</span>', $content);
return $content;
}
public function buildIndexQuery($type, $testDeleted = true)
{
$table = $this->config->objectTables[$type];
if($type == 'story')
{
$query = $this->dao->select('DISTINCT t1.*,t2.spec,t2.verify')->from($table)->alias('t1')->leftJoin(TABLE_STORYSPEC)->alias('t2')->on('t1.id=t2.story')->where('t1.deleted')->eq(0)->andWhere('t1.version=t2.version');
}
elseif($type == 'doc')
{
$query = $this->dao->select('DISTINCT t1.*,t2.content,t2.digest')->from($table)->alias('t1')->leftJoin(TABLE_DOCCONTENT)->alias('t2')->on('t1.id=t2.doc')->where('t1.deleted')->eq(0)->andWhere('t1.version=t2.version');
}
else
{
$data = '';
if($testDeleted) $data = $this->dao->select('*')->from($table)->limit(1)->fetch();
$query = $this->dao->select('t1.*')->from($table)->alias('t1')
->where('1')
->beginIF(isset($data->deleted))->andWhere('t1.deleted')->eq(0)->fi();
}
return $query;
}
/**
* Build all search index.
*
* @access public
* @return bool
*/
public function buildAllIndex($type = '', $lastID = 0)
{
$limit = 100;
$nextObject = false;
if(empty($type))
{
$this->dao->delete()->from(TABLE_SEARCHINDEX)->exec();
$this->dao->delete()->from(TABLE_SEARCHDICT)->exec();
try
{
$this->dbh->exec('ALTER TABLE ' . TABLE_SEARCHINDEX . ' auto_increment=1');
}
catch(Exception $e){}
$type = key($this->config->search->fields);
}
foreach($this->config->search->fields as $module => $field)
{
if($module != $type and !$nextObject) continue;
if($module == $type) $nextObject = true;
if(!isset($this->config->objectTables[$module])) continue;
while(true)
{
$query = $this->buildIndexQuery($module);
$dataList = $query->beginIF($lastID)->andWhere('t1.id')->gt($lastID)->fi()->limit($limit)->fetchAll('id');
if(empty($dataList))
{
$lastID = 0;
break;
}
if($module == 'case') $caseStep = $this->dao->select('*')->from(TABLE_CASESTEP)->where('`case`')->in(array_keys($dataList))->fetchGroup('case', 'id');
$actions = $this->dao->select('*')->from(TABLE_ACTION)
->where('objectType')->eq($module)
->andWhere('objectID')->in(array_keys($dataList))
->orderBy('date asc')
->fetchGroup('objectID', 'id');
$files = $this->dao->select('id,objectID,title,extension')->from(TABLE_FILE)
->where('objectType')->eq($module)
->andWhere('objectID')->in(array_keys($dataList))
->orderBy('id asc')
->fetchGroup('objectID', 'id');
foreach($dataList as $id => $data)
{
$data->comment = '';
if(isset($actions[$id]))
{
foreach($actions[$id] as $action)
{
if($action->action == 'opened')$data->{$field->addedDate} = $action->date;
$data->{$field->editedDate} = $action->date;
if(!empty($action->comment)) $data->comment .= $action->comment . "\n";
}
}
if(isset($files[$id]))
{
foreach($files[$id] as $file)
{
if(!empty($file->title)) $data->comment .= $file->title . '.' . $file->extension . "\n";
}
}
if($module == 'case')
{
$data->desc = '';
$data->expect = '';
if(isset($caseStep[$id]))
{
foreach($caseStep[$id] as $step)
{
if($step->version != $data->version) continue;
$data->desc .= $step->desc . "\n";
$data->expect .= $step->expect . "\n";
}
}
}
}
foreach($dataList as $data) $this->saveIndex($module, $data);
return array('type' => $module, 'count' => count($dataList), 'lastID' => max(array_keys($dataList)));
}
}
return array('finished' => true);
}
/**
* Delete index of an object.
*
* @param string $objectType
* @param int $objectID
* @access public
* @return void
*/
public function deleteIndex($objectType, $objectID)
{
$this->dao->delete()->from(TABLE_SEARCHINDEX)->where('objectType')->eq($objectType)->andWhere('objectID')->eq($objectID)->exec();
return !dao::isError();
}
public static function unify($string, $to = ',')
{
$labels = array('_', '、', ' ', '-', '\n', '?', '@', '&', '%', '~', '`', '+', '*', '/', '\\', '。', ',');
$string = str_replace($labels, $to, $string);
return preg_replace("/[{$to}]+/", $to, trim($string, $to));
}
}
+32
View File
@@ -0,0 +1,32 @@
<?php
/**
* The create view file of article module of chanzhiEPS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv11.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package article
* @version $Id$
* @link http://www.chanzhi.org
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='mainMenu' class='clearfix'>
<div class='btn-toolbar pull-left'><?php common::printAdminSubMenu('system');?></div>
</div>
<div id='mainContent' class='main-content'>
<div class='main-header'>
<h2><i class='icon-refresh'></i> <?php echo $lang->search->index;?></h2>
</div>
<div>
<div class='form-group'>
<ul id='resultBox'></ul>
</div>
<div class='from-group'><?php echo html::a(inlink('buildIndex'), $lang->search->buildIndex, '', "class='btn btn-primary' id='execButton'");?></div>
</div>
</div>
</div>
<script>
$('#subNavbar li[data-id=system]').addClass('active');
</script>
<?php include '../../common/view/footer.html.php';?>
+49
View File
@@ -0,0 +1,49 @@
<?php include '../../common/view/header.html.php';?>
<div class='row'>
<div class='col-md-12'>
<form method='post' action='<?php echo inlink('index')?>' style='margin-bottom:10px;'>
<div class='input-group col-md-8 col-md-offset-2'>
<span class='input-group-btn w-auto'><?php echo html::input('words', $words, "class='form-control'")?></span>
<span class='input-group-btn select'><?php echo html::select('type[]', $lang->search->modules, $type, "class='form-control chosen' multiple")?></span>
<span class='input-group-btn'><?php echo html::submitButton($lang->search->common, '', 'btn btn-primary')?></span>
</div>
</form>
<div class='list list-condensed'>
<header>
<h2><?php echo $lang->search->result;?></h2>
</header>
<section class='items items-hover'>
<?php foreach($results as $object):?>
<div class='item'>
<div class='item-heading'>
<div class="pull-right">
<span><?php echo html::a($object->url . (strpos($object->url, '?') !== false ? '&onlybody=yes' : '?onlybody=yes'), "<i class='icon-eye-open'></i>" . $lang->search->preview, '', "class='iframe' data-width='90%' data-title=\"<a href='$object->url' target='_blank' class='btn'><i class='icon-eye-open'></i>$lang->preview</a>\"")?></span>
</div>
<h4>
<?php
$objectType = $object->objectType == 'case' ? 'testcase' : $object->objectType;
echo html::a($object->url, $object->title, '', 'title="' . strip_tags($object->title) . '"');
echo "<small class=''>[{$lang->searchObjects[$objectType]} #{$object->objectID}]</small> ";
?>
</h4>
</div>
<div class='item-content'>
<div class='text text-muted'><?php echo $object->summary;?></div>
</div>
</div>
<?php endforeach;?>
</section>
<footer class='table-footer'>
<?php echo str_replace($words, urlencode($words), $pager->get('right', 'short'));?>
<span class='execute-info text-muted'><?php printf($lang->search->executeInfo, $pager->recTotal, $consumed);?></span>
</footer>
</div>
</div>
</div>
<script>
$(function()
{
$('#searchbox #searchInput').val(<?php echo json_encode($words)?>);
})
</script>
<?php include '../../common/view/footer.html.php';?>
+12 -12
View File
@@ -643,9 +643,9 @@ class task extends control
else
{
$story = $this->story->getById($task->story, $task->storyVersion);
$task->storySpec = empty($story) ? '' : $this->loadModel('file')->setImgSize($story->spec);
$task->storyVerify = empty($story) ? '' : $this->loadModel('file')->setImgSize($story->verify);
$task->storyFiles = $this->loadModel('file')->getByObject('story', $task->story);
$task->storySpec = empty($story) ? '' : $this->loadModel('file')->setImgSize($story->spec);
$task->storyVerify = empty($story) ? '' : $this->loadModel('file')->setImgSize($story->verify);
$task->storyFiles = $this->loadModel('file')->getByObject('story', $task->story);
}
if($task->team) $this->lang->task->assign = $this->lang->task->transfer;
@@ -664,15 +664,15 @@ class task extends control
$position[] = $this->lang->task->common;
$position[] = $this->lang->task->view;
$this->view->title = $title;
$this->view->position = $position;
$this->view->project = $project;
$this->view->task = $task;
$this->view->actions = $this->loadModel('action')->getList('task', $taskID);
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('task', $taskID);
$this->view->product = $this->tree->getProduct($task->module);
$this->view->modulePath = $this->tree->getParents($task->module);
$this->view->title = $title;
$this->view->position = $position;
$this->view->project = $project;
$this->view->task = $task;
$this->view->actions = $this->loadModel('action')->getList('task', $taskID);
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('task', $taskID);
$this->view->product = $this->tree->getProduct($task->module);
$this->view->modulePath = $this->tree->getParents($task->module);
$this->display();
}