diff --git a/config/zentaopms.php b/config/zentaopms.php
index 958db47c54..426fd2e81d 100644
--- a/config/zentaopms.php
+++ b/config/zentaopms.php
@@ -341,6 +341,9 @@ define('TABLE_COMPILE', '`' . $config->db->prefix . 'compile`');
define('TABLE_MR', '`' . $config->db->prefix . 'mr`');
define('TABLE_MRAPPROVAL', '`' . $config->db->prefix . 'mrapproval`');
+define('TABLE_SERVERROOM', '`' . $config->db->prefix . 'serverroom`');
+define('TABLE_ACCOUNT', '`' . $config->db->prefix . 'account`');
+define('TABLE_HOST', '`' . $config->db->prefix . 'host`');
define('TABLE_REPO', '`' . $config->db->prefix . 'repo`');
define('TABLE_RELATION', '`' . $config->db->prefix . 'relation`');
define('TABLE_REPOHISTORY', '`' . $config->db->prefix . 'repohistory`');
@@ -378,6 +381,10 @@ define('TABLE_PRIVLANG', '`' . $config->db->prefix . 'privlang`');
define('TABLE_PRIVMANAGER', '`' . $config->db->prefix . 'privmanager`');
define('TABLE_PRIVRELATION', '`' . $config->db->prefix . 'privrelation`');
+define('TABLE_SPACE', '`' . $config->db->prefix . 'space`');
+define('TABLE_INSTANCE', '`' . $config->db->prefix . 'instance`');
+define('TABLE_SOLUTION', '`' . $config->db->prefix . 'solution`');
+
$config->objectTables['product'] = TABLE_PRODUCT;
$config->objectTables['productplan'] = TABLE_PRODUCTPLAN;
$config->objectTables['story'] = TABLE_STORY;
diff --git a/module/host/config.php b/module/host/config.php
new file mode 100644
index 0000000000..c223cdbba6
--- /dev/null
+++ b/module/host/config.php
@@ -0,0 +1,34 @@
+host->create = new stdclass();
+$config->host->edit = new stdclass();
+$config->host->changestatus = new stdclass();
+$config->host->create->requiredFields = 'name,zap,tags,provider,intranet,extranet';
+$config->host->edit->requiredFields = 'name,zap,tags,provider,intranet,extranet';
+$config->host->create->intFields = 'cpuNumber,cpuCores,zap';
+$config->host->create->ipFields = 'intranet,extranet';
+
+$config->host->editor = new stdclass();
+$config->host->editor->changestatus = array('id' => 'reason', 'tools' => 'simple');
+
+global $lang;
+$config->host->featureBar = array(
+ array(
+ 'text' => $lang->host->featureBar['browse']['all'],
+ 'active' => false,
+ 'url' => helper::createLink('host', 'browse'),
+ ),
+ array(
+ 'text' => $lang->host->featureBar['browse']['serverroom'],
+ 'active' => false,
+ 'url' => helper::createLink('host', 'treemap', 'type=serverroom'),
+ ),
+ array(
+ 'text' => $lang->host->featureBar['browse']['group'],
+ 'active' => false,
+ 'url' => helper::createLink('host', 'treemap', 'type=group'),
+ ),
+);
+
+$config->host->actions = new stdclass();
+$config->host->actions->view = array();
+$config->host->actions->view['suffixActions'] = array('edit', 'delete');
\ No newline at end of file
diff --git a/module/host/config/dtable.php b/module/host/config/dtable.php
new file mode 100644
index 0000000000..e30d53538d
--- /dev/null
+++ b/module/host/config/dtable.php
@@ -0,0 +1,95 @@
+loadLang('serverroom');
+
+$config->host->dtable = new stdclass();
+
+$config->host->dtable->fieldList['id']['title'] = 'ID';
+$config->host->dtable->fieldList['id']['name'] = 'id';
+$config->host->dtable->fieldList['id']['type'] = 'id';
+
+$config->host->dtable->fieldList['group']['title'] = $lang->host->group;
+$config->host->dtable->fieldList['group']['name'] = 'group';
+$config->host->dtable->fieldList['group']['type'] = 'text';
+$config->host->dtable->fieldList['group']['sortType'] = true;
+$config->host->dtable->fieldList['group']['width'] = 80;
+
+$config->host->dtable->fieldList['name']['title'] = $lang->host->name;
+$config->host->dtable->fieldList['name']['name'] = 'name';
+$config->host->dtable->fieldList['name']['type'] = 'desc';
+$config->host->dtable->fieldList['name']['sortType'] = true;
+$config->host->dtable->fieldList['name']['flex'] = 4;
+$config->host->dtable->fieldList['name']['hint'] = true;
+$config->host->dtable->fieldList['name']['link'] = array('module' => 'host', 'method' => 'view', 'params' => 'id={id}');
+$config->host->dtable->fieldList['name']['data-toggle'] = 'modal';
+
+$config->host->dtable->fieldList['admin']['title'] = $lang->host->admin;
+$config->host->dtable->fieldList['admin']['name'] = 'admin';
+$config->host->dtable->fieldList['admin']['type'] = 'text';
+$config->host->dtable->fieldList['admin']['sortType'] = true;
+$config->host->dtable->fieldList['admin']['link'] = array('module' => 'account', 'method' => 'view', 'params' => 'id={admin}');
+$config->host->dtable->fieldList['admin']['data-toggle'] = 'modal';
+
+$config->host->dtable->fieldList['serverRoom']['title'] = $lang->host->serverRoom;
+$config->host->dtable->fieldList['serverRoom']['name'] = 'serverRoom';
+$config->host->dtable->fieldList['serverRoom']['type'] = 'text';
+$config->host->dtable->fieldList['serverRoom']['sortType'] = true;
+$config->host->dtable->fieldList['serverRoom']['link'] = array('module' => 'serverroom', 'method' => 'view', 'params' => 'id={serverRoom}');
+$config->host->dtable->fieldList['serverRoom']['data-toggle'] = 'modal';
+
+$config->host->dtable->fieldList['intranet']['title'] = $lang->host->intranet;
+$config->host->dtable->fieldList['intranet']['name'] = 'intranet';
+$config->host->dtable->fieldList['intranet']['type'] = 'text';
+$config->host->dtable->fieldList['intranet']['sortType'] = true;
+
+$config->host->dtable->fieldList['extranet']['title'] = $lang->host->extranet;
+$config->host->dtable->fieldList['extranet']['name'] = 'extranet';
+$config->host->dtable->fieldList['extranet']['type'] = 'text';
+$config->host->dtable->fieldList['extranet']['sortType'] = true;
+
+$config->host->dtable->fieldList['osVersion']['title'] = $lang->host->osVersion;
+$config->host->dtable->fieldList['osVersion']['name'] = 'osVersion';
+$config->host->dtable->fieldList['osVersion']['type'] = 'text';
+$config->host->dtable->fieldList['osVersion']['sortType'] = true;
+
+$config->host->dtable->fieldList['status']['title'] = $lang->host->status;
+$config->host->dtable->fieldList['status']['name'] = 'status';
+$config->host->dtable->fieldList['status']['type'] = 'text';
+$config->host->dtable->fieldList['status']['sortType'] = true;
+$config->host->dtable->fieldList['status']['width'] = 80;
+$config->host->dtable->fieldList['status']['map'] = $lang->host->statusList;
+
+$config->host->actionList = array();
+$config->host->actionList['online']['icon'] = 'arrow-up';
+$config->host->actionList['online']['text'] = $lang->host->online;
+$config->host->actionList['online']['hint'] = $lang->host->online;
+$config->host->actionList['online']['data-toggle'] = 'modal';
+$config->host->actionList['online']['url'] = helper::createLink('host', 'changeStatus', 'id={id}&status=offline');
+
+
+$config->host->actionList['offline']['icon'] = 'arrow-down';
+$config->host->actionList['offline']['text'] = $lang->host->offline;
+$config->host->actionList['offline']['hint'] = $lang->host->offline;
+$config->host->actionList['offline']['data-toggle'] = 'modal';
+$config->host->actionList['offline']['url'] = helper::createLink('host', 'changeStatus', 'id={id}&status=online');
+
+$config->host->actionList['edit']['icon'] = 'edit';
+$config->host->actionList['edit']['text'] = $lang->edit;
+$config->host->actionList['edit']['hint'] = $lang->edit;
+$config->host->actionList['edit']['showText'] = true;
+$config->host->actionList['edit']['url'] = array('module' => 'host', 'method' => 'edit', 'params' => 'id={id}');
+
+$config->host->actionList['delete']['icon'] = 'trash';
+$config->host->actionList['delete']['text'] = $lang->delete;
+$config->host->actionList['delete']['hint'] = $lang->delete;
+$config->host->actionList['delete']['showText'] = true;
+$config->host->actionList['delete']['data-confirm'] = $lang->host->confirmDelete;
+$config->host->actionList['delete']['url'] = array('module' => 'host', 'method' => 'delete', 'params' => 'id={id}');
+
+$config->host->dtable->fieldList['actions']['name'] = 'actions';
+$config->host->dtable->fieldList['actions']['title'] = $lang->actions;
+$config->host->dtable->fieldList['actions']['type'] = 'actions';
+$config->host->dtable->fieldList['actions']['sortType'] = false;
+$config->host->dtable->fieldList['actions']['fixed'] = 'right';
+$config->host->dtable->fieldList['actions']['menu'] = array('online|offline', 'edit', 'delete');
+$config->host->dtable->fieldList['actions']['list'] = $config->host->actionList;
diff --git a/module/host/config/search.php b/module/host/config/search.php
new file mode 100644
index 0000000000..85261a7baa
--- /dev/null
+++ b/module/host/config/search.php
@@ -0,0 +1,32 @@
+host->search['module'] = 'host';
+$config->host->search['fields']['name'] = $lang->host->name;
+$config->host->search['fields']['id'] = 'ID';
+$config->host->search['fields']['serverRoom'] = $lang->host->serverRoom;
+$config->host->search['fields']['intranet'] = $lang->host->intranet;
+$config->host->search['fields']['extranet'] = $lang->host->extranet;
+$config->host->search['fields']['group'] = $lang->host->group;
+$config->host->search['fields']['status'] = $lang->host->status;
+$config->host->search['fields']['osName'] = $lang->host->osName;
+
+$config->host->search['fields']['osVersion'] = $lang->host->osVersion;
+$config->host->search['fields']['createdBy'] = $lang->host->createdBy;
+$config->host->search['fields']['createdDate'] = $lang->host->createdDate;
+$config->host->search['fields']['editedBy'] = $lang->host->editedBy;
+$config->host->search['fields']['editedDate'] = $lang->host->editedDate;
+
+$config->host->search['params']['name'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
+$config->host->search['params']['id'] = array('operator' => '=', 'control' => 'input', 'values' => '');
+$config->host->search['params']['serverRoom'] = array('operator' => '=', 'control' => 'select', 'values' => '');
+$config->host->search['params']['intranet'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
+$config->host->search['params']['extranet'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
+$config->host->search['params']['group'] = array('operator' => '=', 'control' => 'select', 'values' => '');
+$config->host->search['params']['status'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->host->statusList);
+$config->host->search['params']['osName'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
+$config->host->search['params']['osVersion'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
+$config->host->search['params']['createdBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
+$config->host->search['params']['createdDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
+$config->host->search['params']['editedBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
+$config->host->search['params']['editedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
diff --git a/module/host/control.php b/module/host/control.php
new file mode 100644
index 0000000000..c8ee7f823a
--- /dev/null
+++ b/module/host/control.php
@@ -0,0 +1,237 @@
+
+ * @package ops
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+class host extends control
+{
+ /**
+ * View host.
+ *
+ * @param int $recTotal
+ * @param int $recPerPage
+ * @param int $pageID
+ * @access public
+ * @return void
+ */
+ public function browse($browseType = 'all', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
+ {
+ $browseType = strtolower($browseType);
+ $param = (int)$param;
+
+ $this->app->session->set('hostList', $this->app->getURI(true));
+ $this->app->loadClass('pager', $static = true);
+ $pager = pager::init($recTotal, $recPerPage, $pageID);
+
+ $hostList = $this->host->getList($browseType, $param, $orderBy, $pager);
+ $rooms = $this->loadModel('serverroom')->getPairs();
+ $accounts = $this->loadModel('account')->getPairs();
+ $groups = array('', '') + $this->loadModel('tree')->getOptionMenu(0, 'host');
+
+ /* Build the search form. */
+ $actionURL = $this->createLink('host', 'browse', "browseType=bySearch&queryID=myQueryID");
+ $this->config->host->search['actionURL'] = $actionURL;
+ $this->config->host->search['queryID'] = $param;
+ $this->config->host->search['onMenuBar'] = 'no';
+ $this->config->host->search['params']['serverRoom']['values'] = $rooms;
+ $this->config->host->search['params']['group']['values'] = $groups;
+ $this->loadModel('search')->setSearchParams($this->config->host->search);
+
+ $this->loadModel('tree');
+ $this->view->title = $this->lang->host->common;
+ $this->view->hostList = $hostList;
+ $this->view->pager = $pager;
+ $this->view->accounts = $accounts;
+ $this->view->rooms = $rooms;
+ $this->view->param = $param;
+ $this->view->orderBy = $orderBy;
+ $this->view->browseType = $browseType;
+ $this->view->moduleTree = $this->tree->getHostTreeMenu();
+ $this->view->optionMenu = $groups;
+
+ $this->view->position[] = $this->lang->host->common;
+
+ $this->display();
+ }
+
+ /**
+ * Create host.
+ *
+ * @access public
+ * @return void
+ */
+ public function create($osName = 'linux')
+ {
+ if($_POST)
+ {
+ $id = $this->host->create();
+ if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
+
+ return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
+ }
+
+ $this->view->defaultParams = array(
+ 'zap' => '8085',
+ 'pri' => '100',
+ 'bridgeID' => 'br0',
+ );
+
+ $this->view->title = $this->lang->host->create;
+ $this->view->osName = $osName;
+ $this->view->position[] = html::a($this->createLink('host', 'browse'), $this->lang->host->common);
+ $this->view->position[] = $this->lang->host->create;
+
+ $this->view->rooms = $this->loadModel('serverroom')->getPairs();
+ $this->view->accounts = $this->loadModel('account')->getPairs();
+ $this->view->optionMenu = $this->loadModel('tree')->getOptionMenu(0, 'host');
+
+ $this->display();
+ }
+
+ /**
+ * Create host.
+ *
+ * @access public
+ * @return void
+ */
+ public function edit($id, $osName = '')
+ {
+ if($_POST)
+ {
+ $changes = $this->host->update($id);
+ if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
+
+ if($changes)
+ {
+ $actionID = $this->loadModel('action')->create('host', $id, 'Edited');
+ if(!empty($changes)) $this->action->logHistory($actionID, $changes);
+ }
+
+ return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => inlink('browse'), 'closeModal' => true));
+ }
+
+ $this->view->accounts = $this->loadModel('account')->getPairs();
+ $this->view->title = $this->lang->host->edit;
+ $this->view->position[] = html::a($this->createLink('host', 'browse'), $this->lang->host->common);
+ $this->view->position[] = $this->lang->host->edit;
+
+ $this->view->host = $this->host->getById($id);
+ $this->view->osName = $osName ? $osName : $this->view->host->osName;
+ $this->view->accounts = $this->loadModel('account')->getPairs();
+ $this->view->rooms = $this->loadModel('serverroom')->getPairs();
+ $this->view->optionMenu = $this->loadModel('tree')->getOptionMenu(0, 'host');
+
+ $this->display();
+ }
+
+ public function view($id)
+ {
+ $this->view->title = $this->lang->host->view;
+ $this->view->position[] = html::a($this->createLink('host', 'browse'), $this->lang->host->common);
+ $this->view->position[] = $this->lang->host->view;
+
+ $this->view->host = $this->host->getById($id);
+ $this->view->rooms = $this->loadModel('serverroom')->getPairs();
+ $this->view->actions = $this->loadModel('action')->getList('host', $id);
+ $this->view->users = $this->loadModel('user')->getPairs('noletter');
+ $this->view->optionMenu = $this->loadModel('tree')->getOptionMenu(0, 'host');
+ $this->display();
+ }
+
+ public function delete($id)
+ {
+ $this->dao->update(TABLE_HOST)->set('deleted')->eq(1)->where('id')->eq($id)->exec();
+ $this->loadModel('action')->create('host', $id, 'deleted', '', $extra = ACTIONMODEL::CAN_UNDELETED);
+
+ if(dao::isError())
+ {
+ $response['result'] = 'fail';
+ $response['message'] = dao::getError(true);
+ }
+ else
+ {
+ $response['result'] = 'success';
+ $response['message'] = '';
+ $response['load'] = inLink('browse');
+ $response['closeModal'] = true;
+
+ if(helper::isAjaxRequest('modal')) return print(js::execute("loadCurrentPage();$('.modal').removeClass('show')"));
+ }
+ $this->send($response);
+ }
+
+ public function changeStatus($id, $status)
+ {
+ $hostStatus = $status == 'offline' ? 'online' : 'offline';
+ $reasonKey = $hostStatus . 'Reason';
+ $reason = $this->lang->host->{$reasonKey};
+ if($_SERVER['REQUEST_METHOD'] == 'POST')
+ {
+ $postData = fixer::input('post')->get();
+ if(empty($postData->reason))
+ {
+ dao::$errors['reason'][] = sprintf($this->lang->error->notempty, $reason);
+ return $this->send(array('result' => 'fail', 'message' => dao::getError()));
+ }
+
+ $this->host->updateStatus($id, $hostStatus);
+
+ $this->loadModel('action')->create('host', $id, $hostStatus, $postData->reason);
+ return $this->send(array('result' => 'success', 'closeModal' => true, 'load' => true));
+ }
+
+ $this->view->title = $this->lang->host->{$hostStatus};
+ $this->view->reason = $reason;
+ $this->display();
+ }
+
+ public function treemap($type = 'serverroom')
+ {
+ $this->view->title = $this->lang->host->featureBar['browse'][$type];
+ $this->view->position[] = html::a(inlink('browse'), $this->lang->host->common);
+ $this->view->position[] = $this->lang->host->featureBar['browse'][$type];
+
+ /* Build the search form. */
+ $actionURL = $this->createLink('host', 'browse', "browseType=bySearch&queryID=myQueryID");
+ $this->config->host->search['actionURL'] = $actionURL;
+ $this->config->host->search['queryID'] = 0;
+ $this->config->host->search['onMenuBar'] = 'no';
+ $this->config->host->search['params']['serverRoom']['values'] = $this->loadModel('serverroom')->getPairs();
+ $this->config->host->search['params']['group']['values'] = $this->loadModel('tree')->getOptionMenu(0, 'host');
+ $this->loadModel('search')->setSearchParams($this->config->host->search);
+
+ $func = "get{$type}Treemap";
+ $this->view->treemap = $this->host->$func();
+ $this->view->type = $type;
+ $this->display();
+ }
+
+ public function ajaxGetByModule($moduleIdList, $defaultHosts = '')
+ {
+ $hosts = $this->host->getPairs($moduleIdList);
+ die(html::select('hosts[]', $hosts, $defaultHosts, "class='form-control chosen' multiple"));
+ }
+
+ public function ajaxGetByService($serviceID)
+ {
+ $hosts = $serviceID ? $this->host->getPairsByService($serviceID) : $this->host->getPairs();
+ $hosts = array(0 => '') + $hosts;
+ die(html::select('hosts[]', $hosts, '', "class='form-control chosen' multiple"));
+ }
+
+ public function ajaxGetOSVersion($field)
+ {
+ die(html::select('osVersion', $this->lang->host->{$field . 'List'}, '', "class='form-control chosen'"));
+ }
+}
diff --git a/module/host/css/common.ui.css b/module/host/css/common.ui.css
new file mode 100644
index 0000000000..48f4fc2cd8
--- /dev/null
+++ b/module/host/css/common.ui.css
@@ -0,0 +1,2 @@
+#status {flex-direction: row;}
+#hostCreateForm .form-row:last-child {width: 66%;}
\ No newline at end of file
diff --git a/module/host/css/create.css b/module/host/css/create.css
new file mode 100644
index 0000000000..00c8e21f88
--- /dev/null
+++ b/module/host/css/create.css
@@ -0,0 +1,3 @@
+#unit {padding: 0px !important; width:0px; border-left: 0px;}
+.input-group-addon {border: 0px;}
+#unit_chosen a {border-left: 0px; border-radius: 0 2px;}
diff --git a/module/host/css/edit.css b/module/host/css/edit.css
new file mode 100644
index 0000000000..2d2de85465
--- /dev/null
+++ b/module/host/css/edit.css
@@ -0,0 +1,2 @@
+span#unit {padding: 0px !important; width: 0px;}
+#unit {border-left: 0px;}
diff --git a/module/host/css/enew.vi.css b/module/host/css/enew.vi.css
new file mode 100644
index 0000000000..62f3e6f10c
--- /dev/null
+++ b/module/host/css/enew.vi.css
@@ -0,0 +1 @@
+.thWidth{width:120px !important;}
diff --git a/module/host/css/treemap.css b/module/host/css/treemap.css
new file mode 100644
index 0000000000..6d4452981e
--- /dev/null
+++ b/module/host/css/treemap.css
@@ -0,0 +1,3 @@
+#hostsTreemap {white-space: nowrap;}
+.m-host-treemap #subHeader .container {background: white; margin-bottom: 12px;}
+.m-host-treemap #subHeader .container #subNavbar {text-align: center;}
\ No newline at end of file
diff --git a/module/host/css/view.css b/module/host/css/view.css
new file mode 100644
index 0000000000..4ca9101427
--- /dev/null
+++ b/module/host/css/view.css
@@ -0,0 +1 @@
+.outer .main .table tr > th:first-child, .outer .main .table tr > td:first-child { padding-left: 10px; }
diff --git a/module/host/css/view.en.css b/module/host/css/view.en.css
new file mode 100644
index 0000000000..62f3e6f10c
--- /dev/null
+++ b/module/host/css/view.en.css
@@ -0,0 +1 @@
+.thWidth{width:120px !important;}
diff --git a/module/host/css/view.ui.css b/module/host/css/view.ui.css
new file mode 100644
index 0000000000..2512ea827b
--- /dev/null
+++ b/module/host/css/view.ui.css
@@ -0,0 +1 @@
+.host-view-table th {width: 110px !important;}
\ No newline at end of file
diff --git a/module/host/css/view.zh-cn.css b/module/host/css/view.zh-cn.css
new file mode 100644
index 0000000000..6e60376bc6
--- /dev/null
+++ b/module/host/css/view.zh-cn.css
@@ -0,0 +1 @@
+.thWidth{width:90px !important;}
diff --git a/module/host/css/view.zh-tw.css b/module/host/css/view.zh-tw.css
new file mode 100644
index 0000000000..6e60376bc6
--- /dev/null
+++ b/module/host/css/view.zh-tw.css
@@ -0,0 +1 @@
+.thWidth{width:90px !important;}
diff --git a/module/host/js/browse.ui.js b/module/host/js/browse.ui.js
new file mode 100644
index 0000000000..1cd652aa99
--- /dev/null
+++ b/module/host/js/browse.ui.js
@@ -0,0 +1,20 @@
+window.createSortLink = function(col)
+{
+ var sort = col.name + '_asc';
+ if(sort == orderBy) sort = col.name + '_desc';
+
+ return sortLink.replace('{orderBy}', sort);
+}
+
+window.renderCell = function(result, {col, row})
+{
+ if(col.name === 'osVersion')
+ {
+ const{osName, osVersion} = row.data;
+ if(osName) result[0] = {html: hostLang[osName + 'List'][osVersion]};
+
+ return result;
+ }
+
+ return result;
+};
diff --git a/module/host/js/create.js b/module/host/js/create.js
new file mode 100644
index 0000000000..7bdbb6d2ae
--- /dev/null
+++ b/module/host/js/create.js
@@ -0,0 +1,11 @@
+$(document).ready(function(){
+ $('#osName').change(function(){
+ var selectVal = $('#osName').val();
+ $.get(createLink('host', 'ajaxGetOSVersion', 'field=' + selectVal), function(data)
+ {
+ $('select#osVersion').replaceWith(data);
+ $('#osVersion_chosen').remove();
+ $("select#osVersion").chosen();
+ });
+ });
+});
diff --git a/module/host/js/create.ui.js b/module/host/js/create.ui.js
new file mode 100644
index 0000000000..44a291ffdb
--- /dev/null
+++ b/module/host/js/create.ui.js
@@ -0,0 +1,4 @@
+window.osChange = function(e)
+{
+ loadPage($.createLink('host', 'create', 'osName=' + e.target.value), '#osVersion');
+}
\ No newline at end of file
diff --git a/module/host/js/edit.js b/module/host/js/edit.js
new file mode 100644
index 0000000000..51bf58b516
--- /dev/null
+++ b/module/host/js/edit.js
@@ -0,0 +1,20 @@
+$(document).ready(function(){
+ /* Change the operating system. */
+ $('#osName').change(function(){
+ var selectVal = $('#osName').val();
+ $.get(createLink('host', 'ajaxGetOSVersion', 'field=' + selectVal), function(data)
+ {
+ $('select#osVersion').replaceWith(data);
+ $('#osVersion_chosen').remove();
+ $("select#osVersion").chosen();
+ });
+ });
+
+ var width = $("[name='unit']").css('width');
+ width = parseInt(width);
+ if(width < 74)
+ {
+ $("[name='unit']").css({'width': '74px'});
+ }
+});
+
diff --git a/module/host/js/edit.ui.js b/module/host/js/edit.ui.js
new file mode 100644
index 0000000000..894d3eed0d
--- /dev/null
+++ b/module/host/js/edit.ui.js
@@ -0,0 +1,4 @@
+window.osChange = function(e)
+{
+ loadPage($.createLink('host', 'edit', 'id=' + host.id + '&osName=' + e.target.value), '#osVersion');
+}
\ No newline at end of file
diff --git a/module/host/lang/de.php b/module/host/lang/de.php
new file mode 100644
index 0000000000..58fd0aa49e
--- /dev/null
+++ b/module/host/lang/de.php
@@ -0,0 +1,175 @@
+host->common = 'Host';
+$lang->host->browse = 'Host List';
+$lang->host->create = 'Add Host';
+$lang->host->view = 'Host View';
+$lang->host->edit = 'Edit';
+$lang->host->editAction = 'Edit Host';
+$lang->host->delete = 'Delete';
+$lang->host->deleteAction = 'Delete Host';
+$lang->host->treemap = 'Host Topology';
+$lang->host->changeStatus = 'Online/Offline';
+$lang->host->byQuery = 'Search';
+$lang->host->reason = 'Reason';
+
+$lang->host->name = 'Name';
+$lang->host->type = 'Type';
+$lang->host->hardwareType = 'Hardware Type';
+$lang->host->group = 'Host Group';
+$lang->host->admin = 'Admin';
+$lang->host->cabinet = 'Cabinet';
+$lang->host->intranet = 'Intranet IP';
+$lang->host->extranet = 'Extranet IP';
+$lang->host->mac = 'MAC';
+$lang->host->cpuBrand = 'CPU Brand';
+$lang->host->cpuModel = 'CPU Model';
+$lang->host->cpuNumber = 'CPU Number';
+$lang->host->cpuCores = 'CPU Cores';
+$lang->host->cpuRate = 'CPU Rate';
+$lang->host->memory = 'Memory Size';
+$lang->host->serverRoom = 'IDC';
+
+$lang->host->createdBy = 'CreatedBy';
+$lang->host->createdDate = 'CreatedDate';
+$lang->host->editedBy = 'EditedBy';
+$lang->host->editedDate = 'EditedDate';
+$lang->host->all = 'All Hosts';
+
+$lang->host->empty = 'No Host';
+
+$lang->host->groupMaintenance = 'Manage Group';
+
+$lang->host->status = 'Status';
+$lang->host->statusList['online'] = 'Online';
+$lang->host->statusList['busy'] = 'Overloaded';
+$lang->host->statusList['offline'] = 'Offline';
+
+$lang->host->online = 'On';
+$lang->host->busy = 'Overload';
+$lang->host->offline = 'Off';
+
+$lang->host->onlineReason = 'Online Reason';
+$lang->host->offlineReason = 'Offline Reason';
+
+$lang->host->unitList['GB'] = 'GB';
+$lang->host->unitList['TB'] = 'TB';
+
+$lang->host->cpuBrandList[''] = '';
+$lang->host->cpuBrandList['intel'] = 'Intel';
+$lang->host->cpuBrandList['amd'] = 'AMD';
+
+$lang->host->database = 'Database';
+$lang->host->databaseList[''] = '';
+$lang->host->databaseList['mysql55'] = 'MySQL 5.5';
+$lang->host->databaseList['mysql56'] = 'MySQL 5.6';
+$lang->host->databaseList['mysql57'] = 'MySQL 5.7';
+$lang->host->databaseList['mysql80'] = 'MySQL 8.0';
+$lang->host->databaseList['oracle10g'] = 'Oracle 10g';
+$lang->host->databaseList['oracle11g'] = 'Oracle 11g';
+$lang->host->databaseList['mongodb30'] = 'MongoDB 3.0';
+$lang->host->databaseList['mongodb34'] = 'MongoDB 3.4';
+$lang->host->databaseList['postgresql95'] = 'PostgreSQL 9.5';
+$lang->host->databaseList['postgresql96'] = 'PostgreSQL 9.6';
+
+$lang->host->webserver = 'Web Server';
+$lang->host->webserverList[''] = '';
+$lang->host->webserverList['apache2425'] = 'Apache 2.4.25';
+$lang->host->webserverList['apache2426'] = 'Apache 2.4.26';
+$lang->host->webserverList['apache2427'] = 'Apache 2.4.27';
+$lang->host->webserverList['nginx181'] = 'Nginx 1.8.1';
+$lang->host->webserverList['nginx1102'] = 'Nginx 1.10.2';
+$lang->host->webserverList['nginx1115'] = 'Nginx 1.11.5';
+$lang->host->webserverList['iis6'] = 'IIS 6';
+$lang->host->webserverList['iis7'] = 'IIS 7';
+$lang->host->webserverList['iis8'] = 'IIS 8';
+$lang->host->webserverList['iis10'] = 'IIS 10';
+
+$lang->host->language = 'Language';
+$lang->host->languageList[''] = '';
+$lang->host->languageList['php56'] = 'PHP 5.6';
+$lang->host->languageList['php70'] = 'PHP 7.0';
+$lang->host->languageList['java7'] = 'JAVA 7';
+$lang->host->languageList['java8'] = 'JAVA 8';
+$lang->host->languageList['c#3'] = 'C# 3.0';
+$lang->host->languageList['c#4'] = 'C# 4.0';
+
+$lang->host->featureBar['browse']['all'] = $lang->host->all;
+$lang->host->featureBar['browse']['serverroom'] = 'Physical Topology';
+$lang->host->featureBar['browse']['group'] = 'Logical Topology';
+
+$lang->host->serverModel = 'Server Model';
+$lang->host->hostType = 'Host Type';
+$lang->host->hostTypeList['physical'] = 'Physical';
+$lang->host->hostTypeList['virtual'] = 'Virtual';
+
+$lang->host->osVersion = 'OS Version';
+$lang->host->osName = 'OS Name';
+$lang->host->zap = 'Agent Port';
+$lang->host->instanceNum = 'Max instances';
+$lang->host->pri = 'Priority';
+$lang->host->tags = 'Platform Label';
+$lang->host->provider = 'Priority';
+$lang->host->bridgeID = 'Virtual Bridge';
+$lang->host->osNameList['linux'] = 'Linux';
+$lang->host->osNameList['windows'] = 'Microsoft Windows';
+$lang->host->osNameList['solaris'] = 'Solaris';
+$lang->host->osNameList['netware'] = 'Novell NetWare';
+$lang->host->osNameList['esx'] = 'VMware ESX';
+$lang->host->osNameList['other'] = 'Others';
+
+$lang->host->tagsList['vm'] = 'VM';
+$lang->host->tagsList['native'] = 'Native';
+$lang->host->providerList['native'] = 'Native';
+
+$lang->host->linux = 'Linux';
+$lang->host->windows = 'Microsoft Windows';
+$lang->host->solaris = 'Solaris';
+$lang->host->netware = 'Novell NetWare';
+$lang->host->esx = 'VMware ESX';
+$lang->host->other = 'Others';
+
+$lang->host->linuxList[''] = '';
+$lang->host->linuxList['centos65'] = 'CentOS 6.5';
+$lang->host->linuxList['centos66'] = 'CentOS 6.6';
+$lang->host->linuxList['centos67'] = 'CentOS 6.7';
+$lang->host->linuxList['centos70'] = 'CentOS 7.0';
+$lang->host->linuxList['centos71'] = 'CentOS 7.1';
+
+$lang->host->windowsList[''] = '';
+$lang->host->windowsList['win10-pro'] = 'Windows 10 pro';
+$lang->host->windowsList['winserver08x64'] = 'Windows Server2008 x64';
+$lang->host->windowsList['winserver12'] = 'Windows Server2012';
+$lang->host->windowsList['winserver16'] = 'Windows Server2016';
+
+$lang->host->solarisList[''] = '';
+$lang->host->solarisList['solaris10'] = 'Solaris 10';
+$lang->host->solarisList['solaris10x64'] = 'Solaris 10 x64';
+$lang->host->solarisList['solaris11'] = 'Solaris 11';
+
+$lang->host->netwareList[''] = '';
+$lang->host->netwareList['netware5'] = 'NetWare 5';
+$lang->host->netwareList['netware6'] = 'NetWare 6';
+
+$lang->host->esxList[''] = '';
+$lang->host->esxList['esx'] = 'VMware ESX/ESXi 4';
+$lang->host->esxList['esx5'] = 'VMware ESXi 5';
+$lang->host->esxList['esx6'] = 'VMware ESXi 6';
+
+$lang->host->otherList[''] = '';
+$lang->host->otherList['freebsd'] = 'FreeBSD';
+$lang->host->otherList['freebsdx64'] = 'FreeBSD X64';
+
+$lang->host->diskSize = 'Disk Size';
+$lang->host->diskType = 'Disk Type';
+$lang->host->diskTypeList['hdd'] = 'HDD';
+$lang->host->diskTypeList['ssd'] = 'SSD';
+
+$lang->host->confirmDelete = 'Do you want to delete this host?';
+
+$lang->host->notice = new stdclass();
+$lang->host->notice->memory = 'Memory size should be numbers!';
+$lang->host->notice->diskSize = 'Disk size should be numbers!';
+$lang->host->notice->cpuNumber = 'CPU number should be numbers!';
+$lang->host->notice->cpuCores = 'CPU cores should be numbers!';
+$lang->host->notice->int = '『%s』should be a positive integer!';
+$lang->host->notice->ip = '『%s』incorrect format!';
diff --git a/module/host/lang/en.php b/module/host/lang/en.php
new file mode 100644
index 0000000000..58fd0aa49e
--- /dev/null
+++ b/module/host/lang/en.php
@@ -0,0 +1,175 @@
+host->common = 'Host';
+$lang->host->browse = 'Host List';
+$lang->host->create = 'Add Host';
+$lang->host->view = 'Host View';
+$lang->host->edit = 'Edit';
+$lang->host->editAction = 'Edit Host';
+$lang->host->delete = 'Delete';
+$lang->host->deleteAction = 'Delete Host';
+$lang->host->treemap = 'Host Topology';
+$lang->host->changeStatus = 'Online/Offline';
+$lang->host->byQuery = 'Search';
+$lang->host->reason = 'Reason';
+
+$lang->host->name = 'Name';
+$lang->host->type = 'Type';
+$lang->host->hardwareType = 'Hardware Type';
+$lang->host->group = 'Host Group';
+$lang->host->admin = 'Admin';
+$lang->host->cabinet = 'Cabinet';
+$lang->host->intranet = 'Intranet IP';
+$lang->host->extranet = 'Extranet IP';
+$lang->host->mac = 'MAC';
+$lang->host->cpuBrand = 'CPU Brand';
+$lang->host->cpuModel = 'CPU Model';
+$lang->host->cpuNumber = 'CPU Number';
+$lang->host->cpuCores = 'CPU Cores';
+$lang->host->cpuRate = 'CPU Rate';
+$lang->host->memory = 'Memory Size';
+$lang->host->serverRoom = 'IDC';
+
+$lang->host->createdBy = 'CreatedBy';
+$lang->host->createdDate = 'CreatedDate';
+$lang->host->editedBy = 'EditedBy';
+$lang->host->editedDate = 'EditedDate';
+$lang->host->all = 'All Hosts';
+
+$lang->host->empty = 'No Host';
+
+$lang->host->groupMaintenance = 'Manage Group';
+
+$lang->host->status = 'Status';
+$lang->host->statusList['online'] = 'Online';
+$lang->host->statusList['busy'] = 'Overloaded';
+$lang->host->statusList['offline'] = 'Offline';
+
+$lang->host->online = 'On';
+$lang->host->busy = 'Overload';
+$lang->host->offline = 'Off';
+
+$lang->host->onlineReason = 'Online Reason';
+$lang->host->offlineReason = 'Offline Reason';
+
+$lang->host->unitList['GB'] = 'GB';
+$lang->host->unitList['TB'] = 'TB';
+
+$lang->host->cpuBrandList[''] = '';
+$lang->host->cpuBrandList['intel'] = 'Intel';
+$lang->host->cpuBrandList['amd'] = 'AMD';
+
+$lang->host->database = 'Database';
+$lang->host->databaseList[''] = '';
+$lang->host->databaseList['mysql55'] = 'MySQL 5.5';
+$lang->host->databaseList['mysql56'] = 'MySQL 5.6';
+$lang->host->databaseList['mysql57'] = 'MySQL 5.7';
+$lang->host->databaseList['mysql80'] = 'MySQL 8.0';
+$lang->host->databaseList['oracle10g'] = 'Oracle 10g';
+$lang->host->databaseList['oracle11g'] = 'Oracle 11g';
+$lang->host->databaseList['mongodb30'] = 'MongoDB 3.0';
+$lang->host->databaseList['mongodb34'] = 'MongoDB 3.4';
+$lang->host->databaseList['postgresql95'] = 'PostgreSQL 9.5';
+$lang->host->databaseList['postgresql96'] = 'PostgreSQL 9.6';
+
+$lang->host->webserver = 'Web Server';
+$lang->host->webserverList[''] = '';
+$lang->host->webserverList['apache2425'] = 'Apache 2.4.25';
+$lang->host->webserverList['apache2426'] = 'Apache 2.4.26';
+$lang->host->webserverList['apache2427'] = 'Apache 2.4.27';
+$lang->host->webserverList['nginx181'] = 'Nginx 1.8.1';
+$lang->host->webserverList['nginx1102'] = 'Nginx 1.10.2';
+$lang->host->webserverList['nginx1115'] = 'Nginx 1.11.5';
+$lang->host->webserverList['iis6'] = 'IIS 6';
+$lang->host->webserverList['iis7'] = 'IIS 7';
+$lang->host->webserverList['iis8'] = 'IIS 8';
+$lang->host->webserverList['iis10'] = 'IIS 10';
+
+$lang->host->language = 'Language';
+$lang->host->languageList[''] = '';
+$lang->host->languageList['php56'] = 'PHP 5.6';
+$lang->host->languageList['php70'] = 'PHP 7.0';
+$lang->host->languageList['java7'] = 'JAVA 7';
+$lang->host->languageList['java8'] = 'JAVA 8';
+$lang->host->languageList['c#3'] = 'C# 3.0';
+$lang->host->languageList['c#4'] = 'C# 4.0';
+
+$lang->host->featureBar['browse']['all'] = $lang->host->all;
+$lang->host->featureBar['browse']['serverroom'] = 'Physical Topology';
+$lang->host->featureBar['browse']['group'] = 'Logical Topology';
+
+$lang->host->serverModel = 'Server Model';
+$lang->host->hostType = 'Host Type';
+$lang->host->hostTypeList['physical'] = 'Physical';
+$lang->host->hostTypeList['virtual'] = 'Virtual';
+
+$lang->host->osVersion = 'OS Version';
+$lang->host->osName = 'OS Name';
+$lang->host->zap = 'Agent Port';
+$lang->host->instanceNum = 'Max instances';
+$lang->host->pri = 'Priority';
+$lang->host->tags = 'Platform Label';
+$lang->host->provider = 'Priority';
+$lang->host->bridgeID = 'Virtual Bridge';
+$lang->host->osNameList['linux'] = 'Linux';
+$lang->host->osNameList['windows'] = 'Microsoft Windows';
+$lang->host->osNameList['solaris'] = 'Solaris';
+$lang->host->osNameList['netware'] = 'Novell NetWare';
+$lang->host->osNameList['esx'] = 'VMware ESX';
+$lang->host->osNameList['other'] = 'Others';
+
+$lang->host->tagsList['vm'] = 'VM';
+$lang->host->tagsList['native'] = 'Native';
+$lang->host->providerList['native'] = 'Native';
+
+$lang->host->linux = 'Linux';
+$lang->host->windows = 'Microsoft Windows';
+$lang->host->solaris = 'Solaris';
+$lang->host->netware = 'Novell NetWare';
+$lang->host->esx = 'VMware ESX';
+$lang->host->other = 'Others';
+
+$lang->host->linuxList[''] = '';
+$lang->host->linuxList['centos65'] = 'CentOS 6.5';
+$lang->host->linuxList['centos66'] = 'CentOS 6.6';
+$lang->host->linuxList['centos67'] = 'CentOS 6.7';
+$lang->host->linuxList['centos70'] = 'CentOS 7.0';
+$lang->host->linuxList['centos71'] = 'CentOS 7.1';
+
+$lang->host->windowsList[''] = '';
+$lang->host->windowsList['win10-pro'] = 'Windows 10 pro';
+$lang->host->windowsList['winserver08x64'] = 'Windows Server2008 x64';
+$lang->host->windowsList['winserver12'] = 'Windows Server2012';
+$lang->host->windowsList['winserver16'] = 'Windows Server2016';
+
+$lang->host->solarisList[''] = '';
+$lang->host->solarisList['solaris10'] = 'Solaris 10';
+$lang->host->solarisList['solaris10x64'] = 'Solaris 10 x64';
+$lang->host->solarisList['solaris11'] = 'Solaris 11';
+
+$lang->host->netwareList[''] = '';
+$lang->host->netwareList['netware5'] = 'NetWare 5';
+$lang->host->netwareList['netware6'] = 'NetWare 6';
+
+$lang->host->esxList[''] = '';
+$lang->host->esxList['esx'] = 'VMware ESX/ESXi 4';
+$lang->host->esxList['esx5'] = 'VMware ESXi 5';
+$lang->host->esxList['esx6'] = 'VMware ESXi 6';
+
+$lang->host->otherList[''] = '';
+$lang->host->otherList['freebsd'] = 'FreeBSD';
+$lang->host->otherList['freebsdx64'] = 'FreeBSD X64';
+
+$lang->host->diskSize = 'Disk Size';
+$lang->host->diskType = 'Disk Type';
+$lang->host->diskTypeList['hdd'] = 'HDD';
+$lang->host->diskTypeList['ssd'] = 'SSD';
+
+$lang->host->confirmDelete = 'Do you want to delete this host?';
+
+$lang->host->notice = new stdclass();
+$lang->host->notice->memory = 'Memory size should be numbers!';
+$lang->host->notice->diskSize = 'Disk size should be numbers!';
+$lang->host->notice->cpuNumber = 'CPU number should be numbers!';
+$lang->host->notice->cpuCores = 'CPU cores should be numbers!';
+$lang->host->notice->int = '『%s』should be a positive integer!';
+$lang->host->notice->ip = '『%s』incorrect format!';
diff --git a/module/host/lang/fr.php b/module/host/lang/fr.php
new file mode 100644
index 0000000000..30216996f3
--- /dev/null
+++ b/module/host/lang/fr.php
@@ -0,0 +1,175 @@
+host->common = 'Serveurs';
+$lang->host->browse = 'Liste Serveurs';
+$lang->host->create = 'Ajouter Serveur';
+$lang->host->view = 'Détail Serveur';
+$lang->host->edit = 'Editer';
+$lang->host->editAction = 'Editer Serveur';
+$lang->host->delete = 'Supprimer';
+$lang->host->deleteAction = 'Supprimer Serveur';
+$lang->host->treemap = 'Topologie Serveur';
+$lang->host->changeStatus = 'Online/Offline';
+$lang->host->byQuery = 'Recherche';
+$lang->host->reason = 'Raison';
+
+$lang->host->name = 'Nom';
+$lang->host->type = 'Type';
+$lang->host->hardwareType = 'Type Hardware';
+$lang->host->group = 'Groupe Serveur';
+$lang->host->admin = 'Admin';
+$lang->host->cabinet = 'Local';
+$lang->host->intranet = 'IP Privée';
+$lang->host->extranet = 'Extranet IP';
+$lang->host->mac = 'MAC';
+$lang->host->cpuBrand = 'CPU Marque';
+$lang->host->cpuModel = 'CPU Modèle';
+$lang->host->cpuNumber = 'CPU Numéro';
+$lang->host->cpuCores = 'CPU Cores';
+$lang->host->cpuRate = 'CPU Freq.';
+$lang->host->memory = 'Capacité Mémoire';
+$lang->host->serverRoom = 'IDC';
+
+$lang->host->createdBy = 'Créé par';
+$lang->host->createdDate = 'Créé le';
+$lang->host->editedBy = 'Edité par';
+$lang->host->editedDate = 'Edité le';
+$lang->host->all = 'Tous Serveurs';
+
+$lang->host->empty = 'No Host';
+
+$lang->host->groupMaintenance = 'Gérer Groupes';
+
+$lang->host->status = 'Statut';
+$lang->host->statusList['online'] = 'Online';
+$lang->host->statusList['busy'] = 'Overloaded';
+$lang->host->statusList['offline'] = 'Offline';
+
+$lang->host->online = 'On';
+$lang->host->busy = 'Overload';
+$lang->host->offline = 'Off';
+
+$lang->host->onlineReason = 'Raison Online';
+$lang->host->offlineReason = 'Raison Offline';
+
+$lang->host->unitList['GB'] = 'GB';
+$lang->host->unitList['TB'] = 'TB';
+
+$lang->host->cpuBrandList[''] = '';
+$lang->host->cpuBrandList['intel'] = 'Intel';
+$lang->host->cpuBrandList['amd'] = 'AMD';
+
+$lang->host->database = 'Database';
+$lang->host->databaseList[''] = '';
+$lang->host->databaseList['mysql55'] = 'MySQL 5.5';
+$lang->host->databaseList['mysql56'] = 'MySQL 5.6';
+$lang->host->databaseList['mysql57'] = 'MySQL 5.7';
+$lang->host->databaseList['mysql80'] = 'MySQL 8.0';
+$lang->host->databaseList['oracle10g'] = 'Oracle 10g';
+$lang->host->databaseList['oracle11g'] = 'Oracle 11g';
+$lang->host->databaseList['mongodb30'] = 'MongoDB 3.0';
+$lang->host->databaseList['mongodb34'] = 'MongoDB 3.4';
+$lang->host->databaseList['postgresql95'] = 'PostgreSQL 9.5';
+$lang->host->databaseList['postgresql96'] = 'PostgreSQL 9.6';
+
+$lang->host->webserver = 'Serveur Web';
+$lang->host->webserverList[''] = '';
+$lang->host->webserverList['apache2425'] = 'Apache 2.4.25';
+$lang->host->webserverList['apache2426'] = 'Apache 2.4.26';
+$lang->host->webserverList['apache2427'] = 'Apache 2.4.27';
+$lang->host->webserverList['nginx181'] = 'Nginx 1.8.1';
+$lang->host->webserverList['nginx1102'] = 'Nginx 1.10.2';
+$lang->host->webserverList['nginx1115'] = 'Nginx 1.11.5';
+$lang->host->webserverList['iis6'] = 'IIS 6';
+$lang->host->webserverList['iis7'] = 'IIS 7';
+$lang->host->webserverList['iis8'] = 'IIS 8';
+$lang->host->webserverList['iis10'] = 'IIS 10';
+
+$lang->host->language = 'Langage';
+$lang->host->languageList[''] = '';
+$lang->host->languageList['php56'] = 'PHP 5.6';
+$lang->host->languageList['php70'] = 'PHP 7.0';
+$lang->host->languageList['java7'] = 'JAVA 7';
+$lang->host->languageList['java8'] = 'JAVA 8';
+$lang->host->languageList['c#3'] = 'C# 3.0';
+$lang->host->languageList['c#4'] = 'C# 4.0';
+
+$lang->host->featureBar['browse']['all'] = $lang->host->all;
+$lang->host->featureBar['browse']['serverroom'] = 'Physical Topology';
+$lang->host->featureBar['browse']['group'] = 'Logical Topology';
+
+$lang->host->serverModel = 'Modèle Serveur';
+$lang->host->hostType = 'Type Serveur';
+$lang->host->hostTypeList['physical'] = 'Physique';
+$lang->host->hostTypeList['virtual'] = 'Virtuel';
+
+$lang->host->osVersion = 'OS Version';
+$lang->host->osName = 'OS Name';
+$lang->host->zap = 'Agent Port';
+$lang->host->instanceNum = 'Max instances';
+$lang->host->pri = 'Priority';
+$lang->host->tags = 'Platform Label';
+$lang->host->provider = 'Priority';
+$lang->host->bridgeID = 'Virtual Bridge';
+$lang->host->osNameList['linux'] = 'Linux';
+$lang->host->osNameList['windows'] = 'Microsoft Windows';
+$lang->host->osNameList['solaris'] = 'Solaris';
+$lang->host->osNameList['netware'] = 'Novell NetWare';
+$lang->host->osNameList['esx'] = 'VMware ESX';
+$lang->host->osNameList['other'] = 'Autres';
+
+$lang->host->tagsList['vm'] = 'VM';
+$lang->host->tagsList['native'] = 'Native';
+$lang->host->providerList['native'] = 'Native';
+
+$lang->host->linux = 'Linux';
+$lang->host->windows = 'Microsoft Windows';
+$lang->host->solaris = 'Solaris';
+$lang->host->netware = 'Novell NetWare';
+$lang->host->esx = 'VMware ESX';
+$lang->host->other = 'Autres';
+
+$lang->host->linuxList[''] = '';
+$lang->host->linuxList['centos65'] = 'CentOS 6.5';
+$lang->host->linuxList['centos66'] = 'CentOS 6.6';
+$lang->host->linuxList['centos67'] = 'CentOS 6.7';
+$lang->host->linuxList['centos70'] = 'CentOS 7.0';
+$lang->host->linuxList['centos71'] = 'CentOS 7.1';
+
+$lang->host->windowsList[''] = '';
+$lang->host->windowsList['win10-pro'] = 'Windows 10 pro';
+$lang->host->windowsList['winserver08x64'] = 'Windows Server2008 x64';
+$lang->host->windowsList['winserver12'] = 'Windows Server2012';
+$lang->host->windowsList['winserver16'] = 'Windows Server2016';
+
+$lang->host->solarisList[''] = '';
+$lang->host->solarisList['solaris10'] = 'Solaris 10';
+$lang->host->solarisList['solaris10x64'] = 'Solaris 10 x64';
+$lang->host->solarisList['solaris11'] = 'Solaris 11';
+
+$lang->host->netwareList[''] = '';
+$lang->host->netwareList['netware5'] = 'NetWare 5';
+$lang->host->netwareList['netware6'] = 'NetWare 6';
+
+$lang->host->esxList[''] = '';
+$lang->host->esxList['esx'] = 'VMware ESX/ESXi 4';
+$lang->host->esxList['esx5'] = 'VMware ESXi 5';
+$lang->host->esxList['esx6'] = 'VMware ESXi 6';
+
+$lang->host->otherList[''] = '';
+$lang->host->otherList['freebsd'] = 'FreeBSD';
+$lang->host->otherList['freebsdx64'] = 'FreeBSD X64';
+
+$lang->host->diskSize = 'Taille Disque';
+$lang->host->diskType = 'Type Disque';
+$lang->host->diskTypeList['hdd'] = 'HDD';
+$lang->host->diskTypeList['ssd'] = 'SSD';
+
+$lang->host->confirmDelete = 'Voulez-vous supprimer ce serveur ?';
+
+$lang->host->notice = new stdclass();
+$lang->host->notice->memory = 'La capacité mémoire doit être numérique !';
+$lang->host->notice->diskSize = 'La capacité du disque doit être numérique !';
+$lang->host->notice->cpuNumber = 'CPU number doit être numérique !';
+$lang->host->notice->cpuCores = 'CPU cores doit être numérique !';
+$lang->host->notice->int = '『%s』should be a positive integer!';
+$lang->host->notice->ip = '『%s』incorrect format!';
diff --git a/module/host/lang/vi.php b/module/host/lang/vi.php
new file mode 100644
index 0000000000..c651ab195b
--- /dev/null
+++ b/module/host/lang/vi.php
@@ -0,0 +1,167 @@
+host->common = 'Host';
+$lang->host->browse = 'Danh sách Host';
+$lang->host->create = 'Thêm Host';
+$lang->host->view = 'Xem Host';
+$lang->host->edit = 'Sửa';
+$lang->host->editAction = 'Sửa Host';
+$lang->host->delete = 'Xóa';
+$lang->host->deleteAction = 'Xóa Host';
+$lang->host->treemap = 'Cấu trúc Host';
+$lang->host->changeStatus = 'Online/Offline';
+$lang->host->byQuery = 'Tìm kiếm';
+$lang->host->reason = 'Lý do';
+
+$lang->host->name = 'Tên';
+$lang->host->type = 'Loại';
+$lang->host->hardwareType = 'Hardware loại';
+
+$lang->host->group = 'Host Group';
+$lang->host->cabinet = 'Cabinet';
+$lang->host->intranet = 'Riêng tư IP';
+$lang->host->extranet = 'Extranet IP';
+$lang->host->mac = 'MAC';
+$lang->host->cpuBrand = 'CPU Brand';
+$lang->host->cpuModel = 'CPU Model';
+$lang->host->cpuNumber = 'CPU Number';
+$lang->host->cpuCores = 'CPU Cores';
+$lang->host->cpuRate = 'CPU Rate';
+$lang->host->memory = 'Memory Size';
+$lang->host->serverRoom = 'IDC';
+
+$lang->host->createdBy = 'Người tạo';
+$lang->host->createdDate = 'Ngày tạo';
+$lang->host->editedBy = 'Người sửa';
+$lang->host->editedDate = 'Ngày sửa';
+$lang->host->all = 'Tất cả Hosts';
+
+$lang->host->groupMaintenance = 'Quản lý Group';
+
+$lang->host->status = 'Tình trạng';
+$lang->host->statusList['online'] = 'Online';
+$lang->host->statusList['offline'] = 'Offline';
+
+$lang->host->online = 'On';
+$lang->host->offline = 'Off';
+
+$lang->host->onlineReason = 'Lý do Online';
+$lang->host->offlineReason = 'Lý do Offline';
+
+$lang->host->unitList['GB'] = 'GB';
+$lang->host->unitList['TB'] = 'TB';
+
+$lang->host->cpuBrandList[''] = '';
+$lang->host->cpuBrandList['intel'] = 'Intel';
+$lang->host->cpuBrandList['amd'] = 'AMD';
+
+$lang->host->database = 'CSDL';
+$lang->host->databaseList[''] = '';
+$lang->host->databaseList['mysql55'] = 'MySQL 5.5';
+$lang->host->databaseList['mysql56'] = 'MySQL 5.6';
+$lang->host->databaseList['mysql57'] = 'MySQL 5.7';
+$lang->host->databaseList['mysql80'] = 'MySQL 8.0';
+$lang->host->databaseList['oracle10g'] = 'Oracle 10g';
+$lang->host->databaseList['oracle11g'] = 'Oracle 11g';
+$lang->host->databaseList['mongodb30'] = 'MongoDB 3.0';
+$lang->host->databaseList['mongodb34'] = 'MongoDB 3.4';
+$lang->host->databaseList['postgresql95'] = 'PostgreSQL 9.5';
+$lang->host->databaseList['postgresql96'] = 'PostgreSQL 9.6';
+
+$lang->host->webserver = 'Web Server';
+$lang->host->webserverList[''] = '';
+$lang->host->webserverList['apache2425'] = 'Apache 2.4.25';
+$lang->host->webserverList['apache2426'] = 'Apache 2.4.26';
+$lang->host->webserverList['apache2427'] = 'Apache 2.4.27';
+$lang->host->webserverList['nginx181'] = 'Nginx 1.8.1';
+$lang->host->webserverList['nginx1102'] = 'Nginx 1.10.2';
+$lang->host->webserverList['nginx1115'] = 'Nginx 1.11.5';
+$lang->host->webserverList['iis6'] = 'IIS 6';
+$lang->host->webserverList['iis7'] = 'IIS 7';
+$lang->host->webserverList['iis8'] = 'IIS 8';
+$lang->host->webserverList['iis10'] = 'IIS 10';
+
+$lang->host->language = 'Ngôn ngữ';
+$lang->host->languageList[''] = '';
+$lang->host->languageList['php56'] = 'PHP 5.6';
+$lang->host->languageList['php70'] = 'PHP 7.0';
+$lang->host->languageList['php72'] = 'PHP 7.2';
+$lang->host->languageList['php73'] = 'PHP 7.3';
+$lang->host->languageList['php74'] = 'PHP 7.4';
+$lang->host->languageList['java7'] = 'JAVA 7';
+$lang->host->languageList['java8'] = 'JAVA 8';
+$lang->host->languageList['c#3'] = 'C# 3.0';
+$lang->host->languageList['c#4'] = 'C# 4.0';
+
+$lang->host->featureBar['browse']['all'] = $lang->host->all;
+$lang->host->featureBar['browse']['serverroom'] = 'Cấu trú c vật lý';
+$lang->host->featureBar['browse']['group'] = 'Cấu trú c Logical';
+
+$lang->host->serverModel = 'Server Model';
+$lang->host->hostType = 'Host loại';
+$lang->host->hostTypeList['physical'] = 'Vật lý';
+$lang->host->hostTypeList['virtual'] = 'Ảo';
+
+$lang->host->osVersion = 'OS Version';
+$lang->host->osName = 'OS tên';
+$lang->host->zap = 'Agent Port';
+$lang->host->instanceNum = 'Max instances';
+$lang->host->pri = 'Priority';
+$lang->host->tags = 'Platform Label';
+$lang->host->provider = 'Priority';
+$lang->host->bridgeID = 'Virtual Bridge';
+$lang->host->osNameList['linux'] = 'Linux';
+$lang->host->osNameList['windows'] = 'Microsoft Windows';
+$lang->host->osNameList['solaris'] = 'Solaris';
+$lang->host->osNameList['netware'] = 'Novell NetWare';
+$lang->host->osNameList['esx'] = 'VMware ESX';
+$lang->host->osNameList['other'] = 'Khác';
+
+$lang->host->linux = 'Linux';
+$lang->host->windows = 'Microsoft Windows';
+$lang->host->solaris = 'Solaris';
+$lang->host->netware = 'Novell NetWare';
+$lang->host->esx = 'VMware ESX';
+$lang->host->other = 'Khác';
+
+$lang->host->linuxList[''] = '';
+$lang->host->linuxList['centos65'] = 'CentOS 6.5';
+$lang->host->linuxList['centos66'] = 'CentOS 6.6';
+$lang->host->linuxList['centos67'] = 'CentOS 6.7';
+$lang->host->linuxList['centos70'] = 'CentOS 7.0';
+$lang->host->linuxList['centos71'] = 'CentOS 7.1';
+
+$lang->host->windowsList[''] = '';
+$lang->host->windowsList['winserver08x64'] = 'Windows Server2008 x64';
+$lang->host->windowsList['winserver12'] = 'Windows Server2012';
+$lang->host->windowsList['winserver16'] = 'Windows Server2016';
+
+$lang->host->solarisList[''] = '';
+$lang->host->solarisList['solaris10'] = 'Solaris 10';
+$lang->host->solarisList['solaris10x64'] = 'Solaris 10 x64';
+$lang->host->solarisList['solaris11'] = 'Solaris 11';
+
+$lang->host->netwareList[''] = '';
+$lang->host->netwareList['netware5'] = 'NetWare 5';
+$lang->host->netwareList['netware6'] = 'NetWare 6';
+
+$lang->host->esxList[''] = '';
+$lang->host->esxList['esx'] = 'VMware ESX/ESXi 4';
+$lang->host->esxList['esx5'] = 'VMware ESXi 5';
+$lang->host->esxList['esx6'] = 'VMware ESXi 6';
+
+$lang->host->otherList[''] = '';
+$lang->host->otherList['freebsd'] = 'FreeBSD';
+$lang->host->otherList['freebsdx64'] = 'FreeBSD X64';
+
+$lang->host->diskSize = 'Disk Size';
+$lang->host->diskType = 'Disk loại';
+$lang->host->diskTypeList['hdd'] = 'HDD';
+$lang->host->diskTypeList['ssd'] = 'SSD';
+
+$lang->host->confirmDelete = 'Bạn có muốn xóa host này?';
+
+$lang->host->notice = new stdclass();
+$lang->host->notice->memory = 'Kích thước bộ nhớ phải là số!';
+$lang->host->notice->diskSize = 'Kích thước ổ đĩa phải là số!';
+$lang->host->notice->cpuNumber = 'Số CPU phải là số!';
+$lang->host->notice->cpuCores = 'Số lõi CPU phải là số!';
diff --git a/module/host/lang/zh-cn.php b/module/host/lang/zh-cn.php
new file mode 100644
index 0000000000..d55d9bee85
--- /dev/null
+++ b/module/host/lang/zh-cn.php
@@ -0,0 +1,176 @@
+host->common = '主机';
+$lang->host->browse = '主机列表';
+$lang->host->create = '添加主机';
+$lang->host->view = '主机详情';
+$lang->host->edit = '编辑';
+$lang->host->editAction = '编辑主机';
+$lang->host->delete = '删除';
+$lang->host->deleteAction = '删除主机';
+$lang->host->treemap = '主机拓扑图';
+$lang->host->changeStatus = '上架/下架';
+$lang->host->byQuery = '搜索';
+$lang->host->reason = '原因';
+
+$lang->host->name = '名称';
+$lang->host->type = '类型';
+$lang->host->hardwareType = '硬件类型';
+$lang->host->group = '主机分组';
+$lang->host->admin = '管理账号';
+$lang->host->cabinet = '机柜';
+$lang->host->intranet = '内网IP';
+$lang->host->extranet = '外网IP';
+$lang->host->mac = 'MAC';
+$lang->host->cpuBrand = 'CPU品牌';
+$lang->host->cpuModel = 'CPU型号';
+$lang->host->cpuNumber = 'CPU数量';
+$lang->host->cpuCores = '单CPU核心数';
+$lang->host->cpuRate = 'CPU频率';
+$lang->host->memory = '内存大小';
+$lang->host->serverRoom = '机房';
+
+$lang->host->createdBy = '由谁创建';
+$lang->host->createdDate = '创建时间';
+$lang->host->editedBy = '由谁编辑';
+$lang->host->editedDate = '编辑时间';
+$lang->host->all = '全部主机';
+
+$lang->host->empty = '暂时没有主机';
+
+$lang->host->groupMaintenance = '分组维护';
+
+$lang->host->status = '状态';
+$lang->host->statusList['online'] = '已上架';
+$lang->host->statusList['busy'] = '已超载';
+$lang->host->statusList['offline'] = '已下架';
+
+$lang->host->online = '上架';
+$lang->host->busy = '超载';
+$lang->host->offline = '下架';
+
+$lang->host->onlineReason = '上架原因';
+$lang->host->offlineReason = '下架原因';
+
+$lang->host->unitList['GB'] = 'GB';
+$lang->host->unitList['TB'] = 'TB';
+
+$lang->host->cpuBrandList[''] = '';
+$lang->host->cpuBrandList['intel'] = '英特尔';
+$lang->host->cpuBrandList['amd'] = 'AMD';
+
+$lang->host->database = '数据库';
+$lang->host->databaseList[''] = '';
+$lang->host->databaseList['mysql55'] = 'MySQL 5.5';
+$lang->host->databaseList['mysql56'] = 'MySQL 5.6';
+$lang->host->databaseList['mysql57'] = 'MySQL 5.7';
+$lang->host->databaseList['mysql80'] = 'MySQL 8.0';
+$lang->host->databaseList['oracle10g'] = 'Oracle 10g';
+$lang->host->databaseList['oracle11g'] = 'Oracle 11g';
+$lang->host->databaseList['mongodb30'] = 'MongoDB 3.0';
+$lang->host->databaseList['mongodb34'] = 'MongoDB 3.4';
+$lang->host->databaseList['postgresql95'] = 'PostgreSQL 9.5';
+$lang->host->databaseList['postgresql96'] = 'PostgreSQL 9.6';
+
+$lang->host->webserver = 'Web Server';
+$lang->host->webserverList[''] = '';
+$lang->host->webserverList['apache2425'] = 'Apache 2.4.25';
+$lang->host->webserverList['apache2426'] = 'Apache 2.4.26';
+$lang->host->webserverList['apache2427'] = 'Apache 2.4.27';
+$lang->host->webserverList['nginx181'] = 'Nginx 1.8.1';
+$lang->host->webserverList['nginx1102'] = 'Nginx 1.10.2';
+$lang->host->webserverList['nginx1115'] = 'Nginx 1.11.5';
+$lang->host->webserverList['iis6'] = 'IIS 6';
+$lang->host->webserverList['iis7'] = 'IIS 7';
+$lang->host->webserverList['iis8'] = 'IIS 8';
+$lang->host->webserverList['iis10'] = 'IIS 10';
+
+$lang->host->language = '语言环境';
+$lang->host->languageList[''] = '';
+$lang->host->languageList['php56'] = 'PHP 5.6';
+$lang->host->languageList['php70'] = 'PHP 7.0';
+$lang->host->languageList['java7'] = 'JAVA 7';
+$lang->host->languageList['java8'] = 'JAVA 8';
+$lang->host->languageList['c#3'] = 'C# 3.0';
+$lang->host->languageList['c#4'] = 'C# 4.0';
+
+$lang->host->featureBar['browse']['all'] = $lang->host->all;
+$lang->host->featureBar['browse']['serverroom'] = '物理拓扑图';
+$lang->host->featureBar['browse']['group'] = '分组拓扑图';
+
+$lang->host->serverModel = '服务器型号';
+$lang->host->hostType = '主机类型';
+$lang->host->hostTypeList['physical'] = '实体主机';
+$lang->host->hostTypeList['virtual'] = '虚拟主机';
+
+$lang->host->osVersion = '系统版本';
+$lang->host->osName = '操作系统';
+$lang->host->zap = 'agent端口';
+$lang->host->instanceNum = '最大实列数';
+$lang->host->pri = '优先级';
+$lang->host->tags = '平台标签';
+$lang->host->provider = '供应商';
+$lang->host->bridgeID = '虚拟网桥';
+
+$lang->host->osNameList['linux'] = 'Linux';
+$lang->host->osNameList['windows'] = 'Microsoft Windows';
+$lang->host->osNameList['solaris'] = 'Solaris';
+$lang->host->osNameList['netware'] = 'Novell NetWare';
+$lang->host->osNameList['esx'] = 'VMware ESX';
+$lang->host->osNameList['other'] = 'Other';
+
+$lang->host->tagsList['vm'] = 'VM';
+$lang->host->tagsList['native'] = 'Native';
+$lang->host->providerList['native'] = 'Native';
+
+$lang->host->linux = 'Linux';
+$lang->host->windows = 'Microsoft Windows';
+$lang->host->solaris = 'Solaris';
+$lang->host->netware = 'Novell NetWare';
+$lang->host->esx = 'VMware ESX';
+$lang->host->other = 'Other';
+
+$lang->host->linuxList[''] = '';
+$lang->host->linuxList['centos65'] = 'CentOS 6.5';
+$lang->host->linuxList['centos66'] = 'CentOS 6.6';
+$lang->host->linuxList['centos67'] = 'CentOS 6.7';
+$lang->host->linuxList['centos70'] = 'CentOS 7.0';
+$lang->host->linuxList['centos71'] = 'CentOS 7.1';
+
+$lang->host->windowsList[''] = '';
+$lang->host->windowsList['win10-pro'] = 'Windows 10 pro';
+$lang->host->windowsList['winserver08x64'] = 'Windows Server2008 x64';
+$lang->host->windowsList['winserver12'] = 'Windows Server2012';
+$lang->host->windowsList['winserver16'] = 'Windows Server2016';
+
+$lang->host->solarisList[''] = '';
+$lang->host->solarisList['solaris10'] = 'Solaris 10';
+$lang->host->solarisList['solaris10x64'] = 'Solaris 10 x64';
+$lang->host->solarisList['solaris11'] = 'Solaris 11';
+
+$lang->host->netwareList[''] = '';
+$lang->host->netwareList['netware5'] = 'NetWare 5';
+$lang->host->netwareList['netware6'] = 'NetWare 6';
+
+$lang->host->esxList[''] = '';
+$lang->host->esxList['esx'] = 'VMware ESX/ESXi 4';
+$lang->host->esxList['esx5'] = 'VMware ESXi 5';
+$lang->host->esxList['esx6'] = 'VMware ESXi 6';
+
+$lang->host->otherList[''] = '';
+$lang->host->otherList['freebsd'] = 'FreeBSD';
+$lang->host->otherList['freebsdx64'] = 'FreeBSD X64';
+
+$lang->host->diskSize = '硬盘容量';
+$lang->host->diskType = '硬盘类型';
+$lang->host->diskTypeList['hdd'] = '机械硬盘';
+$lang->host->diskTypeList['ssd'] = '固态硬盘';
+
+$lang->host->confirmDelete = '是否删除该主机记录?';
+
+$lang->host->notice = new stdclass();
+$lang->host->notice->memory = '内存大小只能为数字!';
+$lang->host->notice->diskSize = '硬盘容量只能为数字!';
+$lang->host->notice->cpuNumber = 'CPU数量只能为数字!';
+$lang->host->notice->cpuCores = 'CPU核心数只能为数字!';
+$lang->host->notice->int = '『%s』应当是正整数!';
+$lang->host->notice->ip = '『%s』格式不正确!';
diff --git a/module/host/lang/zh-tw.php b/module/host/lang/zh-tw.php
new file mode 100644
index 0000000000..076f77df46
--- /dev/null
+++ b/module/host/lang/zh-tw.php
@@ -0,0 +1,153 @@
+host->common = '主機';
+$lang->host->browse = '主機列表';
+$lang->host->create = '添加主機';
+$lang->host->view = '主機詳情';
+$lang->host->edit = '編輯';
+$lang->host->delete = '刪除';
+$lang->host->treemap = '拓撲圖';
+$lang->host->changeStatus = '上架/下架';
+$lang->host->byQuery = '搜索';
+$lang->host->reason = '原因';
+
+$lang->host->name = '名稱';
+$lang->host->type = '類型';
+$lang->host->group = '主機分組';
+$lang->host->cabinet = '機櫃';
+$lang->host->intranet = '內網IP';
+$lang->host->extranet = '外網IP';
+$lang->host->mac = 'MAC';
+$lang->host->cpuBrand = 'CPU品牌';
+$lang->host->cpuModel = 'CPU型號';
+$lang->host->cpuNumber = 'CPU數量';
+$lang->host->cpuCores = '單CPU核心數';
+$lang->host->cpuRate = 'CPU頻率';
+$lang->host->memory = '內存大小';
+$lang->host->serverRoom = '機房';
+
+$lang->host->createdBy = '由誰創建';
+$lang->host->createdDate = '創建時間';
+$lang->host->editedBy = '由誰編輯';
+$lang->host->editedDate = '編輯時間';
+$lang->host->all = '所有主機';
+
+$lang->host->groupMaintenance = '分組維護';
+
+$lang->host->status = '狀態';
+$lang->host->statusList['online'] = '已上架';
+$lang->host->statusList['offline'] = '已下架';
+
+$lang->host->online = '上架';
+$lang->host->offline = '下架';
+
+$lang->host->unitList['GB'] = 'GB';
+$lang->host->unitList['TB'] = 'TB';
+
+$lang->host->cpuBrandList[''] = '';
+$lang->host->cpuBrandList['intel'] = '英特爾';
+$lang->host->cpuBrandList['amd'] = 'AMD';
+
+$lang->host->database = '資料庫';
+$lang->host->databaseList[''] = '';
+$lang->host->databaseList['mysql55'] = 'MySQL 5.5';
+$lang->host->databaseList['mysql56'] = 'MySQL 5.6';
+$lang->host->databaseList['mysql57'] = 'MySQL 5.7';
+$lang->host->databaseList['mysql80'] = 'MySQL 8.0';
+$lang->host->databaseList['oracle10g'] = 'Oracle 10g';
+$lang->host->databaseList['oracle11g'] = 'Oracle 11g';
+$lang->host->databaseList['mongodb30'] = 'MongoDB 3.0';
+$lang->host->databaseList['mongodb34'] = 'MongoDB 3.4';
+$lang->host->databaseList['postgresql95'] = 'PostgreSQL 9.5';
+$lang->host->databaseList['postgresql96'] = 'PostgreSQL 9.6';
+
+$lang->host->webserver = 'Web Server';
+$lang->host->webserverList[''] = '';
+$lang->host->webserverList['apache2425'] = 'Apache 2.4.25';
+$lang->host->webserverList['apache2426'] = 'Apache 2.4.26';
+$lang->host->webserverList['apache2427'] = 'Apache 2.4.27';
+$lang->host->webserverList['nginx181'] = 'Nginx 1.8.1';
+$lang->host->webserverList['nginx1102'] = 'Nginx 1.10.2';
+$lang->host->webserverList['nginx1115'] = 'Nginx 1.11.5';
+$lang->host->webserverList['iis6'] = 'IIS 6';
+$lang->host->webserverList['iis7'] = 'IIS 7';
+$lang->host->webserverList['iis8'] = 'IIS 8';
+$lang->host->webserverList['iis10'] = 'IIS 10';
+
+$lang->host->language = '語言環境';
+$lang->host->languageList[''] = '';
+$lang->host->languageList['php56'] = 'PHP 5.6';
+$lang->host->languageList['php70'] = 'PHP 7.0';
+$lang->host->languageList['java7'] = 'JAVA 7';
+$lang->host->languageList['java8'] = 'JAVA 8';
+$lang->host->languageList['c#3'] = 'C# 3.0';
+$lang->host->languageList['c#4'] = 'C# 4.0';
+
+$lang->host->treemapList['serverroom'] = '物理拓撲圖';
+$lang->host->treemapList['group'] = '分組拓撲圖';
+
+$lang->host->serverModel = '伺服器型號';
+$lang->host->hostType = '主機類型';
+$lang->host->hostTypeList['physical'] = '實體主機';
+$lang->host->hostTypeList['virtual'] = '虛擬主機';
+
+$lang->host->osVersion = '系統版本';
+$lang->host->osName = '操作系統';
+$lang->host->zap = 'agent端口';
+$lang->host->tags = '平臺標簽';
+$lang->host->provide = '供應商';
+$lang->host->osNameList['linux'] = 'Linux';
+$lang->host->osNameList['windows'] = 'Microsoft Windows';
+$lang->host->osNameList['solaris'] = 'Solaris';
+$lang->host->osNameList['netware'] = 'Novell NetWare';
+$lang->host->osNameList['esx'] = 'VMware ESX';
+$lang->host->osNameList['other'] = 'Other';
+
+$lang->host->linux = 'Linux';
+$lang->host->windows = 'Microsoft Windows';
+$lang->host->solaris = 'Solaris';
+$lang->host->netware = 'Novell NetWare';
+$lang->host->esx = 'VMware ESX';
+$lang->host->other = 'Other';
+
+$lang->host->linuxList[''] = '';
+$lang->host->linuxList['centos65'] = 'CentOS 6.5';
+$lang->host->linuxList['centos66'] = 'CentOS 6.6';
+$lang->host->linuxList['centos67'] = 'CentOS 6.7';
+$lang->host->linuxList['centos70'] = 'CentOS 7.0';
+$lang->host->linuxList['centos71'] = 'CentOS 7.1';
+
+$lang->host->windowsList[''] = '';
+$lang->host->windowsList['winserver08x64'] = 'Windows Server2008 x64';
+$lang->host->windowsList['winserver12'] = 'Windows Server2012';
+$lang->host->windowsList['winserver16'] = 'Windows Server2016';
+
+$lang->host->solarisList[''] = '';
+$lang->host->solarisList['solaris10'] = 'Solaris 10';
+$lang->host->solarisList['solaris10x64'] = 'Solaris 10 x64';
+$lang->host->solarisList['solaris11'] = 'Solaris 11';
+
+$lang->host->netwareList[''] = '';
+$lang->host->netwareList['netware5'] = 'NetWare 5';
+$lang->host->netwareList['netware6'] = 'NetWare 6';
+
+$lang->host->esxList[''] = '';
+$lang->host->esxList['esx'] = 'VMware ESX/ESXi 4';
+$lang->host->esxList['esx5'] = 'VMware ESXi 5';
+$lang->host->esxList['esx6'] = 'VMware ESXi 6';
+
+$lang->host->otherList[''] = '';
+$lang->host->otherList['freebsd'] = 'FreeBSD';
+$lang->host->otherList['freebsdx64'] = 'FreeBSD X64';
+
+$lang->host->diskSize = '硬碟容量';
+$lang->host->diskType = '硬碟類型';
+$lang->host->diskTypeList['hdd'] = '機械硬碟';
+$lang->host->diskTypeList['ssd'] = '固態硬碟';
+
+$lang->host->confirmDelete = '是否刪除該主機記錄?';
+
+$lang->host->notice = new stdclass();
+$lang->host->notice->memory = '內存大小只能為數字!';
+$lang->host->notice->diskSize = '硬碟容量只能為數字!';
+$lang->host->notice->cpuNumber = 'CPU數量只能為數字!';
+$lang->host->notice->cpuCores = 'CPU核心數只能為數字!';
diff --git a/module/host/model.php b/module/host/model.php
new file mode 100644
index 0000000000..f04d74093d
--- /dev/null
+++ b/module/host/model.php
@@ -0,0 +1,407 @@
+
+ * @package ops
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+class hostModel extends model
+{
+ /**
+ * Get host by id.
+ *
+ * @param int $id
+ * @access public
+ * @return object
+ */
+ public function getById($id)
+ {
+ $host = $this->dao->select('*,id as hostID')->from(TABLE_HOST)
+ ->where('id')->eq($id)
+ ->fetch();
+
+ return $host;
+ }
+
+ /**
+ * Get hosts by id list.
+ *
+ * @param int $idList
+ * @access public
+ * @return array
+ */
+ public function getByIdList($idList)
+ {
+ return $this->dao->select('*,id as hostID')->from(TABLE_HOST)
+ ->where('id')->in($idList)
+ ->andWhere('deleted')->eq('0')
+ ->fetchAll('id');
+ }
+
+ /**
+ * Get host list.
+ *
+ * @param string $browseType
+ * @param int $param
+ * @param string $orderBy
+ * @param object $pager
+ * @access public
+ * @return array
+ */
+ public function getList($browseType = 'all', $param = 0, $orderBy = 'id_desc', $pager = null)
+ {
+ $query = '';
+ $modules = '';
+ if($browseType == 'bysearch')
+ {
+ /* Concatenate the conditions for the query. */
+ if($param)
+ {
+ $query = $this->loadModel('search')->getQuery($param);
+ if($query)
+ {
+ $this->session->set('hostQuery', $query->sql);
+ $this->session->set('hostForm', $query->form);
+ }
+ else
+ {
+ $this->session->set('hostQuery', ' 1 = 1');
+ }
+ }
+ else
+ {
+ if($this->session->hostQuery == false) $this->session->set('hostQuery', ' 1 = 1');
+ }
+ $query = $this->session->hostQuery;
+ }
+ elseif($browseType == 'bymodule')
+ {
+ $modules = $param ? $this->loadModel('tree')->getAllChildId($param) : '0';
+ }
+
+ $orderBy = str_replace($orderBy, 't1.', '');
+ $host = $this->dao->select('*,id as hostID')->from(TABLE_HOST)
+ ->where('deleted')->eq('0')
+ ->andWhere('type')->eq('normal')
+ ->beginIF($modules)->andWhere('`group`')->in($modules)->fi()
+ ->beginIF($query)->andWhere($query)->fi()
+ ->orderBy($orderBy)
+ ->page($pager)
+ ->fetchAll();
+ return $host;
+ }
+
+ /**
+ * Get pairs by services.
+ *
+ * @param string $services
+ * @access public
+ * @return array
+ */
+ public function getPairsByService($services)
+ {
+ $servers = $this->dao->select('id,hosts')->from(TABLE_SERVICE)->where('id')->in($services)->andWhere('hosts')->ne('')->fetchPairs('id', 'hosts');
+ $hostIdList = array_unique(explode(',', join(',', $servers)));
+
+ return $this->dao->select('id,name')->from(TABLE_HOST)
+ ->where('deleted')->eq('0')
+ ->andWhere('`id`')->in($hostIdList)
+ ->andWhere('type')->eq('normal')
+ ->orderBy('`group`')
+ ->fetchPairs('id', 'name');
+ }
+
+ /**
+ * Get pairs.
+ *
+ * @param string $moduleIdList
+ * @param string $idFrom
+ * @access public
+ * @return array
+ */
+ public function getPairs($moduleIdList = 0)
+ {
+ $modules = array();
+ if($moduleIdList)
+ {
+ $this->loadModel('tree');
+ foreach(explode(',', $moduleIdList) as $moduleID)
+ {
+ if(empty($moduleID)) continue;
+ $modules += $this->tree->getAllChildId($moduleID);
+ }
+ }
+
+ return $this->dao->select("id,name")->from(TABLE_HOST)
+ ->where('deleted')->eq('0')
+ ->andWhere('type')->eq('normal')
+ ->beginIF($modules)->andWhere('`group`')->in($modules)->fi()
+ ->orderBy('`group`')
+ ->fetchPairs('id', 'name');
+ }
+
+ /**
+ * Create a host.
+ *
+ * @access public
+ * @return int|bool
+ */
+ public function create()
+ {
+ $hostInfo = fixer::input('post')
+ ->setDefault('hardwareType', 'server')
+ ->setDefault('cpuNumber,cpuCores,diskSize,memory', 0)
+ ->get();
+
+ $this->dao->update(TABLE_HOST)->data($hostInfo)
+ ->batchCheck($this->config->host->create->requiredFields, 'notempty')
+ ->batchCheck('diskSize,memory', 'float');
+ if(dao::isError()) return false;
+
+ $intFields = explode(',', $this->config->host->create->intFields);
+ foreach($intFields as $field)
+ {
+ if(!preg_match("/^-?\d+$/", $hostInfo->{$field}))
+ {
+ dao::$errors[$field] = sprintf($this->lang->host->notice->int, $this->lang->host->{$field});
+ return false;
+ }
+ }
+
+ $ipFields = explode(',', $this->config->host->create->ipFields);
+ foreach($ipFields as $field)
+ {
+ if(!preg_match('/((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}/', $hostInfo->{$field}))
+ {
+ dao::$errors[$field] = sprintf($this->lang->host->notice->ip, $this->lang->host->{$field});
+ return false;
+ }
+ }
+
+ $hostInfo->type = 'normal';
+ $hostInfo->createdBy = $this->app->user->account;
+ $hostInfo->createdDate = helper::now();
+ $this->dao->insert(TABLE_HOST)->data($hostInfo)->autoCheck()->exec();
+ if(!dao::isError())
+ {
+ $hostID = $this->dao->lastInsertID();
+ $this->loadModel('action')->create('host', $hostID, 'created');
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Update a host.
+ *
+ * @param int $id
+ * @param int $hostID
+ * @access public
+ * @return array|bool
+ */
+ public function update($id)
+ {
+ $oldHost = $this->getById($id);
+ $hostInfo = fixer::input('post')
+ ->setDefault('hardwareType', 'server')
+ ->setDefault('cpuNumber,cpuCores,diskSize,memory', 0)
+ ->get();
+
+ $this->dao->update(TABLE_HOST)->data($hostInfo)
+ ->batchCheck($this->config->host->create->requiredFields, 'notempty')
+ ->batchCheck('diskSize,memory', 'float');
+ if(dao::isError()) return false;
+
+ $intFields = explode(',', $this->config->host->create->intFields);
+ foreach($intFields as $field)
+ {
+ if(!preg_match("/^-?\d+$/", $hostInfo->{$field}))
+ {
+ dao::$errors[$field] = sprintf($this->lang->host->notice->int, $this->lang->host->{$field});
+ return false;
+ }
+ }
+
+ $ipFields = explode(',', $this->config->host->create->ipFields);
+ foreach($ipFields as $field)
+ {
+ if(!preg_match('/((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}/', $hostInfo->{$field}))
+ {
+ dao::$errors[$field] = sprintf($this->lang->host->notice->ip, $this->lang->host->{$field});
+ return false;
+ }
+ }
+
+ $hostInfo->editedBy = $this->app->user->account;
+ $hostInfo->editedDate = helper::now();
+ $this->dao->update(TABLE_HOST)->data($hostInfo)->autoCheck()->where('id')->eq($id)->exec();
+ return common::createChanges($oldHost, $hostInfo);
+ }
+
+ /**
+ * Update a host status.
+ *
+ * @param int $hostID
+ * @param int $status
+ * @access public
+ * @return void
+ */
+ public function updateStatus($hostID, $status)
+ {
+ $this->dao->update(TABLE_HOST)->set('status')->eq($status)->where('id')->eq($hostID)->exec();
+ }
+
+ /**
+ * Get tree map of server room.
+ *
+ * @access public
+ * @return string
+ */
+ public function getServerroomTreemap()
+ {
+ /* Get host list. */
+ $this->app->loadLang('serverroom');
+ $stmt = $this->dao->select('t1.id,t1.name,t3.id as roomID,t3.city,t3.name as roomName,t1.extranet')->from(TABLE_HOST)->alias('t1')
+ ->leftJoin(TABLE_SERVERROOM)->alias('t3')->on('t1.serverRoom=t3.id')
+ ->where('t1.deleted')->eq(0)
+ ->andWhere('t1.type')->eq('normal')
+ ->andWhere('t3.deleted')->eq(0)
+ ->andWhere('t1.serverRoom')->ne(0)
+ ->orderBy('t3.city,t3.id,t1.id')
+ ->query();
+
+ /* Group host by city and server room. */
+ $hostGroup = array();
+ while($host = $stmt->fetch())
+ {
+ $hostGroup[$host->city][$host->roomID][] = $host;
+ }
+
+ /* Generate a tree map. */
+ $treemap = "
";
+ foreach($hostGroup as $city => $rooms)
+ {
+ $treemap .= "- " . zget($this->lang->serverroom->cityList, $city);
+ $treemap .= '
';
+ foreach($rooms as $roomID => $cabinets)
+ {
+ $host = reset($cabinets);
+ if(is_array($host)) $host = reset($host);
+ $treemap .= "- " . htmlspecialchars($host->roomName);
+ $treemap .= '
';
+ foreach($cabinets as $cabinet => $hosts)
+ {
+ if(is_array($hosts))
+ {
+ $treemap .= "- " . htmlspecialchars($cabinet);
+ $treemap .= '
';
+ foreach($hosts as $host) $treemap .= "- " . htmlspecialchars($host->name) . '
';
+ $treemap .= '
';
+ }
+ else
+ {
+ $host = $hosts;
+ $treemap .= "- " . htmlspecialchars($host->name) . '
';
+ }
+ }
+ $treemap .= '
';
+ }
+ $treemap .= '
';
+ }
+ $treemap .= '
';
+ return $treemap;
+ }
+
+ /**
+ * Get tree map by group.
+ *
+ * @access public
+ * @return string
+ */
+ public function getGroupTreemap()
+ {
+ /* Get host list by group. */
+ $this->app->loadLang('serverroom');
+ $hostGroups = $this->dao->select('id,name,`group`,extranet')->from(TABLE_HOST)
+ ->where('deleted')->eq(0)
+ ->andWhere('type')->eq('normal')
+ ->fetchGroup('group', 'id');
+
+ /* Get module list by host group. */
+ $modules = $this->dao->select('*')->from(TABLE_MODULE)->where('id')->in(array_keys($hostGroups))->fetchAll();
+ $paths = array();
+ foreach($modules as $module)
+ {
+ foreach(explode(',', trim($module->path)) as $path) $paths[$path] = $path;
+ }
+ $stmt = $this->dao->select('*')->from(TABLE_MODULE)->where('id')->in($paths)->orderBy('grade_desc,`order`,id')->query();
+
+ /* Generate a tree map. */
+ $treemap = array();
+ while($module = $stmt->fetch())
+ {
+ if(!isset($treemap[$module->parent])) $treemap[$module->parent] = '';
+ $treemap[$module->parent] .= "" . htmlspecialchars($module->name);
+ if(isset($treemap[$module->id]) or isset($hostGroups[$module->id]))
+ {
+ $treemap[$module->parent] .= '';
+ if(isset($treemap[$module->id]))
+ {
+ $treemap[$module->parent] .= $treemap[$module->id];
+ unset($treemap[$module->id]);
+ }
+ if(isset($hostGroups[$module->id]))
+ {
+ foreach($hostGroups[$module->id] as $host)
+ {
+ $treemap[$module->parent] .= "- " . htmlspecialchars($host->name) . "
";
+ }
+ }
+ $treemap[$module->parent] .= '
';
+ }
+ $treemap[$module->parent] .= "";
+ }
+
+ $groupTree = '';
+ if(isset($treemap[0]) or isset($hostGroups[0]))
+ {
+ $groupTree = "";
+ $groupTree .= "- /";
+ $groupTree .= "
";
+ if(isset($treemap[0])) $groupTree .= $treemap[0];
+
+ if(isset($hostGroups[0]))
+ {
+ foreach($hostGroups[0] as $host) $groupTree .= "- " . htmlspecialchars($host->name) . "
";
+ }
+ $groupTree .= "
";
+ }
+ return $groupTree;
+ }
+
+ /**
+ * 判断列表页操作按钮是否可点击。
+ * Judge an action is clickable or not.
+ *
+ * @param object $host
+ * @param string $action
+ * @static
+ * @access public
+ * @return bool
+ */
+ public static function isClickable($host, $action)
+ {
+ if(!$host->id) return false;
+ if (!common::hasPriv('host', 'changeStatus')) return false;
+
+ if($host->status == 'online' && $action == 'online') return false;
+ if($host->status == 'offline' && $action == 'offline') return false;
+
+ return true;
+ }
+}
diff --git a/module/host/ui/browse.html.php b/module/host/ui/browse.html.php
new file mode 100644
index 0000000000..469637d38b
--- /dev/null
+++ b/module/host/ui/browse.html.php
@@ -0,0 +1,66 @@
+
+ * @package host
+ * @link http://www.zentao.net
+ */
+
+namespace zin;
+
+jsVar('orderBy', $orderBy);
+jsVar('hostLang', $lang->host);
+jsVar('sortLink', helper::createLink('host', 'browse', "browseType=$browseType¶m=$param&orderBy={orderBy}&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}"));
+
+$config->host->featureBar[0]['active'] = true;
+$config->host->featureBar[0]['badge'] = $pager->recTotal != '' ? array('text' => $pager->recTotal, 'class' => 'size-sm rounded-full white') : null;
+featureBar
+(
+ set::items($config->host->featureBar),
+ li(searchToggle())
+);
+
+/* zin: Define the toolbar on main menu. */
+$canCreate = hasPriv('host', 'create');
+$createLink = $this->createLink('host', 'create');
+$createItem = array('text' => $lang->host->create, 'url' => $createLink, 'class' => 'primary', 'icon' => 'plus');
+
+$config->host->dtable->fieldList['group']['map'] = $optionMenu;
+$config->host->dtable->fieldList['admin']['map'] = $accounts;
+$config->host->dtable->fieldList['serverRoom']['map'] = $rooms;
+$tableData = initTableData($hostList, $config->host->dtable->fieldList, $this->host);
+
+toolbar
+(
+ $canCreate ? item(set($createItem)) : null,
+);
+
+/* zin: Define the sidebar in main content. */
+sidebar
+(
+ moduleMenu(set(array(
+ 'modules' => $moduleTree,
+ 'activeKey' => $param,
+ 'allText' => $lang->host->group,
+ 'settingText' => $lang->host->groupMaintenance,
+ 'showDisplay' => false,
+ 'settingLink' => $this->createLink('tree', 'browse', "productID=0&view=host"),
+ 'closeLink' => $this->createLink('host', 'browse'),
+ )))
+);
+
+dtable
+(
+ set::userMap($accounts),
+ set::cols(array_values($config->host->dtable->fieldList)),
+ set::data($tableData),
+ set::sortLink(jsRaw('createSortLink')),
+ set::onRenderCell(jsRaw('window.renderCell')),
+ set::footPager(usePager()),
+);
+
+render();
diff --git a/module/host/ui/changestatus.html.php b/module/host/ui/changestatus.html.php
new file mode 100644
index 0000000000..bd9d897912
--- /dev/null
+++ b/module/host/ui/changestatus.html.php
@@ -0,0 +1,27 @@
+
+ * @package host
+ * @link https://www.zentao.net
+ */
+
+namespace zin;
+
+formPanel
+(
+ set::id('hostChangeStatusForm'),
+ set::title($reason),
+ formRow
+ (
+ formGroup
+ (
+ set::name('reason'),
+ set::control('textarea'),
+ ),
+ ),
+);
diff --git a/module/host/ui/create.html.php b/module/host/ui/create.html.php
new file mode 100644
index 0000000000..79f0e0a4f1
--- /dev/null
+++ b/module/host/ui/create.html.php
@@ -0,0 +1,223 @@
+
+ * @package host
+ * @link https://www.zentao.net
+ */
+
+namespace zin;
+
+formPanel
+(
+ set::id('hostCreateForm'),
+ set::title($lang->host->create),
+ formRow
+ (
+ formGroup
+ (
+ set::width('1/3'),
+ set::name('name'),
+ set::label($lang->host->name),
+ set::value($host->name),
+ ),
+ formGroup
+ (
+ set::width('1/3'),
+ set::label($lang->host->admin),
+ set::control('picker'),
+ set::name('admin'),
+ set::items($accounts),
+ set::value($host->admin)
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('1/3'),
+ set::label($lang->host->cpuBrand),
+ set::control('picker'),
+ set::name('cpuBrand'),
+ set::items($lang->host->cpuBrandList),
+ set::value($host->cpuBrand)
+ ),
+ formGroup
+ (
+ set::width('1/3'),
+ set::name('cpuModel'),
+ set::label($lang->host->cpuModel),
+ set::value($host->cpuModel),
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('1/3'),
+ set::name('cpuNumber'),
+ set::label($lang->host->cpuNumber),
+ set::value($host->cpuNumber),
+ ),
+ formGroup
+ (
+ set::width('1/3'),
+ set::name('cpuCores'),
+ set::label($lang->host->cpuCores),
+ set::value($host->cpuCores),
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('1/3'),
+ set::name('memory'),
+ set::label($lang->host->memory),
+ set::value($host->memory),
+ set::control(array
+ (
+ 'type' => 'inputControl',
+ 'suffix' => 'GB',
+ 'suffixWidth' => 40,
+ )),
+ ),
+ formGroup
+ (
+ set::width('1/3'),
+ set::name('diskSize'),
+ set::label($lang->host->diskSize),
+ set::value($host->diskSize),
+ set::control(array
+ (
+ 'type' => 'inputControl',
+ 'suffix' => 'GB',
+ 'suffixWidth' => 40,
+ )),
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('1/3'),
+ set::label($lang->host->group),
+ set::control('picker'),
+ set::name('group'),
+ set::items($optionMenu),
+ set::value($host->group ? $host->group : 0)
+ ),
+ formGroup
+ (
+ set::width('1/3'),
+ set::label($lang->host->serverRoom),
+ set::control('picker'),
+ set::name('serverRoom'),
+ set::items($rooms),
+ set::value($host->serverRoom)
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('1/3'),
+ set::name('serverModel'),
+ set::label($lang->host->serverModel),
+ set::value($host->serverModel),
+ ),
+ formGroup
+ (
+ set::width('1/3'),
+ set::label($lang->host->hostType),
+ set::control('picker'),
+ set::name('hostType'),
+ set::items($lang->host->hostTypeList),
+ set::value($host->hostType ? $host->hostType : 'virtual')
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('1/3'),
+ set::label($lang->host->osName),
+ set::control('picker'),
+ set::name('osName'),
+ set::items($lang->host->osNameList),
+ set::value($osName ? $osName : $host->osName),
+ on::change('osChange'),
+ ),
+ formGroup
+ (
+ set::width('1/3'),
+ set::label($lang->host->osVersion),
+ set::control('picker'),
+ set::name('osVersion'),
+ set::items($lang->host->{"{$osName}List"}),
+ set::value($host->osVersion)
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('1/3'),
+ set::name('zap'),
+ set::label($lang->host->zap),
+ set::value($host->zap ? $host->zap : 8086),
+ ),
+ formGroup
+ (
+ set::width('1/3'),
+ set::label($lang->host->tags),
+ set::control('picker'),
+ set::name('vsoft'),
+ set::items($lang->host->tagsList),
+ set::value($host->tags ? $host->tags : 'vm')
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('1/3'),
+ set::name('intranet'),
+ set::label($lang->host->intranet),
+ set::value($host->intranet),
+ ),
+ formGroup
+ (
+ set::width('1/3'),
+ set::name('extranet'),
+ set::label($lang->host->extranet),
+ set::value($host->extranet),
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('1/3'),
+ set::label($lang->host->provider),
+ set::control('picker'),
+ set::name('provider'),
+ set::items($lang->host->providerList),
+ set::value($host->provider)
+ ),
+ formGroup
+ (
+ set::width('1/3'),
+ set::name('status'),
+ set::control('radioList'),
+ set::label($lang->host->status),
+ set::value($host->status ? $host->status : 'online'),
+ set::inline(true),
+ set::items($lang->host->statusList),
+ )
+ ),
+);
diff --git a/module/host/ui/edit.html.php b/module/host/ui/edit.html.php
new file mode 100644
index 0000000000..fe96fb5525
--- /dev/null
+++ b/module/host/ui/edit.html.php
@@ -0,0 +1,225 @@
+
+ * @package host
+ * @link https://www.zentao.net
+ */
+
+namespace zin;
+
+jsVar('host', $host);
+
+formPanel
+(
+ set::id('hostCreateForm'),
+ set::title($lang->host->edit),
+ formRow
+ (
+ formGroup
+ (
+ set::width('400px'),
+ set::name('name'),
+ set::label($lang->host->name),
+ set::value($host->name),
+ ),
+ formGroup
+ (
+ set::width('400px'),
+ set::label($lang->host->admin),
+ set::control('picker'),
+ set::name('admin'),
+ set::items($accounts),
+ set::value($host->admin)
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('400px'),
+ set::label($lang->host->cpuBrand),
+ set::control('picker'),
+ set::name('cpuBrand'),
+ set::items($lang->host->cpuBrandList),
+ set::value($host->cpuBrand)
+ ),
+ formGroup
+ (
+ set::width('400px'),
+ set::name('cpuModel'),
+ set::label($lang->host->cpuModel),
+ set::value($host->cpuModel),
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('400px'),
+ set::name('cpuNumber'),
+ set::label($lang->host->cpuNumber),
+ set::value($host->cpuNumber),
+ ),
+ formGroup
+ (
+ set::width('400px'),
+ set::name('cpuCores'),
+ set::label($lang->host->cpuCores),
+ set::value($host->cpuCores),
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('400px'),
+ set::name('memory'),
+ set::label($lang->host->memory),
+ set::value($host->memory),
+ set::control(array
+ (
+ 'type' => 'inputControl',
+ 'suffix' => 'GB',
+ 'suffixWidth' => 40,
+ )),
+ ),
+ formGroup
+ (
+ set::width('400px'),
+ set::name('diskSize'),
+ set::label($lang->host->diskSize),
+ set::value($host->diskSize),
+ set::control(array
+ (
+ 'type' => 'inputControl',
+ 'suffix' => 'GB',
+ 'suffixWidth' => 40,
+ )),
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('400px'),
+ set::label($lang->host->group),
+ set::control('picker'),
+ set::name('group'),
+ set::items($optionMenu),
+ set::value($host->group ? $host->group : 0)
+ ),
+ formGroup
+ (
+ set::width('400px'),
+ set::label($lang->host->serverRoom),
+ set::control('picker'),
+ set::name('serverRoom'),
+ set::items($rooms),
+ set::value($host->serverRoom)
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('400px'),
+ set::name('serverModel'),
+ set::label($lang->host->serverModel),
+ set::value($host->serverModel),
+ ),
+ formGroup
+ (
+ set::width('400px'),
+ set::label($lang->host->hostType),
+ set::control('picker'),
+ set::name('hostType'),
+ set::items($lang->host->hostTypeList),
+ set::value($host->hostType ? $host->hostType : 'virtual')
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('400px'),
+ set::label($lang->host->osName),
+ set::control('picker'),
+ set::name('osName'),
+ set::items($lang->host->osNameList),
+ set::value($osName ? $osName : $host->osName),
+ on::change('osChange'),
+ ),
+ formGroup
+ (
+ set::width('400px'),
+ set::label($lang->host->osVersion),
+ set::control('picker'),
+ set::name('osVersion'),
+ set::items($lang->host->{"{$osName}List"}),
+ set::value($host->osVersion)
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('400px'),
+ set::name('zap'),
+ set::label($lang->host->zap),
+ set::value($host->zap ? $host->zap : 8086),
+ ),
+ formGroup
+ (
+ set::width('400px'),
+ set::label($lang->host->tags),
+ set::control('picker'),
+ set::name('vsoft'),
+ set::items($lang->host->tagsList),
+ set::value($host->tags ? $host->tags : 'vm')
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('400px'),
+ set::name('intranet'),
+ set::label($lang->host->intranet),
+ set::value($host->intranet),
+ ),
+ formGroup
+ (
+ set::width('400px'),
+ set::name('extranet'),
+ set::label($lang->host->extranet),
+ set::value($host->extranet),
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('400px'),
+ set::label($lang->host->provider),
+ set::control('picker'),
+ set::name('provider'),
+ set::items($lang->host->providerList),
+ set::value($host->provider)
+ ),
+ formGroup
+ (
+ set::width('400px'),
+ set::name('status'),
+ set::control('radioList'),
+ set::label($lang->host->status),
+ set::value($host->status ? $host->status : 'online'),
+ set::inline(true),
+ set::items($lang->host->statusList),
+ )
+ ),
+);
diff --git a/module/host/ui/view.html.php b/module/host/ui/view.html.php
new file mode 100644
index 0000000000..9da9b70921
--- /dev/null
+++ b/module/host/ui/view.html.php
@@ -0,0 +1,105 @@
+
+ * @package host
+ * @link http://www.zentao.net
+ */
+
+namespace zin;
+detailHeader
+(
+ isAjaxRequest('modal') ? to::prefix() : '',
+ to::title(
+ entityLabel(
+ set(array('entityID' => $host->id, 'level' => 1, 'text' => $host->name))
+ )
+ ),
+);
+
+$actions = $this->loadModel('common')->buildOperateMenu($host);
+
+detailBody
+(
+ sectionList
+ (
+ h::table
+ (
+ setClass('table table-fixed canvas host-view-table'),
+ h::tr
+ (
+ h::th($lang->host->name),
+ h::td($host->name),
+ h::th(),
+ h::td(),
+ ),
+ h::tr
+ (
+ h::th($lang->host->group),
+ h::td($optionMenu[$host->group]),
+ h::th($lang->host->serverRoom),
+ h::td(zget($rooms, $host->serverRoom, "")),
+ ),
+ h::tr
+ (
+ h::th($lang->host->serverModel),
+ h::td($host->serverModel),
+ h::th($lang->host->hostType),
+ h::td(zget($lang->host->hostTypeList, $host->hostType, "")),
+ ),
+ h::tr
+ (
+ h::th($lang->host->cpuBrand),
+ h::td($host->cpuBrand),
+ h::th($lang->host->cpuModel),
+ h::td($host->cpuModel),
+ ),
+ h::tr
+ (
+ h::th($lang->host->cpuNumber),
+ h::td($host->cpuNumber),
+ h::th($lang->host->cpuCores),
+ h::td($host->cpuCores),
+ ),
+ h::tr
+ (
+ h::th($lang->host->memory),
+ h::td($host->memory ? $host->memory . ' GB' : ''),
+ h::th($lang->host->diskSize),
+ h::td($host->diskSize ? $host->diskSize . ' GB' : ''),
+ ),
+ h::tr
+ (
+ h::th($lang->host->intranet),
+ h::td($host->intranet),
+ h::th($lang->host->extranet),
+ h::td($host->extranet),
+ ),
+ h::tr
+ (
+ h::th($lang->host->osName),
+ h::td($host->osName),
+ h::th($lang->host->osVersion),
+ h::td($lang->host->{$host->osName.'List'}[$host->osVersion]),
+ ),
+ h::tr
+ (
+ h::th($lang->host->status),
+ h::td($lang->host->statusList[$host->status]),
+ h::th(),
+ h::td(),
+ )
+ )
+ ),
+ history(),
+ floatToolbar
+ (
+ set::object($host),
+ isAjaxRequest('modal') ? null : to::prefix(backBtn(set::icon('back'), set::class('ghost text-white'), $lang->goback)),
+ set::suffix($actions['suffixActions'])
+ ),
+);
diff --git a/module/host/view/browse.html.php b/module/host/view/browse.html.php
new file mode 100644
index 0000000000..e7f4bdc6c0
--- /dev/null
+++ b/module/host/view/browse.html.php
@@ -0,0 +1,126 @@
+
+ * @package host
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'common/view/header.html.php';?>
+host->confirmDelete)?>
+
+
+' data-module='host'>
+
+
+
+
+
+
+
+
+ host->empty;?>
+ ' . $lang->host->create, '', 'class="btn btn-info"');?>
+
+
+
+
+
+
+ recTotal}&recPerPage={$pager->recPerPage}";?>
+ | idAB);?> |
+ host->group);?> |
+ host->name);?> |
+ host->admin);?> |
+ host->serverRoom);?> |
+ host->intranet);?> |
+ host->extranet);?> |
+ host->osVersion);?> |
+ host->status);?> |
+ actions?> |
+
+
+
+
+
+ | id);?> |
+ '>group, '');?> |
+ inlink('view', "id=$host->id", 'html', true), $host->name, '', "class='iframe'");?> |
+
+
+ admin, "");?>
+ createLink('account', 'view', "id=$host->admin", 'html', true), $accountName, '', "class='iframe'") : ''?> |
+
+ serverRoom, "");?>
+ createLink('serverroom', 'view', "id=$host->serverRoom", 'html', true), $serverRoomName, '', "class='iframe'") : ''?> |
+ intranet;?> |
+ extranet;?> |
+ osName ? $lang->host->{$host->osName.'List'}[$host->osVersion] : '';?> |
+ status ? $lang->host->statusList[$host->status] : '';?> |
+
+ status == 'offline' ? '' : '';
+ $title = $host->status == 'offline' ? $lang->host->online : $lang->host->offline;
+ if (common::hasPriv('host', 'changeStatus', $host)) echo html::a($this->inlink('changeStatus', "id={$host->id}&hostID={$host->id}&status=$host->status", 'html', true), $icon, '', "class='btn iframe' title='{$title}'");
+
+ common::printIcon('host','edit',"id=$host->id", $host, '', 'edit');
+ if(common::hasPriv('host', 'delete', $host))
+ {
+ $deleteURL = $this->createLink('host', 'delete', "id=$host->id&confirm=yes");
+ echo html::a("javascript:ajaxDelete(\"$deleteURL\",\"hostList\",confirmDelete)", '', '', "class='btn' title='{$lang->host->delete}'");
+ }
+ ?>
+ |
+
+
+
+
+
+
+
+
+
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/module/host/view/changestatus.html.php b/module/host/view/changestatus.html.php
new file mode 100644
index 0000000000..4e166deb73
--- /dev/null
+++ b/module/host/view/changestatus.html.php
@@ -0,0 +1,20 @@
+getModuleRoot() . 'common/view/header.html.php';?>
+getModuleRoot() . 'common/view/kindeditor.html.php';?>
+
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/module/host/view/create.html.php b/module/host/view/create.html.php
new file mode 100644
index 0000000000..3d96946631
--- /dev/null
+++ b/module/host/view/create.html.php
@@ -0,0 +1,99 @@
+
+ * @package host
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'common/view/header.html.php';?>
+
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/module/host/view/edit.html.php b/module/host/view/edit.html.php
new file mode 100644
index 0000000000..12f7fb6cc9
--- /dev/null
+++ b/module/host/view/edit.html.php
@@ -0,0 +1,100 @@
+
+ * @package host
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'common/view/header.html.php';?>
+
+
+
host->editAction;?>
+
+
+
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/module/host/view/m.browse.html.php b/module/host/view/m.browse.html.php
new file mode 100644
index 0000000000..60db6a7736
--- /dev/null
+++ b/module/host/view/m.browse.html.php
@@ -0,0 +1,32 @@
+getModuleRoot() . 'common/view/m.header.html.php';?>
+
+getModuleRoot() . 'common/view/m.footer.html.php';?>
diff --git a/module/host/view/m.view.html.php b/module/host/view/m.view.html.php
new file mode 100644
index 0000000000..706207d96c
--- /dev/null
+++ b/module/host/view/m.view.html.php
@@ -0,0 +1,79 @@
+getModuleRoot() . 'common/view/m.header.html.php';?>
+
+getModuleRoot() . 'common/view/m.footer.html.php';?>
diff --git a/module/host/view/treemap.html.php b/module/host/view/treemap.html.php
new file mode 100644
index 0000000000..bb684186fe
--- /dev/null
+++ b/module/host/view/treemap.html.php
@@ -0,0 +1,64 @@
+
+ * @package host
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'common/view/header.html.php';?>
+
+
+
+
+
+
+
+
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/module/host/view/view.html.php b/module/host/view/view.html.php
new file mode 100644
index 0000000000..9bdc57c2e6
--- /dev/null
+++ b/module/host/view/view.html.php
@@ -0,0 +1,90 @@
+
+ * @package host
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'common/view/header.html.php';?>
+
+
+
host->view;?>
+
+
+
+
+
+ | host->name;?> |
+ name;?> |
+ | |
+
+
+ | host->group;?> |
+ group];?> |
+ host->serverRoom;?> |
+ serverRoom, "")?> |
+
+
+ | host->serverModel;?> |
+ serverModel;?> |
+ host->hostType;?> |
+ host->hostTypeList[$host->hostType];?> |
+
+
+ | host->cpuBrand;?> |
+ cpuBrand;?> |
+ host->cpuModel;?> |
+ cpuModel;?> |
+
+
+ | host->cpuNumber;?> |
+ cpuNumber;?> |
+ host->cpuCores;?> |
+ cpuCores;?> |
+
+
+ | host->memory;?> |
+ memory) echo $host->memory . ' GB';?> |
+ host->diskSize;?> |
+ diskSize) echo $host->diskSize . ' GB';?> |
+
+
+ | host->intranet;?> |
+ intranet;?> |
+ host->extranet;?> |
+ extranet;?> |
+
+
+ | host->osName;?> |
+ osName;?> |
+ host->osVersion;?> |
+ host->{$host->osName.'List'}[$host->osVersion];?>
+ |
+
+ | host->status;?> |
+ host->statusList[$host->status];?> |
+
+
+
+ getModuleRoot() . 'common/view/action.html.php'?>
+
+
+
+
+ deleted == 0)
+ {
+ common::printLink('host', 'edit', "id=$host->hostID&hostID=$host->hostID", " " . $lang->edit, '', "class='btn'", '', '', $host);
+ common::printLink('host', 'delete', "id=$host->hostID", " " . $lang->delete, 'hiddenwin', "class='btn'", '', '', $host);
+ }
+ if(!isonlybody()) echo html::backButton(' ' . $lang->goback, '', 'btn btn-secondary');
+ ?>
+
+
+
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/module/ops/control.php b/module/ops/control.php
new file mode 100644
index 0000000000..0ce48bfb1c
--- /dev/null
+++ b/module/ops/control.php
@@ -0,0 +1,121 @@
+
+ * @package ops
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+class ops extends control
+{
+ /**
+ * Index.
+ *
+ * @access public
+ * @return void
+ */
+ public function index()
+ {
+ $this->locate($this->createLink('deploy', 'browse'));
+ }
+
+ /**
+ * 管理机房供应商信息。
+ * Manger provider options of serverroom.
+ *
+ * @param string $currentLang
+ * @access public
+ * @return void
+ */
+ public function provider($currentLang = '')
+ {
+ $this->setting('serverroom', 'provider', 'provider', $currentLang);
+ }
+
+ /**
+ * 管理机房城市信息。
+ * Manger city options of serverroom.
+ *
+ * @param string $currentLang
+ * @access public
+ * @return void
+ */
+ public function city($currentLang = '')
+ {
+ $this->setting('serverroom', 'city', 'city', $currentLang);
+ }
+
+ /**
+ * 管理主机CPU品牌信息。
+ * Manger cpuBrand options of host.
+ *
+ * @param string $currentLang
+ * @access public
+ * @return void
+ */
+ public function cpuBrand($currentLang = '')
+ {
+ $this->setting('host', 'cpuBrand', 'cpuBrand', $currentLang);
+ }
+
+ /**
+ * 管理主机系统版本信息。
+ * Manger OS options of host.
+ *
+ * @param string $currentLang
+ * @param string $field
+ * @access public
+ * @return void
+ */
+ public function os($currentLang = '', $field = 'linux')
+ {
+ $this->setting('host', 'os', $field, $currentLang);
+ }
+
+ /**
+ * 自定义语言项。
+ * Manger options of lang.
+ * @param string $currentLang
+ * @access public
+ * @return void
+ */
+ public function setting($module, $method, $field = 'provider', $currentLang = '')
+ {
+ $fieldList = $field . 'List';
+ if($_POST)
+ {
+ $this->loadModel('custom');
+ $lang = $_POST['lang'];
+ $this->custom->deleteItems("lang=$lang&module=$module§ion=$fieldList");
+ foreach($_POST['keys'] as $index => $key)
+ {
+ $key = htmlspecialchars($key);
+ $value = htmlspecialchars($_POST['values'][$index]);
+ $system = htmlspecialchars($_POST['systems'][$index]);
+
+ $this->custom->setItem("{$lang}.$module.$fieldList.{$key}.{$system}", $value);
+ }
+ if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
+
+ $lang = str_replace('-', '_', $lang);
+ return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $this->createLink('ops', $method, "lang=$lang&field=$field")));
+ }
+
+ $this->app->loadLang('custom');
+ $this->app->loadLang($module);
+
+ if(empty($currentLang)) $currentLang = str_replace('-', '_', $this->app->getClientLang());
+
+ $this->view->title = $this->lang->ops->setting;
+ $this->view->position[] = $this->lang->ops->setting;
+
+ $this->view->module = $module;
+ $this->view->field = $field;
+ $this->view->fieldList = $fieldList;
+ $this->view->currentLang = $currentLang;
+ $this->display();
+ }
+}
diff --git a/module/ops/css/common.ui.css b/module/ops/css/common.ui.css
new file mode 100644
index 0000000000..e613b6ad7c
--- /dev/null
+++ b/module/ops/css/common.ui.css
@@ -0,0 +1,8 @@
+.ops-actions {margin: auto; margin-left: 10px; cursor: pointer;}
+#lang {flex-direction: row;}
+#opsForm .form-row:last-child {width: 50%;}
+.ops-header .form-label {font-weight: 700!important;}
+.osOpsList>a {display: block; padding: 2px 10px 2px 5px; overflow: hidden; line-height: 20px; text-overflow: unset; white-space: nowrap; border-radius: 4px; color: #313c52; margin-top: 5px;}
+.osOpsList>a.active {color: #2e7fff; background-color: #e6f0ff;}
+.osOpsList>a.active:hover, .osOpsList>a:hover {color: #fff; background-color: #2e7fff;}
+.ops-ml-0 {margin-left: 0!important;}
\ No newline at end of file
diff --git a/module/ops/js/common.ui.js b/module/ops/js/common.ui.js
new file mode 100644
index 0000000000..66f38d2f51
--- /dev/null
+++ b/module/ops/js/common.ui.js
@@ -0,0 +1,11 @@
+window.removeItem = function()
+{
+ $(this).parent().parent().remove();
+}
+
+window.addItem = function(e)
+{
+
+ console.log(111, e);
+ $(this).parent().parent().after(template);
+}
\ No newline at end of file
diff --git a/module/ops/lang/de.php b/module/ops/lang/de.php
new file mode 100644
index 0000000000..710442e1d2
--- /dev/null
+++ b/module/ops/lang/de.php
@@ -0,0 +1,11 @@
+ops->common = 'Devops Setting';
+$lang->ops->setting = 'Settings';
+$lang->ops->provider = 'IDC Provider';
+$lang->ops->provider = 'IDC Provider';
+$lang->ops->cpuBrand = 'CPU Brand';
+$lang->ops->city = 'IDC Location';
+$lang->ops->os = 'OS Version';
+$lang->ops->account = 'Account';
+$lang->ops->domain = 'Domain';
+$lang->ops->serverroom = 'IDC';
\ No newline at end of file
diff --git a/module/ops/lang/en.php b/module/ops/lang/en.php
new file mode 100644
index 0000000000..710442e1d2
--- /dev/null
+++ b/module/ops/lang/en.php
@@ -0,0 +1,11 @@
+ops->common = 'Devops Setting';
+$lang->ops->setting = 'Settings';
+$lang->ops->provider = 'IDC Provider';
+$lang->ops->provider = 'IDC Provider';
+$lang->ops->cpuBrand = 'CPU Brand';
+$lang->ops->city = 'IDC Location';
+$lang->ops->os = 'OS Version';
+$lang->ops->account = 'Account';
+$lang->ops->domain = 'Domain';
+$lang->ops->serverroom = 'IDC';
\ No newline at end of file
diff --git a/module/ops/lang/fr.php b/module/ops/lang/fr.php
new file mode 100644
index 0000000000..710442e1d2
--- /dev/null
+++ b/module/ops/lang/fr.php
@@ -0,0 +1,11 @@
+ops->common = 'Devops Setting';
+$lang->ops->setting = 'Settings';
+$lang->ops->provider = 'IDC Provider';
+$lang->ops->provider = 'IDC Provider';
+$lang->ops->cpuBrand = 'CPU Brand';
+$lang->ops->city = 'IDC Location';
+$lang->ops->os = 'OS Version';
+$lang->ops->account = 'Account';
+$lang->ops->domain = 'Domain';
+$lang->ops->serverroom = 'IDC';
\ No newline at end of file
diff --git a/module/ops/lang/vi.php b/module/ops/lang/vi.php
new file mode 100644
index 0000000000..710442e1d2
--- /dev/null
+++ b/module/ops/lang/vi.php
@@ -0,0 +1,11 @@
+ops->common = 'Devops Setting';
+$lang->ops->setting = 'Settings';
+$lang->ops->provider = 'IDC Provider';
+$lang->ops->provider = 'IDC Provider';
+$lang->ops->cpuBrand = 'CPU Brand';
+$lang->ops->city = 'IDC Location';
+$lang->ops->os = 'OS Version';
+$lang->ops->account = 'Account';
+$lang->ops->domain = 'Domain';
+$lang->ops->serverroom = 'IDC';
\ No newline at end of file
diff --git a/module/ops/lang/zh-cn.php b/module/ops/lang/zh-cn.php
new file mode 100644
index 0000000000..93e13faea9
--- /dev/null
+++ b/module/ops/lang/zh-cn.php
@@ -0,0 +1,11 @@
+ops->common = 'devops设置';
+$lang->ops->setting = '设置';
+$lang->ops->provider = '服务商';
+$lang->ops->provider = '服务商';
+$lang->ops->cpuBrand = 'CPU品牌';
+$lang->ops->city = '城市';
+$lang->ops->os = '系统版本';
+$lang->ops->account = '账号';
+$lang->ops->domain = '域名';
+$lang->ops->serverroom = '机房';
\ No newline at end of file
diff --git a/module/ops/lang/zh-tw.php b/module/ops/lang/zh-tw.php
new file mode 100644
index 0000000000..93e13faea9
--- /dev/null
+++ b/module/ops/lang/zh-tw.php
@@ -0,0 +1,11 @@
+ops->common = 'devops设置';
+$lang->ops->setting = '设置';
+$lang->ops->provider = '服务商';
+$lang->ops->provider = '服务商';
+$lang->ops->cpuBrand = 'CPU品牌';
+$lang->ops->city = '城市';
+$lang->ops->os = '系统版本';
+$lang->ops->account = '账号';
+$lang->ops->domain = '域名';
+$lang->ops->serverroom = '机房';
\ No newline at end of file
diff --git a/module/ops/ui/city.html.php b/module/ops/ui/city.html.php
new file mode 100644
index 0000000000..1e8a708279
--- /dev/null
+++ b/module/ops/ui/city.html.php
@@ -0,0 +1,15 @@
+
+ * @package ops
+ * @link https://www.zentao.net
+ */
+
+namespace zin;
+
+include 'setting.html.php';
diff --git a/module/ops/ui/cpubrand.html.php b/module/ops/ui/cpubrand.html.php
new file mode 100644
index 0000000000..f84c2b5225
--- /dev/null
+++ b/module/ops/ui/cpubrand.html.php
@@ -0,0 +1,15 @@
+
+ * @package ops
+ * @link https://www.zentao.net
+ */
+
+namespace zin;
+
+include 'setting.html.php';
diff --git a/module/ops/ui/os.html.php b/module/ops/ui/os.html.php
new file mode 100644
index 0000000000..1de59eed52
--- /dev/null
+++ b/module/ops/ui/os.html.php
@@ -0,0 +1,15 @@
+
+ * @package ops
+ * @link https://www.zentao.net
+ */
+
+namespace zin;
+
+include 'setting.html.php';
diff --git a/module/ops/ui/provider.html.php b/module/ops/ui/provider.html.php
new file mode 100644
index 0000000000..e4575676f3
--- /dev/null
+++ b/module/ops/ui/provider.html.php
@@ -0,0 +1,15 @@
+
+ * @package ops
+ * @link https://www.zentao.net
+ */
+
+namespace zin;
+
+include 'setting.html.php';
diff --git a/module/ops/ui/setting.html.php b/module/ops/ui/setting.html.php
new file mode 100644
index 0000000000..0a24eb03de
--- /dev/null
+++ b/module/ops/ui/setting.html.php
@@ -0,0 +1,123 @@
+
+ * @package ops
+ * @link https://www.zentao.net
+ */
+
+namespace zin;
+
+$template = <<
+
+
+
+
+
+
+
+
+
+
+
+
+EOT;
+jsVar('template', $template);
+$formRows = array();
+foreach($lang->$module->$fieldList as $key => $value)
+{
+ $formRows[] = formRow
+ (
+ formGroup
+ (
+ set::width('150px'),
+ set::label($key === '' ? 'NULL' : $key),
+ set::name('keys[]'),
+ set::control('hidden'),
+ set::value($key),
+ ),
+ input
+ (
+ set::name('systems[]'),
+ set::type('hidden'),
+ set::value(0),
+ ),
+ formGroup
+ (
+ setClass('ml-3'),
+ set::width('1/3'),
+ set::name('values[]'),
+ set::value($value),
+ set::readonly(empty($key) ? true : false)
+ ),
+ div
+ (
+ setClass('ops-actions'),
+ icon('plus', setClass('ml-2'), on::click('addItem')),
+ icon('close', setClass('ml-2'), on::click('removeItem')),
+ )
+ );
+}
+
+$appliedTo = array($this->app->getClientLang() => $lang->custom->currentLang, 'all' => $lang->custom->allLang);
+$formRows[] = formRow
+(
+ formGroup
+ (
+ set::width('1/3'),
+ set::name('lang'),
+ set::control('radioList'),
+ set::value(str_replace('_', '-', $currentLang)),
+ set::inline(true),
+ set::items($appliedTo),
+ )
+);
+
+$hasSideBar = !empty($lang->{$module}->osNameList) && array_key_exists($field, $lang->{$module}->osNameList);
+$actions = array('submit');
+if(common::hasPriv('custom', 'restore')) $actions[] = array('class' => 'ajax-submit', 'text' => $lang->custom->restore, 'data-confirm' => $lang->custom->confirmRestore, 'url' => $this->createLink('custom', 'restore', "module=$module&field=$fieldList"));
+formPanel
+(
+ setID('opsForm'),
+ $hasSideBar ? setClass('ops-ml-0') : null,
+ set::title($lang->$module->common . ' > ' . $lang->$module->$field),
+ set::actions($actions),
+ formRow
+ (
+ setClass('ops-header'),
+ formGroup
+ (
+ set::width('1/4'),
+ set::label($lang->custom->key),
+ ),
+ formGroup
+ (
+ set::width('1/3'),
+ set::label($lang->custom->value),
+ ),
+ ),
+ $formRows,
+);
+
+if($hasSideBar)
+{
+ $osListWg = array();
+ foreach($lang->{$module}->osNameList as $key => $value)
+ {
+ $osListWg[] = a(set::href(inLink('os', "lang=$currentLang&field=$key")), setClass($field == $key ? 'active' : ''), $value);
+ }
+
+ sidebar
+ (
+ div
+ (
+ setClass('flex osOpsList col p-4 bg-white'),
+ $osListWg
+ )
+ );
+}
diff --git a/module/ops/view/city.html.php b/module/ops/view/city.html.php
new file mode 100644
index 0000000000..45b6564a99
--- /dev/null
+++ b/module/ops/view/city.html.php
@@ -0,0 +1,14 @@
+
+ * @package ops
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'ops/view/setting.html.php';?>
+
diff --git a/module/ops/view/cpubrand.html.php b/module/ops/view/cpubrand.html.php
new file mode 100644
index 0000000000..45b6564a99
--- /dev/null
+++ b/module/ops/view/cpubrand.html.php
@@ -0,0 +1,14 @@
+
+ * @package ops
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'ops/view/setting.html.php';?>
+
diff --git a/module/ops/view/os.html.php b/module/ops/view/os.html.php
new file mode 100644
index 0000000000..45b6564a99
--- /dev/null
+++ b/module/ops/view/os.html.php
@@ -0,0 +1,14 @@
+
+ * @package ops
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'ops/view/setting.html.php';?>
+
diff --git a/module/ops/view/provider.html.php b/module/ops/view/provider.html.php
new file mode 100644
index 0000000000..45b6564a99
--- /dev/null
+++ b/module/ops/view/provider.html.php
@@ -0,0 +1,14 @@
+
+ * @package ops
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'ops/view/setting.html.php';?>
+
diff --git a/module/ops/view/setting.html.php b/module/ops/view/setting.html.php
new file mode 100644
index 0000000000..f07c157abf
--- /dev/null
+++ b/module/ops/view/setting.html.php
@@ -0,0 +1,96 @@
+
+ * @package ops
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'common/view/header.html.php';?>
+
+
+
+
+ |
+
+
+ |
+
+
+
+ |
+
+EOT;
+?>
+
+
+ {$module}->osNameList) && array_key_exists($field, $lang->{$module}->osNameList)):?>
+
+
+
+ {$module}->osNameList as $key => $value)
+ {
+ echo html::a(inlink('os', "field=$key"), $value, '', "id='{$key}Tab'");
+ }
+ ?>
+
+
+
+
+
+
+
+
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/module/serverroom/config.php b/module/serverroom/config.php
new file mode 100644
index 0000000000..454718bdff
--- /dev/null
+++ b/module/serverroom/config.php
@@ -0,0 +1,9 @@
+serverroom->create = new stdclass();
+$config->serverroom->create->requiredFields = 'name,line';
+$config->serverroom->edit = new stdclass();
+$config->serverroom->edit->requiredFields = 'name,line';
+
+$config->serverroom->actions = new stdclass();
+$config->serverroom->actions->view = array();
+$config->serverroom->actions->view['suffixActions'] = array('edit');
diff --git a/module/serverroom/config/dtable.php b/module/serverroom/config/dtable.php
new file mode 100644
index 0000000000..295719fbcd
--- /dev/null
+++ b/module/serverroom/config/dtable.php
@@ -0,0 +1,78 @@
+serverroom->dtable = new stdclass();
+
+$config->serverroom->dtable->fieldList['id']['title'] = 'ID';
+$config->serverroom->dtable->fieldList['id']['name'] = 'id';
+$config->serverroom->dtable->fieldList['id']['type'] = 'id';
+
+$config->serverroom->dtable->fieldList['name']['title'] = $lang->serverroom->name;
+$config->serverroom->dtable->fieldList['name']['name'] = 'name';
+$config->serverroom->dtable->fieldList['name']['type'] = 'desc';
+$config->serverroom->dtable->fieldList['name']['sortType'] = true;
+$config->serverroom->dtable->fieldList['name']['flex'] = 4;
+$config->serverroom->dtable->fieldList['name']['hint'] = true;
+$config->serverroom->dtable->fieldList['name']['link'] = array('module' => 'serverroom', 'method' => 'view', 'params' => 'id={id}');
+$config->serverroom->dtable->fieldList['name']['data-toggle'] = 'modal';
+
+$config->serverroom->dtable->fieldList['city']['title'] = $lang->serverroom->city;
+$config->serverroom->dtable->fieldList['city']['name'] = 'city';
+$config->serverroom->dtable->fieldList['city']['type'] = 'text';
+$config->serverroom->dtable->fieldList['city']['sortType'] = true;
+$config->serverroom->dtable->fieldList['city']['map'] = $lang->serverroom->cityList;
+
+$config->serverroom->dtable->fieldList['line']['title'] = $lang->serverroom->line;
+$config->serverroom->dtable->fieldList['line']['name'] = 'line';
+$config->serverroom->dtable->fieldList['line']['type'] = 'text';
+$config->serverroom->dtable->fieldList['line']['sortType'] = true;
+$config->serverroom->dtable->fieldList['line']['map'] = $lang->serverroom->lineList;
+
+$config->serverroom->dtable->fieldList['bandwidth']['title'] = $lang->serverroom->bandwidth;
+$config->serverroom->dtable->fieldList['bandwidth']['name'] = 'bandwidth';
+$config->serverroom->dtable->fieldList['bandwidth']['type'] = 'text';
+$config->serverroom->dtable->fieldList['bandwidth']['sortType'] = true;
+$config->serverroom->dtable->fieldList['bandwidth']['width'] = 80;
+
+$config->serverroom->dtable->fieldList['provider']['title'] = $lang->serverroom->provider;
+$config->serverroom->dtable->fieldList['provider']['name'] = 'provider';
+$config->serverroom->dtable->fieldList['provider']['type'] = 'text';
+$config->serverroom->dtable->fieldList['provider']['sortType'] = true;
+$config->serverroom->dtable->fieldList['provider']['width'] = 80;
+$config->serverroom->dtable->fieldList['provider']['map'] = $lang->serverroom->providerList;
+
+$config->serverroom->dtable->fieldList['owner']['title'] = $lang->serverroom->owner;
+$config->serverroom->dtable->fieldList['owner']['name'] = 'owner';
+$config->serverroom->dtable->fieldList['owner']['type'] = 'user';
+$config->serverroom->dtable->fieldList['owner']['sortType'] = true;
+
+$config->serverroom->dtable->fieldList['createdBy']['title'] = $lang->serverroom->createdBy;
+$config->serverroom->dtable->fieldList['createdBy']['name'] = 'createdBy';
+$config->serverroom->dtable->fieldList['createdBy']['type'] = 'user';
+$config->serverroom->dtable->fieldList['createdBy']['sortType'] = true;
+
+$config->serverroom->dtable->fieldList['createdDate']['title'] = $lang->serverroom->createdDate;
+$config->serverroom->dtable->fieldList['createdDate']['name'] = 'createdDate';
+$config->serverroom->dtable->fieldList['createdDate']['type'] = 'datetime';
+$config->serverroom->dtable->fieldList['createdDate']['sortType'] = true;
+
+$config->serverroom->actionList = array();
+$config->serverroom->actionList['edit']['icon'] = 'edit';
+$config->serverroom->actionList['edit']['text'] = $lang->serverroom->edit;
+$config->serverroom->actionList['edit']['hint'] = $lang->serverroom->edit;
+$config->serverroom->actionList['edit']['showText'] = true;
+$config->serverroom->actionList['edit']['url'] = array('module' => 'serverroom', 'method' => 'edit', 'params' => 'id={id}');
+
+$config->serverroom->actionList['delete']['icon'] = 'trash';
+$config->serverroom->actionList['delete']['text'] = $lang->serverroom->delete;
+$config->serverroom->actionList['delete']['hint'] = $lang->serverroom->delete;
+$config->serverroom->actionList['delete']['ajaxSubmit'] = true;
+$config->serverroom->actionList['delete']['url'] = array('module' => 'serverroom', 'method' => 'delete', 'params' => 'id={id}');
+
+$config->serverroom->dtable->fieldList['actions']['name'] = 'actions';
+$config->serverroom->dtable->fieldList['actions']['title'] = $lang->actions;
+$config->serverroom->dtable->fieldList['actions']['type'] = 'actions';
+$config->serverroom->dtable->fieldList['actions']['sortType'] = false;
+$config->serverroom->dtable->fieldList['actions']['fixed'] = 'right';
+$config->serverroom->dtable->fieldList['actions']['menu'] = array('edit', 'delete');
+$config->serverroom->dtable->fieldList['actions']['list'] = $config->serverroom->actionList;
diff --git a/module/serverroom/config/search.php b/module/serverroom/config/search.php
new file mode 100644
index 0000000000..5cb9d3691e
--- /dev/null
+++ b/module/serverroom/config/search.php
@@ -0,0 +1,27 @@
+serverroom->search['module'] = 'serverroom';
+$config->serverroom->search['fields']['name'] = $lang->serverroom->name;
+$config->serverroom->search['fields']['id'] = 'ID';
+$config->serverroom->search['fields']['city'] = $lang->serverroom->city;
+$config->serverroom->search['fields']['line'] = $lang->serverroom->line;
+$config->serverroom->search['fields']['bandwidth'] = $lang->serverroom->bandwidth;
+$config->serverroom->search['fields']['provider'] = $lang->serverroom->provider;
+$config->serverroom->search['fields']['owner'] = $lang->serverroom->owner;
+$config->serverroom->search['fields']['createdBy'] = $lang->serverroom->createdBy;
+$config->serverroom->search['fields']['createdDate'] = $lang->serverroom->createdDate;
+$config->serverroom->search['fields']['editedBy'] = $lang->serverroom->editedBy;
+$config->serverroom->search['fields']['editedDate'] = $lang->serverroom->editedDate;
+
+$config->serverroom->search['params']['name'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
+$config->serverroom->search['params']['id'] = array('operator' => '=', 'control' => 'input', 'values' => '');
+$config->serverroom->search['params']['city'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->serverroom->cityList);
+$config->serverroom->search['params']['line'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->serverroom->lineList);
+$config->serverroom->search['params']['bandwidth'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
+$config->serverroom->search['params']['provider'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->serverroom->providerList);
+$config->serverroom->search['params']['owner'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
+$config->serverroom->search['params']['createdBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
+$config->serverroom->search['params']['createdDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
+$config->serverroom->search['params']['editedBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
+$config->serverroom->search['params']['editedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
diff --git a/module/serverroom/control.php b/module/serverroom/control.php
new file mode 100644
index 0000000000..ed5bf23784
--- /dev/null
+++ b/module/serverroom/control.php
@@ -0,0 +1,153 @@
+
+ * @package serverroom
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+class serverroom extends control
+{
+ /**
+ * Server room.
+ *
+ * @param string $browseType
+ * @param int $param
+ * @param string $orderBy
+ * @param int $recTotal
+ * @param int $recPerPage
+ * @param int $pageID
+ * @access public
+ * @return void
+ */
+ public function browse($browseType = 'all', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
+ {
+ $browseType = strtolower($browseType);
+ $param = (int)$param;
+
+ $this->app->loadClass('pager', true);
+ $pager = pager::init($recTotal, $recPerPage, $pageID);
+
+ $serverRoomList = $this->serverroom->getList($browseType, $param, $orderBy, $pager);
+
+ /* Build the search form. */
+ $actionURL = $this->createLink('serverroom', 'browse', "browseType=bySearch&queryID=myQueryID");
+ $this->config->serverroom->search['actionURL'] = $actionURL;
+ $this->config->serverroom->search['queryID'] = $param;
+ $this->config->serverroom->search['onMenuBar'] = 'no';
+ $this->loadModel('search')->setSearchParams($this->config->serverroom->search);
+
+ $this->view->title = $this->lang->serverroom->common;
+ $this->view->position[] = $this->lang->serverroom->common;
+
+ $this->view->pager = $pager;
+ $this->view->param = $param;
+ $this->view->users = $this->loadModel('user')->getPairs('noletter|nodeleted');
+ $this->view->orderBy = $orderBy;
+
+ $this->view->browseType = $browseType;
+ $this->view->serverRoomList = $serverRoomList;
+ $this->display();
+ }
+
+ /**
+ * Create server room.
+ *
+ * @access public
+ * @return void
+ */
+ public function create()
+ {
+ if($_POST)
+ {
+ $createID = $this->serverroom->create();
+ if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
+
+ $this->loadModel('action')->create('serverRoom', $createID, 'created');
+ return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $this->createLink('serverroom', 'browse')));
+ }
+
+ $this->view->title = $this->lang->serverroom->create;
+ $this->view->position[] = html::a($this->createLink('serverroom', 'browse'), $this->lang->serverroom->common);
+ $this->view->position[] = $this->lang->serverroom->create;
+
+ $this->view->users = $this->loadModel('user')->getPairs('noletter|nodeleted|noclosed');
+ $this->display();
+ }
+
+ /**
+ * Edit server room.
+ *
+ * @param int $id
+ * @access public
+ * @return void
+ */
+ public function edit($id)
+ {
+ if($_POST)
+ {
+ $changes = $this->serverroom->update($id);
+ if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
+
+ if($changes)
+ {
+ $actionID = $this->loadModel('action')->create('serverRoom', $id, 'Edited');
+ $this->action->logHistory($actionID, $changes);
+ }
+
+ return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => $this->createLink('serverroom', 'view', "room=$id")));
+ }
+
+ $this->view->title = $this->lang->serverroom->edit;
+ $this->view->serverRoom = $this->serverroom->getById($id);
+ $this->view->position[] = html::a($this->createLink('serverroom', 'browse'), $this->lang->serverroom->common);
+ $this->view->position[] = $this->lang->serverroom->edit;
+
+ $this->view->users = $this->loadModel('user')->getPairs('noletter|nodeleted|noclosed');
+ $this->display();
+ }
+
+ public function view($id)
+ {
+ $this->view->title = $this->lang->serverroom->view;
+ $this->view->serverRoom = $this->serverroom->getById($id);
+ $this->view->users = $this->loadModel('user')->getPairs('noletter|nodeleted');
+ $this->view->actions = $this->loadModel('action')->getList('serverroom', $id);
+
+ $this->view->position[] = html::a($this->createLink('serverroom', 'browse'), $this->lang->serverroom->common);
+ $this->view->position[] = $this->lang->serverroom->view;
+
+ $this->display();
+ }
+
+ /**
+ * Delete server room.
+ *
+ * @param int $id
+ * @access public
+ * @return void
+ */
+ public function delete($id)
+ {
+ $this->serverroom->delete(TABLE_SERVERROOM, $id);
+
+ if(dao::isError())
+ {
+ $response['result'] = 'fail';
+ $response['message'] = dao::getError();
+ }
+ else
+ {
+ $response['result'] = 'success';
+ $response['message'] = '';
+ $response['load'] = true;
+ }
+ return $this->send($response);
+ }
+}
diff --git a/module/serverroom/css/browse.css b/module/serverroom/css/browse.css
new file mode 100644
index 0000000000..2825f42c9d
--- /dev/null
+++ b/module/serverroom/css/browse.css
@@ -0,0 +1 @@
+/* #serverRoomList td{white-space: nowrap; text-overflow: ellipsis; overflow: hidden;} */
diff --git a/module/serverroom/css/common.ui.css b/module/serverroom/css/common.ui.css
new file mode 100644
index 0000000000..233e6cd0bd
--- /dev/null
+++ b/module/serverroom/css/common.ui.css
@@ -0,0 +1 @@
+#serverroomCreateForm .form-row {width: 600px;}
\ No newline at end of file
diff --git a/module/serverroom/js/browse.ui.js b/module/serverroom/js/browse.ui.js
new file mode 100644
index 0000000000..f0c0aba9d3
--- /dev/null
+++ b/module/serverroom/js/browse.ui.js
@@ -0,0 +1,7 @@
+window.createSortLink = function(col)
+{
+ var sort = col.name + '_asc';
+ if(sort == orderBy) sort = col.name + '_desc';
+
+ return sortLink.replace('{orderBy}', sort);
+}
\ No newline at end of file
diff --git a/module/serverroom/js/custom.js b/module/serverroom/js/custom.js
new file mode 100644
index 0000000000..38ee2afa87
--- /dev/null
+++ b/module/serverroom/js/custom.js
@@ -0,0 +1,9 @@
+function addItem(clickedButton)
+{
+ $(clickedButton).parent().parent().after(itemRow);
+}
+
+function delItem(clickedButton)
+{
+ $(clickedButton).parent().parent().remove();
+}
diff --git a/module/serverroom/lang/de.php b/module/serverroom/lang/de.php
new file mode 100644
index 0000000000..88a51cbffd
--- /dev/null
+++ b/module/serverroom/lang/de.php
@@ -0,0 +1,44 @@
+serverroom->common = 'IDC';
+$lang->serverroom->browse = 'IDC List';
+$lang->serverroom->create = 'Add IDC';
+$lang->serverroom->edit = 'Edit';
+$lang->serverroom->editAction = 'Edit IDC';
+$lang->serverroom->delete = 'Delete IDC';
+$lang->serverroom->view = 'IDC Detail';
+$lang->serverroom->all = 'All';
+$lang->serverroom->byQuery = 'Search';
+$lang->serverroom->name = 'Name';
+$lang->serverroom->city = 'City';
+$lang->serverroom->line = 'Line';
+$lang->serverroom->bandwidth = 'Bandwidth';
+$lang->serverroom->provider = 'Provider';
+$lang->serverroom->owner = 'Manager';
+$lang->serverroom->region = 'Area';
+$lang->serverroom->createdBy = 'CreatedBy';
+$lang->serverroom->createdDate = 'CreatedDate';
+$lang->serverroom->editedBy = 'EditedBy';
+$lang->serverroom->editedDate = 'Edited';
+$lang->serverroom->noneCity = 'N/A';
+
+$lang->serverroom->empty = 'No IDC';
+
+$lang->serverroom->lineList[''] = '';
+$lang->serverroom->lineList['telecom'] = 'Telecom';
+$lang->serverroom->lineList['unicom'] = 'Unicom';
+$lang->serverroom->lineList['mobile'] = 'Mobile';
+$lang->serverroom->lineList['double'] = 'Double';
+$lang->serverroom->lineList['bgp'] = 'BGP';
+
+$lang->serverroom->confirmDelete = 'Do you want to delete this IDC?';
+
+$lang->serverroom->providerList[''] = '';
+$lang->serverroom->providerList['aliyun'] = 'Ali Cloud';
+$lang->serverroom->providerList['qingyun'] = 'Qing Cloud';
+
+$lang->serverroom->cityList[''] = '';
+$lang->serverroom->cityList['beijing'] = 'Beijing';
+$lang->serverroom->cityList['hangzhou'] = 'Hangzhou';
+$lang->serverroom->cityList['guangdong'] = 'Guangdong';
+
+$lang->serverroom->featureBar['browse']['all'] = $lang->serverroom->all;
diff --git a/module/serverroom/lang/en.php b/module/serverroom/lang/en.php
new file mode 100644
index 0000000000..88a51cbffd
--- /dev/null
+++ b/module/serverroom/lang/en.php
@@ -0,0 +1,44 @@
+serverroom->common = 'IDC';
+$lang->serverroom->browse = 'IDC List';
+$lang->serverroom->create = 'Add IDC';
+$lang->serverroom->edit = 'Edit';
+$lang->serverroom->editAction = 'Edit IDC';
+$lang->serverroom->delete = 'Delete IDC';
+$lang->serverroom->view = 'IDC Detail';
+$lang->serverroom->all = 'All';
+$lang->serverroom->byQuery = 'Search';
+$lang->serverroom->name = 'Name';
+$lang->serverroom->city = 'City';
+$lang->serverroom->line = 'Line';
+$lang->serverroom->bandwidth = 'Bandwidth';
+$lang->serverroom->provider = 'Provider';
+$lang->serverroom->owner = 'Manager';
+$lang->serverroom->region = 'Area';
+$lang->serverroom->createdBy = 'CreatedBy';
+$lang->serverroom->createdDate = 'CreatedDate';
+$lang->serverroom->editedBy = 'EditedBy';
+$lang->serverroom->editedDate = 'Edited';
+$lang->serverroom->noneCity = 'N/A';
+
+$lang->serverroom->empty = 'No IDC';
+
+$lang->serverroom->lineList[''] = '';
+$lang->serverroom->lineList['telecom'] = 'Telecom';
+$lang->serverroom->lineList['unicom'] = 'Unicom';
+$lang->serverroom->lineList['mobile'] = 'Mobile';
+$lang->serverroom->lineList['double'] = 'Double';
+$lang->serverroom->lineList['bgp'] = 'BGP';
+
+$lang->serverroom->confirmDelete = 'Do you want to delete this IDC?';
+
+$lang->serverroom->providerList[''] = '';
+$lang->serverroom->providerList['aliyun'] = 'Ali Cloud';
+$lang->serverroom->providerList['qingyun'] = 'Qing Cloud';
+
+$lang->serverroom->cityList[''] = '';
+$lang->serverroom->cityList['beijing'] = 'Beijing';
+$lang->serverroom->cityList['hangzhou'] = 'Hangzhou';
+$lang->serverroom->cityList['guangdong'] = 'Guangdong';
+
+$lang->serverroom->featureBar['browse']['all'] = $lang->serverroom->all;
diff --git a/module/serverroom/lang/fr.php b/module/serverroom/lang/fr.php
new file mode 100644
index 0000000000..a33eefbe71
--- /dev/null
+++ b/module/serverroom/lang/fr.php
@@ -0,0 +1,44 @@
+serverroom->common = 'IDC';
+$lang->serverroom->browse = 'Liste IDC';
+$lang->serverroom->create = 'Ajout IDC';
+$lang->serverroom->edit = 'Editer';
+$lang->serverroom->editAction = 'Editer IDC';
+$lang->serverroom->delete = 'Suppr. IDC';
+$lang->serverroom->view = 'Détails IDC';
+$lang->serverroom->all = 'Tout';
+$lang->serverroom->byQuery = 'Recherche';
+$lang->serverroom->name = 'Nom';
+$lang->serverroom->city = 'Ville';
+$lang->serverroom->line = 'Ligne';
+$lang->serverroom->bandwidth = 'Bande Passante';
+$lang->serverroom->provider = 'Provider';
+$lang->serverroom->owner = 'Manager';
+$lang->serverroom->region = 'Zone';
+$lang->serverroom->createdBy = 'Créateur';
+$lang->serverroom->createdDate = 'Date de création';
+$lang->serverroom->editedBy = 'Éditeur';
+$lang->serverroom->editedDate = "Date d'édition";
+$lang->serverroom->noneCity = 'N/A';
+
+$lang->serverroom->empty = 'No IDC';
+
+$lang->serverroom->lineList[''] = '';
+$lang->serverroom->lineList['telecom'] = 'Telecom';
+$lang->serverroom->lineList['unicom'] = 'Unicom';
+$lang->serverroom->lineList['mobile'] = 'Mobile';
+$lang->serverroom->lineList['double'] = 'Double';
+$lang->serverroom->lineList['bgp'] = 'BGP';
+
+$lang->serverroom->confirmDelete = 'Voulez-vous supprimer cet IDC ?';
+
+$lang->serverroom->providerList[''] = '';
+$lang->serverroom->providerList['aliyun'] = 'Ali Cloud';
+$lang->serverroom->providerList['qingyun'] = 'Qing Cloud';
+
+$lang->serverroom->cityList[''] = '';
+$lang->serverroom->cityList['beijing'] = 'Beijing';
+$lang->serverroom->cityList['hangzhou'] = 'Hangzhou';
+$lang->serverroom->cityList['guangdong'] = 'Guangdong';
+
+$lang->serverroom->featureBar['browse']['all'] = $lang->serverroom->all;
diff --git a/module/serverroom/lang/vi.php b/module/serverroom/lang/vi.php
new file mode 100644
index 0000000000..3fa4a3b916
--- /dev/null
+++ b/module/serverroom/lang/vi.php
@@ -0,0 +1,43 @@
+serverroom->common = 'IDC';
+$lang->serverroom->browse = 'Danh sách IDC';
+$lang->serverroom->create = 'Thêm IDC';
+$lang->serverroom->edit = 'Sửa';
+$lang->serverroom->editAction = 'Sửa IDC';
+$lang->serverroom->delete = 'Xóa IDC';
+$lang->serverroom->view = 'Chi tiết IDC';
+$lang->serverroom->all = 'Tất cả';
+$lang->serverroom->byQuery = 'Tìm kiếm';
+$lang->serverroom->name = 'Tên';
+$lang->serverroom->city = 'City';
+$lang->serverroom->line = 'Dòng';
+$lang->serverroom->bandwidth = 'Băng thông';
+$lang->serverroom->provider = 'Nhà cung cấp';
+$lang->serverroom->owner = 'Quản lý';
+$lang->serverroom->region = 'Khu vực';
+$lang->serverroom->createdBy = 'Người tạo';
+$lang->serverroom->createdDate = 'Ngày tạo';
+$lang->serverroom->editedBy = 'Người sửa';
+$lang->serverroom->editedDate = 'Ngày sửa';
+$lang->serverroom->noneCity = 'N/A';
+
+$lang->serverroom->lineList[''] = '';
+$lang->serverroom->lineList['fpt'] = 'FPT Telecom';
+$lang->serverroom->lineList['vietel'] = 'Vietel Telecom';
+$lang->serverroom->lineList['mobile'] = 'Mobile';
+$lang->serverroom->lineList['vnpt'] = 'VNPT Telecom';
+$lang->serverroom->lineList['bgp'] = 'BGP';
+
+$lang->serverroom->confirmDelete = 'Bạn có muốn xóa IDC này?';
+
+$lang->serverroom->providerList[''] = '';
+$lang->serverroom->providerList['vietel'] = 'Vietel';
+$lang->serverroom->providerList['nhanhoa'] = 'Nhân hòa';
+
+$lang->serverroom->cityList[''] = '';
+$lang->serverroom->cityList['hanoi'] = 'Hà Nội';
+$lang->serverroom->cityList['hcm'] = 'Hồ Chí Minh';
+$lang->serverroom->cityList['danang'] = 'Đà Năng';
+$lang->serverroom->cityList['haiphong'] = 'Hải Phòng';
+
+$lang->serverroom->featureBar['browse']['all'] = $lang->serverroom->all;
diff --git a/module/serverroom/lang/zh-cn.php b/module/serverroom/lang/zh-cn.php
new file mode 100644
index 0000000000..84bc12c721
--- /dev/null
+++ b/module/serverroom/lang/zh-cn.php
@@ -0,0 +1,44 @@
+serverroom->common = '机房';
+$lang->serverroom->browse = '机房列表';
+$lang->serverroom->create = '添加机房';
+$lang->serverroom->edit = '编辑';
+$lang->serverroom->editAction = '编辑机房';
+$lang->serverroom->delete = '删除机房';
+$lang->serverroom->view = '机房详情';
+$lang->serverroom->all = '全部';
+$lang->serverroom->byQuery = '搜索';
+$lang->serverroom->name = '名称';
+$lang->serverroom->city = '所在城市';
+$lang->serverroom->line = '线路类型';
+$lang->serverroom->bandwidth = '带宽';
+$lang->serverroom->provider = '服务商';
+$lang->serverroom->owner = '负责人';
+$lang->serverroom->region = '区域';
+$lang->serverroom->createdBy = '由谁创建';
+$lang->serverroom->createdDate = '创建时间';
+$lang->serverroom->editedBy = '由谁编辑';
+$lang->serverroom->editedDate = '编辑时间';
+$lang->serverroom->noneCity = '无城市';
+
+$lang->serverroom->empty = '暂时没有机房';
+
+$lang->serverroom->lineList[''] = '';
+$lang->serverroom->lineList['telecom'] = '电信';
+$lang->serverroom->lineList['unicom'] = '联通';
+$lang->serverroom->lineList['mobile'] = '移动';
+$lang->serverroom->lineList['double'] = '双线';
+$lang->serverroom->lineList['bgp'] = 'BGP';
+
+$lang->serverroom->confirmDelete = '是否删除该机房记录?';
+
+$lang->serverroom->providerList[''] = '';
+$lang->serverroom->providerList['aliyun'] = '阿里云';
+$lang->serverroom->providerList['qingyun'] = '青云';
+
+$lang->serverroom->cityList[''] = '';
+$lang->serverroom->cityList['beijing'] = '北京';
+$lang->serverroom->cityList['hangzhou'] = '杭州';
+$lang->serverroom->cityList['guangdong'] = '广东';
+
+$lang->serverroom->featureBar['browse']['all'] = $lang->serverroom->all;
diff --git a/module/serverroom/lang/zh-tw.php b/module/serverroom/lang/zh-tw.php
new file mode 100644
index 0000000000..0fe5f6f9c2
--- /dev/null
+++ b/module/serverroom/lang/zh-tw.php
@@ -0,0 +1,41 @@
+serverroom->common = '機房';
+$lang->serverroom->browse = '機房列表';
+$lang->serverroom->create = '添加機房';
+$lang->serverroom->edit = '編輯';
+$lang->serverroom->delete = '刪除';
+$lang->serverroom->view = '機房詳情';
+$lang->serverroom->all = '所有';
+$lang->serverroom->byQuery = '搜索';
+$lang->serverroom->name = '名稱';
+$lang->serverroom->city = '所在城市';
+$lang->serverroom->line = '線路類型';
+$lang->serverroom->bandwidth = '頻寬';
+$lang->serverroom->provider = '服務商';
+$lang->serverroom->owner = '負責人';
+$lang->serverroom->region = '區域';
+$lang->serverroom->createdBy = '由誰創建';
+$lang->serverroom->createdDate = '創建時間';
+$lang->serverroom->editedBy = '由誰編輯';
+$lang->serverroom->editedDate = '編輯時間';
+$lang->serverroom->noneCity = '無城市';
+
+$lang->serverroom->lineList[''] = '';
+$lang->serverroom->lineList['telecom'] = '電信';
+$lang->serverroom->lineList['unicom'] = '聯通';
+$lang->serverroom->lineList['mobile'] = '移動';
+$lang->serverroom->lineList['double'] = '雙線';
+$lang->serverroom->lineList['bgp'] = 'BGP';
+
+$lang->serverroom->confirmDelete = '是否刪除該機房記錄?';
+
+$lang->serverroom->providerList[''] = '';
+$lang->serverroom->providerList['aliyun'] = '阿里雲';
+$lang->serverroom->providerList['qingyun'] = '青雲';
+
+$lang->serverroom->cityList[''] = '';
+$lang->serverroom->cityList['beijing'] = '北京';
+$lang->serverroom->cityList['hangzhou'] = '杭州';
+$lang->serverroom->cityList['guangdong'] = '廣東';
+
+$lang->serverroom->featureBar['browse']['all'] = $lang->serverroom->all;
diff --git a/module/serverroom/model.php b/module/serverroom/model.php
new file mode 100644
index 0000000000..7f3144d363
--- /dev/null
+++ b/module/serverroom/model.php
@@ -0,0 +1,144 @@
+
+ * @package ops
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+class serverroomModel extends model
+{
+ /**
+ * Get by id.
+ *
+ * @param int $id
+ * @access public
+ * @return object
+ */
+ public function getById($id)
+ {
+ return $this->dao->select('*')->from(TABLE_SERVERROOM)->where('id')->eq($id)->fetch();
+ }
+
+ /**
+ * Get room list.
+ *
+ * @param string $browseType
+ * @param int $param
+ * @param string $orderBy
+ * @param object $pager
+ * @access public
+ * @return array
+ */
+ public function getList($browseType = 'all', $param = 0, $orderBy = 'id_desc', $pager = null)
+ {
+ $query = '';
+ if($browseType == 'bysearch')
+ {
+ if($param)
+ {
+ $query = $this->loadModel('search')->getQuery($param);
+ if($query)
+ {
+ $this->session->set('serverroomQuery', $query->sql);
+ $this->session->set('serverroomForm', $query->form);
+ }
+ else
+ {
+ $this->session->set('serverroomQuery', ' 1 = 1');
+ }
+ }
+ else
+ {
+ if($this->session->serverroomQuery == false) $this->session->set('serverroomQuery', ' 1 = 1');
+ }
+ $query = $this->session->serverroomQuery;
+ }
+
+ $serverRooms = $this->dao->select('*')->from(TABLE_SERVERROOM)
+ ->where('deleted')->eq('0')
+ ->beginIF($query)->andWhere($query)->fi()
+ ->orderBy($orderBy)
+ ->page($pager)
+ ->fetchAll();
+ return $serverRooms;
+ }
+
+ /**
+ * Get server room pairs
+ *
+ * @access public
+ * @return array
+ */
+ public function getPairs()
+ {
+ $stmt = $this->dao->select('*')->from(TABLE_SERVERROOM)
+ ->where('deleted')->eq('0')
+ ->orderBy('id_desc')
+ ->query();
+
+ $rooms[0] = '';
+ while($room = $stmt->fetch())
+ {
+ $name = zget($this->lang->serverroom->cityList, $room->city) == '' ? '' : zget($this->lang->serverroom->cityList, $room->city) . ' - ';
+ $name .= zget($this->lang->serverroom->providerList, $room->provider) == '' ? '' : zget($this->lang->serverroom->providerList, $room->provider) . ' - ';
+ $name .= $room->name;
+ $rooms[$room->id] = $name;
+ }
+ return $rooms;
+ }
+
+ /**
+ * Create.
+ *
+ * @access public
+ * @return int
+ */
+ public function create()
+ {
+ $now = helper::now();
+ $room = fixer::input('post')
+ ->add('createdBy', $this->app->user->account)
+ ->add('createdDate', $now)
+ ->get();
+
+ $this->dao->insert(TABLE_SERVERROOM)->data($room)->autoCheck()
+ ->batchCheck($this->config->serverroom->create->requiredFields, 'notempty')
+ ->exec();
+
+ if(!dao::isError())
+ {
+ $roomID = $this->dao->lastInsertID();
+ return $roomID;
+ }
+ return false;
+ }
+
+ /**
+ * Update
+ *
+ * @param int $id
+ * @access public
+ * @return array
+ */
+ public function update($id)
+ {
+ $oldRoom = $this->getById($id);
+ $now = helper::now();
+ $room = fixer::input('post')
+ ->add('editedBy', $this->app->user->account)
+ ->add('editedDate', $now)
+ ->get();
+
+ $this->dao->update(TABLE_SERVERROOM)->data($room)->autoCheck()
+ ->batchCheck($this->config->serverroom->edit->requiredFields, 'notempty')
+ ->where('id')->eq($id)
+ ->exec();
+
+ if(!dao::isError()) return common::createChanges($oldRoom, $room);
+ return false;
+ }
+}
diff --git a/module/serverroom/ui/browse.html.php b/module/serverroom/ui/browse.html.php
new file mode 100644
index 0000000000..75dbb83aea
--- /dev/null
+++ b/module/serverroom/ui/browse.html.php
@@ -0,0 +1,41 @@
+
+ * @package serverroom
+ * @link http://www.zentao.net
+ */
+
+namespace zin;
+
+featureBar(li(searchToggle()));
+
+/* zin: Define the toolbar on main menu. */
+$canCreate = hasPriv('serverroom', 'create');
+$createLink = $this->createLink('serverroom', 'create');
+$createItem = array('text' => $lang->serverroom->create, 'url' => $createLink, 'class' => 'primary', 'icon' => 'plus');
+
+$tableData = initTableData($serverRoomList, $config->serverroom->dtable->fieldList, $this->serverroom);
+
+toolbar
+(
+ $canCreate ? item(set($createItem)) : null,
+);
+
+jsVar('orderBy', $orderBy);
+jsVar('sortLink', helper::createLink('serverroom', 'browse', "browseType=$browseType¶m=$param&orderBy={orderBy}&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}"));
+
+dtable
+(
+ set::userMap($users),
+ set::cols(array_values($config->serverroom->dtable->fieldList)),
+ set::data($tableData),
+ set::sortLink(jsRaw('createSortLink')),
+ set::footPager(usePager()),
+);
+
+render();
diff --git a/module/serverroom/ui/create.html.php b/module/serverroom/ui/create.html.php
new file mode 100644
index 0000000000..fd53120b86
--- /dev/null
+++ b/module/serverroom/ui/create.html.php
@@ -0,0 +1,85 @@
+
+ * @package serverroom
+ * @link https://www.zentao.net
+ */
+
+namespace zin;
+
+formPanel
+(
+ set::id('serverroomCreateForm'),
+ set::title($lang->serverroom->create),
+ formRow
+ (
+ formGroup
+ (
+ set::name('name'),
+ set::label($lang->serverroom->name),
+ set::value($serverroom->name),
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::name('bandwidth'),
+ set::label($lang->serverroom->bandwidth),
+ set::value($serverroom->bandwidth),
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('1/2'),
+ set::label($lang->serverroom->city),
+ set::control('picker'),
+ set::name('city'),
+ set::items($lang->serverroom->cityList),
+ set::value($serverroom->city)
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('1/2'),
+ set::label($lang->serverroom->line),
+ set::control('picker'),
+ set::name('line'),
+ set::items($lang->serverroom->lineList),
+ set::value($serverroom->line)
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('1/2'),
+ set::label($lang->serverroom->provider),
+ set::control('picker'),
+ set::name('provider'),
+ set::items($lang->serverroom->providerList),
+ set::value($serverroom->provider)
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('1/2'),
+ set::label($lang->serverroom->owner),
+ set::control('picker'),
+ set::name('owner'),
+ set::items($users),
+ set::value($serverroom->owner)
+ )
+ ),
+);
diff --git a/module/serverroom/ui/edit.html.php b/module/serverroom/ui/edit.html.php
new file mode 100644
index 0000000000..475f4f0551
--- /dev/null
+++ b/module/serverroom/ui/edit.html.php
@@ -0,0 +1,87 @@
+
+ * @package serverroom
+ * @link https://www.zentao.net
+ */
+
+namespace zin;
+
+formPanel
+(
+ set::id('serverroomCreateForm'),
+ set::title($lang->serverroom->edit),
+ formRow
+ (
+ formGroup
+ (
+ set::width('600px'),
+ set::name('name'),
+ set::label($lang->serverroom->name),
+ set::value($serverRoom->name),
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('600px'),
+ set::name('bandwidth'),
+ set::label($lang->serverroom->bandwidth),
+ set::value($serverRoom->bandwidth),
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('300px'),
+ set::label($lang->serverroom->city),
+ set::control('picker'),
+ set::name('city'),
+ set::items($lang->serverroom->cityList),
+ set::value($serverRoom->city)
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('300px'),
+ set::label($lang->serverroom->line),
+ set::control('picker'),
+ set::name('line'),
+ set::items($lang->serverroom->lineList),
+ set::value($serverRoom->line)
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('300px'),
+ set::label($lang->serverroom->provider),
+ set::control('picker'),
+ set::name('provider'),
+ set::items($lang->serverroom->providerList),
+ set::value($serverRoom->provider)
+ )
+ ),
+ formRow
+ (
+ formGroup
+ (
+ set::width('300px'),
+ set::label($lang->serverroom->owner),
+ set::control('picker'),
+ set::name('owner'),
+ set::items($users),
+ set::value($serverRoom->owner)
+ )
+ ),
+);
diff --git a/module/serverroom/ui/view.html.php b/module/serverroom/ui/view.html.php
new file mode 100644
index 0000000000..bdc770b95a
--- /dev/null
+++ b/module/serverroom/ui/view.html.php
@@ -0,0 +1,86 @@
+
+ * @package serverroom
+ * @link https://www.zentao.net
+ */
+namespace zin;
+global $lang;
+
+$actions = $this->loadModel('common')->buildOperateMenu($serverRoom);
+
+detailHeader
+(
+ isAjaxRequest('modal') ? to::prefix() : '',
+ to::title(
+ entityLabel(
+ set(array('entityID' => $serverRoom->id, 'level' => 1, 'text' => $serverRoom->name))
+ )
+ ),
+);
+
+detailBody
+(
+ sectionList
+ (
+ section
+ (
+ tableData
+ (
+ item
+ (
+ set::name($lang->serverroom->name),
+ $serverRoom->name
+ ),
+ item
+ (
+ set::name($lang->serverroom->city),
+ \zget($lang->serverroom->cityList, $serverRoom->city)
+ ),
+ item
+ (
+ set::name($lang->serverroom->line),
+ \zget($lang->serverroom->lineList, $serverRoom->line)
+ ),
+ item
+ (
+ set::name($lang->serverroom->bandwidth),
+ $serverRoom->bandwidth
+ ),
+ item
+ (
+ set::name($lang->serverroom->provider),
+ \zget($lang->serverroom->providerList, $serverRoom->provider)
+ ),
+ item
+ (
+ set::name($lang->serverroom->owner),
+ \zget($users, $serverRoom->owner)
+ ),
+ item
+ (
+ set::name($lang->serverroom->createdBy),
+ \zget($users, $serverRoom->createdBy)
+ ),
+ item
+ (
+ set::name($lang->serverroom->createdDate),
+ $serverRoom->createdDate
+ ),
+ )
+ ),
+ ),
+ history(),
+ floatToolbar
+ (
+ set::object($serverRoom),
+ isAjaxRequest('modal') ? null : to::prefix(backBtn(set::icon('back'), set::class('ghost text-white'), $lang->goback)),
+ set::suffix($actions['suffixActions'])
+ ),
+);
+
+render();
diff --git a/module/serverroom/view/browse.html.php b/module/serverroom/view/browse.html.php
new file mode 100644
index 0000000000..25fc21385e
--- /dev/null
+++ b/module/serverroom/view/browse.html.php
@@ -0,0 +1,97 @@
+
+ * @package serverRoom
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'common/view/header.html.php';?>
+serverroom->confirmDelete)?>
+
+
+' data-module='serverroom'>
+
+
+
+
+ serverroom->empty;?>
+ ' . $lang->serverroom->create, '', 'class="btn btn-info"');?>
+
+
+
+
+
+ recTotal}&recPerPage={$pager->recPerPage}";?>
+
+ | idAB);?> |
+ serverroom->name);?> |
+ serverroom->city);?> |
+ serverroom->line);?> |
+ serverroom->bandwidth);?> |
+ serverroom->provider);?> |
+ serverroom->owner);?> |
+ serverroom->createdBy);?> |
+ serverroom->createdDate);?> |
+ actions?> |
+
+
+
+
+
+ | id;?> |
+ inlink('view', "id=$serverRoom->id", 'html', true), $serverRoom->name, '', "class='iframe'");?> |
+ serverroom->cityList, $serverRoom->city)?> |
+ serverroom->lineList, $serverRoom->line);?> |
+ bandwidth;?> |
+ serverroom->providerList, $serverRoom->provider);?>
+ |
+ owner);?> |
+ createdBy);?> |
+ createdDate;?> |
+
+ id", $serverRoom, '', 'edit');
+ if(common::hasPriv('serverroom', 'delete', $serverRoom))
+ {
+ $deleteURL = $this->createLink('serverroom', 'delete', "id=$serverRoom->id");
+ echo html::a("javascript:ajaxDelete(\"$deleteURL\", \"mainContent\", confirmDelete)", '', '', "class='btn' title='{$lang->serverroom->delete}'");
+ }
+ ?>
+ |
+
+
+
+
+
+
+
+
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/module/serverroom/view/create.html.php b/module/serverroom/view/create.html.php
new file mode 100644
index 0000000000..cd2deb4459
--- /dev/null
+++ b/module/serverroom/view/create.html.php
@@ -0,0 +1,54 @@
+
+ * @package serverRoom
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'common/view/header.html.php';?>
+
+
+
serverroom->create?>
+
+
+
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/module/serverroom/view/edit.html.php b/module/serverroom/view/edit.html.php
new file mode 100644
index 0000000000..e4633b0494
--- /dev/null
+++ b/module/serverroom/view/edit.html.php
@@ -0,0 +1,58 @@
+
+ * @package serverRoom
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'common/view/header.html.php';?>
+
+
+
+ id;?>
+ name;?>
+ arrow . $lang->serverroom->edit?>
+
+
+
+
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/module/serverroom/view/m.browse.html.php b/module/serverroom/view/m.browse.html.php
new file mode 100644
index 0000000000..336a560eb7
--- /dev/null
+++ b/module/serverroom/view/m.browse.html.php
@@ -0,0 +1,30 @@
+getModuleRoot() . 'common/view/m.header.html.php';?>
+
+getModuleRoot() . 'common/view/m.footer.html.php';?>
diff --git a/module/serverroom/view/m.view.html.php b/module/serverroom/view/m.view.html.php
new file mode 100644
index 0000000000..815ba2e4a2
--- /dev/null
+++ b/module/serverroom/view/m.view.html.php
@@ -0,0 +1,47 @@
+getModuleRoot() . 'common/view/m.header.html.php';?>
+
+getModuleRoot() . 'common/view/m.footer.html.php';?>
diff --git a/module/serverroom/view/view.html.php b/module/serverroom/view/view.html.php
new file mode 100644
index 0000000000..1e21a6e856
--- /dev/null
+++ b/module/serverroom/view/view.html.php
@@ -0,0 +1,69 @@
+
+ * @package serverroom
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'common/view/header.html.php';?>
+serverroom->confirmDelete)?>
+
+
+
serverroom->view;?>
+
+
+
+ getModuleRoot() . 'common/view/action.html.php'?>
+
+
+
+
+ id", " " . $lang->edit, '', "class='btn'", '', '', $serverRoom);
+ if(!isonlybody()) common::printLink('serverroom', 'browse', "", " " . $lang->goback, '', "class='btn'");
+ ?>
+
+
+
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/module/tree/model.php b/module/tree/model.php
index 0bf796cfde..39d12ef757 100644
--- a/module/tree/model.php
+++ b/module/tree/model.php
@@ -890,6 +890,34 @@ class treeModel extends model
return $menu;
}
+ /**
+ * Get project story tree menu.
+ *
+ * @access public
+ * @return array
+ */
+ public function getHostTreeMenu(): array
+ {
+ $menu = array();
+ /* tree menu. */
+ $treeMenu = array();
+ $stmt = $this->dao->select('*')->from(TABLE_MODULE)
+ ->where('type')->eq('host')
+ ->andWhere('deleted')->eq(0)
+ ->orderBy('grade_desc,id_asc')
+ ->query();
+
+ while($module = $stmt->fetch())
+ {
+ $treeMenu = $this->buildTree($module, '', 0, array('treeModel', 'createHostLink'));
+ if($module->parent == 0) $treeMenu->parent = $module->root;
+
+ $menu[] = $treeMenu;
+ }
+
+ return $menu;
+ }
+
/**
* Build tree.
*