⬆️ Upgrading dependencies. nacos 1.4.1

⬆️ Upgrading dependencies. nacos 1.4.1

⬆️ Upgrading dependencies. nacos 1.4.1
This commit is contained in:
lbw 2021-01-16 11:49:37 +08:00
parent 7c06ed414d
commit ddd507ebf9
300 changed files with 184 additions and 20812 deletions

View File

@ -27,8 +27,7 @@
<description>nacos 注册配置中心</description>
<properties>
<jjwt.version>0.11.2</jjwt.version>
<nacos.version>1.3.2</nacos.version>
<nacos.version>1.4.1</nacos.version>
</properties>
<dependencies>
@ -57,23 +56,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>${jjwt.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>${jjwt.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -14,20 +14,21 @@
* limitations under the License.
*/
package com.alibaba.nacos.controller;
package com.alibaba.nacos.console.controller;
import javax.servlet.http.HttpServletRequest;
import com.alibaba.nacos.config.server.service.repository.PersistService;
import com.alibaba.nacos.naming.controllers.OperatorController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* Health Controller.
*

View File

@ -14,16 +14,16 @@
* limitations under the License.
*/
package com.alibaba.nacos.controller;
package com.alibaba.nacos.console.controller;
import com.alibaba.nacos.auth.annotation.Secured;
import com.alibaba.nacos.auth.common.ActionTypes;
import com.alibaba.nacos.common.model.RestResult;
import com.alibaba.nacos.config.server.model.TenantInfo;
import com.alibaba.nacos.config.server.service.repository.PersistService;
import com.alibaba.nacos.model.Namespace;
import com.alibaba.nacos.model.NamespaceAllInfo;
import com.alibaba.nacos.security.nacos.NacosAuthConfig;
import com.alibaba.nacos.core.auth.ActionTypes;
import com.alibaba.nacos.core.auth.Secured;
import com.alibaba.nacos.console.model.Namespace;
import com.alibaba.nacos.console.model.NamespaceAllInfo;
import com.alibaba.nacos.console.security.nacos.NacosAuthConfig;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;

View File

@ -14,13 +14,13 @@
* limitations under the License.
*/
package com.alibaba.nacos.controller;
package com.alibaba.nacos.console.controller;
import com.alibaba.nacos.auth.annotation.Secured;
import com.alibaba.nacos.auth.common.ActionTypes;
import com.alibaba.nacos.common.model.RestResult;
import com.alibaba.nacos.security.nacos.NacosAuthConfig;
import com.alibaba.nacos.security.nacos.roles.NacosRoleServiceImpl;
import com.alibaba.nacos.core.auth.ActionTypes;
import com.alibaba.nacos.core.auth.Secured;
import com.alibaba.nacos.console.security.nacos.NacosAuthConfig;
import com.alibaba.nacos.console.security.nacos.roles.NacosRoleServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;

View File

@ -14,13 +14,13 @@
* limitations under the License.
*/
package com.alibaba.nacos.controller;
package com.alibaba.nacos.console.controller;
import com.alibaba.nacos.auth.annotation.Secured;
import com.alibaba.nacos.auth.common.ActionTypes;
import com.alibaba.nacos.common.model.RestResult;
import com.alibaba.nacos.security.nacos.NacosAuthConfig;
import com.alibaba.nacos.security.nacos.roles.NacosRoleServiceImpl;
import com.alibaba.nacos.core.auth.ActionTypes;
import com.alibaba.nacos.core.auth.Secured;
import com.alibaba.nacos.console.security.nacos.NacosAuthConfig;
import com.alibaba.nacos.console.security.nacos.roles.NacosRoleServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
@ -30,6 +30,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* Role operation controller.
*
@ -57,6 +59,17 @@ public class RoleController {
return roleService.getRolesFromDatabase(username, pageNo, pageSize);
}
/**
* Fuzzy matching role name .
* @param role role id
* @return role list
*/
@GetMapping("/search")
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "roles", action = ActionTypes.READ)
public List<String> searchRoles(@RequestParam String role) {
return roleService.findRolesLikeRoleName(role);
}
/**
* Add a role to a user
*

View File

@ -14,10 +14,10 @@
* limitations under the License.
*/
package com.alibaba.nacos.controller;
package com.alibaba.nacos.console.controller;
import com.alibaba.nacos.common.utils.VersionUtils;
import com.alibaba.nacos.core.utils.ApplicationUtils;
import com.alibaba.nacos.sys.env.EnvUtil;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@ -42,10 +42,10 @@ public class ServerStateController {
@GetMapping("/state")
public ResponseEntity serverState() {
Map<String, String> serverState = new HashMap<>(3);
serverState.put("standalone_mode", ApplicationUtils.getStandaloneMode() ? ApplicationUtils.STANDALONE_MODE_ALONE
: ApplicationUtils.STANDALONE_MODE_CLUSTER);
serverState.put("standalone_mode",
EnvUtil.getStandaloneMode() ? EnvUtil.STANDALONE_MODE_ALONE : EnvUtil.STANDALONE_MODE_CLUSTER);
serverState.put("function_mode", ApplicationUtils.getFunctionMode());
serverState.put("function_mode", EnvUtil.getFunctionMode());
serverState.put("version", VersionUtils.version);
return ResponseEntity.ok().body(serverState);

View File

@ -16,24 +16,33 @@
package com.alibaba.nacos.controller;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.auth.annotation.Secured;
import com.alibaba.nacos.auth.common.ActionTypes;
import com.alibaba.nacos.auth.common.AuthConfigs;
import com.alibaba.nacos.auth.common.AuthSystemTypes;
import com.alibaba.nacos.auth.exception.AccessException;
import com.alibaba.nacos.common.model.RestResult;
import com.alibaba.nacos.common.utils.JacksonUtils;
import com.alibaba.nacos.common.utils.Objects;
import com.alibaba.nacos.config.server.auth.RoleInfo;
import com.alibaba.nacos.config.server.model.User;
import com.alibaba.nacos.security.nacos.NacosAuthConfig;
import com.alibaba.nacos.security.nacos.NacosAuthManager;
import com.alibaba.nacos.security.nacos.roles.NacosRoleServiceImpl;
import com.alibaba.nacos.security.nacos.users.NacosUser;
import com.alibaba.nacos.security.nacos.users.NacosUserDetailsServiceImpl;
import com.alibaba.nacos.utils.JwtTokenUtils;
import com.alibaba.nacos.config.server.utils.RequestUtil;
import com.alibaba.nacos.console.security.nacos.JwtTokenManager;
import com.alibaba.nacos.console.security.nacos.NacosAuthConfig;
import com.alibaba.nacos.console.security.nacos.NacosAuthManager;
import com.alibaba.nacos.console.security.nacos.roles.NacosRoleServiceImpl;
import com.alibaba.nacos.console.security.nacos.users.NacosUser;
import com.alibaba.nacos.console.security.nacos.users.NacosUserDetailsServiceImpl;
import com.alibaba.nacos.utils.PasswordEncoderUtil;
import com.alibaba.nacos.core.auth.AccessException;
import com.alibaba.nacos.core.auth.ActionTypes;
import com.alibaba.nacos.core.auth.AuthConfigs;
import com.alibaba.nacos.core.auth.AuthSystemTypes;
import com.alibaba.nacos.core.auth.Secured;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
@ -49,10 +58,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* User related methods entry.
*
@ -64,7 +69,7 @@ import java.util.List;
public class UserController {
@Autowired
private JwtTokenUtils jwtTokenUtils;
private JwtTokenManager jwtTokenManager;
@Autowired
private AuthenticationManager authenticationManager;
@ -126,13 +131,20 @@ public class UserController {
* Update an user.
* @param username username of user
* @param newPassword new password of user
* @param response http response
* @param request http request
* @return ok if update succeed
* @throws IllegalArgumentException if user not exist or oldPassword is incorrect
* @since 1.2.0
*/
@PutMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE)
public Object updateUser(@RequestParam String username, @RequestParam String newPassword) {
@Secured(resource = NacosAuthConfig.UPDATE_PASSWORD_ENTRY_POINT, action = ActionTypes.WRITE)
public Object updateUser(@RequestParam String username, @RequestParam String newPassword,
HttpServletResponse response, HttpServletRequest request) throws IOException {
// admin or same user
if (!hasPermission(username, request)) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "authorization failed!");
}
User user = userDetailsService.getUserFromDatabase(username);
if (user == null) {
@ -144,6 +156,23 @@ public class UserController {
return new RestResult<>(200, "update user ok!");
}
private boolean hasPermission(String username, HttpServletRequest request) {
if (!authConfigs.isAuthEnabled()) {
return true;
}
if (Objects.isNull(request.getAttribute(RequestUtil.NACOS_USER_KEY))) {
return false;
}
NacosUser user = (NacosUser) request.getAttribute(RequestUtil.NACOS_USER_KEY);
// admin
if (user.isGlobalAdmin()) {
return true;
}
// same user
return user.getUserName().equals(username);
}
/**
* Get paged users.
* @param pageNo number index of page
@ -198,7 +227,7 @@ public class UserController {
// Authentication 绑定到 SecurityContext
SecurityContextHolder.getContext().setAuthentication(authentication);
// 生成Token
String token = jwtTokenUtils.createToken(authentication);
String token = jwtTokenManager.createToken(authentication);
// 将Token写入到Http头部
response.addHeader(NacosAuthConfig.AUTHORIZATION_HEADER, "Bearer " + token);
rr.setCode(200);
@ -249,4 +278,15 @@ public class UserController {
return rr;
}
/**
* Fuzzy matching username.
* @param username username
* @return Matched username
*/
@GetMapping("/search")
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE)
public List<String> searchUsersLikeUsername(@RequestParam String username) {
return userDetailsService.findUserLikeUsername(username);
}
}

View File

@ -14,10 +14,10 @@
* limitations under the License.
*/
package com.alibaba.nacos.exception;
package com.alibaba.nacos.console.exception;
import com.alibaba.nacos.auth.exception.AccessException;
import com.alibaba.nacos.common.utils.ExceptionUtil;
import com.alibaba.nacos.core.auth.AccessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;

View File

@ -14,11 +14,11 @@
* limitations under the License.
*/
package com.alibaba.nacos.filter;
package com.alibaba.nacos.console.filter;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.security.nacos.JwtTokenManager;
import com.alibaba.nacos.security.nacos.NacosAuthConfig;
import com.alibaba.nacos.console.security.nacos.JwtTokenManager;
import com.alibaba.nacos.console.security.nacos.NacosAuthConfig;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.alibaba.nacos.model;
package com.alibaba.nacos.console.model;
/**
* Namespace.

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.alibaba.nacos.model;
package com.alibaba.nacos.console.model;
/**
* all namespace info.

View File

@ -14,9 +14,9 @@
* limitations under the License.
*/
package com.alibaba.nacos.security.nacos;
package com.alibaba.nacos.console.security.nacos;
import com.alibaba.nacos.security.nacos.users.NacosUserDetailsServiceImpl;
import com.alibaba.nacos.console.security.nacos.users.NacosUserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.alibaba.nacos.security.nacos;
package com.alibaba.nacos.console.security.nacos;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -14,12 +14,13 @@
* limitations under the License.
*/
package com.alibaba.nacos.security.nacos;
package com.alibaba.nacos.console.security.nacos;
import com.alibaba.nacos.core.auth.AuthConfigs;
import com.alibaba.nacos.auth.common.AuthConfigs;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
@ -67,9 +68,8 @@ public class JwtTokenManager {
validity = new Date(now + authConfigs.getTokenValidityInSeconds() * 1000L);
Claims claims = Jwts.claims().setSubject(userName);
return Jwts.builder().setClaims(claims).setExpiration(validity)
.signWith(SignatureAlgorithm.HS256, authConfigs.getSecretKey()).compact();
.signWith(Keys.hmacShaKeyFor(authConfigs.getSecretKeyBytes()), SignatureAlgorithm.HS256).compact();
}
/**
@ -78,8 +78,8 @@ public class JwtTokenManager {
* @return auth info
*/
public Authentication getAuthentication(String token) {
Claims claims = Jwts.parser().setSigningKey(authConfigs.getSecretKey()).parseClaimsJws(token).getBody();
Claims claims = Jwts.parserBuilder().setSigningKey(authConfigs.getSecretKeyBytes()).build()
.parseClaimsJws(token).getBody();
List<GrantedAuthority> authorities = AuthorityUtils
.commaSeparatedStringToAuthorityList((String) claims.get(AUTHORITIES_KEY));
@ -93,7 +93,7 @@ public class JwtTokenManager {
* @param token token
*/
public void validateToken(String token) {
Jwts.parser().setSigningKey(authConfigs.getSecretKey()).parseClaimsJws(token);
Jwts.parserBuilder().setSigningKey(authConfigs.getSecretKeyBytes()).build().parseClaimsJws(token);
}
}

View File

@ -14,12 +14,12 @@
* limitations under the License.
*/
package com.alibaba.nacos.security.nacos;
package com.alibaba.nacos.console.security.nacos;
import com.alibaba.nacos.filter.JwtAuthenticationTokenFilter;
import com.alibaba.nacos.security.nacos.users.NacosUserDetailsServiceImpl;
import com.alibaba.nacos.core.auth.AuthConfigs;
import com.alibaba.nacos.core.auth.AuthSystemTypes;
import com.alibaba.nacos.auth.common.AuthConfigs;
import com.alibaba.nacos.auth.common.AuthSystemTypes;
import com.alibaba.nacos.console.filter.JwtAuthenticationTokenFilter;
import com.alibaba.nacos.console.security.nacos.users.NacosUserDetailsServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
@ -57,6 +57,8 @@ public class NacosAuthConfig extends WebSecurityConfigurerAdapter {
public static final String CONSOLE_RESOURCE_NAME_PREFIX = "console/";
public static final String UPDATE_PASSWORD_ENTRY_POINT = CONSOLE_RESOURCE_NAME_PREFIX + "user/password";
@Autowired
private Environment env;

View File

@ -14,16 +14,17 @@
* limitations under the License.
*/
package com.alibaba.nacos.security.nacos;
package com.alibaba.nacos.console.security.nacos;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.auth.AuthManager;
import com.alibaba.nacos.auth.exception.AccessException;
import com.alibaba.nacos.auth.model.Permission;
import com.alibaba.nacos.auth.model.User;
import com.alibaba.nacos.config.server.auth.RoleInfo;
import com.alibaba.nacos.security.nacos.roles.NacosRoleServiceImpl;
import com.alibaba.nacos.security.nacos.users.NacosUser;
import com.alibaba.nacos.core.auth.AccessException;
import com.alibaba.nacos.core.auth.AuthManager;
import com.alibaba.nacos.core.auth.Permission;
import com.alibaba.nacos.core.auth.User;
import com.alibaba.nacos.config.server.utils.RequestUtil;
import com.alibaba.nacos.console.security.nacos.roles.NacosRoleServiceImpl;
import com.alibaba.nacos.console.security.nacos.users.NacosUser;
import com.alibaba.nacos.core.utils.Loggers;
import io.jsonwebtoken.ExpiredJwtException;
import org.apache.commons.lang3.StringUtils;
@ -92,7 +93,7 @@ public class NacosAuthManager implements AuthManager {
}
}
}
req.setAttribute(RequestUtil.NACOS_USER_KEY, user);
return user;
}

View File

@ -14,17 +14,17 @@
* limitations under the License.
*/
package com.alibaba.nacos.security.nacos.roles;
package com.alibaba.nacos.console.security.nacos.roles;
import com.alibaba.nacos.auth.common.AuthConfigs;
import com.alibaba.nacos.auth.model.Permission;
import com.alibaba.nacos.config.server.auth.PermissionInfo;
import com.alibaba.nacos.config.server.auth.PermissionPersistService;
import com.alibaba.nacos.config.server.auth.RoleInfo;
import com.alibaba.nacos.config.server.auth.RolePersistService;
import com.alibaba.nacos.config.server.model.Page;
import com.alibaba.nacos.security.nacos.NacosAuthConfig;
import com.alibaba.nacos.security.nacos.users.NacosUserDetailsServiceImpl;
import com.alibaba.nacos.core.auth.AuthConfigs;
import com.alibaba.nacos.core.auth.Permission;
import com.alibaba.nacos.console.security.nacos.NacosAuthConfig;
import com.alibaba.nacos.console.security.nacos.users.NacosUserDetailsServiceImpl;
import com.alibaba.nacos.core.utils.Loggers;
import io.jsonwebtoken.lang.Collections;
import org.apache.commons.lang3.StringUtils;
@ -115,6 +115,10 @@ public class NacosRoleServiceImpl {
* @return true if granted, false otherwise
*/
public boolean hasPermission(String username, Permission permission) {
// update password
if (NacosAuthConfig.UPDATE_PASSWORD_ENTRY_POINT.equals(permission.getResource())) {
return true;
}
List<RoleInfo> roleInfoList = getRoles(username);
if (Collections.isEmpty(roleInfoList)) {
@ -235,4 +239,8 @@ public class NacosRoleServiceImpl {
permissionPersistService.deletePermission(role, resource, action);
}
public List<String> findRolesLikeRoleName(String role) {
return rolePersistService.findRolesLikeRoleName(role);
}
}

View File

@ -14,9 +14,9 @@
* limitations under the License.
*/
package com.alibaba.nacos.security.nacos.users;
package com.alibaba.nacos.console.security.nacos.users;
import com.alibaba.nacos.core.auth.User;
import com.alibaba.nacos.auth.model.User;
/**
* Nacos User.

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.alibaba.nacos.security.nacos.users;
package com.alibaba.nacos.console.security.nacos.users;
import com.alibaba.nacos.config.server.model.User;
import org.springframework.security.core.GrantedAuthority;

View File

@ -14,12 +14,12 @@
* limitations under the License.
*/
package com.alibaba.nacos.security.nacos.users;
package com.alibaba.nacos.console.security.nacos.users;
import com.alibaba.nacos.auth.common.AuthConfigs;
import com.alibaba.nacos.config.server.auth.UserPersistService;
import com.alibaba.nacos.config.server.model.Page;
import com.alibaba.nacos.config.server.model.User;
import com.alibaba.nacos.core.auth.AuthConfigs;
import com.alibaba.nacos.core.utils.Loggers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
@ -28,6 +28,7 @@ import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -101,6 +102,10 @@ public class NacosUserDetailsServiceImpl implements UserDetailsService {
return userPersistService.findUserByUsername(username);
}
public List<String> findUserLikeUsername(String username) {
return userPersistService.findUserLikeUsername(username);
}
public void createUser(String username, String password) {
userPersistService.createUser(username, password);
}

View File

@ -31,6 +31,8 @@ spring:
url: http://pig-monitor:5001
username: pig
password: pig
application:
name: @project.artifactId@
useAddressServer: true

View File

@ -1,26 +0,0 @@
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "entry"
}
],
"react-app"
],
"plugins": [
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
],
[
"babel-plugin-import",
{
"libraryName": "@alifd/next",
"style": true
}
]
]
}

View File

@ -1,16 +0,0 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab

View File

@ -1,6 +0,0 @@
*.svg
*.ejs
.DS_Store
build
node_modules
public

View File

@ -1,36 +0,0 @@
{
"extends": "eslint-config-ali/react",
"parser": "babel-eslint",
"env": {},
"globals": {
"window": true
},
"rules": {
"no-shadow": "off",
"no-empty": "off",
"no-useless-escape": "off",
"no-template-curly-in-string": "off",
"no-unused-vars": "off",
"no-tabs": "off",
"no-param-reassign": "off",
"react/no-string-refs": "off",
"react/no-unused-state": "off",
"no-return-assign": "off",
"no-plusplus": "off",
"no-script-url": "off",
"no-mixed-operators": "off",
"react/jsx-indent": "off",
"react/jsx-no-bind": "off",
"react/forbid-prop-types": "off",
"react/no-array-index-key": "off",
"react/sort-comp": "off",
"implicit-arrow-linebreak": "off",
"prefer-const": "off",
"space-before-function-paren": "off",
"generator-star-spacing": "off",
"wrap-iife": "off",
"arrow-parens": "off",
"indent": "off",
"comma-dangle": "off"
}
}

View File

@ -1,19 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
# production
/dist
# log
yarn-error.log
# misc
.DS_Store
npm-debug.log*
# test
test/uirecorder.log
test/reports
test/screenshots/*

View File

@ -1,6 +0,0 @@
*.svg
*.ejs
.DS_Store
build
node_modules
public

View File

@ -1,9 +0,0 @@
{
"tabWidth": 2,
"printWidth": 100,
"semi": true,
"useTabs": false,
"bracketSpacing": true,
"singleQuote": true,
"trailingComma": "es5"
}

View File

@ -1,60 +0,0 @@
# 开始项目
## cnpm 安装(可忽略)
```sh
npm install -g cnpm --registry=https://registry.npm.taobao.org
# 设置匿名
alias cnpm="npm --registry=https://registry.npm.taobao.org \
--cache=$HOME/.npm/.cache/cnpm \
--disturl=https://npm.taobao.org/dist \
--userconfig=$HOME/.cnpmrc"
# Or alias it in .bashrc or .zshrc
$ echo '\n#alias for cnpm\nalias cnpm="npm --registry=https://registry.npm.taobao.org \
--cache=$HOME/.npm/.cache/cnpm \
--disturl=https://npm.taobao.org/dist \
--userconfig=$HOME/.cnpmrc"' >> ~/.zshrc && source ~/.zshrc
```
[详情地址: http://npm.taobao.org/](http://npm.taobao.org/)
## 安装依赖
```sh
yarn
```
```
cnpm install
```
## 启动
```sh
yarn start
```
```
npm start
```
## 构建打包
```sh
yarn build
```
```
npm run build
```
##
# 代理配置
`build/webpack.dev.conf.js`
修改proxy属性
```
proxy: [{
context: ['/'],
changeOrigin: true,
secure: false,
target: 'http://ip:port',
}],
```

View File

@ -1,83 +0,0 @@
{
"name": "console-fe",
"version": "1.0.0",
"description": "console fe",
"main": "index.js",
"scripts": {
"start": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.dev.conf.js",
"build": "cross-env NODE_ENV=production webpack --config build/webpack.prod.conf.js && node build/copyFile.js",
"eslint": "eslint --ext .js src/",
"eslint-fix": "eslint --ext .js --fix src/"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,css,less}": [
"prettier --write",
"git add"
]
},
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "git+https://github.com/alibaba/nacos.git"
},
"devDependencies": {
"@alifd/next-theme-loader": "^1.3.1",
"@babel/cli": "^7.7.7",
"@babel/core": "^7.7.7",
"@babel/plugin-proposal-decorators": "^7.7.4",
"@babel/preset-env": "^7.7.7",
"@babel/runtime": "^7.7.7",
"babel-eslint": "^10.0.1",
"babel-loader": "^8.0.4",
"babel-plugin-import": "^1.13.0",
"babel-preset-react-app": "^9.1.0",
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^5.1.1 ",
"cross-env": "^6.0.3",
"css-loader": "^3.4.0",
"eslint": "^6.8.0",
"eslint-config-ali": "^9.0.2",
"eslint-config-prettier": "^6.8.0",
"eslint-loader": "^3.0.3",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-prettier": "^3.0.0",
"eslint-plugin-react": "^7.17.0",
"eslint-plugin-react-hooks": "^2.3.0",
"file-loader": "^5.0.2",
"html-webpack-plugin": "^3.2.0",
"husky": "^3.1.0",
"lint-staged": "^9.5.0",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.13.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"prettier": "1.19.1",
"sass-loader": "^8.0.0",
"style-loader": "^1.1.2",
"uglifyjs-webpack-plugin": "^2.2.0",
"url-loader": "^3.0.0",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0"
},
"dependencies": {
"@alifd/next": "^1.17.4",
"axios": "^0.18.0",
"moment": "^2.23.0",
"qs": "^6.8.2",
"prop-types": "^15.6.2",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-redux": "^7.1.3",
"react-router": "^5.1.2",
"react-router-dom": "^5.1.2",
"react-router-redux": "^4.0.8",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"yamljs": "^0.3.0"
}
}

View File

@ -1,58 +0,0 @@
<!--
~ Copyright 1999-2018 Alibaba Group Holding Ltd.
~
~ 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 lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Nacos</title>
<link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="css/console1412.css">
<!-- 第三方css开始 -->
<link rel="stylesheet" type="text/css" href="css/codemirror.css">
<link rel="stylesheet" type="text/css" href="css/merge.css">
<link rel="stylesheet" type="text/css" href="css/icon.css">
<link rel="stylesheet" type="text/css" href="css/font-awesome.css">
<!-- 第三方css结束 -->
</head>
<body>
<div id="root" style="overflow:hidden"></div>
<div id="app"></div>
<div id="other"></div>
<!-- 第三方js开始 -->
<script src="js/jquery.js"></script>
<script src="js/codemirror.js"></script>
<script src="js/javascript.js"></script>
<script src="js/xml.js"></script>
<script src="js/codemirror.addone.fullscreen.js"></script>
<script src="js/codemirror.addone.lint.js"></script>
<script src="js/codemirror.lib.json-lint.js"></script>
<script src="js/codemirror.addone.json-lint.js"></script>
<script src="js/codemirror.lib.clike-lint.js"></script>
<script src="js/diff_match_patch.js"></script>
<script src="js/merge.js"></script>
<script src="js/loader.js"></script>
<!-- 第三方js结束 -->
</body>
</html>

View File

@ -1,152 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { Dialog, Pagination, Transfer } from '@alifd/next';
import { request } from '../../globalLib';
import './index.scss';
class BatchHandle extends React.Component {
static propTypes = {
valueList: PropTypes.array,
dataSource: PropTypes.array,
onSubmit: PropTypes.func,
};
constructor(props) {
super(props);
this.state = {
visible: false,
valueList: props.valueList || [],
dataSourceList: props.dataSource || [],
currentPage: 1,
total: 0,
pageSize: 10,
dataSource: {},
};
}
componentDidMount() {}
openDialog(dataSource) {
this.setState(
{
visible: true,
dataSource,
pageSize: dataSource.pageSize,
},
() => {
this.getData();
this.transfer._instance.filterCheckedValue = function(left, right, dataSource) {
const result = {
left,
right,
};
return result;
};
}
);
}
closeDialog() {
this.setState({
visible: false,
});
}
getData() {
const { dataSource } = this.state;
request({
url: `/diamond-ops/configList/serverId/${dataSource.serverId}?dataId=${
dataSource.dataId
}&group=${dataSource.group}&appName=${
dataSource.appName
}&config_tags=${dataSource.config_tags || ''}&pageNo=${this.state.currentPage}&pageSize=${
dataSource.pageSize
}`,
success: res => {
if (res.code === 200) {
this.setState({
dataSourceList:
res.data.map(obj => ({
label: obj.dataId,
value: obj.dataId,
})) || [],
total: res.total,
});
}
},
});
}
changePage(currentPage) {
this.setState(
{
currentPage,
},
() => {
this.getData();
}
);
}
onChange(valueList, data, extra) {
this.setState({
valueList,
});
}
onSubmit() {
this.props.onSubmit && this.props.onSubmit(this.state.valueList);
}
render() {
// console.log("valueList: ", this.state.valueList, this.transfer);
return (
<Dialog
visible={this.state.visible}
style={{ width: '500px' }}
onCancel={this.closeDialog.bind(this)}
onClose={this.closeDialog.bind(this)}
onOk={this.onSubmit.bind(this)}
title={'批量操作'}
>
<div>
<Transfer
ref={ref => (this.transfer = ref)}
listStyle={{ height: 350 }}
dataSource={this.state.dataSourceList || []}
value={this.state.valueList}
onChange={this.onChange.bind(this)}
/>
<Pagination
style={{ marginTop: 10 }}
current={this.state.currentPage}
total={this.state.total}
pageSize={this.state.pageSize}
onChange={this.changePage.bind(this)}
type="simple"
/>
</div>
</Dialog>
);
}
}
export default BatchHandle;

View File

@ -1,19 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import BatchHandle from './BatchHandle';
export default BatchHandle;

View File

@ -1,15 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/

View File

@ -1,239 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import './index.scss';
import { getParams, request } from '../../globalLib';
import { Button, ConfigProvider, Dialog, Field, Form, Select } from '@alifd/next';
const FormItem = Form.Item;
const { AutoComplete: Combobox } = Select;
/**
* @deprecated
*/
@ConfigProvider.config
class CloneDialog extends React.Component {
static displayName = 'CloneDialog';
constructor(props) {
super(props);
this.defaultPolicy = 'abort';
this.state = {
visible: false,
serverId: '',
tenantFrom: {},
tenantTo: '',
dataId: '',
group: '',
appName: '',
configTags: '',
records: [],
namespaces: [],
policy: this.defaultPolicy,
policyLabel: '',
total: 0,
allPolicy: [],
};
this.field = new Field(this);
this.formItemLayout = {
labelCol: {
fixedSpan: 6,
},
wrapperCol: {
span: 18,
},
};
}
componentDidMount() {
const { locale = {} } = this.props;
this.setState({
policyLabel: locale.terminate,
allPolicy: [
{ value: 'abort', label: locale.terminate },
{ value: 'skip', label: locale.skip },
{ value: 'overwrite', label: locale.cover },
],
});
}
openDialog(payload, callback) {
const { locale = {} } = this.props;
const serverId = getParams('serverId') || 'center';
this.checkData = payload.checkData;
this.callback = callback;
request({
type: 'get',
url: `/diamond-ops/service/serverId/${serverId}/namespaceInfo`,
success: res => {
if (res.code === 200) {
const dataSource = [];
res.data.forEach(value => {
if (value.namespace !== payload.tenantFrom.id) {
dataSource.push({
value: value.namespace,
label: `${value.namespaceShowName} | ${value.namespace}`,
});
}
});
this.setState({
visible: true,
serverId: payload.serverId,
tenantFrom: payload.tenantFrom,
tenantTo: '',
dataId: payload.dataId,
group: payload.group,
appName: payload.appName,
configTags: payload.configTags,
records: payload.records,
namespaces: dataSource,
total: payload.total,
});
this.field.setValue('select', '');
} else {
Dialog.alert({
title: locale.getNamespaceFailed,
content: res.message,
});
}
},
});
}
closeDialog() {
this.setState({ visible: false });
}
setTenantTo(value) {
this.field.setValue(value);
this.setState({ tenantTo: value });
}
setPolicy(...value) {
this.setState({
policyLabel: value[1].label,
policy: value[0],
});
}
getQuery() {
const { locale = {} } = this.props;
if (this.state.records.length > 0) return locale.selectedEntry;
if (
this.state.dataId === '' &&
this.state.group === '' &&
this.state.appName === '' &&
this.state.configTags.length === 0
) {
return '';
}
let query = ' |';
if (this.state.dataId !== '') {
query += ` DataId: ${this.state.dataId},`;
}
if (this.state.group !== '') {
query += ` Group: ${this.state.group},`;
}
if (this.state.appName !== '') {
query += `${locale.homeApplication + this.state.appName},`;
}
if (this.state.configTags.length !== 0) {
query += `${locale.tags + this.state.configTags},`;
}
return query.substr(0, query.length - 1);
}
doClone() {
this.field.validate((errors, values) => {
if (errors) {
return;
}
this.closeDialog();
this.checkData.tenantTo = this.state.tenantTo;
this.checkData.policy = this.state.policy;
this.callback(this.checkData, this.state.policyLabel);
});
}
render() {
const { locale = {} } = this.props;
const { init } = this.field;
const footer = (
<div>
<Button
type="primary"
onClick={this.doClone.bind(this)}
{...{ disabled: this.state.total <= 0 }}
>
{locale.startCloning}
</Button>
</div>
);
return (
<div>
<Dialog
visible={this.state.visible}
footer={footer}
footerAlign="center"
style={{ width: 555 }}
onCancel={this.closeDialog.bind(this)}
onClose={this.closeDialog.bind(this)}
title={`${locale.configurationCloning + this.state.serverId}`}
>
<Form field={this.field}>
<FormItem label={locale.source} {...this.formItemLayout}>
<p>
<span style={{ color: '#33cde5' }}>{this.state.tenantFrom.name}</span>
{` | ${this.state.tenantFrom.id}`}
</p>
</FormItem>
<FormItem label={locale.configurationNumber} {...this.formItemLayout}>
<p>
<span style={{ color: '#33cde5' }}>{this.state.total}</span> {this.getQuery()}{' '}
</p>
</FormItem>
<FormItem label={locale.target} {...this.formItemLayout}>
<Combobox
style={{ width: '80%' }}
size="medium"
hasArrow
placeholder={locale.selectNamespace}
dataSource={this.state.namespaces}
{...init('select', {
props: { onChange: this.setTenantTo.bind(this) },
rules: [{ required: true, message: locale.selectNamespace }],
})}
/>
</FormItem>
<FormItem label={locale.conflict} {...this.formItemLayout}>
<Select
size="medium"
hasArrow
defaultValue={this.defaultPolicy}
dataSource={this.state.allPolicy}
onChange={this.setPolicy.bind(this)}
/>
</FormItem>
</Form>
</Dialog>
</div>
);
}
}
export default CloneDialog;

View File

@ -1,19 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import CloneDialog from './CloneDialog';
export default CloneDialog;

View File

@ -1,15 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/

View File

@ -1,122 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { Button, ConfigProvider, Dialog, Grid, Icon } from '@alifd/next';
import './index.scss';
const { Row, Col } = Grid;
@ConfigProvider.config
class DeleteDialog extends React.Component {
static displayName = 'DeleteDialog';
static propTypes = {
locale: PropTypes.object,
};
constructor(props) {
super(props);
this.state = {
visible: false,
title: '',
content: '',
isok: true,
dataId: '',
group: '',
};
}
componentDidMount() {
this.initData();
}
initData() {
const { locale = {} } = this.props;
this.setState({ title: locale.confManagement });
}
openDialog(payload) {
this.setState({
visible: true,
title: payload.title,
content: payload.content,
isok: payload.isok,
dataId: payload.dataId,
group: payload.group,
message: payload.message,
});
}
closeDialog() {
this.setState({
visible: false,
});
}
render() {
const { locale = {} } = this.props;
const footer = (
<div style={{ textAlign: 'right' }}>
<Button type="primary" onClick={this.closeDialog.bind(this)}>
{locale.determine}
</Button>
</div>
);
return (
<div>
<Dialog
visible={this.state.visible}
footer={footer}
style={{ width: 555 }}
onCancel={this.closeDialog.bind(this)}
onClose={this.closeDialog.bind(this)}
title={locale.deletetitle}
>
<div>
<Row>
<Col span={'4'} style={{ paddingTop: 16 }}>
<Icon
type={`${this.state.isok ? 'success' : 'delete'}-filling`}
style={{ color: this.state.isok ? 'green' : 'red' }}
size={'xl'}
/>
</Col>
<Col span={'20'}>
<div>
<h3>{this.state.isok ? locale.deletedSuccessfully : locale.deleteFailed}</h3>
<p>
<span style={{ color: '#999', marginRight: 5 }}>Data ID:</span>
<span style={{ color: '#c7254e' }}>{this.state.dataId}</span>
</p>
<p>
<span style={{ color: '#999', marginRight: 5 }}>Group:</span>
<span style={{ color: '#c7254e' }}>{this.state.group}</span>
</p>
{this.state.isok ? '' : <p style={{ color: 'red' }}>{this.state.message}</p>}
</div>
</Col>
</Row>
</div>
</Dialog>
</div>
);
}
}
export default DeleteDialog;

View File

@ -1,19 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import DeleteDialog from './DeleteDialog';
export default DeleteDialog;

View File

@ -1,15 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/

View File

@ -1,116 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { Button, ConfigProvider, Dialog, Grid } from '@alifd/next';
import './index.scss';
const { Row, Col } = Grid;
@ConfigProvider.config
class DiffEditorDialog extends React.Component {
static displayName = 'DiffEditorDialog';
static propTypes = {
locale: PropTypes.object,
};
static propTypes = {
publishConfig: PropTypes.func,
};
constructor(props) {
super(props);
this.diffeditor = React.createRef();
this.state = {
dialogvisible: false,
};
}
openDialog(letfcode, rightcode) {
this.setState({
dialogvisible: true,
});
setTimeout(() => {
this.createDiffCodeMirror(letfcode, rightcode);
});
}
closeDialog() {
this.setState({
dialogvisible: false,
});
}
createDiffCodeMirror(leftCode, rightCode) {
const target = this.diffeditor.current;
target.innerHTML = '';
this.diffeditor = window.CodeMirror.MergeView(target, {
value: leftCode || '',
readOnly: true,
origLeft: null,
orig: rightCode || '',
lineNumbers: true,
mode: this.mode,
theme: 'xq-light',
highlightDifferences: true,
connect: 'align',
collapseIdentical: false,
});
}
confirmPub() {
this.closeDialog();
this.props.publishConfig();
}
render() {
const { locale = {} } = this.props;
const footer = (
<div>
{' '}
<Button type="primary" onClick={this.confirmPub.bind(this)}>
{locale.publish}
</Button>
</div>
);
return (
<div>
<Dialog
title={locale.contents}
style={{ width: '80%' }}
visible={this.state.dialogvisible}
footer={footer}
onClose={this.closeDialog.bind(this)}
>
<div style={{ height: 400 }}>
<div>
<Row>
<Col style={{ textAlign: 'center' }}>{locale.currentArea}</Col>
<Col style={{ textAlign: 'center' }}>{locale.originalValue}</Col>
</Row>
</div>
<div style={{ clear: 'both', height: 480 }} ref={this.diffeditor} />
</div>
</Dialog>
</div>
);
}
}
export default DiffEditorDialog;

View File

@ -1,19 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import DiffEditorDialog from './DiffEditorDialog';
export default DiffEditorDialog;

View File

@ -1,15 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/

View File

@ -1,215 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { request } from '../../globalLib';
import { Button, ConfigProvider, Dialog, Field, Form, Input, Loading } from '@alifd/next';
import './index.scss';
const FormItem = Form.Item;
@ConfigProvider.config
class EditorNameSpace extends React.Component {
static displayName = 'EditorNameSpace';
static propTypes = {
getNameSpaces: PropTypes.func,
locale: PropTypes.object,
};
constructor(props) {
super(props);
this.state = {
dialogvisible: false,
loading: false,
};
this.field = new Field(this);
}
openDialog(record) {
this.getNamespaceDetail(record);
this.setState({
dialogvisible: true,
type: record.type,
});
}
closeDialog() {
this.setState({
dialogvisible: false,
});
}
openLoading() {
this.setState({
loading: true,
});
}
closeLoading() {
this.setState({
loading: false,
});
}
getNamespaceDetail(record) {
const { locale = {} } = this.props;
this.field.setValues(record);
request({
type: 'get',
url: `v1/console/namespaces?show=all&namespaceId=${record.namespace}`,
success: res => {
if (res !== null) {
this.field.setValue('namespaceDesc', res.namespaceDesc);
} else {
Dialog.alert({
title: locale.notice,
content: res.message,
});
}
},
error: () => {
window.namespaceList = [];
this.handleNameSpaces(window.namespaceList);
},
});
}
handleSubmit() {
const { locale = {} } = this.props;
this.field.validate((errors, values) => {
if (errors) {
return;
}
request({
type: 'put',
beforeSend: () => {
this.openLoading();
},
url: 'v1/console/namespaces',
contentType: 'application/x-www-form-urlencoded',
data: {
namespace: values.namespace,
namespaceShowName: values.namespaceShowName,
namespaceDesc: values.namespaceDesc,
},
success: res => {
if (res === true) {
this.closeDialog();
this.props.getNameSpaces();
this.refreshNameSpace(); // 刷新全局namespace
} else {
Dialog.alert({
title: locale.notice,
content: res.message,
});
}
},
complete: () => {
this.closeLoading();
},
});
});
}
refreshNameSpace() {
setTimeout(() => {
request({
type: 'get',
url: 'v1/console/namespaces',
success: res => {
if (res.code === 200) {
window.namespaceList = res.data;
}
},
});
}, 2000);
}
validateChart(rule, value, callback) {
const { locale = {} } = this.props;
const chartReg = /[@#\$%\^&\*]+/g;
if (chartReg.test(value)) {
callback(locale.pleaseDo);
} else {
callback();
}
}
render() {
const { locale = {} } = this.props;
const formItemLayout = {
labelCol: { fixedSpan: 6 },
wrapperCol: { span: 18 },
};
const footer =
this.state.type === 0 ? (
<div />
) : (
<Button type="primary" onClick={this.handleSubmit.bind(this)}>
{locale.publicSpace}
</Button>
);
return (
<div>
<Dialog
title={locale.confirmModify}
style={{ width: '50%' }}
visible={this.state.dialogvisible}
footer={footer}
onCancel={this.closeDialog.bind(this)}
onClose={this.closeDialog.bind(this)}
>
<Loading
tip={locale.editNamespace}
style={{ width: '100%', position: 'relative' }}
visible={this.state.loading}
>
<Form field={this.field}>
<FormItem label={locale.load} required {...formItemLayout}>
<Input
{...this.field.init('namespaceShowName', {
rules: [
{ required: true, message: locale.namespace },
{ validator: this.validateChart.bind(this) },
],
})}
disabled={this.state.type === 0}
/>
</FormItem>
<FormItem label={locale.description} required {...formItemLayout}>
<Input
{...this.field.init('namespaceDesc', {
rules: [
{ required: true, message: locale.namespaceDesc },
{ validator: this.validateChart.bind(this) },
],
})}
disabled={this.state.type === 0}
/>
</FormItem>
</Form>
</Loading>
</Dialog>
</div>
);
}
}
export default EditorNameSpace;

View File

@ -1,19 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import EditorNameSpace from './EditorNameSpace';
export default EditorNameSpace;

View File

@ -1,15 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/

View File

@ -1,162 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import { Button, ConfigProvider, Dialog, Form } from '@alifd/next';
import './index.scss';
const FormItem = Form.Item;
/**
* @deprecated
*/
@ConfigProvider.config
class ExportDialog extends React.Component {
static displayName = 'ExportDialog';
constructor(props) {
super(props);
this.state = {
visible: false,
serverId: '',
tenant: '',
dataId: '',
group: '',
appName: '',
configTags: '',
records: [],
total: 0,
};
this.formItemLayout = {
labelCol: { fixedSpan: 4 },
wrapperCol: { span: 20 },
};
}
componentDidMount() {}
openDialog(payload) {
this.setState({
visible: true,
serverId: payload.serverId,
tenant: payload.tenant,
dataId: payload.dataId,
group: payload.group,
appName: payload.appName,
configTags: payload.configTags,
records: payload.records,
total: payload.total,
});
}
closeDialog = () => {
this.setState({
visible: false,
});
};
getQuery() {
const { locale = {} } = this.props;
if (this.state.records.length > 0) return locale.selectedEntry;
if (
this.state.dataId === '' &&
this.state.group === '' &&
this.state.appName === '' &&
this.state.configTags.length === 0
) {
return '';
}
let query = ' |';
if (this.state.dataId !== '') {
query += ` DataId: ${this.state.dataId},`;
}
if (this.state.group !== '') {
query += ` Group: ${this.state.group},`;
}
if (this.state.appName !== '') {
query += `${locale.application + this.state.appName},`;
}
if (this.state.configTags.length !== 0) {
query += `${locale.tags + this.state.configTags},`;
}
return query.substr(0, query.length - 1);
}
doExport = () => {
// document.getElementById('downloadLink').click();
const url = this.getLink();
window.open(url);
this.closeDialog();
};
getLink() {
const data = [];
this.state.records.forEach(record => {
data.push({ dataId: record.dataId, group: record.group });
});
const query = `?dataId=${this.state.dataId}&group=${this.state.group}&appName=${
this.state.appName
}&tags=${this.state.configTags || ''}&data=${encodeURI(JSON.stringify(data))}`;
const baseLink = `/diamond-ops/batch/export/serverId/${this.state.serverId}/tenant/${this.state.tenant.id}${query}`;
if (window.globalConfig.isParentEdas()) {
return `/authgw/${window.edasprefix}${baseLink}`;
}
return baseLink;
}
render() {
const { locale = {} } = this.props;
const footer = (
<div>
{/* <a id="downloadLink" style={{ display: "none" }} href={this.getLink()} /> */}
<Button type="primary" onClick={this.doExport} {...{ disabled: this.state.total <= 0 }}>
{locale.exportBtn}
</Button>
</div>
);
return (
<div>
<Dialog
visible={this.state.visible}
footer={footer}
footerAlign="center"
style={{ width: 480 }}
onCancel={this.closeDialog}
onClose={this.closeDialog}
title={`${locale.exportConfiguration + this.state.serverId}`}
>
<Form>
<FormItem label={locale.source} {...this.formItemLayout}>
<p>
<span style={{ color: '#33cde5' }}>{this.state.tenant.name}</span>
{` | ${this.state.tenant.id}`}
</p>
</FormItem>
<FormItem label={locale.items} {...this.formItemLayout}>
<p>
<span style={{ color: '#33cde5' }}>{this.state.total}</span> {this.getQuery()}{' '}
</p>
</FormItem>
</Form>
</Dialog>
</div>
);
}
}
export default ExportDialog;

View File

@ -1,19 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import ExportDialog from './ExportDialog';
export default ExportDialog;

View File

@ -1,15 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/

View File

@ -1,198 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import { isParentEdas } from '@/lib';
import { Balloon, Button, ConfigProvider, Dialog, Form, Icon, Select, Upload } from '@alifd/next';
import './index.scss';
const FormItem = Form.Item;
/**
* @deprecated
*/
@ConfigProvider.config
class ImportDialog extends React.Component {
static displayName = 'ImportDialog';
constructor(props) {
super(props);
this.formItemLayout = {
labelCol: {
fixedSpan: 4,
},
wrapperCol: {
span: 20,
},
};
this.defaultPolicy = 'abort';
this.state = {
visible: false,
serverId: '',
tenant: '',
policy: this.defaultPolicy,
policyLabel: '',
allPolicy: [],
};
}
componentDidMount() {
const { locale = {} } = this.props;
this.setState({
policyLabel: locale.terminate,
allPolicy: [
{ value: 'abort', label: locale.terminate },
{ value: 'skip', label: locale.skip },
{ value: 'overwrite', label: locale.overwrite },
],
});
}
openDialog(payload, callback) {
this.callback = callback;
this.setState({
visible: true,
serverId: payload.serverId,
tenant: payload.tenant,
});
}
closeDialog = () => {
this.setState({
visible: false,
});
};
setPolicy = (...value) => {
this.setState({
policyLabel: value[1].label,
policy: value[0],
});
};
formatter = res => {
if (res.code === 200) {
return {
code: '0',
retData: res,
};
} else {
return {
code: '1',
error: {
message: res.message,
},
retData: res,
};
}
};
render() {
const { locale = {} } = this.props;
let uploadLink = `/diamond-ops/batch/import/serverId/${this.state.serverId}/tenant/${this.state.tenant.id}?policy=${this.state.policy}`;
if (isParentEdas()) {
uploadLink = `/authgw/${window.edasprefix}${uploadLink}`;
}
const helpTip = (
<Balloon
trigger={
<span>
Data ID{' '}
<Icon
type="help"
size="small"
style={{ color: '#1DC11D', marginRight: 5, verticalAlign: 'middle' }}
/>
</span>
}
align="t"
style={{ marginRight: 5 }}
triggerType="hover"
>
<a href={window._getLink && window._getLink('knowDataid')} target="_blank">
{locale.zipFileFormat}
</a>
</Balloon>
);
const footer = (
<div>
<Upload
listType={'text'}
action={uploadLink}
limit={1}
accept={'.zip'}
onSuccess={(...args) => {
this.callback(args[0].retData, this.state.policyLabel);
this.closeDialog();
}}
onError={(...args) => {
this.callback(args[0].response.retData, this.state.policyLabel);
this.closeDialog();
}}
formatter={this.formatter}
headers={{ poweredBy: 'simpleMVC', projectName: 'nacos' }}
>
<Button type={'primary'}>{locale.uploadFile}</Button>
</Upload>
</div>
);
return (
<div>
<Dialog
visible={this.state.visible}
footer={footer}
footerAlign="center"
style={{ width: 480 }}
onCancel={this.closeDialog}
onClose={this.closeDialog}
title={`${locale.importLabel + this.state.serverId}`}
>
<Form>
<FormItem label={locale.target} {...this.formItemLayout}>
<p>
<span style={{ color: '#33cde5' }}>{this.state.tenant.name}</span>
{` | ${this.state.tenant.id}`}
</p>
</FormItem>
<FormItem label={locale.conflict} {...this.formItemLayout}>
<Select
size={'medium'}
hasArrow
defaultValue={this.defaultPolicy}
dataSource={this.state.allPolicy}
onChange={this.setPolicy}
/>
</FormItem>
</Form>
<div style={{ textAlign: 'center' }}>
<Icon
type={'warning'}
style={{ color: '#ff8a00', marginRight: 5, verticalAlign: 'middle' }}
/>
{locale.beSureExerciseCaution}
{helpTip}
</div>
</Dialog>
</div>
);
}
}
export default ImportDialog;

View File

@ -1,19 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import ImportDialog from './ImportDialog';
export default ImportDialog;

View File

@ -1,15 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/

View File

@ -1,114 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import * as React from 'react';
import { MONACO_OPTIONS } from './constant';
import './index.scss';
interface PropsType {
dispatch: (obj: Object) => void;
options: Object;
value: string;
language: string;
width: number;
height: number;
onChange: (value: string) => void;
}
interface StateType {}
class MonacoEditor extends React.Component<PropsType, StateType> {
static displayName = 'MonacoEditor';
private nodeRef: any = React.createRef();
public monacoEditor: any = null;
public state: StateType;
public props: PropsType;
constructor(props: PropsType) {
super(props);
}
componentWillReceiveProps(nextProps): void {
if (!this.monacoEditor) {
return;
}
const { value = '', language = 'js', width, height, options = {} } = this.props;
if (value !== nextProps.value) {
this.monacoEditor.setValue(nextProps.value || '');
}
if (language !== nextProps.language) {
this.monacoEditor.editor.setModelLanguage(this.monacoEditor.getModel(), nextProps.language);
}
if (this.monacoEditor && (width !== nextProps.width || height !== nextProps.height)) {
this.monacoEditor.layout();
}
if (this.monacoEditor && nextProps.options && options !== nextProps.options) {
this.monacoEditor.updateOptions({ ...MONACO_OPTIONS, ...nextProps.options });
}
}
componentDidMount(): void {
if (!window.monaco) {
window.importEditor &&
window.importEditor(() => {
this.initMoacoEditor();
});
} else {
this.initMoacoEditor();
}
}
componentWillUnmount(): void {
this.monacoEditor && this.monacoEditor.dispose();
this.nodeRef = null;
}
initMoacoEditor(): void {
const { options = {}, language = 'js', value = '' } = this.props;
try {
this.monacoEditor = window.monaco.editor.create(this.nodeRef && this.nodeRef.current, {
...MONACO_OPTIONS,
...options,
language,
value,
});
this.editorDidMount(this.monacoEditor);
} catch (error) {}
}
editorDidMount(editor: any) {
const { onChange } = this.props;
editor.onDidChangeModelContent(event => {
const value = editor.getValue();
typeof onChange === 'function' && onChange(value);
});
}
render(): HTMLElement {
const { width = '100%', height = 0 } = this.props;
const style = {
width,
height,
};
return <div ref={this.nodeRef} style={style} />;
}
}
export default MonacoEditor;

View File

@ -1,30 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
export const MONACO_OPTIONS: Object = {
codeLens: true,
selectOnLineNumbers: true,
roundedSelection: false,
readOnly: false,
lineNumbersMinChars: true,
theme: 'vs-dark',
wordWrapColumn: 120,
folding: true,
showFoldingControls: 'always',
wordWrap: 'wordWrapColumn',
cursorStyle: 'line',
automaticLayout: true,
};

View File

@ -1,15 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/

View File

@ -1,19 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import MonacoEditor from './MonacoEditor';
export default MonacoEditor;

View File

@ -1,227 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { ConfigProvider, Dialog } from '@alifd/next';
import { getParams, setParams, request } from '../../globalLib';
import './index.scss';
/**
* 命名空间列表
*/
@ConfigProvider.config
class NameSpaceList extends React.Component {
static displayName = 'NameSpaceList';
static propTypes = {
locale: PropTypes.object,
setNowNameSpace: PropTypes.func,
namespaceCallBack: PropTypes.func,
title: PropTypes.string,
};
constructor(props) {
super(props);
this._namespace = getParams('namespace') || '';
// this._namespaceShowName = getParams('namespaceShowName') || '';
this.state = {
nownamespace: window.nownamespace || this._namespace || '',
namespaceList: window.namespaceList || [],
// namespaceShowName: window.namespaceShowName || this._namespaceShowName || '',
// _dingdingLink: "",
// _forumLink: ""
};
}
componentDidMount() {
// this.getLink("dingding", "_dingdingLink");
// this.getLink("discuz", "_forumLink");
}
getLink(linkKey, keyName) {
if (window[keyName] === null) {
request({
url: 'com.alibaba.nacos.service.getLink',
data: {
linkKey,
},
success: res => {
if (res.code === 200) {
window[keyName] = res.data;
this.setState({
[keyName]: res.data,
});
}
},
});
} else {
this.setState({
[keyName]: window[keyName],
});
}
}
// if (!this.state.namespaceList || this.state.namespaceList.length === 0) {
// this.getNameSpaces();
// } else {
// this.calleeParent();
// }
/**
切换namespace
* */
changeNameSpace(ns, nsName) {
localStorage.setItem('namespace', ns);
this.setnamespace(ns || '');
setParams({
namespace: ns || '',
namespaceShowName: nsName,
});
window.nownamespace = ns;
window.namespaceShowName = nsName;
this.calleeParent(true);
this.props.setNowNameSpace && this.props.setNowNameSpace(nsName, ns);
}
calleeParent(needclean = false) {
this.props.namespaceCallBack && this.props.namespaceCallBack(needclean);
}
getNameSpaces() {
const { locale = {} } = this.props;
if (window.namespaceList && window.namespaceList.length) {
this.handleNameSpaces(window.namespaceList);
} else {
request({
type: 'get',
url: 'v1/console/namespaces',
success: res => {
if (res.code === 200) {
this.handleNameSpaces(res.data);
} else {
Dialog.alert({
title: locale.notice,
content: res.message,
});
}
},
error: () => {
window.namespaceList = [];
this.handleNameSpaces(window.namespaceList);
},
});
}
}
handleNameSpaces(data) {
const nownamespace = getParams('namespace') || '';
// let namespaceShowName = this._namespaceShowName || data[0].namespaceShowName || '';
window.namespaceList = data;
window.nownamespace = nownamespace;
let namespaceShowName = '';
for (let i = 0; i < data.length; i++) {
if (data[i].namespace === nownamespace) {
({ namespaceShowName } = data[i]);
break;
}
}
window.namespaceShowName = namespaceShowName;
setParams('namespace', nownamespace || '');
localStorage.setItem('namespace', nownamespace);
// setParams('namespaceShowName', namespaceShowName);
this.props.setNowNameSpace && this.props.setNowNameSpace(namespaceShowName, nownamespace);
this.setState({
nownamespace,
namespaceList: data,
});
this.calleeParent();
}
setnamespace(ns) {
this.setState({
nownamespace: ns,
});
}
rendernamespace(namespaceList) {
const { nownamespace } = this.state; // 获得当前namespace
const namespacesBtn = namespaceList.map((obj, index) => {
const style =
obj.namespace === nownamespace
? { color: '#00C1DE', marginRight: 10, border: 'none', fontSize: 12 }
: { color: '#666', marginRight: 10, border: 'none', fontSize: 12 };
return (
<div key={index} style={{ float: 'left', cursor: 'pointer' }}>
{index === 0 ? '' : <span style={{ marginRight: 5, marginLeft: 5 }}>|</span>}
<span
type={'light'}
style={style}
onClick={this.changeNameSpace.bind(this, obj.namespace, obj.namespaceShowName)}
key={index}
>
{obj.namespaceShowName}
</span>
</div>
);
});
return <div style={{ paddingTop: 9 }}>{namespacesBtn}</div>;
}
render() {
const namespaceList = this.state.namespaceList || [];
const title = this.props.title || '';
const namespacestyle = {
marginTop: 5,
marginBottom: '10px',
paddingBottom: '10px',
borderBottom: '1px solid #ccc',
};
return (
<div
className={namespaceList.length ? 'namespacewrapper' : ''}
style={namespaceList.length ? namespacestyle : {}}
>
{}
{title ? (
<p
style={{
height: 30,
lineHeight: '30px',
paddingTop: 0,
paddingBottom: 0,
borderLeft: '2px solid #09c',
float: 'left',
margin: 0,
paddingLeft: 10,
}}
>
{this.props.title}
</p>
) : (
''
)}
<div style={{ float: 'left' }}>{this.rendernamespace(namespaceList)}</div>
</div>
);
}
}
export default NameSpaceList;

View File

@ -1,19 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import NameSpaceList from './NameSpaceList';
export default NameSpaceList;

View File

@ -1,15 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/

View File

@ -1,297 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import { request } from '../../globalLib';
import { Button, ConfigProvider, Dialog, Field, Form, Input, Loading } from '@alifd/next';
import './index.scss';
import PropTypes from 'prop-types';
const FormItem = Form.Item;
const formItemLayout = {
labelCol: { fixedSpan: 6 },
wrapperCol: { span: 18 },
};
@ConfigProvider.config
class NewNameSpace extends React.Component {
static displayName = 'NewNameSpace';
static propTypes = {
locale: PropTypes.object,
getNameSpaces: PropTypes.func,
};
constructor(props) {
super(props);
this.state = {
dialogvisible: false,
loading: false,
disabled: false,
dataSource: [],
};
this.field = new Field(this);
this.disabled = false;
}
componentDidMount() {
this.groupLabel = document.getElementById('groupwrapper');
}
openDialog(dataSource) {
this.setState({
dialogvisible: true,
disabled: false,
dataSource,
});
this.disabled = false;
}
closeDialog() {
this.setState({
dialogvisible: false,
});
}
openLoading() {
this.setState({
loading: true,
});
}
closeLoading() {
this.setState({
loading: false,
});
}
showGroup() {
this.groupLabel.style.display = 'block';
}
hideGroup() {
this.groupLabel.style.display = 'none';
}
changeType(value) {
if (value === 0) {
this.showGroup();
} else {
this.hideGroup();
}
}
handleSubmit() {
const { locale = {} } = this.props;
this.field.validate((errors, values) => {
if (errors) return;
const flag = this.state.dataSource.every(
val => val.namespaceShowName !== values.namespaceShowName
);
if (!flag) {
Dialog.alert({ content: locale.norepeat });
return;
}
this.disabled = true;
this.setState({
disabled: true,
});
let { customNamespaceId } = values;
if (!customNamespaceId) {
customNamespaceId = '';
}
request({
type: 'get',
url: 'v1/console/namespaces?checkNamespaceIdExist=true',
contentType: 'application/x-www-form-urlencoded',
beforeSend: () => this.openLoading(),
data: {
customNamespaceId,
},
success: res => {
this.disabled = false;
this.setState({
disabled: false,
});
if (res === true) {
Dialog.alert({
title: locale.notice,
content: locale.namespaceIdAlreadyExist,
});
} else {
request({
type: 'post',
url: 'v1/console/namespaces',
contentType: 'application/x-www-form-urlencoded',
beforeSend: () => this.openLoading(),
data: {
customNamespaceId,
namespaceName: values.namespaceShowName,
namespaceDesc: values.namespaceDesc,
},
success: res => {
this.disabled = false;
this.setState({
disabled: false,
});
if (res === true) {
this.closeDialog();
this.props.getNameSpaces();
this.refreshNameSpace(); // 刷新全局namespace
} else {
Dialog.alert({
title: locale.notice,
content: locale.newnamespceFailedMessage,
});
}
},
complete: () => this.closeLoading(),
});
}
},
complete: () => this.closeLoading(),
});
});
}
refreshNameSpace() {
setTimeout(() => {
request({
type: 'get',
url: 'v1/console/namespaces',
success: res => {
if (res.code === 200) {
window.namespaceList = res.data;
}
},
});
}, 2000);
}
validateChart(rule, value, callback) {
const { locale = {} } = this.props;
const chartReg = /[@#\$%\^&\*]+/g;
if (chartReg.test(value)) {
callback(locale.input);
} else {
callback();
}
}
validateNamespzecId(rule, value, callback) {
if (!value || value.trim() === '') {
callback();
} else {
const { locale = {} } = this.props;
if (value.length > 128) {
callback(locale.namespaceIdTooLong);
}
const chartReg = /^[\w-]+/g;
const matchResult = value.match(chartReg);
if (matchResult) {
if (matchResult.length > 1) {
callback(locale.input);
} else {
if (value.length !== matchResult[0].length) {
callback(locale.input);
return;
}
callback();
}
} else {
callback(locale.input);
}
}
}
render() {
const { locale = {} } = this.props;
const footer = (
<div>
<Button type="primary" onClick={this.handleSubmit.bind(this)} disabled={this.disabled}>
{locale.ok}
</Button>
<Button type="normal" onClick={this.closeDialog.bind(this)} style={{ marginLeft: 5 }}>
{locale.cancel}
</Button>
</div>
);
return (
<div>
<Dialog
title={locale.newnamespce}
style={{ width: '50%' }}
visible={this.state.dialogvisible}
onOk={this.handleSubmit.bind(this)}
onCancel={this.closeDialog.bind(this)}
footer={footer}
onClose={this.closeDialog.bind(this)}
>
<Form field={this.field}>
<Loading
tip={locale.loading}
style={{ width: '100%', position: 'relative' }}
visible={this.state.loading}
>
<FormItem label={locale.namespaceId} {...formItemLayout}>
<Input
{...this.field.init('customNamespaceId', {
rules: [{ validator: this.validateNamespzecId.bind(this) }],
})}
style={{ width: '100%' }}
/>
</FormItem>
<FormItem label={locale.name} required {...formItemLayout}>
<Input
{...this.field.init('namespaceShowName', {
rules: [
{
required: true,
message: locale.namespacenotnull,
},
{ validator: this.validateChart.bind(this) },
],
})}
style={{ width: '100%' }}
/>
</FormItem>
<FormItem label={locale.description} required {...formItemLayout}>
<Input
{...this.field.init('namespaceDesc', {
rules: [
{
required: true,
message: locale.namespacedescnotnull,
},
{ validator: this.validateChart.bind(this) },
],
})}
style={{ width: '100%' }}
/>
</FormItem>
</Loading>
</Form>
</Dialog>
</div>
);
}
}
export default NewNameSpace;

View File

@ -1,19 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import NewNameSpace from './NewNameSpace';
export default NewNameSpace;

View File

@ -1,15 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/

View File

@ -1,331 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import $ from 'jquery';
import { Button } from '@alifd/next';
import NameSpaceList from '../NameSpaceList';
import { setParams, request } from '../../globalLib';
import './index.scss';
class RegionGroup extends React.Component {
static propTypes = {
url: PropTypes.string,
left: PropTypes.any,
right: PropTypes.any,
namespaceCallBack: PropTypes.func,
setNowNameSpace: PropTypes.func,
};
constructor(props) {
super(props);
this.state = {
instanceData: [],
currRegionId: '',
url: props.url || '/diamond-ops/env/domain',
left: props.left,
right: props.right,
regionWidth: 700,
hideRegionList: false,
};
this.currRegionId = '';
this.styles = {
title: {
// marginTop: '8px',
// marginBottom: '8px',
margin: 0,
lineHeight: '32px',
display: 'inline-block',
textIndent: '8px',
marginRight: '8px',
borderLeft: '2px solid #88b7E0',
fontSize: '16px',
},
};
this.nameSpaceList = React.createRef();
this.mainRef = null;
this.titleRef = null;
this.regionRef = null;
this.extraRef = null;
this.resizer = null;
this.timer = null;
this.handleResize = this.handleResize.bind(this);
this.handleAliyunNav = this.handleAliyunNav.bind(this);
!window.viewframeSetting && (window.viewframeSetting = {});
}
componentDidMount() {
// this.setRegionWidth();
// window.postMessage({ type: 'CONSOLE_HAS_REGION' }, window.location)
// $(".aliyun-console-regionbar").show();
// $(window).bind("resize", this.handleResize);
// window.addEventListener("message", this.handleAliyunNav);
// this.getRegionList();
// setTimeout(() => {
// this.setRegionWidth();
// this.handleRegionListStatus();
// });
const nameSpaceList = this.nameSpaceList.current;
if (nameSpaceList) {
nameSpaceList.getInstance().getNameSpaces();
}
}
componentWillUnmount() {
$(window).unbind('resize', this.handleResize);
window.postMessage({ type: 'CONSOLE_HIDE_REGION' }, window.location);
$('.aliyun-console-regionbar').hide();
}
UNSAFE_componentWillReceiveProps(nextProps) {
this.setState({
url: nextProps.url,
left: nextProps.left,
right: nextProps.right,
});
}
handleAliyunNav(event = {}) {
const { type, payload } = (event && event.data) || {};
switch (type) {
case 'TOPBAR_SIDEBAR_DID_MOUNT':
// this.getRegionList();
this.handleRegionListStatus();
this.changeRegionBarRegionId(this.currRegionId);
setTimeout(() => {
this.changeRegionBarRegionId(this.currRegionId);
}, 1000);
break;
case 'CONSOLE_REGION_CHANGE':
this.changeTableData(payload.toRegionId);
break;
default:
break;
}
}
handleRegionListStatus() {
const isPrivateClound = window.globalConfig && window.globalConfig.isParentEdas();
this.setState(
{
hideRegionList: isPrivateClound
? false
: window.location.search.indexOf('hideTopbar=') === -1,
},
() => this.setRegionWidth()
);
}
handleResize() {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.setRegionWidth();
}, 100);
}
setRegionWidth() {
try {
const mainWidth = $(this.mainRef).width();
const titleWidth = $(this.titleRef).width();
const extraWidth = $(this.extraRef).width();
const regionWidth = mainWidth - extraWidth - titleWidth - 50;
this.setState({
regionWidth: regionWidth > 100 ? regionWidth : 100,
});
} catch (error) {}
}
getRegionList() {
if (window._regionList) {
this.handleRegionList(window._regionList);
} else {
// TODO
const nameSpaceList = this.nameSpaceList.current;
if (nameSpaceList) {
nameSpaceList.getInstance().getNameSpaces();
}
request({
url: this.state.url,
data: {},
success: res => {
if (res && res.data) {
window._regionList = res.data;
this.handleRegionList(res.data);
}
},
});
}
}
handleRegionList(data = {}) {
let envcontent = '';
const { envGroups } = data;
let instanceData = [];
for (let i = 0; i < envGroups.length; i++) {
const obj = envGroups[i].envs || [];
instanceData = obj;
for (let j = 0; j < obj.length; j++) {
if (obj[j].active) {
envcontent = obj[j].serverId;
}
}
}
this.currRegionId = envcontent || (instanceData[0] && instanceData[0].serverId);
setParams('serverId', this.currRegionId);
this.setRegionBarRegionList(instanceData, this.currRegionId);
this.changeRegionBarRegionId(this.currRegionId);
setTimeout(() => {
this.changeRegionBarRegionId(this.currRegionId);
}, 1000);
const nameSpaceList = this.nameSpaceList.current;
if (nameSpaceList) {
nameSpaceList.getInstance().getNameSpaces();
}
this.setState({
currRegionId: envcontent,
instanceData,
});
}
changeTableData(serverId) {
setParams('serverId', serverId);
if (this.state.currRegionId === serverId) {
return;
}
this.currRegionId = serverId;
const { instanceData } = this.state;
let inEdas = false;
if (window.globalConfig.isParentEdas()) {
inEdas = true;
}
instanceData.forEach(obj => {
if (obj.serverId === serverId) {
const lastHash = window.location.hash.split('?')[0];
if (inEdas) {
setParams('serverId', obj.serverId);
const url = window.location.href;
window.location.href = url;
} else {
let url = obj.domain + window.location.search + lastHash;
if (lastHash.indexOf('serverId') === -1) {
if (lastHash.indexOf('?') === -1) {
url += `?serverId=${serverId}`;
} else {
url += `&serverId=${serverId}`;
}
}
window.location.href = `${window.location.protocol}//${url}`;
}
}
});
}
setRegionBarRegionList(regionList, regionId) {
if (window.viewframeSetting) {
window.viewframeSetting.regionList = regionList;
window.postMessage(
{ type: 'TOGGLE_REGIONBAR_STATUS', payload: { regionList, defaultRegionId: regionId } },
window.location
);
}
}
changeRegionBarRegionId(regionId) {
window.viewframeSetting && (window.viewframeSetting.defaultRegionId = regionId);
window.postMessage(
{ type: 'SET_ACTIVE_REGION_ID', payload: { defaultRegionId: regionId } },
window.location
);
}
render() {
return (
<div>
<div ref={ref => (this.mainRef = ref)} className="clearfix">
<div style={{ overflow: 'hidden' }}>
<div id="left" style={{ float: 'left', display: 'inline-block', marginRight: 20 }}>
<div
ref={ref => (this.titleRef = ref)}
style={{ display: 'inline-block', verticalAlign: 'top' }}
>
{typeof this.state.left === 'string' ? (
<h5 style={this.styles.title}>{this.state.left}</h5>
) : (
this.state.left
)}
</div>
{this.state.hideRegionList ? null : (
<div
ref={ref => (this.regionRef = ref)}
style={{
width: this.state.regionWidth,
display: 'inline-block',
lineHeight: '40px',
marginLeft: 20,
}}
>
{this.state.instanceData.map((val, key) => (
<Button
key={val.serverId}
type={this.state.currRegionId === val.serverId ? 'primary' : 'normal'}
style={{
fontSize: '12px',
marginRight: 10,
backgroundColor:
this.state.currRegionId === val.serverId ? '#546478' : '#D9DEE4',
}}
onClick={this.changeTableData.bind(this, val.serverId)}
>
{' '}
{val.name}{' '}
</Button>
))}
</div>
)}
</div>
<div
ref={ref => (this.extraRef = ref)}
style={{ float: 'right', display: 'inline-block', paddingTop: 6 }}
>
{Object.prototype.toString.call(this.state.right) === '[object Function]'
? this.state.right()
: this.state.right}
</div>
</div>
{this.props.namespaceCallBack && (
<div>
<NameSpaceList
ref={this.nameSpaceList}
namespaceCallBack={this.props.namespaceCallBack}
setNowNameSpace={this.props.setNowNameSpace}
/>
</div>
)}
</div>
</div>
);
}
}
export default RegionGroup;

View File

@ -1,19 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import RegionGroup from './RegionGroup';
export default RegionGroup;

View File

@ -1,15 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/

View File

@ -1,331 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { getParams } from '../../globalLib';
import { ConfigProvider, Dialog, Loading, Tab } from '@alifd/next';
import './index.scss';
const TabPane = Tab.Item;
@ConfigProvider.config
class ShowCodeing extends React.Component {
static displayName = 'ShowCodeing';
static propTypes = {
locale: PropTypes.object,
};
constructor(props) {
super(props);
this.state = {
dialogvisible: false,
loading: false,
};
this.defaultCode = '';
this.nodejsCode = 'TODO';
this.cppCode = 'TODO';
this.shellCode = 'TODO';
this.pythonCode = 'TODO';
this.record = {};
this.sprigboot_code = `// Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-boot-example/nacos-spring-boot-config-example
package com.alibaba.nacos.example.spring.boot.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
@Controller
@RequestMapping("config")
public class ConfigController {
@Value("\${useLocalCache:false}")
private boolean useLocalCache;
public void setUseLocalCache(boolean useLocalCache) {
this.useLocalCache = useLocalCache;
}
@RequestMapping(value = "/get", method = GET)
@ResponseBody
public boolean get() {
return useLocalCache;
}
}`;
this.sprigcloud_code = `// Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-config-example
package com.alibaba.nacos.example.spring.cloud.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigController {
@Value("\${useLocalCache:false}")
private boolean useLocalCache;
@RequestMapping("/get")
public boolean get() {
return useLocalCache;
}
}`;
}
componentDidMount() {}
openLoading() {
this.setState({
loading: true,
});
}
closeLoading() {
this.setState({
loading: false,
});
}
getData() {
const namespace = getParams('namespace'); // 获取ak,sk
const obj = {
group: this.record.group || '',
dataId: this.record.dataId || '',
namespace,
inEdas: window.globalConfig.isParentEdas(),
};
this.defaultCode = this.getJavaCode(obj);
this.createCodeMirror('text/x-java', this.defaultCode);
this.nodejsCode = this.getNodejsCode(obj);
this.cppCode = this.getCppCode(obj);
this.shellCode = this.getShellCode(obj);
this.pythonCode = this.getPythonCode(obj);
this.forceUpdate();
}
getJavaCode(data) {
return `/*
* Demo for Nacos
* pom.xml
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>\${version}</version>
</dependency>
*/
package com.alibaba.nacos.example;
import java.util.Properties;
import java.util.concurrent.Executor;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
/**
* Config service example
*
* @author Nacos
*
*/
public class ConfigExample {
public static void main(String[] args) throws NacosException, InterruptedException {
String serverAddr = "localhost";
String dataId = "${data.dataId}";
String group = "${data.group}";
Properties properties = new Properties();
properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);
ConfigService configService = NacosFactory.createConfigService(properties);
String content = configService.getConfig(dataId, group, 5000);
System.out.println(content);
configService.addListener(dataId, group, new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
System.out.println("recieve:" + configInfo);
}
@Override
public Executor getExecutor() {
return null;
}
});
boolean isPublishOk = configService.publishConfig(dataId, group, "content");
System.out.println(isPublishOk);
Thread.sleep(3000);
content = configService.getConfig(dataId, group, 5000);
System.out.println(content);
boolean isRemoveOk = configService.removeConfig(dataId, group);
System.out.println(isRemoveOk);
Thread.sleep(3000);
content = configService.getConfig(dataId, group, 5000);
System.out.println(content);
Thread.sleep(300000);
}
}
`;
}
getNodejsCode(data) {
return 'TODO';
}
getCppCode(data) {
return 'TODO';
}
getShellCode(data) {
return 'TODO';
}
getPythonCode(data) {
return 'TODO';
}
openDialog(record) {
this.setState({
dialogvisible: true,
});
this.record = record;
setTimeout(() => {
this.getData(); // 获取数据
});
}
closeDialog() {
this.setState({
dialogvisible: false,
});
}
createCodeMirror(mode, value) {
const commontarget = this.refs.codepreview;
if (commontarget) {
commontarget.innerHTML = '';
this.cm = window.CodeMirror(commontarget, {
value,
mode,
height: 400,
width: 500,
lineNumbers: true,
theme: 'xq-light',
lint: true,
tabMode: 'indent',
autoMatchParens: true,
textWrapping: true,
gutters: ['CodeMirror-lint-markers'],
extraKeys: {
F1(cm) {
cm.setOption('fullScreen', !cm.getOption('fullScreen'));
},
Esc(cm) {
if (cm.getOption('fullScreen')) cm.setOption('fullScreen', false);
},
},
});
}
// this.cm.setSize(window.innerWidth*0.8-10,400);//设置宽高
}
changeTab(key, code) {
setTimeout(() => {
this[key] = true;
this.createCodeMirror('text/javascript', code);
});
}
render() {
const { locale = {} } = this.props;
const footer = <div />;
return (
<div>
<Dialog
title={locale.sampleCode}
style={{ width: '80%' }}
visible={this.state.dialogvisible}
footer={footer}
onClose={this.closeDialog.bind(this)}
>
<div style={{ height: 500 }}>
<Loading tip={locale.loading} style={{ width: '100%' }} visible={this.state.loading}>
<Tab shape={'text'} style={{ height: 40, paddingBottom: 10 }}>
<TabPane
title={'Java'}
key={1}
onClick={this.changeTab.bind(this, 'commoneditor1', this.defaultCode)}
/>
<TabPane
title={'Spring Boot'}
key={2}
onClick={this.changeTab.bind(this, 'commoneditor2', this.sprigboot_code)}
/>
<TabPane
title={'Spring Cloud'}
key={21}
onClick={this.changeTab.bind(this, 'commoneditor21', this.sprigcloud_code)}
/>
<TabPane
title={'Node.js'}
key={3}
onClick={this.changeTab.bind(this, 'commoneditor3', this.nodejsCode)}
/>
<TabPane
title={'C++'}
key={4}
onClick={this.changeTab.bind(this, 'commoneditor4', this.cppCode)}
/>
<TabPane
title={'Shell'}
key={5}
onClick={this.changeTab.bind(this, 'commoneditor5', this.shellCode)}
/>
<TabPane
title={'Python'}
key={6}
onClick={this.changeTab.bind(this, 'commoneditor6', this.pythonCode)}
/>
{}
</Tab>
<div ref={'codepreview'} />
</Loading>
</div>
</Dialog>
</div>
);
}
}
export default ShowCodeing;

View File

@ -1,493 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { getParams } from '../../globalLib';
import { ConfigProvider, Dialog, Loading, Tab } from '@alifd/next';
import './index.scss';
const TabPane = Tab.Item;
/**
*
* Service Registration Sample Code Show Window
* @author yongchao9 #2019年05月18日 下午4:26:19
*
*/
@ConfigProvider.config
class ShowServiceCodeing extends React.Component {
static displayName = 'ShowServiceCodeing';
static propTypes = {
locale: PropTypes.object,
};
constructor(props) {
super(props);
this.state = {
dialogvisible: false,
loading: false,
};
this.defaultCode = '';
this.nodejsCode = 'TODO';
this.cppCode = 'TODO';
this.shellCode = 'TODO';
this.pythonCode = 'TODO';
this.record = {};
this.springCode = 'TODO';
this.sprigbootCode = 'TODO';
this.sprigcloudCode = 'TODO';
}
componentDidMount() {}
openLoading() {
this.setState({
loading: true,
});
}
closeLoading() {
this.setState({
loading: false,
});
}
getData() {
const namespace = getParams('namespace'); // 获取ak,sk
const obj = {
group: this.record.group || '',
dataId: this.record.dataId || '',
namespace,
inEdas: window.globalConfig.isParentEdas(),
};
this.defaultCode = this.getJavaCode(obj);
this.createCodeMirror('text/x-java', this.defaultCode);
this.springCode = this.getSpringCode(obj);
this.sprigbootCode = this.getSpringBootCode(obj);
this.sprigcloudCode = this.getSpringCloudCode(obj);
this.nodejsCode = this.getNodejsCode(obj);
this.cppCode = this.getCppCode(obj);
this.shellCode = this.getShellCode(obj);
this.pythonCode = this.getPythonCode(obj);
this.forceUpdate();
}
getJavaCode(data) {
return `/* Refer to document: https://github.com/alibaba/nacos/blob/master/example/src/main/java/com/alibaba/nacos/example
* pom.xml
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>$\{latest.version}</version>
</dependency>
*/
package com.alibaba.nacos.example;
import java.util.Properties;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.Event;
import com.alibaba.nacos.api.naming.listener.EventListener;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
/**
* @author nkorange
*/
public class NamingExample {
public static void main(String[] args) throws NacosException {
Properties properties = new Properties();
properties.setProperty("serverAddr", System.getProperty("serverAddr"));
properties.setProperty("namespace", System.getProperty("namespace"));
NamingService naming = NamingFactory.createNamingService(properties);
naming.registerInstance("${this.record.name}", "11.11.11.11", 8888, "TEST1");
naming.registerInstance("${this.record.name}", "2.2.2.2", 9999, "DEFAULT");
System.out.println(naming.getAllInstances("${this.record.name}"));
naming.deregisterInstance("${this.record.name}", "2.2.2.2", 9999, "DEFAULT");
System.out.println(naming.getAllInstances("${this.record.name}"));
naming.subscribe("${this.record.name}", new EventListener() {
@Override
public void onEvent(Event event) {
System.out.println(((NamingEvent)event).getServiceName());
System.out.println(((NamingEvent)event).getInstances());
}
});
}
}`;
}
getSpringCode(data) {
return `/* Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-example/nacos-spring-discovery-example
* pom.xml
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-spring-context</artifactId>
<version>\${latest.version}</version>
</dependency>
*/
// Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-example/nacos-spring-discovery-example/src/main/java/com/alibaba/nacos/example/spring
package com.alibaba.nacos.example.spring;
import com.alibaba.nacos.api.annotation.NacosProperties;
import com.alibaba.nacos.spring.context.annotation.discovery.EnableNacosDiscovery;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableNacosDiscovery(globalProperties = @NacosProperties(serverAddr = "127.0.0.1:8848"))
public class NacosConfiguration {
}
// Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-example/nacos-spring-discovery-example/src/main/java/com/alibaba/nacos/example/spring/controller
package com.alibaba.nacos.example.spring.controller;
import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
@Controller
@RequestMapping("discovery")
public class DiscoveryController {
@NacosInjected
private NamingService namingService;
@RequestMapping(value = "/get", method = GET)
@ResponseBody
public List<Instance> get(@RequestParam String serviceName) throws NacosException {
return namingService.getAllInstances(serviceName);
}
}`;
}
getSpringBootCode(data) {
return `/* Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-boot-example/nacos-spring-boot-discovery-example
* pom.xml
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-discovery-spring-boot-starter</artifactId>
<version>\${latest.version}</version>
</dependency>
*/
/* Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-boot-example/nacos-spring-boot-discovery-example/src/main/resources
* application.properties
nacos.discovery.server-addr=127.0.0.1:8848
*/
// Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-boot-example/nacos-spring-boot-discovery-example/src/main/java/com/alibaba/nacos/example/spring/boot/controller
package com.alibaba.nacos.example.spring.boot.controller;
import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
@Controller
@RequestMapping("discovery")
public class DiscoveryController {
@NacosInjected
private NamingService namingService;
@RequestMapping(value = "/get", method = GET)
@ResponseBody
public List<Instance> get(@RequestParam String serviceName) throws NacosException {
return namingService.getAllInstances(serviceName);
}
}`;
}
getSpringCloudCode(data) {
return `/* Refer to document: https://github.com/nacos-group/nacos-examples/blob/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/
* pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>\${latest.version}</version>
</dependency>
*/
// nacos-spring-cloud-provider-example
/* Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/nacos-spring-cloud-provider-example/src/main/resources
* application.properties
server.port=18080
spring.application.name=${this.record.name}
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
*/
// Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/nacos-spring-cloud-provider-example/src/main/java/com/alibaba/nacos/example/spring/cloud
package com.alibaba.nacos.example.spring.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* @author xiaojing
*/
@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderApplication {
public static void main(String[] args) {
SpringApplication.run(NacosProviderApplication.class, args);
}
@RestController
class EchoController {
@RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)
public String echo(@PathVariable String string) {
return "Hello Nacos Discovery " + string;
}
}
}
// nacos-spring-cloud-consumer-example
/* Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/nacos-spring-cloud-consumer-example/src/main/resources
* application.properties
spring.application.name=micro-service-oauth2
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
*/
// Refer to document: https://github.com/nacos-group/nacos-examples/tree/master/nacos-spring-cloud-example/nacos-spring-cloud-discovery-example/nacos-spring-cloud-consumer-example/src/main/java/com/alibaba/nacos/example/spring/cloud
package com.alibaba.nacos.example.spring.cloud;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @author xiaojing
*/
@SpringBootApplication
@EnableDiscoveryClient
public class NacosConsumerApplication {
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(NacosConsumerApplication.class, args);
}
@RestController
public class TestController {
private final RestTemplate restTemplate;
@Autowired
public TestController(RestTemplate restTemplate) {this.restTemplate = restTemplate;}
@RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
public String echo(@PathVariable String str) {
return restTemplate.getForObject("http://service-provider/echo/" + str, String.class);
}
}
}`;
}
getNodejsCode(data) {
return 'TODO';
}
getCppCode(data) {
return 'TODO';
}
getShellCode(data) {
return 'TODO';
}
getPythonCode(data) {
return 'TODO';
}
openDialog(record) {
this.setState({
dialogvisible: true,
});
this.record = record;
setTimeout(() => {
this.getData(); // 获取数据
});
}
closeDialog() {
this.setState({
dialogvisible: false,
});
}
createCodeMirror(mode, value) {
const commontarget = this.refs.codepreview;
if (commontarget) {
commontarget.innerHTML = '';
this.cm = window.CodeMirror(commontarget, {
value,
mode,
height: 400,
width: 500,
lineNumbers: true,
theme: 'xq-light',
lint: true,
tabMode: 'indent',
autoMatchParens: true,
textWrapping: true,
gutters: ['CodeMirror-lint-markers'],
extraKeys: {
F1(cm) {
cm.setOption('fullScreen', !cm.getOption('fullScreen'));
},
Esc(cm) {
if (cm.getOption('fullScreen')) cm.setOption('fullScreen', false);
},
},
});
// this.cm.setSize('300px',height:'222px');
this.cm.setSize('auto', '490px');
}
// this.cm.setSize(window.innerWidth*0.8-10,400);//设置宽高
}
changeTab(key, code) {
setTimeout(() => {
this[key] = true;
this.createCodeMirror('text/javascript', code);
});
}
render() {
const { locale = {} } = this.props;
const footer = <div />;
return (
<div>
<Dialog
title={locale.sampleCode}
style={{ width: '80%' }}
visible={this.state.dialogvisible}
footer={footer}
onClose={this.closeDialog.bind(this)}
>
<div style={{ height: 500 }}>
<Loading tip={locale.loading} style={{ width: '100%' }} visible={this.state.loading}>
<Tab shape={'text'} style={{ height: 40, paddingBottom: 10 }}>
<TabPane
title={'Java'}
key={0}
onClick={this.changeTab.bind(this, 'commoneditor1', this.defaultCode)}
/>
<TabPane
title={'Spring'}
key={1}
onClick={this.changeTab.bind(this, 'commoneditor1', this.springCode)}
/>
<TabPane
title={'Spring Boot'}
key={2}
onClick={this.changeTab.bind(this, 'commoneditor2', this.sprigbootCode)}
/>
<TabPane
title={'Spring Cloud'}
key={21}
onClick={this.changeTab.bind(this, 'commoneditor21', this.sprigcloudCode)}
/>
<TabPane
title={'Node.js'}
key={3}
onClick={this.changeTab.bind(this, 'commoneditor3', this.nodejsCode)}
/>
<TabPane
title={'C++'}
key={4}
onClick={this.changeTab.bind(this, 'commoneditor4', this.cppCode)}
/>
<TabPane
title={'Shell'}
key={5}
onClick={this.changeTab.bind(this, 'commoneditor5', this.shellCode)}
/>
<TabPane
title={'Python'}
key={6}
onClick={this.changeTab.bind(this, 'commoneditor6', this.pythonCode)}
/>
{}
</Tab>
<div ref={'codepreview'} />
</Loading>
</div>
</Dialog>
</div>
);
}
}
export default ShowServiceCodeing;

View File

@ -1,19 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import ShowCodeing from './ShowCodeing';
export default ShowCodeing;

View File

@ -1,15 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/

View File

@ -1,135 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { Button, ConfigProvider, Dialog, Grid, Icon } from '@alifd/next';
import './index.scss';
const { Row, Col } = Grid;
@ConfigProvider.config
class SuccessDialog extends React.Component {
static displayName = 'SuccessDialog';
static propTypes = {
locale: PropTypes.object,
unpushtrace: PropTypes.bool,
};
constructor(props) {
super(props);
this.state = {
visible: false,
title: '',
maintitle: '',
content: '',
isok: true,
dataId: '',
group: '',
};
}
componentDidMount() {
this.initData();
}
initData() {
const { locale = {} } = this.props;
this.setState({ title: locale.title });
}
openDialog(_payload) {
let payload = _payload;
if (this.props.unpushtrace) {
payload.title = '';
}
this.setState({
visible: true,
maintitle: payload.maintitle,
title: payload.title,
content: payload.content,
isok: payload.isok,
dataId: payload.dataId,
group: payload.group,
message: payload.message,
});
}
closeDialog() {
this.setState({
visible: false,
});
}
render() {
const { locale = {} } = this.props;
const footer = (
<div style={{ textAlign: 'right' }}>
<Button type="primary" onClick={this.closeDialog.bind(this)}>
{locale.determine}
</Button>
</div>
);
return (
<div>
<Dialog
visible={this.state.visible}
footer={footer}
style={{ width: 555 }}
onCancel={this.closeDialog.bind(this)}
onClose={this.closeDialog.bind(this)}
title={this.state.maintitle || this.state.title}
>
<div>
<Row>
<Col span={'4'} style={{ paddingTop: 16 }}>
{this.state.isok ? (
<Icon type="success-filling" style={{ color: 'green' }} size={'xl'} />
) : (
<Icon type="delete-filling" style={{ color: 'red' }} size={'xl'} />
)}
</Col>
<Col span={'20'}>
<div>
{this.state.isok ? (
<h3>{this.state.title}</h3>
) : (
<h3>
{this.state.title} {locale.failure}
</h3>
)}
<p>
<span style={{ color: '#999', marginRight: 5 }}>Data ID:</span>
<span style={{ color: '#c7254e' }}>{this.state.dataId}</span>
</p>
<p>
<span style={{ color: '#999', marginRight: 5 }}>Group:</span>
<span style={{ color: '#c7254e' }}>{this.state.group}</span>
</p>
{this.state.isok ? '' : <p style={{ color: 'red' }}>{this.state.message}</p>}
</div>
</Col>
</Row>
</div>
</Dialog>
</div>
);
}
}
export default SuccessDialog;

View File

@ -1,19 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import SuccessDialog from './SuccessDialog';
export default SuccessDialog;

View File

@ -1,15 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/

View File

