Commit eb37797f by lepdou

Merge pull request #211 from lepdou/table_view

table view cru
parents 3808305a 6aaa2773
...@@ -36,7 +36,14 @@ public class ItemController { ...@@ -36,7 +36,14 @@ public class ItemController {
BeanUtils.copyEntityProperties(entity, managedEntity); BeanUtils.copyEntityProperties(entity, managedEntity);
entity = itemService.update(managedEntity); entity = itemService.update(managedEntity);
} else { } else {
Item lastItem = itemService.findLastOne(appId, clusterName, namespaceName);
int lineNum = 1;
if (lastItem != null){
lineNum = lastItem.getLineNum() + 1;
}
entity.setLineNum(lineNum);
entity.setDataChangeCreatedBy(user.getUsername()); entity.setDataChangeCreatedBy(user.getUsername());
entity.setDataChangeLastModifiedBy(user.getUsername());
entity = itemService.save(entity); entity = itemService.save(entity);
} }
......
...@@ -12,4 +12,5 @@ public interface ItemRepository extends PagingAndSortingRepository<Item, Long> { ...@@ -12,4 +12,5 @@ public interface ItemRepository extends PagingAndSortingRepository<Item, Long> {
List<Item> findByNamespaceIdOrderByLineNumAsc(Long namespaceId); List<Item> findByNamespaceIdOrderByLineNumAsc(Long namespaceId);
Item findFirst1ByNamespaceIdOrderByLineNumDesc(Long namespaceId);
} }
...@@ -45,6 +45,17 @@ public class ItemService { ...@@ -45,6 +45,17 @@ public class ItemService {
return item; return item;
} }
public Item findLastOne(String appId, String clusterName, String namespaceName) {
Namespace namespace = namespaceRepository.findByAppIdAndClusterNameAndNamespaceName(appId,
clusterName, namespaceName);
if (namespace == null) {
throw new NotFoundException(
String.format("namespace not found for %s %s %s", appId, clusterName, namespaceName));
}
Item item = itemRepository.findFirst1ByNamespaceIdOrderByLineNumDesc(namespace.getId());
return item;
}
public Item findOne(long itemId) { public Item findOne(long itemId) {
Item item = itemRepository.findOne(itemId); Item item = itemRepository.findOne(itemId);
return item; return item;
......
...@@ -115,6 +115,12 @@ public class AdminServiceAPI { ...@@ -115,6 +115,12 @@ public class AdminServiceAPI {
.format("apps/%s/clusters/%s/namespaces/%s/itemset", appId, clusterName, namespace), .format("apps/%s/clusters/%s/namespaces/%s/itemset", appId, clusterName, namespace),
changeSets, Void.class); changeSets, Void.class);
} }
public ItemDTO createOrUpdateItem(String appId, Env env, String clusterName, String namespace, ItemDTO item){
return restTemplate.postForEntity(getAdminServiceHost(env) + String
.format("apps/%s/clusters/%s/namespaces/%s/items", appId, clusterName, namespace),
item, ItemDTO.class).getBody();
}
} }
@Service @Service
......
...@@ -37,7 +37,7 @@ public class PortalConfigController { ...@@ -37,7 +37,7 @@ public class PortalConfigController {
@RequestBody NamespaceTextModel model) { @RequestBody NamespaceTextModel model) {
if (model == null) { if (model == null) {
throw new BadRequestException("request payload shoud not be null"); throw new BadRequestException("request payload should not be null");
} }
model.setAppId(appId); model.setAppId(appId);
model.setClusterName(clusterName); model.setClusterName(clusterName);
...@@ -51,13 +51,39 @@ public class PortalConfigController { ...@@ -51,13 +51,39 @@ public class PortalConfigController {
configService.updateConfigItemByText(model); configService.updateConfigItemByText(model);
} }
@RequestMapping(value = "/apps/{appId}/env/{env}/clusters/{clusterName}/namespaces/{namespaceName}/item", method = RequestMethod.POST)
public ItemDTO createItem(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String namespaceName,
@RequestBody ItemDTO item){
if (StringUtils.isContainEmpty(appId, env, clusterName, namespaceName)){
throw new BadRequestException("request payload should not be contain empty.");
}
if (!isValidItem(item) && item.getNamespaceId() <= 0){
throw new BadRequestException("request model is invalid");
}
return configService.createOrUpdateItem(appId, Env.valueOf(env), clusterName, namespaceName, item);
}
@RequestMapping(value = "/apps/{appId}/env/{env}/clusters/{clusterName}/namespaces/{namespaceName}/item", method = RequestMethod.PUT)
public ItemDTO updateItem(@PathVariable String appId, @PathVariable String env,
@PathVariable String clusterName, @PathVariable String namespaceName,
@RequestBody ItemDTO item){
if (StringUtils.isContainEmpty(appId, env, clusterName, namespaceName)){
throw new BadRequestException("request payload should not be contain empty.");
}
if (!isValidItem(item)){
throw new BadRequestException("request model is invalid");
}
return configService.createOrUpdateItem(appId, Env.valueOf(env), clusterName, namespaceName, item);
}
@RequestMapping(value = "/apps/{appId}/env/{env}/clusters/{clusterName}/namespaces/{namespaceName}/release", method = RequestMethod.POST, consumes = { @RequestMapping(value = "/apps/{appId}/env/{env}/clusters/{clusterName}/namespaces/{namespaceName}/release", method = RequestMethod.POST, consumes = {
"application/json"}) "application/json"})
public ReleaseDTO createRelease(@PathVariable String appId, public ReleaseDTO createRelease(@PathVariable String appId,
@PathVariable String env, @PathVariable String clusterName, @PathVariable String env, @PathVariable String clusterName,
@PathVariable String namespaceName, @RequestBody NamespaceReleaseModel model) { @PathVariable String namespaceName, @RequestBody NamespaceReleaseModel model) {
if (model == null) { if (model == null) {
throw new BadRequestException("request payload shoud not be null"); throw new BadRequestException("request payload should not be null");
} }
model.setAppId(appId); model.setAppId(appId);
model.setClusterName(clusterName); model.setClusterName(clusterName);
...@@ -77,7 +103,7 @@ public class PortalConfigController { ...@@ -77,7 +103,7 @@ public class PortalConfigController {
@PathVariable String clusterName, @PathVariable String namespaceName){ @PathVariable String clusterName, @PathVariable String namespaceName){
if (StringUtils.isContainEmpty(appId, env, clusterName, namespaceName)){ if (StringUtils.isContainEmpty(appId, env, clusterName, namespaceName)){
throw new BadRequestException("appid,env,cluster name,namespace name can not be null"); throw new BadRequestException("appid,env,cluster name,namespace name can not be empty");
} }
return configService.findItems(appId, Env.valueOf(env), clusterName, namespaceName); return configService.findItems(appId, Env.valueOf(env), clusterName, namespaceName);
...@@ -87,7 +113,7 @@ public class PortalConfigController { ...@@ -87,7 +113,7 @@ public class PortalConfigController {
"application/json"}) "application/json"})
public List<ItemDiffs> diff(@RequestBody NamespaceSyncModel model){ public List<ItemDiffs> diff(@RequestBody NamespaceSyncModel model){
if (model == null){ if (model == null){
throw new BadRequestException("request payload shoud not be null"); throw new BadRequestException("request payload should not be null");
} }
if (model.isInvalid()) { if (model.isInvalid()) {
throw new BadRequestException("request model is invalid"); throw new BadRequestException("request model is invalid");
...@@ -100,7 +126,7 @@ public class PortalConfigController { ...@@ -100,7 +126,7 @@ public class PortalConfigController {
"application/json"}) "application/json"})
public ResponseEntity<Void> update(@RequestBody NamespaceSyncModel model){ public ResponseEntity<Void> update(@RequestBody NamespaceSyncModel model){
if (model == null){ if (model == null){
throw new BadRequestException("request payload shoud not be null"); throw new BadRequestException("request payload should not be null");
} }
if (model.isInvalid()) { if (model.isInvalid()) {
throw new BadRequestException("request model is invalid"); throw new BadRequestException("request model is invalid");
...@@ -109,4 +135,8 @@ public class PortalConfigController { ...@@ -109,4 +135,8 @@ public class PortalConfigController {
return ResponseEntity.status(HttpStatus.OK).build(); return ResponseEntity.status(HttpStatus.OK).build();
} }
private boolean isValidItem(ItemDTO item){
return item != null && !StringUtils.isContainEmpty(item.getKey(), item.getValue());
}
} }
...@@ -71,6 +71,11 @@ public class PortalConfigService { ...@@ -71,6 +71,11 @@ public class PortalConfigService {
} }
} }
public ItemDTO createOrUpdateItem(String appId, Env env, String clusterName, String namespaceName, ItemDTO item){
return itemAPI.createOrUpdateItem(appId, env, clusterName, namespaceName, item);
}
/** /**
* createRelease config items * createRelease config items
*/ */
......
...@@ -25,26 +25,26 @@ ...@@ -25,26 +25,26 @@
<div class="panel-body"> <div class="panel-body">
<form class="form-horizontal" ng-controller="CreateAppController" ng-submit="create()"> <form class="form-horizontal" ng-controller="CreateAppController" ng-submit="create()">
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label"><font style="color: red">*</font> 应用ID</label> <label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled> 应用ID</label>
<div class="col-sm-3"> <div class="col-sm-3">
<input type="text" class="form-control" name="appAppId" ng-model="app.appId" <input type="text" class="form-control" name="appAppId" ng-model="app.appId"
required> required>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label"><font style="color: red">*</font> 应用名称</label> <label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled> 应用名称</label>
<div class="col-sm-5"> <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" required>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label"><font style="color: red">*</font>应用Owner</label> <label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled>应用Owner</label>
<div class="col-sm-3"> <div class="col-sm-3">
<input type="text" class="form-control" name="appOwner" ng-model="app.ownerName" required> <input type="text" class="form-control" name="appOwner" ng-model="app.ownerName" required>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label"><font style="color: red">*</font>邮箱地址</label> <label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled>邮箱地址</label>
<div class="col-sm-4"> <div class="col-sm-4">
<input type="email" class="form-control" ng-model="app.ownerEmail" required> <input type="email" class="form-control" ng-model="app.ownerEmail" required>
</div> </div>
......
...@@ -108,7 +108,8 @@ ...@@ -108,7 +108,8 @@
<div class="checkbox" ng-repeat="env in missEnvs"> <div class="checkbox" ng-repeat="env in missEnvs">
<label> <label>
<input type="checkbox" name="selectedEnvs[]" value="{{env}}" <input type="checkbox" name="selectedEnvs[]" value="{{env}}"
ng-checked="selectedEnvs.indexOf(env) > -1" ng-click="toggleSelection(env)"><span ng-bind="env"><span/> ng-checked="selectedEnvs.indexOf(env) > -1"
ng-click="toggleSelection(env)"><span ng-bind="env"></span>
</label> </label>
</div> </div>
</div> </div>
...@@ -116,7 +117,8 @@ ...@@ -116,7 +117,8 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button> <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary" data-dismiss="modal" ng-click="createEnvs()">添加 <button type="button" class="btn btn-primary" data-dismiss="modal"
ng-click="createEnvs()">添加
</button> </button>
</div> </div>
</div> </div>
...@@ -132,7 +134,8 @@ ...@@ -132,7 +134,8 @@
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-4">
<b ng-bind="namespace.namespace.namespaceName"></b> <b ng-bind="namespace.namespace.namespaceName"></b>
<span class="label label-primary" ng-show="namespace.itemModifiedCnt > 0">有修改 <span class="label label-primary"
ng-show="namespace.itemModifiedCnt > 0">有修改
<span class="badge" ng-bind="namespace.itemModifiedCnt"></span></span> <span class="badge" ng-bind="namespace.itemModifiedCnt"></span></span>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
...@@ -153,7 +156,7 @@ ...@@ -153,7 +156,7 @@
<button type="button" <button type="button"
class="btn btn-default btn-sm J_tableview_btn">授权 class="btn btn-default btn-sm J_tableview_btn">授权
</button> </button>
<a type="button" target="_blank" <a type="button"
href="config/sync.html?#/appid={{pageContext.appId}}&env={{pageContext.env}}&clusterName={{pageContext.clusterName}}&namespaceName={{namespace.namespace.namespaceName}}" href="config/sync.html?#/appid={{pageContext.appId}}&env={{pageContext.env}}&clusterName={{pageContext.clusterName}}&namespaceName={{namespace.namespace.namespaceName}}"
class="btn btn-default btn-sm J_tableview_btn">同步 class="btn btn-default btn-sm J_tableview_btn">同步
</a> </a>
...@@ -182,7 +185,8 @@ ...@@ -182,7 +185,8 @@
</div> </div>
<div class="col-md-1 text-right"> <div class="col-md-1 text-right">
<a data-tooltip="tooltip" data-placement="bottom" title="取消修改" <a data-tooltip="tooltip" data-placement="bottom" title="取消修改"
ng-show="namespace.isTextEditing" ng-click="toggleTextEditStatus(namespace)"> ng-show="namespace.isTextEditing && namespace.viewType == 'text'"
ng-click="toggleTextEditStatus(namespace)">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span> <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</a> </a>
<a data-tooltip="tooltip" data-placement="bottom" title="修改配置" <a data-tooltip="tooltip" data-placement="bottom" title="修改配置"
...@@ -193,9 +197,17 @@ ...@@ -193,9 +197,17 @@
&nbsp; &nbsp;
<a data-tooltip="tooltip" data-placement="bottom" title="提交修改" <a data-tooltip="tooltip" data-placement="bottom" title="提交修改"
data-toggle="modal" data-target="#commitModal" data-toggle="modal" data-target="#commitModal"
ng-show="namespace.isTextEditing" ng-click="saveDraft(namespace)"> ng-show="namespace.isTextEditing && namespace.viewType == 'text'"
ng-click="saveDraft(namespace)">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span> <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
</a> </a>
<a data-tooltip="tooltip" data-placement="bottom" title="添加配置"
ng-show="namespace.viewType == 'table'"
data-toggle="modal" data-target="#itemModal"
ng-click="createItem(namespace)">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
</a>
</div> </div>
</div> </div>
</header> </header>
...@@ -203,13 +215,14 @@ ...@@ -203,13 +215,14 @@
<!--text view--> <!--text view-->
<textarea class="form-control" rows="{{namespace.itemCnt}}" style="border-radius: 0px" <textarea class="form-control" rows="{{namespace.itemCnt}}" style="border-radius: 0px"
ng-show="namespace.viewType == 'text'" ng-show="namespace.viewType == 'text'"
ng-disabled="!namespace.isTextEditing" ng-model="namespace.text" ng-bind="namespace.text"> ng-disabled="!namespace.isTextEditing" ng-model="namespace.text"
ng-bind="namespace.text">
</textarea> </textarea>
<!--table view--> <!--table view-->
<div class="namespace-view-table"> <div class="namespace-view-table">
<table class="table table-bordered table-striped text-center table-hover" <table class="table table-bordered table-striped text-center table-hover"
ng-show="namespace.viewType == 'table'"> ng-show="namespace.viewType == 'table' && namespace.items.length > 0">
<thead> <thead>
<tr> <tr>
<th> <th>
...@@ -227,29 +240,45 @@ ...@@ -227,29 +240,45 @@
<th> <th>
最后修改时间 最后修改时间
</th> </th>
<th>
操作
</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr title="点击查看" data-toggle="modal" data-target="#oldValueModal" <tr ng-repeat="config in namespace.items" ng-class="{warning:config.isModified}"
ng-repeat="config in namespace.items" ng-class="{warning:config.modified}" ng-if="config.item.key">
ng-if="config.item.key" <td width="20%">
ng-click="watchItem(config.item.key, config.item.value, config.oldValue)">
<td width="25%" >
<span ng-bind="config.item.key | limitTo: 20"></span> <span ng-bind="config.item.key | limitTo: 20"></span>
<span ng-bind="config.item.key.length > 20 ? '...' :''"></span> <span ng-bind="config.item.key.length > 20 ? '...' :''"></span>
</td> </td>
<td width="30%" > <td width="25%">
<span ng-bind="config.item.value | limitTo: 20"></span> <span ng-bind="config.item.value | limitTo: 20"></span>
<span ng-bind="config.item.value.length > 20 ? '...': ''"></span> <span ng-bind="config.item.value.length > 20 ? '...': ''"></span>
</td> </td>
<td width="20%" > <td width="20%">
<span ng-bind="config.item.comment | limitTo: 20"></span> <span ng-bind="config.item.comment | limitTo: 20"></span>
<span ng-bind="config.item.comment.length > 20 ?'...' : ''"></span> <span ng-bind="config.item.comment.length > 20 ?'...' : ''"></span>
</td> </td>
<td width="10%" ng-bind="config.item.lastModifiedBy"> <td width="10%" ng-bind="config.item.lastModifiedBy">
</td> </td>
<td width="15%" ng-bind="config.item.lastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'"> <td width="15%"
ng-bind="config.item.lastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'">
</td>
<td width="10%">
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"
data-tooltip="tooltip" data-placement="bottom" title="查看"
data-toggle="modal" data-target="#itemModal"
ng-click="retrieveItem(config.item, config.oldValue)">
</span>
&nbsp;
<span class="glyphicon glyphicon-edit" aria-hidden="true"
data-tooltip="tooltip" data-placement="bottom" title="修改"
data-toggle="modal" data-target="#itemModal"
ng-click="editItem(namespace, config.item)">
</span>
</td> </td>
</tr> </tr>
...@@ -304,78 +333,140 @@ ...@@ -304,78 +333,140 @@
</div> </div>
</div> </div>
<!-- view old value Modal --> <!-- commit modify config modal-->
<div class="modal fade" id="oldValueModal" tabindex="-1" role="dialog"> <div class="modal fade" id="commitModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header panel-primary"> <div class="modal-header panel-primary">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button> aria-hidden="true">&times;</span></button>
<h4 class="modal-title">{{watch.key}}</h4> <h4 class="modal-title">Commit changes</h4>
</div>
<div class="modal-body" style="word-wrap: break-word;">
{{watch.value}}
<div ng-show="watch.oldValue">
<hr>
<b>已发布的值:</b>{{watch.oldValue}}
</div> </div>
<div class="modal-body">
<textarea rows="4" class="form-control" style="width:570px;"
placeholder="Add an optional extended description..."
ng-model="commitComment"></textarea>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button> <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary" data-dismiss="modal"
ng-click="commitChange()">
提交
</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- commit modify config modal--> <!--create release modal-->
<div class="modal fade" id="commitModal" tabindex="-1" role="dialog"> <form class="modal fade form-horizontal" id="releaseModal" tabindex="-1" role="dialog"
ng-submit="release()">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header panel-primary"> <div class="modal-header panel-primary">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button> aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Commit changes</h4> <h4 class="modal-title">发布</h4>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<textarea rows="4" class="form-control" style="width:570px;" placeholder="Add an optional extended description..." <div class="form-group">
ng-model="commitComment"></textarea> <label class="col-sm-3 control-label">
<apollorequiredfiled></apollorequiredfiled>
Release Name:</label>
<div class="col-sm-9">
<input type="text" class="form-control" placeholder="input release title"
ng-model="releaseTitle" ng-required="true">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Comment:</label>
<div class="col-sm-9">
<textarea rows="4" class="form-control" style="margin-top: 15px;"
ng-model="releaseComment"
placeholder="Add an optional extended description..."></textarea>
</div>
</div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button> <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary" data-dismiss="modal" ng-click="commitChange()"> <button type="submit" class="btn btn-primary">提交
提交
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</div> </form>
<!--create release modal--> <!--table mode item modal-->
<div class="modal fade" id="releaseModal" tabindex="-1" role="dialog"> <form class="modal fade form-horizontal" id="itemModal" role="dialog" ng-submit="doItem()">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header panel-primary"> <div class="modal-header panel-primary">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button> aria-hidden="true">&times;</span></button>
<h4 class="modal-title">发布</h4> <h4 class="modal-title">
<span ng-show="tableViewOperType == 'create'"> 添加配置项</span>
<span ng-show="tableViewOperType == 'retrieve'"> 查看配置项</span>
<span ng-show="tableViewOperType == 'update'"> 修改配置项</span>
</h4>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<input type="text" class="form-control" placeholder="input release title" <div class="form-group">
ng-model="releaseTitle" required="required"> <label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled>Key</label>
<textarea rows="4" class="form-control" style="margin-top: 15px;" ng-model="releaseComment" <div class="col-sm-10">
placeholder="Add an optional extended description..."></textarea> <input type="text" class="form-control" ng-model="item.key"
ng-required="true" ng-disabled="tableViewOperType != 'create'">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled>Value</label>
<div class="col-sm-10">
<textarea type="text" class="form-control" rows="4" ng-model="item.value"
ng-required="true" ng-disabled="tableViewOperType == 'retrieve'">
</textarea>
</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">
<textarea type="text" class="form-control" rows="4" ng-model="item.oldValue"
ng-disabled="true" ng-show="item.oldVale">
</textarea>
<span ng-show="!item.oldVale">这是新增的配置</span>
</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="4"
ng-disabled="tableViewOperType == 'retrieve'">
</textarea>
</div>
</div>
<div class="form-group" ng-show="tableViewOperType != 'retrieve'">
<label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled>选择集群</label>
<div class="col-sm-10">
<apolloclusterselector apollo-app-id="pageContext.appId" apollo-default-checked="false"
apollo-select="collectSelectedClusters"></apolloclusterselector>
</div>
</div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button> <button type="button" class="btn btn-default" ng-click="switchToEdit()" ng-show="tableViewOperType == 'retrieve'">修改</button>
<button type="submit" class="btn btn-primary" data-dismiss="modal" ng-click="release()">提交 <button type="button" class="btn btn-default" data-dismiss="modal">关闭
</button>
<button type="submit" class="btn btn-primary" ng-show="tableViewOperType != 'retrieve'">提交
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</form>
</div> </div>
</div> </div>
</div> </div>
</div>
</div> </div>
</div> </div>
......
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
<label class="control-label">需要同步的配置</label> <label class="control-label">需要同步的配置</label>
</div> </div>
<div class="col-sm-10"> <div class="col-sm-10">
<table class="table table-bordered table-striped table-hover"> <table class="table table-bordered table-striped table-hover" >
<thead> <thead>
<tr> <tr>
<td><input type="checkbox" ng-click="toggleItemsCheckedStatus()"></td> <td><input type="checkbox" ng-click="toggleItemsCheckedStatus()"></td>
......
...@@ -5,42 +5,50 @@ application_module.controller("ConfigNamespaceController", ...@@ -5,42 +5,50 @@ application_module.controller("ConfigNamespaceController",
////// namespace ////// ////// namespace //////
var namespace_view_type = { var namespace_view_type = {
TEXT:'text', TEXT: 'text',
TABLE: 'table', TABLE: 'table',
LOG: 'log' LOG: 'log'
}; };
$rootScope.refreshNamespaces = function (viewType) { $rootScope.refreshNamespaces = function (viewType) {
if ($rootScope.pageContext.env == ''){ if ($rootScope.pageContext.env == '') {
return; return;
} }
ConfigService.load_all_namespaces($rootScope.pageContext.appId, $rootScope.pageContext.env, ConfigService.load_all_namespaces($rootScope.pageContext.appId,
$rootScope.pageContext.clusterName, viewType).then( $rootScope.pageContext.env,
$rootScope.pageContext.clusterName,
viewType).then(
function (result) { function (result) {
$scope.namespaces = result; $scope.namespaces = result;
//初始化视图 //初始化视图
if ($scope.namespaces) { if ($scope.namespaces) {
$scope.namespaces.forEach(function (item) { $scope.namespaces.forEach(function (namespace) {
item.isModify = false;
if (!viewType) {//default text view if (!viewType) {//default text view
$scope.switchView(item, namespace_view_type.TEXT); $scope.switchView(namespace, namespace_view_type.TABLE);
} else if (viewType == namespace_view_type.TABLE) { } else if (viewType == namespace_view_type.TABLE) {
item.viewType = namespace_view_type.TABLE; namespace.viewType = namespace_view_type.TABLE;
} }
item.isTextEditing = false; namespace.isTextEditing = false;
}); });
} }
setInterval(function () { setInterval(function () {
$('[data-tooltip="tooltip"]').tooltip(); $('[data-tooltip="tooltip"]').tooltip();
},2500); $('.namespace-view-table').bind( 'mousewheel DOMMouseScroll', function ( e ) {
var e0 = e.originalEvent,
delta = e0.wheelDelta || -e0.detail;
this.scrollTop += ( delta < 0 ? 1 : -1 ) * 30;
e.preventDefault();
});
}, 2500);
}, function (result) { }, function (result) {
toastr.error(AppUtil.errorMsg(result), "加载配置信息出错"); toastr.error(AppUtil.errorMsg(result), "加载配置信息出错");
}); });
} };
////// global view oper ////// ////// global view oper //////
...@@ -69,7 +77,7 @@ application_module.controller("ConfigNamespaceController", ...@@ -69,7 +77,7 @@ application_module.controller("ConfigNamespaceController",
} else { } else {
result += item.item.comment + "\n"; result += item.item.comment + "\n";
} }
itemCnt ++; itemCnt++;
}); });
namespace.itemCnt = itemCnt > MAX_ROW_SIZE ? MAX_ROW_SIZE : itemCnt + 3; namespace.itemCnt = itemCnt > MAX_ROW_SIZE ? MAX_ROW_SIZE : itemCnt + 3;
...@@ -87,8 +95,10 @@ application_module.controller("ConfigNamespaceController", ...@@ -87,8 +95,10 @@ application_module.controller("ConfigNamespaceController",
$scope.commitComment = ''; $scope.commitComment = '';
//更新配置 //更新配置
$scope.commitChange = function () { $scope.commitChange = function () {
ConfigService.modify_items($scope.pageContext.appId, $scope.pageContext.env, $scope.pageContext.clusterName, ConfigService.modify_items($scope.pageContext.appId, $scope.pageContext.env,
$scope.draft.namespace.namespaceName, $scope.draft.text, $scope.pageContext.clusterName,
$scope.draft.namespace.namespaceName,
$scope.draft.text,
$scope.draft.namespace.id, $scope.commitComment).then( $scope.draft.namespace.id, $scope.commitComment).then(
function (result) { function (result) {
toastr.success("更新成功"); toastr.success("更新成功");
...@@ -104,30 +114,20 @@ application_module.controller("ConfigNamespaceController", ...@@ -104,30 +114,20 @@ application_module.controller("ConfigNamespaceController",
); );
}; };
//文本编辑框状态切换 //文本编辑框状态切换
$scope.toggleTextEditStatus = function (namespace) { $scope.toggleTextEditStatus = function (namespace) {
namespace.isTextEditing = !namespace.isTextEditing; namespace.isTextEditing = !namespace.isTextEditing;
if (namespace.isTextEditing){//切换为编辑状态,保存一下原来值 if (namespace.isTextEditing) {//切换为编辑状态,保存一下原来值
$scope.draft.backupText = namespace.text; $scope.draft.backupText = namespace.text;
}else { } else {
if ($scope.draft.backupText){//取消编辑,则复原 if ($scope.draft.backupText) {//取消编辑,则复原
namespace.text = $scope.draft.backupText; namespace.text = $scope.draft.backupText;
} }
} }
}; };
////// table view oper //////
$scope.watch = {};
//查看配置
$scope.watchItem = function (key, value, oldValue) {
$scope.watch.key = key;
$scope.watch.value = value;
$scope.watch.oldValue = oldValue;
};
/////// release /////// /////// release ///////
var releaseModal = $('#releaseModal');
var releaseNamespace = {}; var releaseNamespace = {};
$scope.prepareReleaseNamespace = function (namespace) { $scope.prepareReleaseNamespace = function (namespace) {
...@@ -138,9 +138,11 @@ application_module.controller("ConfigNamespaceController", ...@@ -138,9 +138,11 @@ application_module.controller("ConfigNamespaceController",
$scope.release = function () { $scope.release = function () {
ConfigService.release($rootScope.pageContext.appId, $rootScope.pageContext.env, ConfigService.release($rootScope.pageContext.appId, $rootScope.pageContext.env,
$rootScope.pageContext.clusterName, $rootScope.pageContext.clusterName,
releaseNamespace.namespace.namespaceName, $scope.releaseTitle, releaseNamespace.namespace.namespaceName,
$scope.releaseTitle,
$scope.releaseComment).then( $scope.releaseComment).then(
function (result) { function (result) {
releaseModal.modal('hide');
toastr.success("发布成功"); toastr.success("发布成功");
//refresh all namespace items //refresh all namespace items
$rootScope.refreshNamespaces(); $rootScope.refreshNamespaces();
...@@ -152,6 +154,94 @@ application_module.controller("ConfigNamespaceController", ...@@ -152,6 +154,94 @@ application_module.controller("ConfigNamespaceController",
); );
}; };
var TABLE_VIEW_OPER_TYPE = {
RETRIEVE: 'retrieve',
CREATE: 'create',
UPDATE: 'update'
};
$scope.tableViewOperType = '', $scope.item = {};
//查看配置
$scope.retrieveItem = function (item, oldValue) {
switchTableViewOperType(TABLE_VIEW_OPER_TYPE.RETRIEVE);
$scope.item = item;
$scope.item.oldValue = oldValue;
};
var toOperationNamespaceName = '';
//修改配置
$scope.editItem = function (namespace, item) {
switchTableViewOperType(TABLE_VIEW_OPER_TYPE.UPDATE);
$scope.item = item;
toOperationNamespaceName = namespace.namespace.namespaceName;
};
//新增配置
$scope.createItem = function (namespace) {
switchTableViewOperType(TABLE_VIEW_OPER_TYPE.CREATE);
$scope.item = {};
$scope.item.namespaceId = namespace.namespace.id;
toOperationNamespaceName = namespace.namespace.namespaceName;
};
$scope.switchToEdit = function () {
switchTableViewOperType(TABLE_VIEW_OPER_TYPE.UPDATE);
};
var selectedClusters = [];
$scope.collectSelectedClusters = function (data) {
selectedClusters = data;
};
function switchTableViewOperType(type) {
$scope.tableViewOperType = type;
}
var itemModal = $("#itemModal");
$scope.doItem = function () {
if (selectedClusters.length == 0) {
toastr.error("请选择集群");
} else {
selectedClusters.forEach(function (cluster) {
if ($scope.tableViewOperType == TABLE_VIEW_OPER_TYPE.CREATE) {
ConfigService.create_item($rootScope.pageContext.appId,
cluster.env,
cluster.name,
toOperationNamespaceName,
$scope.item).then(
function (result) {
toastr.success("[" + cluster.env + "," + cluster.name + "]",
"创建成功");
itemModal.modal('hide');
$rootScope.refreshNamespaces(namespace_view_type.TABLE);
}, function (result) {
AppUtil.errorMsg(result);
});
} else if ($scope.tableViewOperType == TABLE_VIEW_OPER_TYPE.UPDATE) {
ConfigService.update_item($rootScope.pageContext.appId,
cluster.env,
cluster.name,
toOperationNamespaceName,
$scope.item).then(
function (result) {
toastr.success("[" + cluster.env + "," + cluster.name + "]",
"更新成功");
itemModal.modal('hide');
$rootScope.refreshNamespaces(namespace_view_type.TABLE);
}, function (result) {
AppUtil.errorMsg(result);
});
}
});
}
};
$('.config-item-container').removeClass('hide'); $('.config-item-container').removeClass('hide');
}]); }]);
/** navbar */ /** navbar */
directive_module.directive('apollonav', function ($compile, $window, AppService, EnvService) { directive_module.directive('apollonav', function ($compile, $window, AppService, EnvService) {
return { return {
...@@ -44,14 +43,14 @@ directive_module.directive('apollonav', function ($compile, $window, AppService, ...@@ -44,14 +43,14 @@ directive_module.directive('apollonav', function ($compile, $window, AppService,
}; };
scope.jumpToConfigPage = function () { scope.jumpToConfigPage = function () {
if (selectedApp.appId){ if (selectedApp.appId) {
var needReloadPage = false; var needReloadPage = false;
if ($window.location.href.indexOf("config.html") > -1){ if ($window.location.href.indexOf("config.html") > -1) {
needReloadPage = true; needReloadPage = true;
} }
$window.location.href = '/config.html?#appid=' + selectedApp.appId; $window.location.href = '/config.html?#appid=' + selectedApp.appId;
if (needReloadPage){ if (needReloadPage) {
$window.location.reload(); $window.location.reload();
} }
} }
...@@ -72,10 +71,10 @@ directive_module.directive('apollonav', function ($compile, $window, AppService, ...@@ -72,10 +71,10 @@ directive_module.directive('apollonav', function ($compile, $window, AppService,
scope.copyedApps[--selectedAppIdx].selected = true; scope.copyedApps[--selectedAppIdx].selected = true;
} }
} else if (event.keyCode == 13) { } else if (event.keyCode == 13) {
if (scope.shouldShowAppList && selectedAppIdx > -1){ if (scope.shouldShowAppList && selectedAppIdx > -1) {
select(scope.copyedApps[selectedAppIdx]); select(scope.copyedApps[selectedAppIdx]);
event.preventDefault(); event.preventDefault();
}else { } else {
scope.jumpToConfigPage(); scope.jumpToConfigPage();
} }
...@@ -157,15 +156,21 @@ directive_module.directive('apolloclusterselector', function ($compile, $window, ...@@ -157,15 +156,21 @@ directive_module.directive('apolloclusterselector', function ($compile, $window,
scope.select(collectSelectedClusters()); scope.select(collectSelectedClusters());
}; };
scope.switchSelect = function (o) { scope.switchSelect = function (o, $event) {
o.checked = !o.checked; o.checked = !o.checked;
$event.stopPropagation();
scope.select(collectSelectedClusters());
};
scope.toggleClusterCheckedStatus = function (cluster) {
cluster.checked = !cluster.checked;
scope.select(collectSelectedClusters()); scope.select(collectSelectedClusters());
}; };
function collectSelectedClusters() { function collectSelectedClusters() {
var selectedClusters = []; var selectedClusters = [];
scope.clusters.forEach(function (cluster) { scope.clusters.forEach(function (cluster) {
if (cluster.checked){ if (cluster.checked) {
cluster.clusterName = cluster.name; cluster.clusterName = cluster.name;
selectedClusters.push(cluster); selectedClusters.push(cluster);
} }
...@@ -177,3 +182,13 @@ directive_module.directive('apolloclusterselector', function ($compile, $window, ...@@ -177,3 +182,13 @@ directive_module.directive('apolloclusterselector', function ($compile, $window,
} }
}); });
directive_module.directive('apollorequiredfiled', function ($compile, $window) {
return {
restrict: 'E',
template: '<span style="color: red">*</span>',
transclude: true,
replace: true
}
});
...@@ -5,10 +5,10 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q) ...@@ -5,10 +5,10 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
isArray: true, isArray: true,
url: '/apps/:appId/env/:env/clusters/:clusterName/namespaces' url: '/apps/:appId/env/:env/clusters/:clusterName/namespaces'
}, },
find_items:{ find_items: {
method:'GET', method: 'GET',
isArray: true, isArray: true,
url:'/apps/:appId/env/:env/clusters/:clusterName/namespaces/:namespaceName/items' url: '/apps/:appId/env/:env/clusters/:clusterName/namespaces/:namespaceName/items'
}, },
modify_items: { modify_items: {
method: 'PUT', method: 'PUT',
...@@ -16,7 +16,7 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q) ...@@ -16,7 +16,7 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
}, },
release: { release: {
method: 'POST', method: 'POST',
url:'/apps/:appId/env/:env/clusters/:clusterName/namespaces/:namespaceName/release' url: '/apps/:appId/env/:env/clusters/:clusterName/namespaces/:namespaceName/release'
}, },
diff: { diff: {
method: 'POST', method: 'POST',
...@@ -27,6 +27,14 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q) ...@@ -27,6 +27,14 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
method: 'PUT', method: 'PUT',
url: '/namespaces/:namespaceName/items', url: '/namespaces/:namespaceName/items',
isArray: false isArray: false
},
create_item: {
method: 'POST',
url: '/apps/:appId/env/:env/clusters/:clusterName/namespaces/:namespaceName/item'
},
update_item: {
method: 'PUT',
url: '/apps/:appId/env/:env/clusters/:clusterName/namespaces/:namespaceName/item'
} }
}); });
...@@ -70,7 +78,7 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q) ...@@ -70,7 +78,7 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
{ {
configText: configText, configText: configText,
namespaceId: namespaceId, namespaceId: namespaceId,
comment:comment comment: comment
}, function (result) { }, function (result) {
d.resolve(result); d.resolve(result);
...@@ -120,6 +128,36 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q) ...@@ -120,6 +128,36 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
d.reject(result); d.reject(result);
}); });
return d.promise; return d.promise;
},
create_item: function (appId, env, clusterName, namespaceName, item) {
var d = $q.defer();
config_source.create_item({
appId: appId,
env: env,
clusterName: clusterName,
namespaceName: namespaceName
}, item, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
},
update_item: function (appId, env, clusterName, namespaceName, item) {
var d = $q.defer();
config_source.update_item({
appId: appId,
env: env,
clusterName: clusterName,
namespaceName: namespaceName
}, item, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
} }
} }
......
...@@ -212,22 +212,21 @@ table th { ...@@ -212,22 +212,21 @@ table th {
} }
.namespace-view-table { .namespace-view-table {
max-height: 700px;
}
.namespace-view-table table {
table-layout: fixed;
} }
.namespace-view-table tr { .namespace-view-table table {
cursor: pointer; table-layout: inherit;
} }
.namespace-view-table td { .namespace-view-table td {
word-wrap: break-word; word-wrap: break-word;
} }
.namespace-view-table .glyphicon{
cursor: pointer;
}
.history-view { .history-view {
padding: 50px 20px; padding: 50px 20px;
......
<table class="table table-hover"> <table class="table table-hover" style="width: 250px">
<thead> <thead>
<tr> <tr>
<td><input type="checkbox" ng-checked="envAllSelected" ng-click="toggleEnvsCheckedStatus()"></td> <td><input type="checkbox" ng-checked="envAllSelected" ng-click="toggleEnvsCheckedStatus()"></td>
...@@ -8,9 +8,9 @@ ...@@ -8,9 +8,9 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="cluster in clusters"> <tr style="cursor: pointer" ng-repeat="cluster in clusters" ng-click="toggleClusterCheckedStatus(cluster)">
<td width="10%"><input type="checkbox" ng-checked="cluster.checked" <td width="10%"><input type="checkbox" ng-checked="cluster.checked"
ng-click="switchSelect(cluster)"></td> ng-click="switchSelect(cluster, $event)"></td>
<td width="30%" ng-bind="cluster.env"></td> <td width="30%" ng-bind="cluster.env"></td>
<td width="60%" ng-bind="cluster.name"></td> <td width="60%" ng-bind="cluster.name"></td>
</tr> </tr>
......
19575
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment