Skip to content

Commit

Permalink
feature: A user-friendly config management page for apollo portal (#4592
Browse files Browse the repository at this point in the history
)

* 提交

* feature: A user-friendly config management page for apollo portal(update sql)

* A user-friendly config management page for apollo portal(update code style)

* feature: A user-friendly config management page for apollo portal

* update

* update

* update

* update json

* update code style

* change json

* add license headers

* update(only portal,delete configDB)

* update

* update

* update 1 file

* update

* update test

* update test

* update

* update

* update (pageable分页)

* update

* update test

* update

* update

* update

* update

* update(CHANGES.md)

* update(使用文档)

* update
  • Loading branch information
webSue authored Oct 20, 2022
1 parent 67030ba commit f8d35bd
Show file tree
Hide file tree
Showing 14 changed files with 464 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Apollo 2.1.0
* [Add nodejs client sdk and fix doc](https://github.com/apolloconfig/apollo/pull/4590)
* [Move apollo-core, apollo-client, apollo-mockserver, apollo-openapi and apollo-client-config-data to apollo-java repo](https://github.com/apolloconfig/apollo/pull/4594)
* [fix get the openapi interface that contains namespace information for deleted items](https://github.com/apolloconfig/apollo/pull/4596)
* [A user-friendly config management page for apollo portal](https://github.com/apolloconfig/apollo/pull/4592)

------------------
All issues and pull requests are [here](https://github.com/apolloconfig/apollo/milestone/11?closed=1)
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
import com.ctrip.framework.apollo.common.utils.BeanUtils;
import com.ctrip.framework.apollo.portal.entity.po.ServerConfig;
import com.ctrip.framework.apollo.portal.repository.ServerConfigRepository;
import com.ctrip.framework.apollo.portal.service.ServerConfigService;
import com.ctrip.framework.apollo.portal.spi.UserInfoHolder;
import java.util.List;
import java.util.Objects;
import javax.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
Expand All @@ -38,10 +40,12 @@ public class ServerConfigController {

private final ServerConfigRepository serverConfigRepository;
private final UserInfoHolder userInfoHolder;
private final ServerConfigService serverConfigService;

public ServerConfigController(final ServerConfigRepository serverConfigRepository, final UserInfoHolder userInfoHolder) {
public ServerConfigController(final ServerConfigRepository serverConfigRepository, final UserInfoHolder userInfoHolder, final ServerConfigService serverConfigService) {
this.serverConfigRepository = serverConfigRepository;
this.userInfoHolder = userInfoHolder;
this.serverConfigService = serverConfigService;
}

@PreAuthorize(value = "@permissionValidator.isSuperAdmin()")
Expand All @@ -63,6 +67,12 @@ public ServerConfig createOrUpdate(@Valid @RequestBody ServerConfig serverConfig
return serverConfigRepository.save(storedConfig);
}

@PreAuthorize(value = "@permissionValidator.isSuperAdmin()")
@GetMapping("/server/config/find-all-config")
public List<ServerConfig> findAllServerConfig() {
return serverConfigService.findAll();
}

@PreAuthorize(value = "@permissionValidator.isSuperAdmin()")
@GetMapping("/server/config/{key:.+}")
public ServerConfig loadServerConfig(@PathVariable String key) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2022 Apollo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.ctrip.framework.apollo.portal.service;


import com.ctrip.framework.apollo.portal.entity.po.ServerConfig;
import com.ctrip.framework.apollo.portal.repository.ServerConfigRepository;
import com.google.common.collect.Lists;
import java.util.List;
import org.springframework.stereotype.Service;

@Service
public class ServerConfigService {

private final ServerConfigRepository serverConfigRepository;

public ServerConfigService(final ServerConfigRepository serverConfigRepository) {
this.serverConfigRepository = serverConfigRepository;
}

public List<ServerConfig> findAll() {
Iterable<ServerConfig> serverConfigs = serverConfigRepository.findAll();
return Lists.newArrayList(serverConfigs);
}
}
230 changes: 230 additions & 0 deletions apollo-portal/src/main/resources/static/config-manage.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
<!--
~ Copyright 2022 Apollo Authors
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~
-->
<!doctype html>
<html ng-app="user">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="icon" href="./img/config.png">
<!-- styles -->
<link rel="stylesheet" type="text/css" href="vendor/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="vendor/angular/angular-toastr-1.4.1.min.css">
<link rel="stylesheet" type="text/css" href="vendor/select2/select2.min.css">
<link rel="stylesheet" type="text/css" media='all' href="vendor/angular/loading-bar.min.css">
<link rel="stylesheet" type="text/css" href="styles/common-style.css">

<title>{{'ServiceConfig.Title' | translate }}</title>
</head>

<body>

<apollonav></apollonav>
<div id ="user-list" class="container-fluid apollo-container" ng-controller="ConfigController">
<div class="col-md-8 col-md-offset-2 panel">
<section class="panel-body" ng-show="isRootUser">
<div class="main-table"></div>
<div class="row">

<div class="table-responsive" ng-show="status==='1'" >
<div>
<div style="height: 15px"></div>
<div>
<header class="panel-heading">
{{'ServiceConfig.Title' | translate }}
<small>{{'ServiceConfig.Tips' | translate }}</small>
</header>
<button type="button" ng-click="configEdit('3')"
class="btn btn-primary">
{{'Config.Add' | translate }}
</button>
<form class="form-inline" style="display:inline">
<div class="form-group">
<input type="text" class="form-control" id="searchUserInput"
placeholder="{{'Config.SortByKey' | translate }}"
ng-model="searchKey">
</div>
<button type="button" class="btn btn-default" ng-click="searchKeys()">
<span class="glyphicon glyphicon-filter"></span>
{{'Config.FilterConfig' | translate }}
</button>
<button type="button" class="btn btn-default" ng-click="resetSearchKey()">
{{'Config.Reset' | translate }}
</button>
</form>
</div>
<div style="height: 15px"></div>
</div>

<table class="table table-bordered table-striped table-hover">
<tr>
<th style="text-align: left">{{'Config.Key' | translate }}</th>
<th style="text-align: left">{{'Config.Value' | translate }}</th>
<th style="text-align: left">{{'Config.Comment' | translate }}</th>
<th style="text-align: left">{{'Config.Operation' | translate }}</th>
</tr>
<tr ng-repeat="config in filterConfig" href="#" class="hover cursor-pointer">
<td>{{ config.key }}</td>
<td>{{ config.value }}</td>
<td>{{ config.comment }}</td>
<td>
<span class="btn btn-primary" ng-click="configEdit('2', config)">
{{'UserMange.Edit' | translate }}
</span>
</td>
</tr>
</table>

<div style="text-align: end;">
</div>
</div>

<div ng-show="status==='2'">
<div class="panel-body">
<form class="form-horizontal panel-body" name="appForm"
valdr-type="App" ng-submit="create()">
<div class="form-group">
<label class="col-sm-2 control-label">
<apollorequiredfield></apollorequiredfield>
{{'ServiceConfig.Key' | translate }}
</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="key" ng-model="serverConfig.key"
required>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">
<apollorequiredfield></apollorequiredfield>
{{'ServiceConfig.Value' | translate }}
</label>
<div class="col-sm-9">
<textarea class="form-control" rows="4" name="value"
ng-model="serverConfig.value"></textarea>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">
{{'ServiceConfig.Comment' | translate }}</label>
<div class="col-sm-9">
<textarea class="form-control" rows="4" name="comment"
ng-model="serverConfig.comment"></textarea>
</div>
</div>

<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary" ng-disabled="appForm.$invalid || submitBtnDisabled">
{{'Common.Save' | translate }}
</button>
<button type="button" ng-click="goback()" class="btn">{{'UserMange.Back' | translate }}</button>
</div>
</div>
</form>
</div>
</div>

<div ng-show="status==='3'">
<div class="panel-body">
<form class="form-horizontal panel-body" name="appForm"
valdr-type="App" ng-submit="create()">
<div class="form-group">
<label class="col-sm-2 control-label">
<apollorequiredfield></apollorequiredfield>
{{'ServiceConfig.Key' | translate }}
</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="key" ng-model="serverConfig.key"
required>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">
<apollorequiredfield></apollorequiredfield>
{{'ServiceConfig.Value' | translate }}
</label>
<div class="col-sm-9">
<textarea class="form-control" rows="4" name="value"
ng-model="serverConfig.value"></textarea>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">
{{'ServiceConfig.Comment' | translate }}</label>
<div class="col-sm-9">
<textarea class="form-control" rows="4" name="comment"
ng-model="serverConfig.comment"></textarea>
</div>
</div>

<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary" ng-disabled="appForm.$invalid || submitBtnDisabled">
{{'Common.Save' | translate }}
</button>
<button type="button" ng-click="goback()" class="btn">{{'UserMange.Back' | translate }}</button>
</div>
</div>
</form>
</div>
</div>

</div>
</section>
</div>
</div>

<div ng-include="'views/common/footer.html'"></div>

<!--angular-->
<script src="vendor/angular/angular.min.js"></script>
<script src="vendor/angular/angular-resource.min.js"></script>
<script src="vendor/angular/angular-toastr-1.4.1.tpls.min.js"></script>
<script src="vendor/angular/loading-bar.min.js"></script>
<script src="vendor/angular/angular-cookies.min.js"></script>

<script src="vendor/angular/angular-translate.2.18.1/angular-translate.min.js"></script>
<script src="vendor/angular/angular-translate.2.18.1/angular-translate-loader-static-files.min.js"></script>
<script src="vendor/angular/angular-translate.2.18.1/angular-translate-storage-cookie.min.js"></script>

<!-- jquery.js -->
<script src="vendor/jquery.min.js" type="text/javascript"></script>
<script src="vendor/select2/select2.min.js" type="text/javascript"></script>

<!-- 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>
<script type="application/javascript" src="scripts/services/ServerConfigService.js"></script>
<script type="application/javascript" src="scripts/services/UserService.js"></script>
<script type="application/javascript" src="scripts/services/CommonService.js"></script>
<script type="application/javascript" src="scripts/AppUtils.js"></script>
<script type="application/javascript" src="scripts/services/OrganizationService.js"></script>
<script type="application/javascript" src="scripts/directive/directive.js"></script>
<script type="application/javascript" src="scripts/services/PermissionService.js"></script>

<script type="application/javascript" src="scripts/controller/ConfigController.js"></script>

<script src="scripts/valdr.js" type="text/javascript"></script>
</body>

</html>
10 changes: 9 additions & 1 deletion apollo-portal/src/main/resources/static/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,14 @@
"Config.DeleteNamespaceFailedTips": "The following projects are associated with this public namespace and they must all be deleted deleting the public Namespace",
"Config.DeleteNamespaceNoPermissionFailedTitle": "Failed to delete",
"Config.DeleteNamespaceNoPermissionFailedTips": "You do not have Project Administrator permission. Only Administrators can delete namespace. Please ask Project Administrators [{{users}}] to delete namespace.",
"Config.Key": "Key",
"Config.Value": "Value",
"Config.Comment": "Comment",
"Config.Operation": "Operation",
"Config.Add": "Add Config",
"Config.SortByKey": "Filter Config by Key",
"Config.FilterConfig": "Filter",
"Config.Reset": "Reset",
"Delete.Title": "Delete applications, clusters, AppNamespace",
"Delete.DeleteApp": "Delete application",
"Delete.DeleteAppTips": "(Because deleting applications has very large impacts, only system administrators are allowed to delete them for the time being. Make sure that no client fetches the configuration of the application before deleting it.)",
Expand Down Expand Up @@ -489,7 +497,7 @@
"Namespace.PleaseChooseCluster": "Select Cluster",
"Namespace.CheckNamespaceNameLengthTip": "The namespace name should not be longer than 32 characters. Department prefix:'{{departmentLength}}' characters, name {{namespaceLength}} characters",
"ServiceConfig.Title": "System Configuration",
"ServiceConfig.Tips": "(Maintain Apollo PortalDB.ServerConfig table data, will override configuration items if they already exist, or create configuration items. Configuration updates take effect automatically in a minute)",
"ServiceConfig.Tips": "(Maintain Apollo PortalDB.ServerConfig table data, will override configuration items if they already exist in the edit operation, or create configuration items. Configuration updates take effect automatically in a minute)",
"ServiceConfig.Key": "Key",
"ServiceConfig.KeyTips": "(Please query the configuration information before modifying the configuration)",
"ServiceConfig.Value": "Value",
Expand Down
Loading

0 comments on commit f8d35bd

Please sign in to comment.