@ -1,145 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
module.exports = {
server: '',
PAGESIZE: 15,
TIMERDEFAULT: '5s',
TIMEDURINT: 2000,
is_preview: process.env.NODE_ENV === 'development',
projectName: 'nacos',
defaultLanguage: 'zh-cn',
'en-us': {
pageMenu: [
{
key: 'home', // 用作顶部菜单的选中
text: 'HOME',
link: 'https://nacos.io/en-us/index.html',
},
{
key: 'docs',
text: 'DOCS',
link: 'https://nacos.io/en-us/docs/quick-start.html',
},
{
key: 'blog',
text: 'BLOG',
link: 'https://nacos.io/en-us/blog',
},
{
key: 'community',
text: 'COMMUNITY',
link: 'https://nacos.io/en-us/community',
},
// {
// text: 'ALI-SUPPORT',
// href: 'https://developer.aliyun.com/opensource/project/nacos',
// },
],
disclaimer: {
title: 'Vision',
content:
'By providing an easy-to-use service infrastructure such as dynamic service discovery, service configuration, service sharing and management and etc., Nacos help users better construct, deliver and manage their own service platform, reuse and composite business service faster and deliver value of business innovation more quickly so as to win market for users in the era of cloud native and in all cloud environments, such as private, mixed, or public clouds.',
},
documentation: {
title: 'Documentation',
list: [
{
text: 'Overview',
link: '/en-us/docs/what-is-nacos.html',
},
{
text: 'Quick start',
link: '/en-us/docs/quick-start.html',
},
{
text: 'Developer guide',
link: '/en-us/docs/contributing.html',
},
],
},
resources: {
title: 'Resources',
list: [
{
text: 'Community',
link: '/en-us/community/index.html',
},
],
},
copyright: '@ 2018 The Nacos Authors | An Alibaba Middleware (Aliware) Project',
},
'zh-cn': {
pageMenu: [
{
key: 'home',
text: '首页',
link: 'https://nacos.io/zh-cn/',
},
{
key: 'docs',
text: '文档',
link: 'https://nacos.io/zh-cn/docs/what-is-nacos.html',
},
{
key: 'blog',
text: '博客',
link: 'https://nacos.io/zh-cn/blog/index.html',
},
{
key: 'community',
text: '社区',
link: 'https://nacos.io/zh-cn/community/index.html',
},
// {
// text: '阿里开发者中心',
// href: 'https://developer.aliyun.com/opensource/project/nacos',
// },
],
disclaimer: {
title: '愿景',
content:
'Nacos 通过提供简单易用的动态服务发现、服务配置、服务共享与管理等服务基础设施,帮助用户在云原生时代,在私有云、混合云或者公有云等所有云环境中,更好的构建、交付、管理自己的微服务平台,更快的复用和组合业务服务,更快的交付商业创新的价值,从而为用户赢得市场。',
},
documentation: {
title: '文档',
list: [
{
text: '概览',
link: '/zh-cn/docs/what-is-nacos.html',
},
{
text: '快速开始',
link: '/zh-cn/docs/quick-start.html',
},
{
text: '开发者指南',
link: '/zh-cn/docs/contributing.html',
},
],
},
resources: {
title: '资源',
list: [
{
text: '社区',
link: '/zh-cn/community/index.html',
},
],
},
copyright: '@ 2018 The Nacos Authors | An Alibaba Middleware (Aliware) Project',
},
};

View File

@ -1,42 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
export const LANGUAGE_KEY = 'docsite_language';
export const LANGUAGE_SWITCH = 'LANGUAGE_SWITCH';
// TODO: 后端暂时没有统一成功失败标记
// export const SUCCESS_RESULT_CODE = 'SUCCESS';
export const REDUX_DEVTOOLS = '__REDUX_DEVTOOLS_EXTENSION__';
export const GET_STATE = 'GET_STATE';
export const GET_SUBSCRIBERS = 'GET_SUBSCRIBERS';
export const REMOVE_SUBSCRIBERS = 'REMOVE_SUBSCRIBERS';
export const UPDATE_USER = 'UPDATE_USER';
export const SIGN_IN = 'SIGN_IN';
export const USER_LIST = 'USER_LIST';
export const ROLE_LIST = 'ROLE_LIST';
export const PERMISSIONS_LIST = 'PERMISSIONS_LIST';
export const GET_NAMESPACES = 'GET_NAMESPACES';
export const GET_CONFIGURATION = 'GET_CONFIGURATION';
export const GLOBAL_PAGE_SIZE_LIST = [10, 20, 30, 50, 100];

View File

