提交 4818f2a8 编写于 作者: L lepdou

用户打点& 多处优化

上级 d706ac7f
......@@ -55,15 +55,6 @@ public class ReleaseController {
return BeanUtils.batchTransform(ReleaseDTO.class, releases);
}
// TODO: 16/7/25 兼容老接口,下版本删除
@RequestMapping("/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases")
public List<ReleaseDTO> findReleases(@PathVariable("appId") String appId,
@PathVariable("clusterName") String clusterName,
@PathVariable("namespaceName") String namespaceName,
Pageable page) {
List<Release> releases = releaseService.findAllReleases(appId, clusterName, namespaceName, page);
return BeanUtils.batchTransform(ReleaseDTO.class, releases);
}
@RequestMapping("/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/active")
public List<ReleaseDTO> findActiveReleases(@PathVariable("appId") String appId,
......
package com.ctrip.framework.apollo.portal.configutation;
package com.ctrip.framework.apollo.portal.configuration;
import com.ctrip.framework.apollo.portal.auth.ctrip.CtripLogoutHandler;
import com.ctrip.framework.apollo.portal.auth.ctrip.CtripSsoHeartbeatHandler;
......
package com.ctrip.framework.apollo.portal.configutation;
package com.ctrip.framework.apollo.portal.configuration;
import com.google.common.base.Strings;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.filters.RecordAccessUserFilter;
import com.ctrip.framework.apollo.portal.service.ServerConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.boot.context.embedded.ServletContextInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
......@@ -15,13 +18,15 @@ import javax.servlet.ServletException;
@Configuration
@Profile("ctrip")
public class ServletContextConfiguration {
public class WebContextConfiguration {
@Autowired
private ServerConfigService serverConfigService;
@Autowired
private UserInfoHolder userInfoHolder;
@Bean
public ServletContextInitializer initializer() {
public ServletContextInitializer servletContextInitializer() {
return new ServletContextInitializer() {
......@@ -31,13 +36,21 @@ public class ServletContextConfiguration {
String loggingServerPort = serverConfigService.getValue("loggingServerPort");
String credisServiceUrl = serverConfigService.getValue("credisServiceUrl");
servletContext.setInitParameter("loggingServerIP",
Strings.isNullOrEmpty(loggingServerIP) ? "" : loggingServerIP);
Strings.isNullOrEmpty(loggingServerIP) ? "" : loggingServerIP);
servletContext.setInitParameter("loggingServerPort",
Strings.isNullOrEmpty(loggingServerPort) ? "" : loggingServerPort);
Strings.isNullOrEmpty(loggingServerPort) ? "" : loggingServerPort);
servletContext.setInitParameter("credisServiceUrl",
Strings.isNullOrEmpty(credisServiceUrl) ? "" : credisServiceUrl);
Strings.isNullOrEmpty(credisServiceUrl) ? "" : credisServiceUrl);
}
};
}
@Bean
public FilterRegistrationBean recordAccessUserFilter() {
FilterRegistrationBean filter = new FilterRegistrationBean();
filter.setFilter(new RecordAccessUserFilter(userInfoHolder));
filter.addUrlPatterns("/apps");
return filter;
}
}
......@@ -18,4 +18,6 @@ public interface CatEventType {
String API_RETRY = "API.Retry";
String USER_ACCESS = "User.Access";
}
package com.ctrip.framework.apollo.portal.filters;
import com.ctrip.framework.apollo.portal.auth.UserInfoHolder;
import com.ctrip.framework.apollo.portal.constant.CatEventType;
import com.dianping.cat.Cat;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class RecordAccessUserFilter implements Filter {
private UserInfoHolder userInfoHolder;
public RecordAccessUserFilter(UserInfoHolder userInfoHolder) {
this.userInfoHolder = userInfoHolder;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
Cat.logEvent(CatEventType.USER_ACCESS, userInfoHolder.getUser().getUserId());
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
......@@ -24,30 +24,43 @@
</header>
<div class="panel-body">
<div class="alert alert-info" role="alert">apollo系统目前正在框架部门内测阶段,如非框架项目接入请先联系song_s@ctrip.com,zhanglea@ctrip.com</div>
<form class="form-horizontal" ng-controller="CreateAppController" ng-submit="create()">
<div class="alert alert-info" role="alert">
apollo系统目前正在框架部门内测阶段,如非框架项目接入请先联系song_s@ctrip.com,zhanglea@ctrip.com
</div>
<form class="form-horizontal" name="appForm" ng-controller="CreateAppController" valdr-type="App"
ng-submit="create()">
<div class="form-group">
<label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled> 部门</label>
<label class="col-sm-2 control-label">
<apollorequiredfiled></apollorequiredfiled>
部门</label>
<div class="col-sm-3">
<select id="organization"><option></option></select>
<select id="organization">
<option></option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled> 应用AppId</label>
<div class="form-group" valdr-form-group>
<label class="col-sm-2 control-label">
<apollorequiredfiled></apollorequiredfiled>
应用Id</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="appAppId" ng-model="app.appId"
required><small>(CMS上申请的App Id)</small>
<input type="text" class="form-control" name="appId" ng-model="app.appId">
<small>(CMS上申请的App Id)</small>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled> 应用名称</label>
<div class="form-group" valdr-form-group>
<label class="col-sm-2 control-label">
<apollorequiredfiled></apollorequiredfiled>
应用名称</label>
<div class="col-sm-5">
<input type="text" class="form-control" name="appName" ng-model="app.name" required>
<input type="text" class="form-control" name="appName" ng-model="app.name">
<small>(建议格式 xx-yy-zz 例:apollo-server)</small>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled> 应用负责人</label>
<label class="col-sm-2 control-label">
<apollorequiredfiled></apollorequiredfiled>
应用负责人</label>
<div class="col-sm-6">
<apollouserselector apollo-id="userSelectWidgetId"></apollouserselector>
<small>(负责人具有项目管理的最高权限,比如分配配置的修改权,发布权等)</small>
......@@ -57,7 +70,9 @@
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary" ng-disabled="submitBtnDisabled">提交</button>
<button type="submit" class="btn btn-primary"
ng-disabled="appForm.$invalid || submitBtnDisabled">提交
</button>
</div>
</div>
</form>
......@@ -83,6 +98,10 @@
<!-- bootstrap.js -->
<script src="vendor/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
<!--valdr-->
<script src="vendor/valdr/valdr.min.js" type="text/javascript"></script>
<script src="vendor/valdr/valdr-message.min.js" type="text/javascript"></script>
<script type="application/javascript" src="scripts/app.js"></script>
<script type="application/javascript" src="scripts/services/AppService.js"></script>
<script type="application/javascript" src="scripts/services/EnvService.js"></script>
......@@ -92,5 +111,7 @@
<script type="application/javascript" src="scripts/directive/directive.js"></script>
<script type="application/javascript" src="scripts/controller/AppController.js"></script>
<script src="scripts/valdr.js" type="text/javascript"></script>
</body>
</html>
......@@ -33,7 +33,8 @@
</header>
<div class="panel-body">
<form class="form-horizontal" ng-show="step == 1" ng-submit="create()">
<form class="form-horizontal" name="clusterForm" valdr-type="Cluster" ng-show="step == 1"
ng-submit="create()">
<div class="form-group">
<label class="col-sm-2 control-label">
<apollorequiredfiled></apollorequiredfiled>
......@@ -41,12 +42,12 @@
<div class="col-sm-6" ng-bind="appId">
</div>
</div>
<div class="form-group">
<div class="form-group" valdr-form-group>
<label class="col-sm-2 control-label">
<apollorequiredfiled></apollorequiredfiled>
集群名称</label>
<div class="col-sm-6">
<input type="text" class="form-control" name="appName" ng-model="clusterName" required>
<input type="text" class="form-control" name="clusterName" ng-model="clusterName">
<small>(部署集群如:SHAJQ,SHAOY 或自定义集群如:SHAJQ-xx,SHAJQ-yy)</small>
</div>
</div>
......@@ -57,7 +58,8 @@
<div class="col-sm-5">
<table class="table table-hover" style="width: 100px">
<tbody>
<tr style="cursor: pointer" ng-repeat="env in envs" ng-click="toggleEnvCheckedStatus(env)">
<tr style="cursor: pointer" ng-repeat="env in envs"
ng-click="toggleEnvCheckedStatus(env)">
<td width="10%"><input type="checkbox" ng-checked="env.checked"
ng-click="switchChecked(env, $event)"></td>
<td width="30%" ng-bind="env.name"></td>
......@@ -70,7 +72,9 @@
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary" ng-disabled="submitBtnDisabled">提交</button>
<button type="submit" class="btn btn-primary"
ng-disabled="clusterForm.$invalid || submitBtnDisabled">提交
</button>
</div>
</div>
</form>
......@@ -100,6 +104,10 @@
<!-- bootstrap.js -->
<script src="vendor/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
<!--valdr-->
<script src="vendor/valdr/valdr.min.js" type="text/javascript"></script>
<script src="vendor/valdr/valdr-message.min.js" type="text/javascript"></script>
<script type="application/javascript" src="scripts/app.js"></script>
<script type="application/javascript" src="scripts/services/AppService.js"></script>
<script type="application/javascript" src="scripts/services/EnvService.js"></script>
......@@ -109,5 +117,7 @@
<script type="application/javascript" src="scripts/directive/directive.js"></script>
<script type="application/javascript" src="scripts/controller/ClusterController.js"></script>
<script src="scripts/valdr.js" type="text/javascript"></script>
</body>
</html>
......@@ -32,7 +32,7 @@
</header>
<div class="panel-body">
<table class="project-info">
<tbody>
<tbody class="text-left">
<tr>
<th>AppId:</th>
<td ng-bind="appBaseInfo.appId"></td>
......@@ -122,7 +122,7 @@
<!--create createRelease modal-->
<form class="modal fade form-horizontal" id="releaseModal" tabindex="-1" role="dialog"
<form class="modal fade form-horizontal" name="releaseForm" valdr-type="Release" id="releaseModal" tabindex="-1" role="dialog"
ng-submit="release()">
<div class="modal-dialog" role="document" style="width: 960px">
<div class="modal-content">
......@@ -135,7 +135,7 @@
<div class="form-group">
<label class="col-sm-2 control-label">
Changes:</label>
<div class="col-sm-10" ng-if="toReleaseNamespace.itemModifiedCnt">
<div class="col-sm-10" ng-if="toReleaseNamespace.itemModifiedCnt" valdr-form-group>
<!--properites format-->
<table class="table table-bordered table-striped text-center table-hover"
......@@ -203,7 +203,7 @@
</div>
</div>
<div class="col-sm-5">
<div class="col-sm-5" valdr-form-group>
<span ng-show="!toReleaseNamespace.itemModifiedCnt">
配置没有变化
</span>
......@@ -214,15 +214,15 @@
<label class="col-sm-2 control-label">
<apollorequiredfiled></apollorequiredfiled>
Release Name:</label>
<div class="col-sm-5">
<input type="text" class="form-control" placeholder="input release title"
<div class="col-sm-5" valdr-form-group>
<input type="text" name="releaseName" class="form-control" placeholder="input release name"
ng-model="releaseTitle" ng-required="true">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Comment:</label>
<div class="col-sm-10">
<textarea rows="4" class="form-control" style="margin-top: 15px;"
<div class="col-sm-10" valdr-form-group>
<textarea rows="4" name="comment" class="form-control" style="margin-top: 15px;"
ng-model="releaseComment"
placeholder="Add an optional extended description..."></textarea>
</div>
......@@ -232,7 +232,7 @@
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="submit" class="btn btn-primary" ng-disabled="releaseBtnDisabled">发布
<button type="submit" class="btn btn-primary" ng-disabled="releaseForm.$invalid || releaseBtnDisabled">发布
</button>
</div>
</div>
......@@ -240,7 +240,7 @@
</form>
<!--table mode item modal-->
<form class="modal fade form-horizontal" id="itemModal" role="dialog" ng-submit="doItem()">
<form class="modal fade form-horizontal" name="itemForm" valdr-type="Item" id="itemModal" role="dialog" ng-submit="doItem()">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header panel-primary">
......@@ -259,8 +259,8 @@
ng-show="tableViewOperType != 'retrieve'"></apollorequiredfiled>
Key
</label>
<div class="col-sm-10">
<input type="text" class="form-control" ng-model="item.key"
<div class="col-sm-10" valdr-form-group>
<input type="text" name="key" class="form-control" ng-model="item.key"
ng-required="true" ng-disabled="tableViewOperType != 'create'">
</div>
</div>
......@@ -270,26 +270,15 @@
ng-show="tableViewOperType != 'retrieve'"></apollorequiredfiled>
Value
</label>
<div class="col-sm-10">
<textarea type="text" class="form-control" rows="6" ng-model="item.value"
ng-show="tableViewOperType != 'retrieve'">
<div class="col-sm-10" valdr-form-group>
<textarea type="text" name="value" class="form-control" rows="6" ng-model="item.value">
</textarea>
<p ng-bind="item.value" ng-show="tableViewOperType == 'retrieve'"></p>
</div>
</div>
<div class="form-group" ng-show="tableViewOperType == 'retrieve'">
<label class="col-sm-2 control-label">Released Value</label>
<div class="col-sm-10">
<p ng-show="!item.oldValue">这是新增的配置</p>
<p ng-show="item.oldValue" ng-bind="item.oldValue"></p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Comment</label>
<div class="col-sm-10">
<textarea class="form-control" ng-model="item.comment" rows="2"
ng-disabled="tableViewOperType == 'retrieve'">
<div class="col-sm-10" valdr-form-group>
<textarea class="form-control" name="comment" ng-model="item.comment" rows="2">
</textarea>
</div>
</div>
......@@ -316,7 +305,7 @@
</button>
<button type="submit" class="btn btn-primary"
ng-show="tableViewOperType != 'retrieve'"
ng-disabled="addItemBtnDisabled && tableViewOperType == 'create'">提交
ng-disabled="itemForm.$invalid || (addItemBtnDisabled && tableViewOperType == 'create')">提交
</button>
</div>
</div>
......@@ -453,6 +442,10 @@
<script src="vendor/bootstrap/js/bootstrap-treeview.min.js" type="text/javascript"></script>
<!--valdr-->
<script src="vendor/valdr/valdr.min.js" type="text/javascript"></script>
<script src="vendor/valdr/valdr-message.min.js" type="text/javascript"></script>
<!--biz script-->
<script type="application/javascript" src="scripts/app.js"></script>
......@@ -479,5 +472,6 @@
<script type="application/javascript" src="scripts/PageCommon.js"></script>
<script src="scripts/valdr.js" type="text/javascript"></script>
</body>
</html>
......@@ -40,10 +40,10 @@
</div>
</div>
<form class="form-horizontal" style="margin-top: 30px;" ng-show="step == 1" ng-submit="createNamespace()">
<form class="form-horizontal" name="namespaceForm" valdr-type="AppNamespace" style="margin-top: 30px;" ng-show="step == 1" ng-submit="createNamespace()">
<div class="form-group">
<label class="col-sm-3 control-label">应用ID</label>
<div class="col-sm-6">
<div class="col-sm-6" valdr-form-group>
<label ng-bind="appId"></label>
</div>
</div>
......@@ -52,7 +52,7 @@
<label class="col-sm-3 control-label">
<apollorequiredfiled></apollorequiredfiled>
选择集群</label>
<div class="col-sm-6">
<div class="col-sm-6" valdr-form-group>
<apolloclusterselector apollo-app-id="appId" apollo-default-all-checked="true"
apollo-select="collectSelectedClusters"></apolloclusterselector>
</div>
......@@ -62,14 +62,14 @@
<label class="col-sm-3 control-label">
<apollorequiredfiled></apollorequiredfiled>
名称</label>
<div class="col-sm-4">
<div class="col-sm-5" valdr-form-group>
<div class="input-group" ng-show="appNamespace.isPublic">
<span class="input-group-addon" ng-bind="appBaseInfo.namespacePrefix"></span>
<input type="text" class="form-control" ng-model="appNamespace.name"
<input type="text" name="namespaceName" class="form-control" ng-model="appNamespace.name"
ng-required="type == 'create'">
</div>
<div ng-show="!appNamespace.isPublic">
<input type="text" class="form-control" ng-model="appNamespace.name"
<input type="text" name="namespaceName" class="form-control" ng-model="appNamespace.name"
ng-required="type == 'create'">
</div>
</div>
......@@ -86,7 +86,7 @@
<label class="col-sm-3 control-label">
<apollorequiredfiled></apollorequiredfiled>
类型</label>
<div class="col-sm-4">
<div class="col-sm-4" valdr-form-group>
<label class="radio-inline">
<input type="radio" name="namespaceType" value="true" ng-value="true" ng-model="appNamespace.isPublic"> public
</label>
......@@ -95,17 +95,17 @@
</label>
</div>
</div>
<div class="form-group" ng-show="type == 'create'">
<div class="form-group" ng-show="type == 'create'" valdr-form-group>
<label class="col-sm-3 control-label">备注</label>
<div class="col-sm-7">
<textarea class="form-control" rows="3" ng-model="appNamespace.comment"></textarea>
<div class="col-sm-7" valdr-form-group>
<textarea class="form-control" rows="3" name="comment" ng-model="appNamespace.comment"></textarea>
</div>
</div>
<div class="form-group" ng-show="type == 'link'">
<label class="col-sm-3 control-label">
<apollorequiredfiled></apollorequiredfiled>
namespace</label>
<div class="col-sm-4">
<div class="col-sm-4" valdr-form-group>
<select id="namespaces">
<option></option>
</select>
......@@ -114,7 +114,7 @@
<div class="form-group">
<div class="col-sm-offset-3 col-sm-10">
<button type="submit" class="btn btn-primary" ng-disabled="submitBtnDisabled">提交</button>
<button type="submit" class="btn btn-primary" ng-disabled="namespaceForm.$invalid || submitBtnDisabled">提交</button>
</div>
</div>
</form>
......@@ -147,6 +147,9 @@
<!-- bootstrap.js -->
<script src="vendor/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
<script src="vendor/valdr/valdr.min.js" type="text/javascript"></script>
<script src="vendor/valdr/valdr-message.min.js" type="text/javascript"></script>
<script type="application/javascript" src="scripts/app.js"></script>
<script type="application/javascript" src="scripts/services/AppService.js"></script>
<script type="application/javascript" src="scripts/services/EnvService.js"></script>
......@@ -160,6 +163,7 @@
<script type="application/javascript" src="scripts/controller/NamespaceController.js"></script>
<script src="scripts/valdr.js" type="text/javascript"></script>
</body>
</html>
/**service module 定义*/
var appService = angular.module('app.service', ['ngResource']);
/**utils*/
var appUtil = angular.module('app.util', ['toastr']);
/**service module 定义*/
var appService = angular.module('app.service', ['ngResource']);
/** directive */
var directive_module = angular.module('apollo.directive', ['app.service', 'app.util', 'toastr']);
......@@ -11,19 +11,19 @@ var directive_module = angular.module('apollo.directive', ['app.service', 'app.u
// 首页
var index_module = angular.module('index', ['toastr', 'app.service', 'app.util', 'angular-loading-bar']);
//项目主页
var application_module = angular.module('application', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);
var application_module = angular.module('application', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar', 'valdr']);
//创建项目页面
var create_app_module = angular.module('create_app', ['apollo.directive', 'toastr', 'app.service', 'app.util', 'angular-loading-bar']);
var app_module = angular.module('create_app', ['apollo.directive', 'toastr', 'app.service', 'app.util', 'angular-loading-bar', 'valdr']);
//配置同步页面
var sync_item_module = angular.module('sync_item', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);
//namespace
var namespace_module = angular.module('namespace', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);
var namespace_module = angular.module('namespace', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar', 'valdr']);
//server config
var server_config_module = angular.module('server_config', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);
//role
var role_module = angular.module('role', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);
//cluster
var cluster_module = angular.module('cluster', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);
var cluster_module = angular.module('cluster', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar' , 'valdr']);
//release history
var release_history_module = angular.module('release_history', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']);
......
create_app_module.controller('CreateAppController', ['$scope', '$window', 'toastr', 'AppService', 'UserService', 'AppUtil', 'OrganizationService',
function ($scope, $window, toastr, AppService, UserService, AppUtil, OrganizationService) {
app_module.controller('CreateAppController', ['$scope', '$window', 'toastr', 'AppService', 'UserService', 'AppUtil', 'OrganizationService',
function ($scope, $window, toastr, AppService, UserService, AppUtil, OrganizationService) {
$scope.submitBtnDisabled = false;
......
......@@ -33,6 +33,7 @@ cluster_module.controller('ClusterController',
};
$scope.create = function () {
var noEnvChecked = true;
$scope.envs.forEach(function (env) {
if (env.checked) {
......
......@@ -11,32 +11,60 @@ index_module.controller('IndexController', ['$scope', '$window', 'toastr', 'AppS
toastr.error(AppUtil.errorMsg(result), "load env error");
});
var apps = [];
$scope.switchEnv = function (env) {
$scope.selectedEnv = env;
loadApps(env);
};
var sourceApps = [];
function loadApps(env){
AppService.find_all_app(env).then(function (result) {
apps = result;
$scope.apps = apps;
$scope.appsCount = apps.length;
sourceApps = sortApps(result);
$scope.apps = sourceApps;
$scope.appsCount = sourceApps.length;
$scope.selectedEnv = env;
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "load apps error");
});
toastr.error(AppUtil.errorMsg(result), "load apps error");
});
}
var VISITED_APPS_STORAGE_KEY = "VisitedApps";
//访问过的App放在列表最前面,方便用户选择
function sortApps(sourceApps) {
var visitedApps = JSON.parse(localStorage.getItem(VISITED_APPS_STORAGE_KEY));
if (!visitedApps){
return;
}
var existedVisitedAppsMap = {};
visitedApps.forEach(function (app) {
existedVisitedAppsMap[app] = true;
});
var sortedApps = [];
sourceApps.forEach(function (app) {
if (existedVisitedAppsMap[app.appId]){
sortedApps.push(app);
}
});
sourceApps.forEach(function (app) {
if (!existedVisitedAppsMap[app.appId]){
sortedApps.push(app);
}
});
return sortedApps;
}
$scope.search = function () {
var key = $scope.searchKey.toLocaleLowerCase();
if (key == '') {
$scope.apps = apps;
$scope.apps = sourceApps;
return;
}
var result = [];
apps.forEach(function (item) {
sourceApps.forEach(function (item) {
if (item.appId.toLocaleLowerCase().indexOf(key) >= 0 ||
item.name.toLocaleLowerCase().indexOf(key) >= 0) {
result.push(item);
......
......@@ -109,6 +109,7 @@ namespace_module.controller("LinkNamespaceController",
toastr.error(AppUtil.errorMsg(result));
});
} else {
$scope.submitBtnDisabled = true;
NamespaceService.createAppNamespace($scope.appId, $scope.appNamespace).then(
function (result) {
......
......@@ -6,6 +6,27 @@ application_module.controller("ConfigBaseInfoController",
var appId = AppUtil.parseParams($location.$$url).appid;
//save user recent visited apps
var VISITED_APPS_STORAGE_KEY = "VisitedApps";
var visitedApps = JSON.parse(localStorage.getItem(VISITED_APPS_STORAGE_KEY));
var hasSaved = false;
if (visitedApps){
visitedApps.forEach(function (app) {
if (app == appId){
hasSaved = true;
return;
}
});
}else {
visitedApps = [];
}
if (!hasSaved){
visitedApps.push(appId);
localStorage.setItem(VISITED_APPS_STORAGE_KEY,
JSON.stringify(visitedApps));
}
//load session storage to recovery scene
var scene = JSON.parse(sessionStorage.getItem(appId));
......
......@@ -131,6 +131,7 @@ application_module.controller("ConfigNamespaceController",
$scope.releaseComment = '';
function release() {
$scope.releaseBtnDisabled = true;
ReleaseService.release($rootScope.pageContext.appId, $rootScope.pageContext.env,
$rootScope.pageContext.clusterName,
......@@ -289,6 +290,7 @@ application_module.controller("ConfigNamespaceController",
}
selectedClusters.forEach(function (cluster) {
if ($scope.tableViewOperType == TABLE_VIEW_OPER_TYPE.CREATE) {
//check key unique
var hasRepeatKey = false;
toOperationNamespace.items.forEach(function (item) {
......@@ -324,6 +326,7 @@ application_module.controller("ConfigNamespaceController",
if (!$scope.item.comment) {
$scope.item.comment = "";
}
ConfigService.update_item($rootScope.pageContext.appId,
cluster.env,
cluster.name,
......
app_module.config(function (valdrProvider) {
valdrProvider.addConstraints({
'App': {
'appId': {
'size': {
'max': 32,
'message': 'AppId长度不能多于32个字符'
},
'required': {
'message': 'AppId不能为空'
}
},
'appName': {
'size': {
'max': 32,
'message': '应用名称长度不能多于32个字符'
},
'required': {
'message': '应用名称不能为空'
}
}
}
})
});
cluster_module.config(function (valdrProvider) {
valdrProvider.addConstraints({
'Cluster': {
'clusterName': {
'size': {
'max': 32,
'message': '集群名称长度不能多于32个字符'
},
'required': {
'message': '集群名称不能为空'
}
}
}
})
});
namespace_module.config(function (valdrProvider) {
valdrProvider.addConstraints({
'AppNamespace': {
'namespaceName': {
'size': {
'max': 32,
'message': 'Namespace名称长度不能多于32个字符'
},
'required': {
'message': 'Namespace名称不能为空'
}
},
'comment': {
'size': {
'max': 64,
'message': '备注长度不能多于64个字符'
}
}
}
})
});
application_module.config(function (valdrProvider) {
valdrProvider.addConstraints({
'Item': {
'key': {
'size': {
'max': 128,
'message': 'Key长度不能多于128个字符'
},
'required': {
'message': 'Key不能为空'
}
},
'value': {
'required': {
'message': 'value不能为空'
}
},
'comment': {
'size': {
'max': 64,
'message': '备注长度不能多于64个字符'
}
}
},
'Release': {
'releaseName': {
'size': {
'max': 64,
'message': 'Release Name长度不能多于64个字符'
},
'required': {
'message': 'Release Name不能为空'
}
},
'comment': {
'size': {
'max': 64,
'message': '备注长度不能多于64个字符'
}
}
}
})
});
......@@ -25,15 +25,15 @@ p, td, span {
word-break: break-all;
}
table{
table {
text-align: center;
}
.no-radius{
.no-radius {
border-radius: 0px;
}
.hide-border-top{
.hide-border-top {
border-top: 0px;
}
......@@ -270,13 +270,12 @@ table th {
background: #f1f2f7;
}
.namespace-attribute-public{
.namespace-attribute-public {
background: #31708f;
width: 40px;
cursor: pointer;
}
.second-panel-heading .nav-tabs {
border-bottom: 0px;
}
......@@ -400,60 +399,74 @@ table th {
height: 5px;
}
.release-history .media-body{
.release-history .media-body {
padding-left: 20px;
}
.release-history .panel-body .load-more{
.release-history .panel-body .load-more {
margin-top: 20px;
}
.release-history .media-body textarea{
.release-history .media-body textarea {
margin-top: 10px;
}
.release-history .icon{
.release-history .icon {
font-size: 13px;
}
.release-history .info{
.release-history .info {
font-size: 13px;
margin-left: 5px;
margin-top: 2px;
}
.release-history .user .info{
.release-history .user .info {
font-size: 22px;
}
.release-history .time{
.release-history .time {
padding-top: 8px;
}
.release-history .comment{
.release-history .comment {
padding-top: 10px;
}
.release-history .table{
.release-history .table {
margin-top: 15px;
}
.release-history .badge-0{
.release-history .badge-0 {
background: #f0ad4e;
}
.release-history .badge-1{
.release-history .badge-1 {
background: #c3c3c3;
}
.release-history .badge-2{
.release-history .badge-2 {
background: #27AE60;
}
.release-history .badge-3{
.release-history .badge-3 {
background: #3478a8;
}
.release-history .label{
.release-history .label {
margin-right: 15px;
}
.valdr-message {
display: none;
}
.valdr-message.ng-dirty.ng-invalid.ng-touched {
display: inline;
color: #a94442;
}
.form-group .form-control.ng-invalid.ng-dirty.ng-touched {
border-color: #a94442;
}
!function(a,b){"use strict";angular.module("valdr").provider("valdrMessage",function(){var a,b,c={},d="valdr/default-message.html",e='<div class="valdr-message">{{ violation.message }}</div>',f='<div class="valdr-message" ng-show="violation"><span translate="{{ violation.message }}" translate-values="violation"></span></div>';this.setTemplate=function(a){b=a},this.setTemplateUrl=function(b){a=b},this.addMessages=function(a){angular.extend(c,a)};var g=this.addMessages;this.getMessage=function(a,b,d){var e=a+"."+b+"."+d;return c[e]||c[d]||"["+d+"]"};var h=this.getMessage;this.$get=["$templateCache","$injector",function(c,i){function j(){try{return i.get("$translate")}catch(a){return void 0}}function k(){try{return i.get("valdrFieldNameKeyGenerator")}catch(a){return function(a){return a.type+"."+a.field}}}function l(){return angular.isDefined(b)?b:p?f:e}function m(){c.put(d,l()),a&&b&&c.put(a,b)}var n=!1,o=j(),p=angular.isDefined(o),q=k();return m(),{templateUrl:a||d,setTemplate:function(a){b=a,m()},translateAvailable:p,$translate:o,fieldNameKeyGenerator:q,addMessages:g,getMessage:h,angularMessagesEnabled:n}}]});var c=function(a){return["$compile",function(b){return{restrict:a,require:["?^valdrType","?^ngModel","?^valdrFormGroup"],link:function(a,c,d,e){var f=e[0],g=e[1],h=e[2],i=d.valdrNoValidate,j=d.valdrNoMessage,k=d.name;if(f&&h&&g&&!angular.isDefined(i)&&!angular.isDefined(j)){var l=angular.element('<span valdr-message="'+k+'"></span>');b(l)(a),h.addMessageElement(g,l),a.$on("$destroy",function(){h.removeMessageElement(g)})}}}}]},d=c("E"),e=c("A"),f={getType:angular.noop};angular.module("valdr").directive("input",d).directive("select",d).directive("textarea",d).directive("enableValdrMessage",e).directive("valdrMessage",["$rootScope","$injector","valdrMessage","valdrUtil",function(a,b,c,d){return{replace:!0,restrict:"A",scope:{formFieldName:"@valdrMessage"},templateUrl:function(){return c.templateUrl},require:["^form","?^valdrType"],link:function(b,e,g,h){var i=h[0],j=h[1]||f,k=function(){c.translateAvailable&&angular.isArray(b.violations)&&angular.forEach(b.violations,function(a){c.$translate(c.fieldNameKeyGenerator(a)).then(function(b){a.fieldName=b})})},l=function(a){var d=j.getType(),e=b.formFieldName;return{type:d,field:e,validator:a,message:c.getMessage(d,e,a)}},m=function(){b.violations=[],angular.forEach(b.formField.valdrViolations,function(a){b.violations.push(a)}),c.angularMessagesEnabled&&angular.forEach(b.formField.$error,function(a,c){d.startsWith(c,"valdr")||b.violations.push(l(c))}),b.violation=b.violations[0],k()},n=function(){b.violations=void 0,b.violation=void 0},o=function(){return b.formField=i[b.formFieldName],b.formField?{valdr:b.formField.valdrViolations,error:b.formField.$error}:void 0};b.$watch(o,function(){b.formField&&b.formField.$invalid?m():n()},!0),a.$on("$translateChangeSuccess",function(){k()})}}}])}(window,document);
\ No newline at end of file
!function(a,b){"use strict";angular.module("valdr",["ng"]).constant("valdrEvents",{revalidate:"valdr-revalidate"}).value("valdrConfig",{addFormGroupClass:!0}).value("valdrClasses",{formGroup:"form-group",valid:"ng-valid",invalid:"ng-invalid",dirty:"ng-dirty",pristine:"ng-pristine",touched:"ng-touched",untouched:"ng-untouched",invalidDirtyTouchedGroup:"valdr-invalid-dirty-touched-group"}),angular.module("valdr").factory("valdrUtil",[function(){var a=function(a){return-1===a.lastIndexOf(".")?a:a.substring(a.lastIndexOf(".")+1,a.length)},b=/[A-Z]/g,c=function(a){return a.replace(b,function(a,b){return(b?"-":"")+a.toLowerCase()})},d=function(b){if(angular.isString(b)){var d=a(b);return d=c(d),"valdr-"+d}return b};return{validatorNameToToken:d,isNaN:function(a){return this.isNumber(a)&&a!==+a},isNumber:function(a){var b=typeof a;return"number"===b||a&&"object"===b&&"[object Number]"===Object.prototype.toString.call(a)||!1},has:function(a,b){return a?Object.prototype.hasOwnProperty.call(a,b):!1},notEmpty:function(a){return this.isNaN(a)?!1:angular.isDefined(a)&&""!==a&&null!==a},isEmpty:function(a){return this.isNaN(a)?!1:!this.notEmpty(a)},startsWith:function(a,b){return angular.isString(a)&&angular.isString(b)&&0===a.lastIndexOf(b,0)}}}]),angular.module("valdr").factory("valdrRequiredValidator",["valdrUtil",function(a){return{name:"required",validate:function(b){return a.notEmpty(b)}}}]),angular.module("valdr").factory("valdrMinValidator",["valdrUtil",function(a){return{name:"min",validate:function(b,c){var d=Number(c.value),e=Number(b);return a.isNaN(b)?!1:a.isEmpty(b)||e>=d}}}]),angular.module("valdr").factory("valdrMaxValidator",["valdrUtil",function(a){return{name:"max",validate:function(b,c){var d=Number(c.value),e=Number(b);return a.isNaN(b)?!1:a.isEmpty(b)||d>=e}}}]),angular.module("valdr").factory("valdrSizeValidator",function(){return{name:"size",validate:function(a,b){var c=b.min||0,d=b.max;return a=a||"",a.length>=c&&(void 0===d||a.length<=d)}}}),angular.module("valdr").factory("valdrEmailValidator",["valdrUtil",function(a){var b=/^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;return{name:"email",validate:function(c){return a.isEmpty(c)||b.test(c)}}}]),angular.module("valdr").factory("valdrUrlValidator",["valdrUtil",function(a){var b=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;return{name:"url",validate:function(c){return a.isEmpty(c)||b.test(c)}}}]),angular.module("valdr").factory("valdrDigitsValidator",["valdrUtil",function(a){var b=new RegExp("[^.\\d]","g"),c=function(a){return Number(a).toString().replace(b,"")},d=function(a,b){return a?a.length<=b:!0},e=function(a,b){var e,f,g=b.integer,h=b.fraction;return e=c(a),f=e.split("."),d(f[0],g)&&d(f[1],h)};return{name:"digits",validate:function(b,c){return a.isEmpty(b)?!0:a.isNaN(Number(b))?!1:e(b,c)}}}]),angular.module("valdr").factory("futureAndPastSharedValidator",["valdrUtil",function(a){var b=["D-M-YYYY","D.M.YYYY","D/M/YYYY","D. M. YYYY","YYYY.M.D"];return{validate:function(c,d){var e,f=moment();if(a.isEmpty(c))return!0;e=moment(c);for(var g=0;g<b.length&&!e.isValid();g++)e=moment(c,b[g],!0);return e.isValid()&&d(e,f)}}}]),angular.module("valdr").factory("valdrPastValidator",["futureAndPastSharedValidator",function(a){return{name:"past",validate:function(b){return a.validate(b,function(a,b){return a.isBefore(b)})}}}]),angular.module("valdr").factory("valdrFutureValidator",["futureAndPastSharedValidator",function(a){return{name:"future",validate:function(b){return a.validate(b,function(a,b){return a.isAfter(b)})}}}]),angular.module("valdr").factory("valdrPatternValidator",["valdrUtil",function(a){var b=/^\/(.*)\/([gim]*)$/,c=function(a){var c;if(a.test)return a;if(c=a.match(b))return new RegExp(c[1],c[2]);throw"Expected "+a+" to be a RegExp"};return{name:"pattern",validate:function(b,d){var e=c(d.value);return a.isEmpty(b)||e.test(b)}}}]),angular.module("valdr").factory("valdrMinLengthValidator",["valdrUtil",function(a){return{name:"minLength",validate:function(b,c){var d=c.number;return a.isEmpty(b)?0===d:"string"==typeof b?b.length>=d:!1}}}]),angular.module("valdr").factory("valdrMaxLengthValidator",["valdrUtil",function(a){return{name:"maxLength",validate:function(b,c){var d=c.number;return a.isEmpty(b)?!0:"string"==typeof b?b.length<=d:!1}}}]),angular.module("valdr").factory("valdrHibernateEmailValidator",["valdrUtil",function(a){var b="[a-z0-9!#$%&'*+/=?^_`{|}~-]",c="^"+b+"+(\\."+b+"+)*$",d="^\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\]$",e=new RegExp("^"+b+"+(\\."+b+"+)*$","i"),f=new RegExp(c+"|"+d,"i");return{name:"hibernateEmail",validate:function(b){if(a.isEmpty(b))return!0;var c=b.split("@");return 2!==c.length?!1:e.test(c[0])?f.test(c[1]):!1}}}]),angular.module("valdr").provider("valdr",function(){var a,b,c={},d={},e={},f=["valdrRequiredValidator","valdrSizeValidator","valdrMinLengthValidator","valdrMaxLengthValidator","valdrMinValidator","valdrMaxValidator","valdrEmailValidator","valdrUrlValidator","valdrDigitsValidator","valdrFutureValidator","valdrPastValidator","valdrPatternValidator","valdrHibernateEmailValidator"],g=function(a){angular.extend(c,a)};this.addConstraints=g;var h=function(a){angular.isArray(a)?angular.forEach(a,function(a){delete c[a]}):angular.isString(a)&&delete c[a]};this.removeConstraints=h,this.setConstraintUrl=function(b){a=b},this.addValidator=function(a){f.push(a)},this.addConstraintAlias=function(a,b){angular.isArray(e[a])||(e[a]=[]),e[a].push(b)},this.$get=["$log","$injector","$rootScope","$http","valdrEvents","valdrUtil","valdrClasses",function(i,j,k,l,m,n,o){angular.forEach(f,function(a){var b=j.get(a);d[b.name]=b,angular.isArray(e[b.name])&&angular.forEach(e[b.name],function(a){d[a]=b})}),a&&(b=!0,l.get(a).then(function(a){b=!1,g(a.data),k.$broadcast(m.revalidate)})["finally"](function(){b=!1}));var p=function(a){return n.has(c,a)?c[a]:void(b||i.warn("No constraints for type '"+a+"' available."))};return{validate:function(a,b,c){var e={valid:!0},f=p(a);if(n.has(f,b)){var g=f[b],h=!0,j=[],k=[];return angular.forEach(g,function(f,g){var l=d[g];if(angular.isUndefined(l))return i.warn("No validator defined for '"+g+"'. Can not validate field '"+b+"'"),e;var m=l.validate(c,f),n={valid:m,value:c,field:b,type:a,validator:g};angular.extend(n,f),j.push(n),m||k.push(n),h=h&&m}),{valid:h,violations:0===k.length?void 0:k,validationResults:0===j.length?void 0:j}}return e},addConstraints:function(a){g(a),k.$broadcast(m.revalidate)},removeConstraints:function(a){h(a),k.$broadcast(m.revalidate)},getConstraints:function(){return c},setClasses:function(a){angular.extend(o,a),k.$broadcast(m.revalidate)}}}]});var c=["valdrClasses","valdrConfig",function(a,b){return{restrict:"EA",link:function(c,d){b.addFormGroupClass&&d.addClass(a.formGroup)},controller:["$scope","$element",function(b,c){var d=[],e={},f=function(){var a={invalidDirtyTouchedGroup:!1,valid:!0,itemStates:[]};return angular.forEach(d,function(b){b.$touched&&b.$dirty&&b.$invalid&&(a.invalidDirtyTouchedGroup=!0),b.$invalid&&(a.valid=!1);var c={name:b.$name,touched:b.$touched,dirty:b.$dirty,valid:b.$valid};a.itemStates.push(c)}),a},g=function(b){c.toggleClass(a.invalidDirtyTouchedGroup,b.invalidDirtyTouchedGroup),c.toggleClass(a.valid,b.valid),c.toggleClass(a.invalid,!b.valid),angular.forEach(b.itemStates,function(b){var c=e[b.name];c&&(c.toggleClass(a.valid,b.valid),c.toggleClass(a.invalid,!b.valid),c.toggleClass(a.dirty,b.dirty),c.toggleClass(a.pristine,!b.dirty),c.toggleClass(a.touched,b.touched),c.toggleClass(a.untouched,!b.touched))})};b.$watch(f,g,!0),this.addFormItem=function(a){d.push(a)},this.removeFormItem=function(a){var b=d.indexOf(a);b>=0&&d.splice(b,1)},this.addMessageElement=function(a,b){c.append(b),e[a.$name]=b},this.removeMessageElement=function(a){e[a.$name].remove()}}]}}];angular.module("valdr").directive("valdrFormGroup",c),angular.module("valdr").directive("valdrType",function(){return{priority:1,controller:["$attrs",function(a){this.getType=function(){return a.valdrType}}]}});var d={isEnabled:function(){return!0}},e={addFormItem:angular.noop,removeFormItem:angular.noop},f=function(a){return["valdrEvents","valdr","valdrUtil",function(b,c,f){return{restrict:a,require:["?^valdrType","?^ngModel","?^valdrFormGroup","?^valdrEnabled"],link:function(a,g,h,i){var j=i[0],k=i[1],l=i[2]||e,m=i[3]||d,n=h.valdrNoValidate,o=h.name;if(j&&k&&!angular.isDefined(n)){l.addFormItem(k),f.isEmpty(o)&&m.isEnabled()&&console.warn('Form element with ID "'+h.id+'" is not bound to a field name.');var p=function(a){if(m.isEnabled()){var b=["valdr"];angular.forEach(a.validationResults,function(a){var c=f.validatorNameToToken(a.validator);k.$setValidity(c,a.valid),b.push(c)}),k.$setValidity("valdr",a.valid),k.valdrViolations=a.violations,angular.forEach(k.$error,function(a,c){-1===b.indexOf(c)&&f.startsWith(c,"valdr")&&k.$setValidity(c,!0)})}else angular.forEach(k.$error,function(a,b){f.startsWith(b,"valdr")&&k.$setValidity(b,!0)}),k.valdrViolations=void 0},q=function(a){var b=c.validate(j.getType(),o,a);return p(b),m.isEnabled()?b.valid:!0};k.$validators.valdr=q,a.$on(b.revalidate,function(){q(k.$modelValue)}),a.$on("$destroy",function(){l.removeFormItem(k)})}}}}]},g=f("E"),h=f("A");angular.module("valdr").directive("input",g).directive("select",g).directive("textarea",g).directive("enableValdrValidation",h),angular.module("valdr").directive("valdrEnabled",["valdrEvents",function(a){return{controller:["$scope","$attrs",function(b,c){b.$watch(c.valdrEnabled,function(){b.$broadcast(a.revalidate)}),this.isEnabled=function(){var a=b.$eval(c.valdrEnabled);return void 0===a?!0:a}}]}}])}(window,document);
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册