@ -1,560 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import projectConfig from './config';
import $ from 'jquery';
import { Message } from '@alifd/next';
function goLogin() {
const url = window.location.href;
localStorage.removeItem('token');
const base_url = url.split('#')[0];
console.log('base_url', base_url);
window.location = `${base_url}#/login`;
}
const global = window;
/**
* 获取cookie值
* @param {*String} keyName cookie名
*/
const aliwareGetCookieByKeyName = function(keyName) {
let result = '';
const cookieList = (document.cookie && document.cookie.split(';')) || [];
cookieList.forEach(str => {
const [name = '', value = ''] = str.split('=') || [];
if (name.trim().indexOf(keyName) !== -1) {
result = value;
}
});
return result.trim();
};
/**
* 监听事件对象
*/
const nacosEvent = (function(_global) {
const eventListObj = {};
const ignoreEventListObj = {};
return {
/**
* 只监听一次
*/
once(eventName, callback) {
this.listen.call(this, eventName, callback, true);
},
/**
* 监听事件<eventName: String 监听事件名, callback: function 回调函数, once: boolean 是否监听一次>
*/
listen(eventName, callback, once = false) {
if (!eventName || !callback) {
return;
}
!eventListObj[eventName] && (eventListObj[eventName] = []);
eventListObj[eventName].push({
callback,
once,
});
},
/**
* 监听事件, 之前未消费的消息也会进行触发<eventName: String 监听事件名, callback: function 回调函数, once: boolean 是否监听一次>
*/
listenAllTask(...args) {
const self = this;
const argsList = Array.prototype.slice.call(args);
const eventName = argsList[0];
if (!eventName) {
return;
}
// 监听事件
self.listen(...argsList);
// 判断是否有未消费的消息
if (ignoreEventListObj[eventName] && ignoreEventListObj[eventName].length > 0) {
const eventObj = ignoreEventListObj[eventName].pop();
self.trigger.apply(eventObj.self, eventObj.argsList);
}
},
/**
* 触发事件
*/
trigger(...args) {
const self = this;
const argsList = Array.prototype.slice.call(args);
const eventName = argsList.shift();
// 如果还没有订阅消息, 将其放到未消费队列里
if (!eventListObj[eventName]) {
!ignoreEventListObj[eventName] && (ignoreEventListObj[eventName] = []);
ignoreEventListObj[eventName].push({
argsList: Array.prototype.slice.call(args),
self,
});
return;
}
const newList = [];
eventListObj[eventName].forEach((_obj, index) => {
if (Object.prototype.toString.call(_obj.callback) !== '[object Function]') {
return;
}
_obj.callback.apply(self, argsList);
// 删除只触发一次的事件
if (!_obj.once) {
newList.push(_obj);
}
});
eventListObj[eventName] = newList;
},
/**
* 删除监听事件
*/
remove(eventName, callback) {
if (!eventName || !eventListObj[eventName]) {
return;
}
if (!callback) {
eventListObj[eventName] = null;
} else {
const newList = [];
eventListObj[eventName].forEach((_obj, index) => {
if (_obj.callback !== callback) {
newList.push(_obj);
}
});
eventListObj[eventName] = newList.length ? newList : null;
}
},
};
})(global);
/**
* nacos的工具类
*/
const nacosUtils = (function(_global) {
let loadingCount = 0;
let loadingState = {
visible: false,
shape: 'flower',
tip: 'loading...',
// color: "#333",
// style: { height: "100%", width: "100%" }
};
return {
/**
* 改变loading 的样式
*/
changeLoadingAttr(obj) {
if (Object.prototype.toString.call(obj) === '[object Object]') {
loadingState = Object.assign({}, loadingCount, obj);
}
},
/**
* 打开loading效果
*/
openLoading() {
loadingCount++;
nacosEvent.trigger(
'nacosLoadingEvent',
Object.assign(loadingState, {
visible: true,
spinning: true,
})
);
},
/**
* 尝试关闭loading, 只有当loadingCount小于0时才会关闭loading效果
*/
closeLoading() {
loadingCount--;
if (loadingCount <= 0) {
loadingCount = 0;
nacosEvent.trigger(
'nacosLoadingEvent',
Object.assign(loadingState, {
visible: false,
spinning: false,
})
);
}
},
/**
* 关闭loading效果
*/
closeAllLoading() {
loadingCount = 0;
nacosEvent.trigger(
'nacosLoadingEvent',
Object.assign(loadingState, {
visible: false,
spinning: false,
})
);
},
/**
* 获取资源地址, 如果资源需要静态化输出 请调用此方法
*/
getURISource(url) {
return url;
},
};
})(global);
/**
* 获取url中的参数
*/
const getParams = (function(_global) {
return function(name) {
const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`, 'i');
let result = [];
if (_global.location.hash !== '') {
result = _global.location.hash.split('?'); // 优先判别hash
} else {
result = _global.location.href.split('?');
}
if (result.length === 1) {
result = _global.parent.location.hash.split('?');
}
if (result.length > 1) {
const r = result[1].match(reg);
if (r != null) {
return decodeURIComponent(r[2]);
}
}
return null;
};
})(global);
/**
* 设置参数
*/
const setParams = (function(global) {
let _global = global;
const _originHref = _global.location.href.split('#')[0];
return function(name, value) {
if (!name) {
return;
}
let obj = {};
if (typeof name === 'string') {
obj = {
[name]: value,
};
}
if (Object.prototype.toString.call(name) === '[object Object]') {
obj = name;
}
let hashArr = [];
if (_global.location.hash) {
hashArr = _global.location.hash.split('?');
}
const paramArr = (hashArr[1] && hashArr[1].split('&')) || [];
let paramObj = {};
paramArr.forEach(val => {
const tmpArr = val.split('=');
paramObj[tmpArr[0]] = decodeURIComponent(tmpArr[1] || '');
});
paramObj = Object.assign({}, paramObj, obj);
const resArr =
Object.keys(paramObj).map(key => `${key}=${encodeURIComponent(paramObj[key] || '')}`) || [];
hashArr[1] = resArr.join('&');
const hashStr = hashArr.join('?');
if (_global.history.replaceState) {
const url = _originHref + hashStr;
_global.history.replaceState(null, '', url);
} else {
_global.location.hash = hashStr;
}
};
})(global);
/**
* 设置参数
*/
const setParam = function(...args) {
return setParams.apply(this, args);
};
/**
* 删除参数
*/
const removeParams = (function(global) {
let _global = global;
const _originHref = _global.location.href.split('#')[0];
return function(name) {
let removeList = [];
const nameType = Object.prototype.toString.call(name);
if (nameType === '[object String]') {
removeList.push(name);
} else if (nameType === '[object Array]') {
removeList = name;
} else if (nameType === '[object Object]') {
removeList = Object.keys(name);
} else {
return;
}
let hashArr = [];
if (_global.location.hash) {
hashArr = _global.location.hash.split('?');
}
let paramArr = (hashArr[1] && hashArr[1].split('&')) || [];
// let paramObj = {};
paramArr = paramArr.filter(val => {
const tmpArr = val.split('=');
return removeList.indexOf(tmpArr[0]) === -1;
});
hashArr[1] = paramArr.join('&');
const hashStr = hashArr.join('?');
if (_global.history.replaceState) {
const url = _originHref + hashStr;
_global.history.replaceState(null, '', url);
} else {
_global.location.hash = hashStr;
}
};
})(global);
/**
* 封装的ajax请求
*/
const request = (function(_global) {
const middlewareList = [];
const middlewareBackList = [];
const serviceMap = {};
const serviceList = [];
const methodList = [];
/**
* 获取真实url信息
*/
const NacosRealUrlMapper = (function() {
serviceList.forEach(obj => {
serviceMap[obj.registerName] = obj;
});
return function(registerName) {
const serviceObj = serviceMap[registerName];
if (!serviceObj) {
return null;
}
// 获取正确请求方式
serviceObj.methodType = methodList[serviceObj.method];
return serviceObj;
};
})();
/**
* 添加中间件函数
* @param {*function} callback 回调函数
*/
function middleWare(callback, isBack = true) {
if (isBack) {
middlewareBackList.push(callback);
} else {
middlewareList.push(callback);
}
return this;
}
/**
* 处理中间件
* @param {*Object} config ajax请求配置信息
*/
function handleMiddleWare(...allArgs) {
// 获取除config外传入的参数
let [config, ...args] = allArgs;
// 最后一个参数为middlewareList
const middlewareList = args.pop() || [];
if (middlewareList && middlewareList.length > 0) {
config = middlewareList.reduce((config, callback) => {
if (typeof callback === 'function') {
return callback.apply(this, [config, ...args]) || config;
}
return config;
}, config);
}
return config;
}
/**
* 处理自定义url
* @param {*Object} config ajax请求配置信息
*/
function handleCustomService(...args) {
let [config] = args;
// 只处理com.alibaba.开头的url
if (config && config.url && config.url.indexOf('com.alibaba.') === 0) {
const registerName = config.url;
const serviceObj = NacosRealUrlMapper(registerName);
if (serviceObj && serviceObj.url && serviceObj.url.replace) {
// 有mock数据 直接返回 生产环境失效
if (projectConfig.is_preview && serviceObj.is_mock && config.success) {
let code = null;
try {
code = JSON.parse(serviceObj.defaults);
} catch (error) {}
config.success(code);
return;
}
// 替换url中的占位符
config.url = serviceObj.url.replace(/{([^\}]+)}/g, ($1, $2) => config.$data[$2]);
try {
// 添加静态参数
if (serviceObj.is_param && typeof config.data === 'object') {
config.data = Object.assign({}, JSON.parse(serviceObj.params), config.data);
}
} catch (e) {}
// 替换请求方式
if (serviceObj.method && !config.type) {
config.type = serviceObj.methodType;
}
// 将请求参数变为json格式
if (serviceObj.isJsonData && typeof config.data === 'object') {
config.data = JSON.stringify(config.data);
config.processData = false;
config.dataType = 'json';
config.contentType = 'application/json';
}
try {
// 设置临时代理 生产环境失效
if (projectConfig.is_preview && serviceObj.is_proxy) {
const { beforeSend } = config;
config.beforeSend = function(xhr) {
serviceObj.cookie && xhr.setRequestHeader('tmpCookie', serviceObj.cookie);
serviceObj.header && xhr.setRequestHeader('tmpHeader', serviceObj.header);
serviceObj.proxy && xhr.setRequestHeader('tmpProxy', serviceObj.proxy);
beforeSend && beforeSend(xhr);
};
}
} catch (e) {}
// 设置自动loading效果
if (serviceObj.autoLoading) {
// nacosUtils.openLoading();
const prevComplete = config.complete;
config.complete = function() {
nacosUtils.closeLoading();
typeof prevComplete === 'function' &&
prevComplete.apply($, Array.prototype.slice.call(args));
};
}
// serviceObj = null;
}
}
return config;
}
function Request(...allArgs) {
// 除了config外的传参
let [config, ...args] = allArgs;
// 处理前置中间件
config = handleMiddleWare.apply(this, [config, ...args, middlewareList]);
// 处理自定义url
config = handleCustomService.apply(this, [config, ...args]);
if (!config) return;
// xsrf
if (
config.type &&
config.type.toLowerCase() === 'post' &&
config.data &&
Object.prototype.toString.call(config.data) === '[object Object]' &&
!config.data.sec_token
) {
const sec_token = aliwareGetCookieByKeyName('XSRF-TOKEN');
sec_token && (config.data.sec_token = sec_token);
}
// 处理后置中间件
config = handleMiddleWare.apply(this, [config, ...args, middlewareBackList]);
let token = {};
try {
token = JSON.parse(localStorage.token);
} catch (e) {
console.log('Token Erro', localStorage.token, e);
goLogin();
}
const { accessToken = '' } = token;
const [url, paramsStr = ''] = config.url.split('?');
const params = paramsStr.split('&');
params.push(`accessToken=${accessToken}`);
return $.ajax(
Object.assign({}, config, {
type: config.type,
url: [url, params.join('&')].join('?'),
data: config.data || '',
dataType: config.dataType || 'json',
beforeSend(xhr) {
config.beforeSend && config.beforeSend(xhr);
},
headers: {
Authorization: localStorage.getItem('token'),
},
})
).then(
success => {},
error => {
// 处理403 forbidden
const { status, responseJSON = {} } = error || {};
if (responseJSON.message) {
Message.error(responseJSON.message);
}
if (
[401, 403].includes(status) &&
['unknown user!', 'token invalid!', 'token expired!'].includes(responseJSON.message)
) {
goLogin();
}
return error;
}
);
}
// 暴露方法
Request.handleCustomService = handleCustomService;
Request.handleMiddleWare = handleMiddleWare;
Request.NacosRealUrlMapper = NacosRealUrlMapper;
Request.serviceList = serviceList;
Request.serviceMap = serviceMap;
Request.middleWare = middleWare;
return Request;
})(global);
export {
nacosEvent,
nacosUtils,
aliwareGetCookieByKeyName,
removeParams,
getParams,
setParam,
setParams,
request,
};

View File

@ -1,156 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
/**
* 入口页
*/
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, combineReducers, compose, applyMiddleware } from 'redux';
import { routerReducer } from 'react-router-redux';
import thunk from 'redux-thunk';
import { Provider, connect } from 'react-redux';
import { HashRouter, Route, Switch, Redirect } from 'react-router-dom';
import { ConfigProvider, Loading } from '@alifd/next';
import './lib';
import Layout from './layouts/MainLayout';
import { LANGUAGE_KEY, REDUX_DEVTOOLS } from './constants';
import Login from './pages/Login';
import Namespace from './pages/NameSpace';
import Newconfig from './pages/ConfigurationManagement/NewConfig';
import Configsync from './pages/ConfigurationManagement/ConfigSync';
import Configdetail from './pages/ConfigurationManagement/ConfigDetail';
import Configeditor from './pages/ConfigurationManagement/ConfigEditor';
import HistoryDetail from './pages/ConfigurationManagement/HistoryDetail';
import ConfigRollback from './pages/ConfigurationManagement/ConfigRollback';
import HistoryRollback from './pages/ConfigurationManagement/HistoryRollback';
import ListeningToQuery from './pages/ConfigurationManagement/ListeningToQuery';
import ConfigurationManagement from './pages/ConfigurationManagement/ConfigurationManagement';
import ServiceList from './pages/ServiceManagement/ServiceList';
import ServiceDetail from './pages/ServiceManagement/ServiceDetail';
import SubscriberList from './pages/ServiceManagement/SubscriberList';
import ClusterNodeList from './pages/ClusterManagement/ClusterNodeList';
import UserManagement from './pages/AuthorityControl/UserManagement';
import PermissionsManagement from './pages/AuthorityControl/PermissionsManagement';
import RolesManagement from './pages/AuthorityControl/RolesManagement';
import Welcome from './pages/Welcome/Welcome';
import reducers from './reducers';
import { changeLanguage } from './reducers/locale';
import './index.scss';
import PropTypes from 'prop-types';
module.hot && module.hot.accept();
if (!localStorage.getItem(LANGUAGE_KEY)) {
localStorage.setItem(LANGUAGE_KEY, navigator.language === 'zh-CN' ? 'zh-CN' : 'en-US');
}
const reducer = combineReducers({
...reducers,
routing: routerReducer,
});
const store = createStore(
reducer,
compose(applyMiddleware(thunk), window[REDUX_DEVTOOLS] ? window[REDUX_DEVTOOLS]() : f => f)
);
const MENU = [
{ path: '/', exact: true, render: () => <Redirect to="/welcome" /> },
{ path: '/welcome', component: Welcome },
{ path: '/namespace', component: Namespace },
{ path: '/newconfig', component: Newconfig },
{ path: '/configsync', component: Configsync },
{ path: '/configdetail', component: Configdetail },
{ path: '/configeditor', component: Configeditor },
{ path: '/historyDetail', component: HistoryDetail },
{ path: '/configRollback', component: ConfigRollback },
{ path: '/historyRollback', component: HistoryRollback },
{ path: '/listeningToQuery', component: ListeningToQuery },
{ path: '/configurationManagement', component: ConfigurationManagement },
{ path: '/serviceManagement', component: ServiceList },
{ path: '/serviceDetail', component: ServiceDetail },
{ path: '/subscriberList', component: SubscriberList },
{ path: '/clusterManagement', component: ClusterNodeList },
{ path: '/userManagement', component: UserManagement },
{ path: '/rolesManagement', component: RolesManagement },
{ path: '/permissionsManagement', component: PermissionsManagement },
];
@connect(state => ({ ...state.locale }), { changeLanguage })
class App extends React.Component {
static propTypes = {
locale: PropTypes.object,
changeLanguage: PropTypes.func,
};
constructor(props) {
super(props);
this.state = {
shownotice: 'none',
noticecontent: '',
nacosLoading: {},
};
}
componentDidMount() {
const language = localStorage.getItem(LANGUAGE_KEY);
this.props.changeLanguage(language);
}
get router() {
return (
<HashRouter>
<Switch>
<Route path="/login" component={Login} />
<Layout>
{MENU.map(item => (
<Route key={item.path} {...item} />
))}
</Layout>
</Switch>
</HashRouter>
);
}
render() {
const { locale } = this.props;
return (
<Loading
className="nacos-loading"
shape="flower"
tip="loading..."
visible={false}
fullScreen
{...this.state.nacosLoading}
>
<ConfigProvider locale={locale}>{this.router}</ConfigProvider>
</Loading>
);
}
}
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);

View File

@ -1,148 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import { withRouter } from 'react-router-dom';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { ConfigProvider, Dropdown, Menu } from '@alifd/next';
import siteConfig from '../config';
import { changeLanguage } from '@/reducers/locale';
import PasswordReset from '../pages/AuthorityControl/UserManagement/PasswordReset';
import { passwordReset } from '../reducers/authority';
import './index.scss';
@withRouter
@connect(state => ({ ...state.locale }), { changeLanguage })
@ConfigProvider.config
class Header extends React.Component {
static displayName = 'Header';
static propTypes = {
locale: PropTypes.object,
history: PropTypes.object,
location: PropTypes.object,
language: PropTypes.string,
changeLanguage: PropTypes.func,
};
state = { passwordResetUser: '' };
switchLang = () => {
const { language = 'en-US', changeLanguage } = this.props;
const currentLanguage = language === 'en-US' ? 'zh-CN' : 'en-US';
changeLanguage(currentLanguage);
};
logout = () => {
window.localStorage.clear();
this.props.history.push('/login');
};
changePassword = () => {
this.setState({
passwordResetUser: this.getUsername(),
});
};
getUsername = () => {
const token = window.localStorage.getItem('token');
if (token) {
const [, base64Url = ''] = token.split('.');
const base64 = base64Url.replace('-', '+').replace('_', '/');
try {
const parsedToken = JSON.parse(window.atob(base64));
return parsedToken.sub;
} catch (e) {
delete localStorage.token;
location.reload();
}
}
return '';
};
render() {
const {
locale = {},
language = 'en-us',
location: { pathname },
} = this.props;
const { home, docs, blog, community, languageSwitchButton } = locale;
const { passwordResetUser = '' } = this.state;
const BASE_URL = `https://nacos.io/${language.toLocaleLowerCase()}/`;
const NAV_MENU = [
{ id: 1, title: home, link: BASE_URL },
{ id: 2, title: docs, link: `${BASE_URL}docs/what-is-nacos.html` },
{ id: 3, title: blog, link: `${BASE_URL}blog/index.html` },
{ id: 4, title: community, link: `${BASE_URL}community/index.html` },
];
return (
<>
<header className="header-container header-container-primary">
<div className="header-body">
<a
href={`https://nacos.io/${language.toLocaleLowerCase()}/`}
target="_blank"
rel="noopener noreferrer"
>
<img
src="img/logo-2000-390.svg"
className="logo"
alt={siteConfig.name}
title={siteConfig.name}
/>
</a>
{/* if is login page, we will show logout */}
{pathname !== '/login' && (
<Dropdown trigger={<div className="logout">{this.getUsername()}</div>}>
<Menu>
<Menu.Item onClick={this.logout}>{locale.logout}</Menu.Item>
<Menu.Item onClick={this.changePassword}>{locale.changePassword}</Menu.Item>
</Menu>
</Dropdown>
)}
<span className="language-switch language-switch-primary" onClick={this.switchLang}>
{languageSwitchButton}
</span>
<div className="header-menu header-menu-open">
<ul>
{NAV_MENU.map(item => (
<li key={item.id} className="menu-item menu-item-primary">
<a href={item.link} target="_blank" rel="noopener noreferrer">
{item.title}
</a>
</li>
))}
</ul>
</div>
</div>
</header>
<PasswordReset
username={passwordResetUser}
onOk={user =>
passwordReset(user).then(res => {
return res;
})
}
onCancel={() => this.setState({ passwordResetUser: undefined })}
/>
</>
);
}
}
export default Header;

View File

@ -1,144 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { ConfigProvider, Icon, Menu } from '@alifd/next';
import Header from './Header';
import { getState } from '../reducers/base';
import getMenuData from './menu';
const { SubMenu, Item } = Menu;
@withRouter
@connect(state => ({ ...state.locale, ...state.base }), { getState })
@ConfigProvider.config
class MainLayout extends React.Component {
static displayName = 'MainLayout';
static propTypes = {
locale: PropTypes.object,
location: PropTypes.object,
history: PropTypes.object,
version: PropTypes.any,
getState: PropTypes.func,
functionMode: PropTypes.string,
children: PropTypes.object,
};
componentDidMount() {
this.props.getState();
}
goBack() {
this.props.history.goBack();
}
navTo(url) {
const { search } = this.props.location;
this.props.history.push([url, search].join(''));
}
isCurrentPath(url) {
const { location } = this.props;
return url === location.pathname ? 'current-path' : undefined;
}
defaultOpenKeys() {
const MenuData = getMenuData(this.props.functionMode);
for (let i = 0, len = MenuData.length; i < len; i++) {
const { children } = MenuData[i];
if (children && children.filter(({ url }) => url === this.props.location.pathname).length) {
return String(i);
}
}
}
isShowGoBack() {
const urls = [];
const MenuData = getMenuData(this.props.functionMode);
MenuData.forEach(item => {
if (item.url) urls.push(item.url);
if (item.children) item.children.forEach(({ url }) => urls.push(url));
});
return !urls.includes(this.props.location.pathname);
}
render() {
const { locale = {}, version, functionMode } = this.props;
const MenuData = getMenuData(functionMode);
return (
<>
<Header />
<div className="main-container">
<div className="left-panel">
{this.isShowGoBack() ? (
<div className="go-back" onClick={() => this.goBack()}>
<Icon type="arrow-left" />
</div>
) : (
<>
<h1 className="nav-title">
{locale.nacosName}
<span>{version}</span>
</h1>
<Menu
defaultOpenKeys={this.defaultOpenKeys()}
className="nav-menu"
openMode="single"
>
{MenuData.map((subMenu, idx) => {
if (subMenu.children) {
return (
<SubMenu key={String(idx)} label={locale[subMenu.key]}>
{subMenu.children.map((item, i) => (
<Item
key={[idx, i].join('-')}
onClick={() => this.navTo(item.url)}
className={this.isCurrentPath(item.url)}
>
{locale[item.key]}
</Item>
))}
</SubMenu>
);
}
return (
<Item
key={idx}
className={['first-menu', this.isCurrentPath(subMenu.url)]
.filter(c => c)
.join(' ')}
onClick={() => this.navTo(subMenu.url)}
>
{locale[subMenu.key]}
</Item>
);
})}
</Menu>
</>
)}
</div>
<div className="right-panel">{this.props.children}</div>
</div>
</>
);
}
}
export default MainLayout;

View File

@ -1,91 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import { isJsonString } from '../utils/nacosutil';
const configurationMenu = {
key: 'configurationManagementVirtual',
children: [
{
key: 'configurationManagement',
url: '/configurationManagement',
},
{
key: 'historyRollback',
url: '/historyRollback',
},
{
key: 'listeningToQuery',
url: '/listeningToQuery',
},
],
};
/**
* 权限控制相关
*/
const authorityControlMenu = {
key: 'authorityControl',
children: [
{
key: 'userList',
url: '/userManagement',
},
{
key: 'roleManagement',
url: '/rolesManagement',
},
{
key: 'privilegeManagement',
url: '/permissionsManagement',
},
],
};
export default function(model) {
const { token = '{}' } = localStorage;
const { globalAdmin } = isJsonString(token) ? JSON.parse(token) || {} : {};
return [
model === 'naming' ? undefined : configurationMenu,
{
key: 'serviceManagementVirtual',
children: [
{
key: 'serviceManagement',
url: '/serviceManagement',
},
{
key: 'subscriberList',
url: '/subscriberList',
},
],
},
globalAdmin ? authorityControlMenu : undefined,
{
key: 'namespace',
url: '/namespace',
},
{
key: 'clusterManagementVirtual',
children: [
{
key: 'clusterManagement',
url: '/clusterManagement',
},
],
},
].filter(item => item);
}

View File

@ -1,212 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import { getParams, request, aliwareIntl } from './globalLib';
let hasAlert = false;
window.edasprefix = 'acm'; // 固定的edas网关需要的项目名
export const isParentEdas = () =>
window.parent && window.parent.location.host.indexOf('edas') !== -1;
window.globalConfig = {
isParentEdas,
};
request.middleWare((_config = {}) => {
let config = _config;
let { url = '' } = config;
const namespace = localStorage.getItem('namespace') ? localStorage.getItem('namespace') : '';
// 如果url中已经有 namespaceId, 不在data中添加namespaceId
config.data =
url.indexOf('namespaceId=') === -1
? Object.assign({}, config.data, { namespaceId: namespace })
: config.data;
let tenant = window.nownamespace || getParams('namespace') || '';
tenant = tenant === 'global' ? '' : tenant;
const splitArr = url.split('?');
if (splitArr.length > 1) {
const params = splitArr[1];
if (params.indexOf('dataId') !== -1) {
url += `&tenant=${tenant}`;
config.url = url;
}
}
const preSucess = config.success;
const preErorr = config.error;
config.success = function(res) {
if (res.code === 'ConsoleNeedLogin' && window.location.host.indexOf('acm') !== -1) {
window.location.reload();
}
if (res.code === 403 && !hasAlert) {
hasAlert = true;
window.Dialog.alert({
style: { width: 400 },
content: res.message,
onOk: () => {
hasAlert = false;
},
onCancel: () => {
hasAlert = false;
},
onClose: () => {
hasAlert = false;
},
});
} else {
typeof preSucess === 'function' && preSucess(res);
}
};
config.error = function(res) {
if (res.status === 403 && !hasAlert) {
hasAlert = true;
window.Dialog.alert({
style: { width: 400 },
content: aliwareIntl.get('com.alibaba.nacos.pubshow'), // '子账号没有权限请联系主账号负责人RAM上授权',
onOk: () => {
hasAlert = false;
},
onCancel: () => {
hasAlert = false;
},
onClose: () => {
hasAlert = false;
},
});
} else {
typeof preErorr === 'function' && preErorr(res);
}
};
return config;
});
/**
* 配置 monaco
*/
window.require.config({
paths: { vs: process.env.NODE_ENV === 'production' ? 'console-fe/public/js/vs' : 'js/vs' },
});
window.require.config({
'vs/nls': {
availableLanguages: {
'*': 'zh-cn',
},
},
});
window.require(['vs/editor/editor.main'], () => {
// Register a new language
window.monaco.languages.register({ id: 'properties' });
// Register a tokens provider for the language
window.monaco.languages.setMonarchTokensProvider('properties', {
tokenizer: {
root: [
[/^\#.*/, 'comment'],
[/.*\=/, 'key'],
[/^=.*/, 'value'],
],
},
});
// Define a new theme that constains only rules that match this language
window.monaco.editor.defineTheme('properties', {
base: 'vs',
inherit: false,
rules: [
{ token: 'key', foreground: '009968' },
{ token: 'value', foreground: '009968' },
{ token: 'comment', foreground: '666666' },
],
});
// Register a completion item provider for the new language
window.monaco.languages.registerCompletionItemProvider('properties', {
provideCompletionItems: () => [
{
label: 'simpleText',
kind: window.monaco.languages.CompletionItemKind.Text,
},
{
label: 'testing',
kind: window.monaco.languages.CompletionItemKind.Keyword,
insertText: {
value: 'testing(${1:condition})',
},
},
{
label: 'ifelse',
kind: window.monaco.languages.CompletionItemKind.Snippet,
insertText: {
value: ['if (${1:condition}) {', '\t$0', '} else {', '\t', '}'].join('\n'),
},
documentation: 'If-Else Statement',
},
],
});
});
window.importEditor = callback => {
window.require(['vs/editor/editor.main'], () => {
callback && callback();
});
};
// 同步获取命名空间地址
window._getLink = (function() {
const _linkObj = {};
// request({
// url: "com.alibaba.nacos.service.getLinks",
// async: false,
// data: {},
// success: res => {
// if (res.code === 200) {
// _linkObj = res.data;
// }
// }
// });
return function(linkName) {
return _linkObj[linkName] || '';
};
})(window);
window.addEventListener('resize', () => {
try {
if (this.timmer) {
clearTimeout(this.timmer);
}
this.timmer = setTimeout(() => {
let height = document.body.clientHeight;
height = height > 800 ? height : 800;
window.parent.adjustHeight && window.parent.adjustHeight(height);
}, 500);
} catch (e) {}
});
// 判断是否是国际站国际用户
window.isIntel = function() {
const { host } = window.location;
return host.indexOf('alibabacloud.com') !== -1;
};
export default {};

View File

@ -1,595 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
const I18N_CONF = {
Header: {
home: 'HOME',
docs: 'DOCS',
blog: 'BLOG',
community: 'COMMUNITY',
languageSwitchButton: '中',
logout: 'logout',
changePassword: 'modify password',
passwordRequired: 'password should not be empty',
usernameRequired: 'username should not be empty',
},
Login: {
login: 'Login',
submit: 'Submit',
pleaseInputUsername: 'Please input username',
pleaseInputPassword: 'Please input password',
invalidUsernameOrPassword: 'invalid username or password',
},
MainLayout: {
nacosName: 'NACOS',
doesNotExist: 'The page you visit does not exist',
configurationManagementVirtual: 'ConfigManagement',
configurationManagement: 'Configurations',
configdetail: 'Configuration Details',
configsync: 'Synchronize Configuration',
configeditor: 'Edit Configuration',
newconfig: 'Create Configuration',
historyRollback: 'Historical Versions',
configRollback: 'Configuration Rollback',
historyDetail: 'History Details',
listeningToQuery: 'Listening Query',
serviceManagementVirtual: 'ServiceManagement',
serviceManagement: 'Service List',
subscriberList: 'Subscribers',
serviceDetail: 'Service Details',
namespace: 'Namespace',
clusterManagementVirtual: 'ClusterManagement',
clusterManagement: 'Cluster Node List',
authorityControl: 'Authority Control',
userList: 'User List',
roleManagement: 'Role Management',
privilegeManagement: 'Privilege Management',
},
Password: {
passwordNotConsistent: 'The passwords are not consistent',
passwordRequired: 'password should not be empty',
pleaseInputOldPassword: 'Please input original password',
pleaseInputNewPassword: 'Please input new password',
pleaseInputNewPasswordAgain: 'Please input new password again',
oldPassword: 'Original password',
newPassword: 'New password',
checkPassword: 'Check password',
changePassword: 'modify password',
invalidPassword: 'Invalid original password',
modifyPasswordFailed: 'Modify password failed',
},
NameSpace: {
namespace: 'Namespaces',
prompt: 'Notice',
namespaceDetails: 'Namespace details',
namespaceName: 'Name',
namespaceID: 'ID:',
configuration: 'Number of Configurations',
description: 'Description',
removeNamespace: 'Remove the namespace',
confirmDelete: 'Sure you want to delete the following namespaces?',
configurationManagement: 'Configurations',
removeSuccess: 'Remove the namespace success',
deletedSuccessfully: 'Deleted successfully',
deletedFailure: 'Delete failed',
namespaceDelete: 'Delete',
details: 'Details',
edit: 'Edit',
namespacePublic: 'public(to retain control)',
pubNoData: 'No results found.',
namespaceAdd: 'Create Namespace',
namespaceNames: 'Namespaces',
namespaceNumber: 'Namespace ID',
namespaceOperation: 'Actions',
},
ServiceList: {
serviceList: 'Service List',
serviceName: 'Service Name',
serviceNamePlaceholder: 'Enter Service Name',
hiddenEmptyService: 'Hidden Empty Service',
query: 'Search',
pubNoData: 'No results found.',
columnServiceName: 'Service Name',
groupName: 'Group Name',
groupNamePlaceholder: 'Enter Group Name',
columnClusterCount: 'Cluster Count',
columnIpCount: 'Instance Count',
columnHealthyInstanceCount: 'Healthy Instance Count',
columnTriggerFlag: 'Trigger Protection Threshold',
operation: 'Operation',
detail: 'Details',
sampleCode: 'Code Example',
deleteAction: 'Delete',
prompt: 'Confirm',
promptDelete: 'Do you want to delete the service?',
create: 'Create Service',
},
SubscriberList: {
subscriberList: 'Subscriber List',
serviceName: 'Service Name',
serviceNamePlaceholder: 'Enter Service Name',
groupName: 'Group Name',
groupNamePlaceholder: 'Enter Group Name',
query: 'Search',
pubNoData: 'No results found.',
address: 'Address',
clientVersion: 'Client Version',
appName: 'Application Name',
searchServiceNamePrompt: 'Service name required!',
},
ClusterNodeList: {
clusterNodeList: 'Node List',
nodeIp: 'NodeIp',
nodeIpPlaceholder: 'Please enter node Ip',
query: 'Search',
pubNoData: 'No results found.',
nodeState: 'NodeState',
extendInfo: 'NodeMetaData',
},
EditClusterDialog: {
updateCluster: 'Update Cluster',
checkType: 'Check Type',
checkPort: 'Check Port',
useIpPortCheck: 'Use port of IP',
checkPath: 'Check Path',
checkHeaders: 'Check Headers',
metadata: 'Metadata',
},
ServiceDetail: {
serviceDetails: 'Service Details',
back: 'Back',
editCluster: 'Edit Cluster',
cluster: 'Cluster',
metadata: 'Metadata',
selector: 'Selector',
type: 'Type',
groupName: 'Group Name',
protectThreshold: 'Protect Threshold',
serviceName: 'Service Name',
editService: 'Edit Service',
},
EditServiceDialog: {
createService: 'Create Service',
updateService: 'Edit Service',
serviceName: 'Service Name',
metadata: 'Metadata',
groupName: 'Group Name',
type: 'Type',
typeLabel: 'Label',
typeNone: 'None',
selector: 'Selector',
protectThreshold: 'Protect Threshold',
serviceNameRequired: 'Please enter a service name',
protectThresholdRequired: 'Please enter a protect threshold',
},
InstanceTable: {
operation: 'Operation',
port: 'Port',
weight: 'Weight',
healthy: 'Healthy',
metadata: 'Metadata',
editor: 'Edit',
offline: 'Offline',
online: 'Online',
ephemeral: 'Ephemeral',
},
EditInstanceDialog: {
port: 'Port',
weight: 'Weight',
metadata: 'Metadata',
updateInstance: 'Update Instance',
whetherOnline: 'Whether Online',
},
ListeningToQuery: {
success: 'Success',
failure: 'Failure',
configuration: 'Configuration',
pubNoData: 'No results found.',
listenerQuery: 'Listening Query',
queryDimension: 'Dimension',
pleaseEnterTheDataId: 'Enter Data ID',
dataIdCanNotBeEmpty: 'Data ID cannot be empty',
pleaseInputGroup: 'Enter Group',
groupCanNotBeEmpty: 'Group cannot be empty',
pleaseInputIp: 'Enter IP',
query: 'Search',
queryResultsQuery: 'Search Results: Found',
articleMeetRequirementsConfiguration: 'configuration items.',
},
HistoryRollback: {
details: 'Details',
rollback: 'Roll Back',
pubNoData: 'No results found.',
toConfigure: 'Historical Versions (Configuration record is retained for 30 days.)',
dataId: 'Enter Data ID',
dataIdCanNotBeEmpty: 'Data ID cannot be empty',
group: 'Enter Group',
groupCanNotBeEmpty: 'Group cannot be empty',
query: 'Search',
queryResult: 'Search Results: Found',
articleMeet: 'configuration items.',
lastUpdateTime: 'Last Modified At',
operation: 'Operation',
},
HistoryDetail: {
historyDetails: 'History Details',
update: 'Update',
insert: 'Insert',
deleteAction: 'Delete',
recipientFrom: 'Collapse',
moreAdvancedOptions: 'Advanced Options',
home: 'Application:',
actionType: 'Action Type:',
configureContent: 'Configuration Content:',
back: 'Back',
},
DashboardCard: {
importantReminder0: 'Important reminder',
viewDetails1: 'view details',
},
ConfigurationManagement: {
questionnaire2: 'questionnaire',
ad:
'a ACM front-end monitoring questionnaire, the time limit to receive Ali cloud voucher details shoved stamp: the',
noLongerDisplay4: 'no longer display:',
removeConfiguration: 'Delete Configuration',
sureDelete: 'Are you sure you want to delete the following configuration?',
environment: 'Region:',
configurationManagement: 'Configurations',
details: 'Details',
sampleCode: 'Code Example',
edit: 'Edit',
deleteAction: 'Delete',
more: 'More',
version: 'Historical Versions',
listenerQuery: 'Configuration Listening Query',
failedEntry: 'Failed Entry:',
successfulEntry: 'Successful Entry:',
unprocessedEntry: 'Unprocessed Entry:',
pubNoData: 'No results found.',
configurationManagement8: 'configuration management',
queryResults: 'Search Results: Found',
articleMeetRequirements: 'configuration items',
fuzzyd: 'Enter Data ID',
fuzzyg: 'Enter Group',
query: 'Search',
advancedQuery9: 'Advanced Query',
application0: 'Application:',
app1: 'Enter App Name\n',
tags: 'Tags:',
pleaseEnterTag: 'Enter Tag',
application: 'Application',
operation: 'Operation',
export: 'Export query results',
import: 'Import',
uploadBtn: 'Upload File',
importSucc: 'The import was successful',
importAbort: 'Import abort',
importSuccBegin: 'The import was successful,with ',
importSuccEnd: 'configuration items imported',
importFail: 'Import failed',
importFail403: 'Unauthorized!',
importDataValidationError: 'No legitimate data was read, please check the imported data file.',
metadataIllegal: 'The imported metadata file is illegal',
namespaceNotExist: 'namespace does not exist',
abortImport: 'Abort import',
skipImport: 'Skip',
overwriteImport: 'Overwrite',
importRemind:
'File upload will be imported directly into the configuration, please be careful!',
samePreparation: 'Same preparation',
targetNamespace: 'Target namespace',
conflictConfig: 'Conflict-detected configuration items',
failureEntries: 'Failure entries',
unprocessedEntries: 'Unprocessed entries',
skippedEntries: 'skipped entries',
exportSelected: 'Export selected configs',
clone: 'Clone',
exportSelectedAlertTitle: 'Export config',
exportSelectedAlertContent: 'please select the configuration to export',
cloneSucc: 'The clone was successful',
cloneAbort: 'Clone abort',
cloneSuccBegin: 'The clone was successful,with ',
cloneSuccEnd: 'configuration items cloned',
cloneFail: 'Clone failed',
getNamespaceFailed: 'get the namespace failed',
startCloning: 'Start Clone',
cloningConfiguration: 'Clone config',
source: 'Source :',
configurationNumber: 'Items:',
target: 'Target:',
selectNamespace: 'Select Namespace',
selectedEntry: '| Selected Entry',
cloneSelectedAlertTitle: 'Clone config',
cloneSelectedAlertContent: 'please select the configuration to clone',
delSelectedAlertTitle: 'Delete config',
delSelectedAlertContent: 'please select the configuration to delete',
delSuccessMsg: 'delete successful',
cloneEditableTitle: 'Modify Data Id and Group (optional)',
},
NewConfig: {
newListingMain: 'Create Configuration',
newListing: 'Create Configuration',
publishFailed: 'Publish failed. Make sure parameters are entered correctly.',
doNotEnter: 'Illegal characters not allowed',
newConfig: 'Data ID cannot be empty.',
dataIdIsNotEmpty: 'Data ID cannot exceed 255 characters in length',
groupPlaceholder: 'Enter your group name',
moreAdvanced: 'Group cannot be empty',
groupNotEmpty: 'Group ID cannot exceed 127 characters in length',
annotation:
'Notice: You are going to add configuration to a new group, please make sure that the version of Pandora which clients are using is higher than 3.4.0, otherwise this configuration may be unreadable to clients.',
dataIdLength: 'Collapse',
collapse: 'Advanced Options',
tags: 'Tags:',
pleaseEnterTag: 'Enter Tag',
groupIdCannotBeLonger: 'Application:',
description: 'Description:',
targetEnvironment: 'Format:',
configurationFormat: 'Configuration Content',
configureContentsOf: 'Press F1 to view in full screen',
fullScreen: 'Press Esc to exit',
escExit: 'Publish',
release: 'Back',
confirmSyanx: 'The configuration information may has a syntax error. Are you sure to submit?',
dataIdExists: 'Configuration already exists. Enter a new Data ID and Group name.',
dataRequired: 'Data cannot be empty, submission failed',
},
CloneDialog: {
terminate: 'Terminate',
skip: 'Skip',
cover: 'Cover',
getNamespaceFailed: 'get the namespace failed',
selectedEntry: '| Selected Entry',
homeApplication: 'Home Application:',
tags: 'tags:',
startCloning: 'Start Clone',
source: 'Source :',
configurationNumber: 'Items:',
target: 'Target:',
conflict: 'Conflict:',
selectNamespace: 'Select Namespace',
configurationCloning: 'Clone',
},
DeleteDialog: {
confManagement: 'Configuration Management',
determine: 'OK',
deletetitle: 'Delete Configuration',
deletedSuccessfully: 'Configuration deleted',
deleteFailed: 'Deleting configuration failed',
},
DiffEditorDialog: {
publish: 'Publish',
contents: 'Content Comparison',
currentArea: 'Current Value',
originalValue: 'Original Value',
},
ConfigEditor: {
official: 'Official',
production: 'Production',
beta: 'BETA',
wrong: 'Error',
submitFailed: 'Cannot be empty, submit failed',
toedittitle: 'Edit Configuration',
newConfigEditor: 'New Config Editor',
toedit: 'Edit Configuration',
vdchart: 'Illegal characters not allowed',
recipientFrom: 'Data ID cannot be empty',
homeApplication: 'Group name cannot be empty',
collapse: 'Collapse',
groupNotEmpty: 'Advanced Options',
tags: 'Tags:',
pleaseEnterTag: 'Enter Tag',
targetEnvironment: 'Application:',
description: 'Description:',
format: 'Format:',
configcontent: 'Configuration Content',
escExit: 'Press F1 to view in full screen',
releaseBeta: 'Press Esc to exit ',
release: 'Beta Publish',
stopPublishBeta: 'Stop Beta',
betaPublish: 'Beta Publish:',
betaSwitchPrompt: 'Not checked by default.',
publish: 'Publish',
back: 'Back',
codeValErrorPrompt: 'Configuration information may have syntax errors. Are you sure to submit?',
},
EditorNameSpace: {
notice: 'Notice',
pleaseDo: 'Illegal characters not allowed',
publicSpace: 'OK',
confirmModify: 'Edit Namespace',
editNamespace: 'Loading...',
load: 'Namespace:',
namespace: 'Namespace cannot be empty',
namespaceDesc: 'Namespace description cannot be empty',
description: 'Description:',
},
ExportDialog: {
selectedEntry: '| Selected Entry',
application: 'Application:',
tags: 'Tags:',
exportBtn: 'Export',
exportConfiguration: 'Export ( ',
source: 'Source',
items: 'Items:',
},
ImportDialog: {
terminate: 'Terminate',
skip: 'Skip',
overwrite: 'Overwrite',
zipFileFormat: 'Only upload. zip file format',
uploadFile: 'Upload File',
importLabel: 'Import ( ',
target: 'Target:',
conflict: 'Conflict:',
beSureExerciseCaution: 'Caution: data will be imported directly after uploading.',
},
ShowCodeing: {
sampleCode: 'Sample Code',
loading: 'Loading...',
},
SuccessDialog: {
title: 'Configuration Management',
determine: 'OK',
failure: 'Failed',
},
ConfigSync: {
error: 'Error',
syncConfigurationMain: 'Synchronize Configuration',
syncConfiguration: 'Synchronize Configuration Successfully',
advancedOptions: 'Advanced Options',
collapse: 'Collapse',
home: 'Application',
region: 'Region',
configuration: 'Configuration Content',
target: 'Target Region',
sync: 'Synchronize',
back: 'Back',
},
NewNameSpace: {
norepeat: 'Duplicate namespace. Please enter a different name.',
notice: 'Notice',
input: 'Illegal characters not allowed',
ok: 'OK',
cancel: 'Cancel',
newnamespce: 'Create Namespace',
loading: 'Loading...',
name: 'Namespace:',
namespaceId: 'Namespace ID(automatically generated if not filled):',
namespaceIdTooLong: 'The namespace ID length cannot exceed 128',
namespacenotnull: 'Namespace cannot be empty',
namespacedescnotnull: 'Namespace description cannot be empty',
description: 'Description:',
namespaceIdAlreadyExist: 'namespaceId already exist',
newnamespceFailedMessage:
'namespaceId format is incorrect/namespaceId length greater than 128/namespaceId already exist',
},
NameSpaceList: {
notice: 'Notice',
},
ConfigDetail: {
official: 'Official',
error: 'Error',
configurationDetails: 'Configuration Details',
collapse: 'Collapse',
more: 'Advanced Options',
home: 'Application:',
tags: 'Tags:',
description: 'Description:',
betaRelease: 'Beta Publish:',
configuration: 'Configuration Content:',
back: 'Back',
},
ConfigRollback: {
rollBack: 'Roll Back',
determine: 'Are you sure you want to roll back',
followingConfiguration: 'the following configuration?',
configurationRollback: 'Configuration Rollback',
collapse: 'Collapse',
more: 'Advanced Options',
home: 'Application:',
actionType: 'Action Type:',
configuration: 'Configuration Content:',
back: 'Back',
rollbackSuccessful: 'Rollback Successful',
rollbackDelete: 'Delete',
update: 'Update',
insert: 'Insert',
},
UserManagement: {
userManagement: 'User Management',
createUser: 'Create user',
resetPassword: 'Edit',
deleteUser: 'Delete',
deleteUserTip: 'Do you want to delete this user?',
username: 'Username',
password: 'Password',
operation: 'Operation',
},
NewUser: {
createUser: 'Create user',
username: 'Username',
password: 'Password',
rePassword: 'Repeat',
usernamePlaceholder: 'Please Enter Username',
passwordPlaceholder: 'Please Enter Password',
rePasswordPlaceholder: 'Please Enter Repeat Password',
usernameError: 'User name cannot be empty!',
passwordError: 'Password cannot be empty!',
rePasswordError: 'Repeat Password cannot be empty!',
rePasswordError2: 'Passwords are inconsistent!',
},
PasswordReset: {
resetPassword: 'Password Reset',
username: 'Username',
password: 'Password',
rePassword: 'Repeat',
passwordPlaceholder: 'Please Enter Password',
rePasswordPlaceholder: 'Please Enter Repeat Password',
passwordError: 'Password cannot be empty!',
rePasswordError: 'Repeat Password cannot be empty!',
rePasswordError2: 'Passwords are inconsistent!',
},
RolesManagement: {
roleManagement: 'Role management',
bindingRoles: 'Binding roles',
role: 'Role',
username: 'Username',
operation: 'Operation',
deleteRole: 'Delete',
deleteRoleTip: 'Do you want to delete this role?',
},
NewRole: {
bindingRoles: 'Binding roles',
username: 'Username',
role: 'Role',
usernamePlaceholder: 'Please Enter Username',
rolePlaceholder: 'Please Enter Role',
usernameError: 'User name cannot be empty!',
roleError: 'Role cannot be empty!',
},
PermissionsManagement: {
privilegeManagement: 'Permissions Management',
addPermission: 'Add Permission',
role: 'Role',
resource: 'Resource',
action: 'Action',
operation: 'Operation',
deletePermission: 'Delete',
deletePermissionTip: 'Do you want to delete this permission?',
readOnly: 'read only',
writeOnly: 'write only',
readWrite: 'Read and write',
},
NewPermissions: {
addPermission: 'Add Permission',
role: 'Role',
resource: 'Resource',
action: 'Action',
resourcePlaceholder: 'Please select resources',
rolePlaceholder: 'Please enter Role',
actionPlaceholder: 'Please select Action',
resourceError: 'Resource cannot be empty!',
roleError: 'Role cannot be empty!',
actionError: 'Action cannot be empty!',
readOnly: 'read only',
writeOnly: 'write only',
readWrite: 'Read and write',
},
};
export default I18N_CONF;

View File

@ -1,20 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import enUS from './en-US';
import zhCN from './zh-CN';
export default { enUS, zhCN };

View File

@ -1,592 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
const I18N_CONF = {
Header: {
home: '首页',
docs: '文档',
blog: '博客',
community: '社区',
languageSwitchButton: 'En',
logout: '登出',
changePassword: '修改密码',
},
Login: {
login: '登录',
submit: '提交',
pleaseInputUsername: '请输入用户名',
pleaseInputPassword: '请输入密码',
invalidUsernameOrPassword: '用户名或密码错误',
passwordRequired: '密码不能为空',
usernameRequired: '用户名不能为空',
},
MainLayout: {
nacosName: 'NACOS',
doesNotExist: '您访问的页面不存在',
configurationManagementVirtual: '配置管理',
configurationManagement: '配置列表',
configdetail: '配置详情',
configsync: '同步配置',
configeditor: '配置编辑',
newconfig: '新建配置',
historyRollback: '历史版本',
configRollback: '配置回滚',
historyDetail: '历史详情',
listeningToQuery: '监听查询',
serviceManagementVirtual: '服务管理',
serviceManagement: '服务列表',
subscriberList: '订阅者列表',
serviceDetail: '服务详情',
namespace: '命名空间',
clusterManagementVirtual: '集群管理',
clusterManagement: '节点列表',
authorityControl: '权限控制',
userList: '用户列表',
roleManagement: '角色管理',
privilegeManagement: '权限管理',
},
Password: {
passwordNotConsistent: '两次输入密码不一致',
passwordRequired: '密码不能为空',
pleaseInputOldPassword: '请输入原始密码',
pleaseInputNewPassword: '请输入新密码',
pleaseInputNewPasswordAgain: '请再次输入新密码',
oldPassword: '原始密码',
newPassword: '新密码',
checkPassword: '再次输入',
changePassword: '修改密码',
invalidPassword: '原始密码错误',
modifyPasswordFailed: '修改密码失败',
},
NameSpace: {
namespace: '命名空间',
prompt: '提示',
namespaceDetails: '命名空间详情',
namespaceName: '命名空间名称',
namespaceID: '命名空间ID',
configuration: '配置数',
description: '描述',
removeNamespace: '删除命名空间',
confirmDelete: '确定要删除以下命名空间吗?',
configurationManagement: '配置列表',
removeSuccess: '删除命名空间成功',
deletedSuccessfully: '删除成功',
deletedFailure: '删除失败',
namespaceDelete: '删除',
details: '详情',
edit: '编辑',
namespacePublic: 'public(保留空间)',
pubNoData: '没有数据',
namespaceAdd: '新建命名空间',
namespaceNames: '命名空间名称',
namespaceNumber: '命名空间ID',
namespaceOperation: '操作',
},
ServiceList: {
serviceList: '服务列表',
serviceName: '服务名称',
serviceNamePlaceholder: '请输入服务名称',
hiddenEmptyService: '隐藏空服务',
query: '查询',
pubNoData: '没有数据',
columnServiceName: '服务名',
groupName: '分组名称',
groupNamePlaceholder: '请输入分组名称',
columnClusterCount: '集群数目',
columnIpCount: '实例数',
columnHealthyInstanceCount: '健康实例数',
columnTriggerFlag: '触发保护阈值',
operation: '操作',
detail: '详情',
sampleCode: '示例代码',
deleteAction: '删除',
prompt: '提示',
promptDelete: '确定要删除当前服务吗?',
create: '创建服务',
},
SubscriberList: {
subscriberList: '订阅者列表',
serviceName: '服务名称',
serviceNamePlaceholder: '请输入服务名称',
groupName: '分组名称',
groupNamePlaceholder: '请输入分组名称',
query: '查询',
pubNoData: '没有数据',
address: '地址',
clientVersion: '客户端版本',
appName: '应用名',
searchServiceNamePrompt: '请输入服务名称!',
},
ClusterNodeList: {
clusterNodeList: '节点列表',
nodeIp: '节点Ip',
nodeIpPlaceholder: '请输入节点Ip',
query: '查询',
pubNoData: '没有数据',
nodeState: '节点状态',
extendInfo: '节点元数据',
},
EditClusterDialog: {
updateCluster: '更新集群',
checkType: '检查类型',
checkPort: '检查端口',
useIpPortCheck: '使用IP端口检查',
checkPath: '检查路径',
checkHeaders: '检查头',
metadata: '元数据',
},
ServiceDetail: {
serviceDetails: '服务详情',
back: '返回',
editCluster: '集群配置',
cluster: '集群',
metadata: '元数据',
selector: '表达式',
type: '服务路由类型',
groupName: '分组',
protectThreshold: '保护阈值',
serviceName: '服务名',
editService: '编辑服务',
},
EditServiceDialog: {
createService: '创建服务',
updateService: '更新服务',
serviceName: '服务名',
metadata: '元数据',
groupName: '分组',
type: '服务路由类型',
typeLabel: '标签',
typeNone: '默认',
selector: '表达式',
protectThreshold: '保护阈值',
serviceNameRequired: '请输入服务名',
protectThresholdRequired: '请输入保护阈值',
},
InstanceTable: {
operation: '操作',
port: '端口',
weight: '权重',
healthy: '健康状态',
metadata: '元数据',
editor: '编辑',
offline: '下线',
online: '上线',
ephemeral: '临时实例',
},
EditInstanceDialog: {
port: '端口',
weight: '权重',
metadata: '元数据',
updateInstance: '编辑实例',
whetherOnline: '是否上线',
},
ListeningToQuery: {
success: '成功',
failure: '失败',
configuration: '配置',
pubNoData: '没有数据',
listenerQuery: '监听查询',
queryDimension: '查询维度',
pleaseEnterTheDataId: '请输入Data ID',
dataIdCanNotBeEmpty: 'Data ID不能为空',
pleaseInputGroup: '请输入Group',
groupCanNotBeEmpty: 'Group不能为空',
pleaseInputIp: '请输入IP',
query: '查询',
queryResultsQuery: '查询结果:共查询到',
articleMeetRequirementsConfiguration: '条满足要求的配置。',
},
HistoryRollback: {
details: '详情',
rollback: '回滚',
pubNoData: '没有数据',
toConfigure: '历史版本(保留30天)',
dataId: '请输入Data ID',
dataIdCanNotBeEmpty: 'Data ID不能为空',
group: '请输入Group',
groupCanNotBeEmpty: 'Group不能为空',
query: '查询',
queryResult: '查询结果:共查询到',
articleMeet: '条满足要求的配置。',
lastUpdateTime: '最后更新时间',
operation: '操作',
},
HistoryDetail: {
historyDetails: '历史详情',
update: '更新',
insert: '插入',
deleteAction: '删除',
recipientFrom: '收起',
moreAdvancedOptions: '更多高级选项',
home: '归属应用:',
actionType: '操作类型:',
configureContent: '配置内容:',
back: '返回',
},
DashboardCard: {
importantReminder0: '重要提醒',
viewDetails1: '查看详情',
},
ConfigurationManagement: {
questionnaire2: '问卷调查',
ad: '答 ACM 前端监控调查问卷,限时领取阿里云代金券\t 详情猛戳:',
noLongerDisplay4: '不再显示:',
removeConfiguration: '删除配置',
sureDelete: '确定要删除以下配置吗?',
environment: '地域:',
configurationManagement: '配置列表',
details: '详情',
sampleCode: '示例代码',
edit: '编辑',
deleteAction: '删除',
more: '更多',
version: '历史版本',
listenerQuery: '监听查询',
failedEntry: '失败的条目:',
successfulEntry: '成功的条目:',
unprocessedEntry: '未处理的条目:',
pubNoData: '没有数据',
configurationManagement8: '配置管理',
queryResults: '查询结果:共查询到',
articleMeetRequirements: '条满足要求的配置。',
fuzzyd: '模糊查询请输入Data ID',
fuzzyg: '模糊查询请输入Group',
query: '查询',
advancedQuery9: '高级查询',
application0: '归属应用:',
app1: '请输入应用名',
tags: '标签:',
pleaseEnterTag: '请输入标签',
application: '归属应用:',
operation: '操作',
export: '导出查询结果',
import: '导入配置',
uploadBtn: '上传文件',
importSucc: '导入成功',
importAbort: '导入终止',
importSuccBegin: '导入成功,导入了',
importSuccEnd: '项配置',
importFail: '导入失败',
importFail403: '没有权限!',
importDataValidationError: '未读取到合法数据,请检查导入的数据文件。',
metadataIllegal: '导入的元数据文件非法',
namespaceNotExist: 'namespace 不存在',
abortImport: '终止导入',
skipImport: '跳过',
overwriteImport: '覆盖',
importRemind: '文件上传后将直接导入配置,请务必谨慎操作!',
samePreparation: '相同配置',
targetNamespace: '目标空间',
conflictConfig: '检测到冲突的配置项',
failureEntries: '失败的条目',
unprocessedEntries: '未处理的条目',
skippedEntries: '跳过的条目',
exportSelected: '导出选中的配置',
clone: '克隆',
exportSelectedAlertTitle: '配置导出',
exportSelectedAlertContent: '请选择要导出的配置',
cloneSucc: '克隆成功',
cloneAbort: '克隆终止',
cloneSuccBegin: '克隆成功,克隆了',
cloneSuccEnd: '项配置',
cloneFail: '克隆失败',
getNamespaceFailed: '获取命名空间失败',
startCloning: '开始克隆',
cloningConfiguration: '克隆配置',
source: '源空间:',
configurationNumber: '配置数量:',
target: '目标空间:',
selectNamespace: '请选择命名空间',
selectedEntry: '| 选中的条目',
cloneSelectedAlertTitle: '配置克隆',
cloneSelectedAlertContent: '请选择要克隆的配置',
delSelectedAlertTitle: '配置删除',
delSelectedAlertContent: '请选择要删除的配置',
delSuccessMsg: '删除成功',
cloneEditableTitle: '修改 Data Id 和 Group (可选操作)',
},
NewConfig: {
newListingMain: '新建配置',
newListing: '新建配置',
publishFailed: '发布失败。请检查参数是否正确。',
doNotEnter: '不允许非法字符',
newConfig: 'Data ID 不能为空',
dataIdIsNotEmpty: 'Data ID 长度不能超过255字符',
groupPlaceholder: '请输入Group名称',
moreAdvanced: 'Group不能为空',
groupNotEmpty: 'Group ID长度不能超过127字符',
annotation:
'注您正在往一个自定义分组新增配置请确保客户端使用的Pandora版本高于3.4.0,否则可能读取不到该配置。',
dataIdLength: '收起',
collapse: '更多高级选项',
tags: '标签:',
pleaseEnterTag: '请输入标签',
groupIdCannotBeLonger: '归属应用:',
description: '描述:',
targetEnvironment: '配置格式:',
configurationFormat: '配置内容:',
configureContentsOf: '按F1显示全屏',
fullScreen: '按Esc退出全屏',
escExit: '发布',
release: '返回',
confirmSyanx: '配置信息可能有语法错误, 确定提交吗?',
dataIdExists: '配置已存在, 试试别的dataid和group的组合吧',
dataRequired: '数据不能为空, 提交失败',
},
CloneDialog: {
terminate: '终止克隆',
skip: '跳过',
cover: '覆盖',
getNamespaceFailed: '获取命名空间失败',
selectedEntry: '| 选中的条目',
homeApplication: '归属应用:',
tags: '标签:',
startCloning: '开始克隆',
source: '源空间:',
configurationNumber: '配置数量:',
target: '目标空间:',
conflict: '相同配置:',
selectNamespace: '请选择命名空间',
configurationCloning: '配置克隆(',
},
DeleteDialog: {
confManagement: '配置管理',
determine: '确定',
deletetitle: '删除配置',
deletedSuccessfully: '删除配置成功',
deleteFailed: '删除配置失败',
},
DiffEditorDialog: {
publish: '确认发布',
contents: '内容比较',
currentArea: '当前值',
originalValue: '原始值',
},
ConfigEditor: {
official: '正式',
production: '正式',
beta: 'BETA',
wrong: '错误',
submitFailed: '不能为空, 提交失败',
toedittitle: '编辑配置',
toedit: '编辑配置',
newConfigEditor: '新建配置',
vdchart: '请勿输入非法字符',
recipientFrom: 'Data ID不能为空',
homeApplication: 'Group不能为空',
collapse: '收起',
groupNotEmpty: '更多高级选项',
tags: '标签:',
pleaseEnterTag: '请输入标签',
targetEnvironment: '归属应用:',
description: '描述:',
format: '配置格式:',
configcontent: '配置内容',
escExit: '按F1显示全屏',
releaseBeta: '按Esc退出全屏',
release: '发布Beta',
stopPublishBeta: '停止Beta',
betaPublish: 'Beta发布:',
betaSwitchPrompt: '默认不要勾选。',
publish: '发布',
back: '返回',
codeValErrorPrompt: '配置信息可能有语法错误, 确定提交吗?',
},
EditorNameSpace: {
notice: '提示',
pleaseDo: '请勿输入非法字符',
publicSpace: '确认修改',
confirmModify: '编辑命名空间',
editNamespace: '加载中...',
load: '命名空间名:',
namespace: '命名空间不能为空',
namespaceDesc: '命名空间描述不能为空',
description: '描述:',
},
ExportDialog: {
selectedEntry: '| 选中的条目',
application: '归属应用:',
tags: '标签:',
exportBtn: '导出',
exportConfiguration: '导出配置(',
source: '源空间:',
items: '配置数量:',
},
ImportDialog: {
terminate: '终止导入',
skip: '跳过',
overwrite: '覆盖',
zipFileFormat: '只能上传.zip格式的文件',
uploadFile: '上传文件',
importLabel: '导入配置 ( ',
target: '目标空间:',
conflict: '相同配置:',
beSureExerciseCaution: '文件上传后将直接导入配置,请务必谨慎操作',
},
ShowCodeing: {
sampleCode: '示例代码',
loading: '加载中...',
},
SuccessDialog: {
title: '配置管理',
determine: '确定',
failure: '失败',
},
ConfigSync: {
error: '错误',
syncConfigurationMain: '同步配置',
syncConfiguration: '同步配置成功',
advancedOptions: '更多高级选项',
collapse: '收起',
home: '归属应用:',
region: '所属地域:',
configuration: '配置内容:',
target: '目标地域:',
sync: '同步',
back: '返回',
},
NewNameSpace: {
norepeat: '命名空间名称不能重复',
notice: '提示',
input: '请勿输入非法字符',
ok: '确定',
cancel: '取消',
newnamespce: '新建命名空间',
loading: '加载中...',
name: '命名空间名:',
namespaceId: '命名空间ID(不填则自动生成)',
namespaceIdTooLong: '命名空间ID长度不能超过128',
namespacenotnull: '命名空间不能为空',
namespacedescnotnull: '命名空间描述不能为空',
description: '描述:',
namespaceIdAlreadyExist: 'namespaceId已存在',
newnamespceFailedMessage: 'namespaceId格式不正确/namespaceId长度大于128/namespaceId已存在',
},
NameSpaceList: {
notice: '提示',
},
ConfigDetail: {
official: '正式',
error: '错误',
configurationDetails: '配置详情',
collapse: '收起',
more: '更多高级选项',
home: '归属应用:',
tags: '标签:',
description: '描述:',
betaRelease: 'Beta发布',
configuration: '配置内容:',
back: '返回',
},
ConfigRollback: {
rollBack: '回滚配置',
determine: '确定要',
followingConfiguration: '以下配置吗?',
configurationRollback: '配置回滚',
collapse: '收起',
more: '更多高级选项',
home: '归属应用:',
actionType: '操作类型:',
configuration: '配置内容:',
back: '返回',
rollbackSuccessful: '回滚成功',
rollbackDelete: '删除',
update: '更新',
insert: '插入',
},
UserManagement: {
userManagement: '用户管理',
createUser: '创建用户',
resetPassword: '修改',
deleteUser: '删除',
deleteUserTip: '是否要删除该用户?',
username: '用户名',
password: '密码',
operation: '操作',
},
NewUser: {
createUser: '创建用户',
username: '用户名',
password: '密码',
rePassword: '确认密码',
usernamePlaceholder: '请输入用户名',
passwordPlaceholder: '请输入密码',
rePasswordPlaceholder: '请输入确认密码',
usernameError: '用户名不能为空!',
passwordError: '密码不能为空!',
rePasswordError: '确认密码不能为空!',
rePasswordError2: '两次输入密码不一致!',
},
PasswordReset: {
resetPassword: '密码重置',
username: '用户名',
password: '密码',
rePassword: '确认密码',
passwordError: '密码不能为空!',
passwordPlaceholder: '请输入密码',
rePasswordPlaceholder: '请输入确认密码',
rePasswordError: '确认密码不能为空!',
rePasswordError2: '两次输入密码不一致!',
},
RolesManagement: {
roleManagement: '角色管理',
bindingRoles: '绑定角色',
role: '角色名',
username: '用户名',
operation: '操作',
deleteRole: '删除',
deleteRoleTip: '是否要删除该角色?',
},
NewRole: {
bindingRoles: '绑定角色',
username: '用户名',
role: '角色名',
usernamePlaceholder: '请输入用户名',
rolePlaceholder: '请输入角色名',
usernameError: '用户名不能为空!',
roleError: '角色名不能为空!',
},
PermissionsManagement: {
privilegeManagement: '权限管理',
addPermission: '添加权限',
role: '角色名',
resource: '资源',
action: '动作',
operation: '操作',
deletePermission: '删除',
deletePermissionTip: '是否要删除该权限?',
readOnly: '只读',
writeOnly: '只写',
readWrite: '读写',
},
NewPermissions: {
addPermission: '添加权限',
role: '角色名',
resource: '资源',
action: '动作',
resourcePlaceholder: '请选择资源',
rolePlaceholder: '请输入角色名',
actionPlaceholder: '请选择动作',
resourceError: '资源不能为空!',
roleError: '角色名不能为空!',
actionError: '动作不能为空!',
readOnly: '只读',
writeOnly: '只写',
readWrite: '读写',
},
};
export default I18N_CONF;

View File

@ -1,124 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { Field, Form, Input, Select, Dialog, ConfigProvider } from '@alifd/next';
import { connect } from 'react-redux';
import { getNamespaces } from '../../../reducers/namespace';
const FormItem = Form.Item;
const { Option } = Select;
const formItemLayout = {
labelCol: { fixedSpan: 4 },
wrapperCol: { span: 19 },
};
@connect(state => ({ namespaces: state.namespace.namespaces }), { getNamespaces })
@ConfigProvider.config
class NewPermissions extends React.Component {
static displayName = 'NewPermissions';
field = new Field(this);
static propTypes = {
locale: PropTypes.object,
visible: PropTypes.bool,
getNamespaces: PropTypes.func,
onOk: PropTypes.func,
onCancel: PropTypes.func,
namespaces: PropTypes.array,
};
componentDidMount() {
this.props.getNamespaces();
}
check() {
const { locale } = this.props;
const errors = {
role: locale.roleError,
resource: locale.resourceError,
action: locale.actionError,
};
const vals = Object.keys(errors).map(key => {
const val = this.field.getValue(key);
if (!val) {
this.field.setError(key, errors[key]);
}
return val;
});
if (vals.filter(v => v).length === 3) {
return vals;
}
return null;
}
render() {
const { getError } = this.field;
const { visible, onOk, onCancel, locale, namespaces } = this.props;
return (
<>
<Dialog
title={locale.addPermission}
visible={visible}
onOk={() => {
const vals = this.check();
if (vals) {
onOk(vals).then(() => onCancel());
}
}}
onClose={onCancel}
onCancel={onCancel}
afterClose={() => this.field.reset()}
>
<Form style={{ width: 400 }} {...formItemLayout} field={this.field}>
<FormItem label={locale.role} required help={getError('role')}>
<Input name="role" trim placeholder={locale.rolePlaceholder} />
</FormItem>
<FormItem label={locale.resource} required help={getError('resource')}>
<Select
name="resource"
placeholder={locale.resourcePlaceholder}
style={{ width: '100%' }}
>
{namespaces.map(({ namespace, namespaceShowName }) => (
<Option value={`${namespace}:*:*`}>
{namespaceShowName} {namespace ? `(${namespace})` : ''}
</Option>
))}
</Select>
</FormItem>
<FormItem label={locale.action} required help={getError('action')}>
<Select
name="action"
placeholder={locale.actionPlaceholder}
style={{ width: '100%' }}
>
<Option value="r">{locale.readOnly}(r)</Option>
<Option value="w">{locale.writeOnly}(w)</Option>
<Option value="rw">{locale.readWrite}(rw)</Option>
</Select>
</FormItem>
</Form>
</Dialog>
</>
);
}
}
export default NewPermissions;

View File

@ -1,165 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { Button, Dialog, Pagination, Table, ConfigProvider } from '@alifd/next';
import { connect } from 'react-redux';
import { getPermissions, createPermission, deletePermission } from '../../../reducers/authority';
import { getNamespaces } from '../../../reducers/namespace';
import RegionGroup from '../../../components/RegionGroup';
import NewPermissions from './NewPermissions';
import './PermissionsManagement.scss';
@connect(
state => ({
permissions: state.authority.permissions,
namespaces: state.namespace.namespaces,
}),
{ getPermissions, getNamespaces }
)
@ConfigProvider.config
class PermissionsManagement extends React.Component {
static displayName = 'PermissionsManagement';
static propTypes = {
locale: PropTypes.object,
permissions: PropTypes.object,
namespaces: PropTypes.object,
getPermissions: PropTypes.func,
getNamespaces: PropTypes.func,
};
constructor(props) {
super(props);
this.state = {
loading: true,
pageNo: 1,
pageSize: 9,
createPermission: false,
};
}
componentDidMount() {
this.getPermissions();
this.props.getNamespaces();
}
getPermissions() {
const { pageNo, pageSize } = this.state;
this.props
.getPermissions({ pageNo, pageSize })
.then(() => {
if (this.state.loading) {
this.setState({ loading: false });
}
})
.catch(() => this.setState({ loading: false }));
}
colseCreatePermission() {
this.setState({ createPermissionVisible: false });
}
getActionText(action) {
const { locale } = this.props;
return {
r: `${locale.readOnly} (r)`,
w: `${locale.writeOnly} (w)`,
rw: `${locale.readWrite} (rw)`,
}[action];
}
render() {
const { permissions, namespaces = [], locale } = this.props;
const { loading, pageSize, pageNo, createPermissionVisible } = this.state;
return (
<>
<RegionGroup left={locale.privilegeManagement} />
<div className="filter-panel">
<Button type="primary" onClick={() => this.setState({ createPermissionVisible: true })}>
{locale.addPermission}
</Button>
</div>
<Table dataSource={permissions.pageItems} loading={loading} maxBodyHeight={476} fixedHeader>
<Table.Column title={locale.role} dataIndex="role" />
<Table.Column
title={locale.resource}
dataIndex="resource"
cell={value => {
const [item = {}] = namespaces.filter(({ namespace }) => {
const [itemNamespace] = value.split(':');
return itemNamespace === namespace;
});
const { namespaceShowName = '', namespace = '' } = item;
return namespaceShowName + (namespace ? ` (${namespace})` : '');
}}
/>
<Table.Column
title={locale.action}
dataIndex="action"
cell={action => this.getActionText(action)}
/>
<Table.Column
title={locale.operation}
cell={(value, index, record) => (
<>
<Button
type="primary"
warning
onClick={() =>
Dialog.confirm({
title: locale.deletePermission,
content: locale.deletePermissionTip,
onOk: () =>
deletePermission(record).then(() => {
this.setState({ pageNo: 1 }, () => this.getPermissions());
}),
})
}
>
{locale.deletePermission}
</Button>
</>
)}
/>
</Table>
{permissions.totalCount > pageSize && (
<Pagination
className="users-pagination"
current={pageNo}
total={permissions.totalCount}
pageSize={pageSize}
onChange={pageNo => this.setState({ pageNo }, () => this.getPermissions())}
/>
)}
<NewPermissions
visible={createPermissionVisible}
onOk={permission =>
createPermission(permission).then(res => {
this.setState({ pageNo: 1 }, () => this.getPermissions());
return res;
})
}
onCancel={() => this.colseCreatePermission()}
/>
</>
);
}
}
export default PermissionsManagement;

View File

@ -1,15 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/

View File

@ -1,19 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import PermissionsManagement from './PermissionsManagement';
export default PermissionsManagement;

View File

@ -1,7 +0,0 @@
# 权限控制
> AuthorityControl
1. UserManagement => 用户管理
2. RolesManagement => 角色管理
3. PermissionsManagement => 权限管理

View File

@ -1,93 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { Field, Form, Input, Dialog, ConfigProvider } from '@alifd/next';
const FormItem = Form.Item;
const formItemLayout = {
labelCol: { fixedSpan: 4 },
wrapperCol: { span: 19 },
};
@ConfigProvider.config
class NewRole extends React.Component {
static displayName = 'NewRole';
field = new Field(this);
static propTypes = {
locale: PropTypes.object,
visible: PropTypes.bool,
onOk: PropTypes.func,
onCancel: PropTypes.func,
};
check() {
const { locale } = this.props;
const errors = {
role: locale.roleError,
username: locale.usernameError,
};
const vals = Object.keys(errors).map(key => {
const val = this.field.getValue(key);
if (!val) {
this.field.setError(key, errors[key]);
}
return val;
});
if (vals.filter(v => v).length === 2) {
return vals;
}
return null;
}
render() {
const { locale } = this.props;
const { getError } = this.field;
const { visible, onOk, onCancel } = this.props;
return (
<>
<Dialog
title={locale.bindingRoles}
visible={visible}
onOk={() => {
const vals = this.check();
if (vals) {
onOk(vals).then(() => onCancel());
}
}}
onClose={onCancel}
onCancel={onCancel}
afterClose={() => this.field.reset()}
>
<Form style={{ width: 400 }} {...formItemLayout} field={this.field}>
<FormItem label={locale.role} required help={getError('role')}>
<Input name="role" trim placeholder={locale.rolePlaceholder} />
</FormItem>
<FormItem label={locale.username} required help={getError('username')}>
<Input name="username" placeholder={locale.usernamePlaceholder} />
</FormItem>
</Form>
</Dialog>
</>
);
}
}
export default NewRole;

View File

@ -1,133 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { Button, Dialog, Pagination, Table, ConfigProvider } from '@alifd/next';
import { connect } from 'react-redux';
import { getRoles, createRole, deleteRole } from '../../../reducers/authority';
import RegionGroup from '../../../components/RegionGroup';
import NewRole from './NewRole';
import './RolesManagement.scss';
@connect(state => ({ roles: state.authority.roles }), { getRoles })
@ConfigProvider.config
class RolesManagement extends React.Component {
static displayName = 'RolesManagement';
static propTypes = {
locale: PropTypes.object,
roles: PropTypes.object,
getRoles: PropTypes.func,
};
constructor(props) {
super(props);
this.state = {
loading: true,
pageNo: 1,
pageSize: 9,
};
}
componentDidMount() {
this.getRoles();
}
getRoles() {
const { pageNo, pageSize } = this.state;
this.props
.getRoles({ pageNo, pageSize })
.then(() => {
if (this.state.loading) {
this.setState({ loading: false });
}
})
.catch(() => this.setState({ loading: false }));
}
colseCreateRole() {
this.setState({ createRoleVisible: false });
}
render() {
const { roles, locale } = this.props;
const { loading, pageSize, pageNo, createRoleVisible, passwordResetUser } = this.state;
return (
<>
<RegionGroup left={locale.roleManagement} />
<div className="filter-panel">
<Button type="primary" onClick={() => this.setState({ createRoleVisible: true })}>
{locale.bindingRoles}
</Button>
</div>
<Table dataSource={roles.pageItems} loading={loading} maxBodyHeight={476} fixedHeader>
<Table.Column title={locale.role} dataIndex="role" />
<Table.Column title={locale.username} dataIndex="username" />
<Table.Column
title={locale.operation}
dataIndex="role"
cell={(value, index, record) => {
if (value === 'ROLE_ADMIN') {
return null;
}
return (
<Button
type="primary"
warning
onClick={() =>
Dialog.confirm({
title: locale.deleteRole,
content: locale.deleteRoleTip,
onOk: () =>
deleteRole(record).then(() => {
this.setState({ pageNo: 1 }, () => this.getRoles());
}),
})
}
>
{locale.deleteRole}
</Button>
);
}}
/>
</Table>
{roles.totalCount > pageSize && (
<Pagination
className="users-pagination"
current={pageNo}
total={roles.totalCount}
pageSize={pageSize}
onChange={pageNo => this.setState({ pageNo }, () => this.getRoles())}
/>
)}
<NewRole
visible={createRoleVisible}
onOk={role =>
createRole(role).then(res => {
this.getRoles();
return res;
})
}
onCancel={() => this.colseCreateRole()}
/>
</>
);
}
}
export default RolesManagement;

View File

@ -1,15 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/

View File

@ -1,19 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import RolesManagement from './RolesManagement';
export default RolesManagement;

View File

@ -1,107 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { Field, Form, Input, Dialog, ConfigProvider } from '@alifd/next';
import './UserManagement.scss';
const FormItem = Form.Item;
const formItemLayout = {
labelCol: { fixedSpan: 4 },
wrapperCol: { span: 19 },
};
@ConfigProvider.config
class NewUser extends React.Component {
static displayName = 'NewUser';
field = new Field(this);
static propTypes = {
locale: PropTypes.object,
visible: PropTypes.bool,
onOk: PropTypes.func,
onCancel: PropTypes.func,
};
check() {
const { locale } = this.props;
const errors = {
username: locale.usernameError,
password: locale.passwordError,
rePassword: locale.rePasswordError,
};
const vals = Object.keys(errors).map(key => {
const val = this.field.getValue(key);
if (!val) {
this.field.setError(key, errors[key]);
}
return val;
});
if (vals.filter(v => v).length !== 3) {
return null;
}
const [password, rePassword] = ['password', 'rePassword'].map(k => this.field.getValue(k));
if (password !== rePassword) {
this.field.setError('rePassword', locale.rePasswordError2);
return null;
}
return vals;
}
render() {
const { locale } = this.props;
const { getError } = this.field;
const { visible, onOk, onCancel } = this.props;
return (
<>
<Dialog
title={locale.createUser}
visible={visible}
onOk={() => {
const vals = this.check();
if (vals) {
onOk(vals).then(() => onCancel());
}
}}
onClose={onCancel}
onCancel={onCancel}
afterClose={() => this.field.reset()}
>
<Form style={{ width: 400 }} {...formItemLayout} field={this.field}>
<FormItem label={locale.username} required help={getError('username')}>
<Input name="username" trim placeholder={locale.usernamePlaceholder} />
</FormItem>
<FormItem label={locale.password} required help={getError('password')}>
<Input name="password" htmlType="password" placeholder={locale.passwordPlaceholder} />
</FormItem>
<FormItem label={locale.rePassword} required help={getError('rePassword')}>
<Input
name="rePassword"
htmlType="password"
placeholder={locale.rePasswordPlaceholder}
/>
</FormItem>
</Form>
</Dialog>
</>
);
}
}
export default NewUser;

View File

@ -1,107 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { Field, Form, Input, Dialog, ConfigProvider } from '@alifd/next';
import './UserManagement.scss';
const FormItem = Form.Item;
const formItemLayout = {
labelCol: { fixedSpan: 4 },
wrapperCol: { span: 19 },
};
@ConfigProvider.config
class PasswordReset extends React.Component {
static displayName = 'PasswordReset';
field = new Field(this);
static propTypes = {
locale: PropTypes.object,
visible: PropTypes.bool,
username: PropTypes.string,
onCancel: PropTypes.func,
onOk: PropTypes.func,
};
check() {
const { locale } = this.props;
const errors = {
password: locale.passwordError,
rePassword: locale.rePasswordError,
};
const vals = Object.keys(errors).map(key => {
const val = this.field.getValue(key);
if (!val) {
this.field.setError(key, errors[key]);
}
return val;
});
if (vals.filter(v => v).length !== 2) {
return null;
}
const [password, rePassword] = ['password', 'rePassword'].map(k => this.field.getValue(k));
if (password !== rePassword) {
this.field.setError('rePassword', locale.rePasswordError2);
return null;
}
return [this.props.username, ...vals];
}
render() {
const { locale } = this.props;
const { getError } = this.field;
const { username, onOk, onCancel } = this.props;
return (
<>
<Dialog
title={locale.resetPassword}
visible={username}
onOk={() => {
const vals = this.check();
if (vals) {
onOk(vals).then(() => onCancel());
}
}}
onClose={onCancel}
onCancel={onCancel}
afterClose={() => this.field.reset()}
>
<Form style={{ width: 400 }} {...formItemLayout} field={this.field}>
<FormItem label={locale.username} required>
<p>{username}</p>
</FormItem>
<FormItem label={locale.password} required help={getError('password')}>
<Input name="password" htmlType="password" placeholder={locale.passwordPlaceholder} />
</FormItem>
<FormItem label={locale.rePassword} required help={getError('rePassword')}>
<Input
name="rePassword"
htmlType="password"
placeholder={locale.rePasswordPlaceholder}
/>
</FormItem>
</Form>
</Dialog>
</>
);
}
}
export default PasswordReset;

View File

@ -1,153 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import React from 'react';
import PropTypes from 'prop-types';
import { Button, Dialog, Pagination, Table, ConfigProvider } from '@alifd/next';
import { connect } from 'react-redux';
import { getUsers, createUser, deleteUser, passwordReset } from '../../../reducers/authority';
import RegionGroup from '../../../components/RegionGroup';
import NewUser from './NewUser';
import PasswordReset from './PasswordReset';
import './UserManagement.scss';
@connect(state => ({ users: state.authority.users }), { getUsers })
@ConfigProvider.config
class UserManagement extends React.Component {
static displayName = 'UserManagement';
static propTypes = {
locale: PropTypes.object,
users: PropTypes.object,
getUsers: PropTypes.func,
createUser: PropTypes.func,
};
constructor(props) {
super(props);
this.state = {
loading: true,
pageNo: 1,
pageSize: 9,
};
}
componentDidMount() {
this.getUsers();
}
getUsers() {
const { pageNo, pageSize } = this.state;
this.props
.getUsers({ pageNo, pageSize })
.then(() => {
if (this.state.loading) {
this.setState({ loading: false });
}
})
.catch(() => this.setState({ loading: false }));
}
colseCreateUser() {
this.setState({ createUserVisible: false });
}
render() {
const { users, locale } = this.props;
const { loading, pageSize, pageNo, createUserVisible, passwordResetUser } = this.state;
return (
<>
<RegionGroup left={locale.userManagement} />
<div className="filter-panel">
<Button type="primary" onClick={() => this.setState({ createUserVisible: true })}>
{locale.createUser}
</Button>
</div>
<Table dataSource={users.pageItems} loading={loading} maxBodyHeight={476} fixedHeader>
<Table.Column title={locale.username} dataIndex="username" />
<Table.Column
title={locale.password}
dataIndex="password"
cell={value => value.replace(/\S/g, '*')}
/>
<Table.Column
title={locale.operation}
dataIndex="username"
cell={username => (
<>
<Button
type="primary"
onClick={() => this.setState({ passwordResetUser: username })}
>
{locale.resetPassword}
</Button>
&nbsp;&nbsp;&nbsp;
<Button
type="primary"
warning
onClick={() =>
Dialog.confirm({
title: locale.deleteUser,
content: locale.deleteUserTip,
onOk: () =>
deleteUser(username).then(() => {
this.setState({ pageNo: 1 }, () => this.getUsers());
}),
})
}
>
{locale.deleteUser}
</Button>
</>
)}
/>
</Table>
{users.totalCount > pageSize && (
<Pagination
className="users-pagination"
current={pageNo}
total={users.totalCount}
pageSize={pageSize}
onChange={pageNo => this.setState({ pageNo }, () => this.getUsers())}
/>
)}
<NewUser
visible={createUserVisible}
onOk={user =>
createUser(user).then(res => {
this.setState({ pageNo: 1 }, () => this.getUsers());
return res;
})
}
onCancel={() => this.colseCreateUser()}
/>
<PasswordReset
username={passwordResetUser}
onOk={user =>
passwordReset(user).then(res => {
this.getUsers();
return res;
})
}
onCancel={() => this.setState({ passwordResetUser: undefined })}
/>
</>
);
}
}
export default UserManagement;

View File

@ -1,21 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
@import '../authority.scss';
.users-pagination {
float: right;
margin-top: 20px;
}

View File

@ -1,19 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
import UserManagement from './UserManagement';
export default UserManagement;

View File

@ -1,20 +0,0 @@
/*!
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.
*/
.filter-panel {
text-align: right;
padding: 10px 0;
}

Some files were not shown because too many files have changed in this diff Show More