diff --git a/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/AppController.java b/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/AppController.java index 5977863c844925068fbef7701c2c6e16748586f0..1a6d24b99af6bc9558664c421c32c0af7f6a1ad7 100644 --- a/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/AppController.java +++ b/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/AppController.java @@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; +import java.util.Objects; @RestController public class AppController { @@ -47,7 +48,7 @@ public class AppController { return dto; } - @RequestMapping(path = "/apps/{appId}", method = RequestMethod.DELETE) + @RequestMapping(value = "/apps/{appId}", method = RequestMethod.DELETE) public void delete(@PathVariable("appId") String appId, @RequestParam String operator) { App entity = appService.findOne(appId); if (entity == null) { @@ -56,6 +57,15 @@ public class AppController { appService.delete(entity.getId(), operator); } + @RequestMapping(value = "/apps/{appId}", method = RequestMethod.PUT) + public void update(@PathVariable String appId, @RequestBody App app) { + if (!Objects.equals(appId, app.getAppId())) { + throw new BadRequestException("The App Id of path variable and request body is different"); + } + + appService.update(app); + } + @RequestMapping(value = "/apps", method = RequestMethod.GET) public List find(@RequestParam(value = "name", required = false) String name, Pageable pageable) { diff --git a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppService.java b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppService.java index eb0f57b8a1ce14f203e0d762517e3caef1f4e8cc..5578121b98e360010c028d547ea816b04f6ad881 100644 --- a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppService.java +++ b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppService.java @@ -3,6 +3,7 @@ package com.ctrip.framework.apollo.biz.service; import com.ctrip.framework.apollo.biz.entity.Audit; import com.ctrip.framework.apollo.biz.repository.AppRepository; import com.ctrip.framework.apollo.common.entity.App; +import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.ServiceException; import com.ctrip.framework.apollo.common.utils.BeanUtils; @@ -71,14 +72,25 @@ public class AppService { } @Transactional - public App update(App app) { - App managedApp = appRepository.findByAppId(app.getAppId()); - BeanUtils.copyEntityProperties(app, managedApp); + public void update(App app) { + String appId = app.getAppId(); + + App managedApp = appRepository.findByAppId(appId); + if (managedApp == null) { + throw new BadRequestException(String.format("App not exists. AppId = %s", appId)); + } + + managedApp.setName(app.getName()); + managedApp.setOrgId(app.getOrgId()); + managedApp.setOrgName(app.getOrgName()); + managedApp.setOwnerName(app.getOwnerName()); + managedApp.setOwnerEmail(app.getOwnerEmail()); + managedApp.setDataChangeLastModifiedBy(app.getDataChangeLastModifiedBy()); + managedApp = appRepository.save(managedApp); auditService.audit(App.class.getSimpleName(), managedApp.getId(), Audit.OP.UPDATE, managedApp.getDataChangeLastModifiedBy()); - return managedApp; } } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java index f0a2b399d498a6b80c42dcf040c2bef81006e10c..e92c5cca07c0768591487ed05ffe695d9625d4f6 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java @@ -58,6 +58,10 @@ public class AdminServiceAPI { public AppDTO createApp(Env env, AppDTO app) { return restTemplate.post(env, "apps", app, AppDTO.class); } + + public void updateApp(Env env, AppDTO app) { + restTemplate.put(env, "apps/{appId}", app, app.getAppId()); + } } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/PermissionValidator.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/PermissionValidator.java index 3f2f36e478cdfae359befc488340d2f509465314..86a0892f81c3dbd331e0cd19de2b5bd75ab2ae97 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/PermissionValidator.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/component/PermissionValidator.java @@ -65,6 +65,10 @@ public class PermissionValidator { } } + public boolean isAppAdmin(String appId) { + return isSuperAdmin() || hasAssignRolePermission(appId); + } + public boolean isSuperAdmin() { return rolePermissionService.isSuperAdmin(userInfoHolder.getUser().getUserId()); } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/AppController.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/AppController.java index 65873d9d5cb7f4969776ae2cf23444ba72ca76f1..aa37020a8cddc9190690be5ca4e18b8d0419c14d 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/AppController.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/AppController.java @@ -14,6 +14,7 @@ import com.ctrip.framework.apollo.portal.component.PortalSettings; import com.ctrip.framework.apollo.portal.entity.model.AppModel; import com.ctrip.framework.apollo.portal.entity.vo.EnvClusterInfo; import com.ctrip.framework.apollo.portal.listener.AppCreationEvent; +import com.ctrip.framework.apollo.portal.listener.AppInfoChangedEvent; import com.ctrip.framework.apollo.portal.service.AppService; import com.ctrip.framework.apollo.portal.service.RolePermissionService; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; @@ -24,6 +25,7 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.PathVariable; @@ -35,6 +37,7 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.HttpClientErrorException; import java.util.List; +import java.util.Objects; import java.util.Set; @@ -69,6 +72,38 @@ public class AppController { return appService.findByOwnerName(owner, page); } + @RequestMapping(value = "", method = RequestMethod.POST) + public App create(@RequestBody AppModel appModel) { + + App app = transformToApp(appModel); + + App createdApp = appService.createAppInLocal(app); + + publisher.publishEvent(new AppCreationEvent(createdApp)); + + Set admins = appModel.getAdmins(); + if (!CollectionUtils.isEmpty(admins)) { + rolePermissionService.assignRoleToUsers(RoleUtils.buildAppMasterRoleName(createdApp.getAppId()), + admins, userInfoHolder.getUser().getUserId()); + } + + return createdApp; + } + + @PreAuthorize(value = "@permissionValidator.isAppAdmin(#appId)") + @RequestMapping(value = "/{appId}", method = RequestMethod.PUT) + public void update(@PathVariable String appId, @RequestBody AppModel appModel) { + if (!Objects.equals(appId, appModel.getAppId())) { + throw new BadRequestException("The App Id of path variable and request body is different"); + } + + App app = transformToApp(appModel); + + App updatedApp = appService.updateAppInLocal(app); + + publisher.publishEvent(new AppInfoChangedEvent(updatedApp)); + } + @RequestMapping(value = "/{appId}/navtree", method = RequestMethod.GET) public MultiResponseEntity nav(@PathVariable String appId) { @@ -86,41 +121,6 @@ public class AppController { return response; } - @RequestMapping(value = "", method = RequestMethod.POST) - public App create(@RequestBody AppModel appModel) { - - String appId = appModel.getAppId(); - String appName = appModel.getName(); - String ownerName = appModel.getOwnerName(); - String orgId = appModel.getOrgId(); - String orgName = appModel.getOrgName(); - - RequestPrecondition.checkArgumentsNotEmpty(appId, appName, ownerName, orgId, orgName); - - if (!InputValidator.isValidClusterNamespace(appModel.getAppId())) { - throw new BadRequestException(String.format("AppId格式错误: %s", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE)); - } - - App app = new App(); - app.setAppId(appId); - app.setName(appName); - app.setOwnerName(ownerName); - app.setOrgId(orgId); - app.setOrgName(orgName); - - App createdApp = appService.create(app); - - publisher.publishEvent(new AppCreationEvent(createdApp)); - - Set admins = appModel.getAdmins(); - if (!CollectionUtils.isEmpty(admins)) { - rolePermissionService - .assignRoleToUsers(RoleUtils.buildAppMasterRoleName(appId), admins, userInfoHolder.getUser().getUserId()); - } - - return createdApp; - } - @RequestMapping(value = "/envs/{env}", method = RequestMethod.POST, consumes = { "application/json"}) public ResponseEntity create(@PathVariable String env, @RequestBody App app) { @@ -131,7 +131,7 @@ public class AppController { throw new BadRequestException(InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE); } - appService.createApp(Env.valueOf(env), app); + appService.createAppInRemote(Env.valueOf(env), app); return ResponseEntity.ok().build(); } @@ -155,7 +155,8 @@ public class AppController { response.addResponseEntity(RichResponseEntity.ok(env)); } else { response.addResponseEntity(RichResponseEntity.error(HttpStatus.INTERNAL_SERVER_ERROR, - String.format("load appId:%s from env %s error.", appId,env) + String.format("load appId:%s from env %s error.", appId, + env) + e.getMessage())); } } @@ -164,4 +165,27 @@ public class AppController { return response; } + + private App transformToApp(AppModel appModel) { + String appId = appModel.getAppId(); + String appName = appModel.getName(); + String ownerName = appModel.getOwnerName(); + String orgId = appModel.getOrgId(); + String orgName = appModel.getOrgName(); + + RequestPrecondition.checkArgumentsNotEmpty(appId, appName, ownerName, orgId, orgName); + + if (!InputValidator.isValidClusterNamespace(appModel.getAppId())) { + throw new BadRequestException(String.format("AppId格式错误: %s", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE)); + } + + App app = new App(); + app.setAppId(appId); + app.setName(appName); + app.setOwnerName(ownerName); + app.setOrgId(orgId); + app.setOrgName(orgName); + + return app; + } } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppInfoChangedEvent.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppInfoChangedEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..7a61141da56d207852305dec3448a66c36f31ed8 --- /dev/null +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppInfoChangedEvent.java @@ -0,0 +1,19 @@ +package com.ctrip.framework.apollo.portal.listener; + +import com.google.common.base.Preconditions; + +import com.ctrip.framework.apollo.common.entity.App; + +import org.springframework.context.ApplicationEvent; + +public class AppInfoChangedEvent extends ApplicationEvent{ + + public AppInfoChangedEvent(Object source) { + super(source); + } + + public App getApp() { + Preconditions.checkState(source != null); + return (App) this.source; + } +} diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppInfoChangedListener.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppInfoChangedListener.java new file mode 100644 index 0000000000000000000000000000000000000000..c37ab28ec0e6ec5a84c1e814e6867e777e1d4304 --- /dev/null +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppInfoChangedListener.java @@ -0,0 +1,45 @@ +package com.ctrip.framework.apollo.portal.listener; + +import com.ctrip.framework.apollo.common.dto.AppDTO; +import com.ctrip.framework.apollo.common.utils.BeanUtils; +import com.ctrip.framework.apollo.core.enums.Env; +import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; +import com.ctrip.framework.apollo.portal.component.PortalSettings; +import com.ctrip.framework.apollo.tracer.Tracer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class AppInfoChangedListener { + private static final Logger logger = LoggerFactory.getLogger(AppInfoChangedListener.class); + + @Autowired + private AdminServiceAPI.AppAPI appAPI; + @Autowired + private PortalSettings portalSettings; + + + @EventListener + public void onAppInfoChange(AppInfoChangedEvent event) { + AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, event.getApp()); + String appId = appDTO.getAppId(); + + List envs = portalSettings.getActiveEnvs(); + for (Env env : envs) { + try { + appAPI.updateApp(env, appDTO); + } catch (Throwable e) { + logger.error("Update app's info failed. Env = {}, AppId = {}", env, appId, e); + Tracer.logError(String.format("Update app's info failed. Env = {}, AppId = {}", env, appId), e); + } + } + + } + +} diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/CreationListener.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/CreationListener.java index 11115c3fc791aea5325b1e552f37113de03503a6..a7e73b347536da132d16025c376399f965ebd104 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/CreationListener.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/CreationListener.java @@ -36,8 +36,8 @@ public class CreationListener { try { appAPI.createApp(env, appDTO); } catch (Throwable e) { - logger.error("call appAPI.createApp error.(appId={appId}, env={env})", appDTO.getAppId(), env, e); - Tracer.logError(String.format("call appAPI.createApp error. (appId=%s, env=%s)", appDTO.getAppId(), env), e); + logger.error("Create app failed. appId = {}, env = {})", appDTO.getAppId(), env, e); + Tracer.logError(String.format("Create app failed. appId = %s, env = %s", appDTO.getAppId(), env), e); } } } @@ -50,8 +50,8 @@ public class CreationListener { try { namespaceAPI.createAppNamespace(env, appNamespace); } catch (Throwable e) { - logger.error("call appAPI.createApp error.(appId={appId}, env={env})", appNamespace.getAppId(), env, e); - Tracer.logError(String.format("call appAPI.createApp error. (appId=%s, env=%s)", appNamespace.getAppId(), env), e); + logger.error("Create appNamespace failed. appId = {}, env = {}", appNamespace.getAppId(), env, e); + Tracer.logError(String.format("Create appNamespace failed. appId = %s, env = %s", appNamespace.getAppId(), env), e); } } } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppService.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppService.java index 280ab5e471e3ae78575ae881d5251e8cb46a474e..d0546910a89a3a8b9bea526524c111c67304e504 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppService.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppService.java @@ -6,7 +6,6 @@ import com.ctrip.framework.apollo.common.dto.AppDTO; import com.ctrip.framework.apollo.common.entity.App; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.BeanUtils; -import com.ctrip.framework.apollo.common.utils.ExceptionUtils; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import com.ctrip.framework.apollo.portal.constant.CatEventType; @@ -17,13 +16,10 @@ import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.spi.UserService; import com.ctrip.framework.apollo.tracer.Tracer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.client.HttpStatusCodeException; import java.util.Collections; import java.util.List; @@ -32,8 +28,6 @@ import java.util.Set; @Service public class AppService { - private Logger logger = LoggerFactory.getLogger(AppService.class); - @Autowired private UserInfoHolder userInfoHolder; @Autowired @@ -78,26 +72,17 @@ public class AppService { return appAPI.loadApp(env, appId); } - public void createApp(Env env, App app) { - enrichUserInfo(app); - try { - AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, app); - appAPI.createApp(env, appDTO); - } catch (HttpStatusCodeException e) { - logger.error(ExceptionUtils.toString(e)); - throw e; - } - } - - public void enrichUserInfo(App app) { + public void createAppInRemote(Env env, App app) { String username = userInfoHolder.getUser().getUserId(); app.setDataChangeCreatedBy(username); app.setDataChangeLastModifiedBy(username); - } + AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, app); + appAPI.createApp(env, appDTO); + } @Transactional - public App create(App app) { + public App createAppInLocal(App app) { String appId = app.getAppId(); App managedApp = appRepository.findByAppId(appId); @@ -125,6 +110,33 @@ public class AppService { return createdApp; } + @Transactional + public App updateAppInLocal(App app) { + String appId = app.getAppId(); + + App managedApp = appRepository.findByAppId(appId); + if (managedApp == null) { + throw new BadRequestException(String.format("App not exists. AppId = %s", appId)); + } + + managedApp.setName(app.getName()); + managedApp.setOrgId(app.getOrgId()); + managedApp.setOrgName(app.getOrgName()); + + String ownerName = app.getOwnerName(); + UserInfo owner = userService.findByUserId(ownerName); + if (owner == null) { + throw new BadRequestException(String.format("App's owner not exists. owner = %s", ownerName)); + } + managedApp.setOwnerName(owner.getUserId()); + managedApp.setOwnerEmail(owner.getEmail()); + + String operator = userInfoHolder.getUser().getUserId(); + managedApp.setDataChangeLastModifiedBy(operator); + + return appRepository.save(managedApp); + } + public EnvClusterInfo createEnvNavNode(Env env, String appId) { EnvClusterInfo node = new EnvClusterInfo(env); node.setClusters(clusterService.findClusters(env, appId)); diff --git a/apollo-portal/src/main/resources/static/app.html b/apollo-portal/src/main/resources/static/app.html index 5b69ebbddd936e116abf67152ba56c7c2fbb13d9..221e854276631d27637fcac61c3e37ff60dc523b 100644 --- a/apollo-portal/src/main/resources/static/app.html +++ b/apollo-portal/src/main/resources/static/app.html @@ -25,71 +25,71 @@ 创建项目 -
-
-
- -
- -
+ +
+ +
+
-
- -
- - (CMS上申请的App Id) -
+
+
+ +
+ + (CMS上申请的App Id)
-
- -
- - (建议格式 xx-yy-zz 例:apollo-server) -
+
+
+ +
+ + (建议格式 xx-yy-zz 例:apollo-server)
-
- -
- -
+
+
+ +
+
+
-
-
diff --git a/apollo-portal/src/main/resources/static/app/role.html b/apollo-portal/src/main/resources/static/app/role.html deleted file mode 100644 index fd1bc44a04ff8dc9b39aeffc35dfbfc44db33ae0..0000000000000000000000000000000000000000 --- a/apollo-portal/src/main/resources/static/app/role.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - - - - - - 权限管理 - - - - - - -
-
-
-
-
- -
- -
-
-
-
-
-
- -
-
-
- -
- -
- -
- -
- - -
-
- -
-
-
-
- - -
-
-

您没有权限哟!

-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apollo-portal/src/main/resources/static/app/setting.html b/apollo-portal/src/main/resources/static/app/setting.html new file mode 100644 index 0000000000000000000000000000000000000000..040d7b15d421da520fff375313be1e659468fe72 --- /dev/null +++ b/apollo-portal/src/main/resources/static/app/setting.html @@ -0,0 +1,200 @@ + + + + + + + + + + + + 项目管理 + + + + + + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apollo-portal/src/main/resources/static/config.html b/apollo-portal/src/main/resources/static/config.html index d76d4cbdedcc07d3d528b0e3ccfd0e7af81c21c8..f786aee4ab66a393705e5e8ca058182f68fb911e 100644 --- a/apollo-portal/src/main/resources/static/config.html +++ b/apollo-portal/src/main/resources/static/config.html @@ -34,7 +34,7 @@
-  环境列表 + 环境列表 @@ -47,16 +47,22 @@
- 项目信息 - - - - - - + 项目信息 + + + + + + + +
@@ -101,6 +107,9 @@
+ +

补缺环境

@@ -129,9 +138,7 @@
- +
@@ -169,14 +176,14 @@ 集群的实例只会使用 - 集群(当前页面)的配置,只有当对应namespace在当前集群没有发布过配置时,才会使用default集群的配置! + 集群(当前页面)的配置,只有当对应namespace在当前集群没有发布过配置时,才会使用default集群的配置。
-

注意:以下环境/集群有未发布的配置,客户端获取不到未发布的配置,请及时发布。

+

注意: 以下环境/集群有未发布的配置,客户端获取不到未发布的配置,请及时发布。

diff --git a/apollo-portal/src/main/resources/static/img/add.png b/apollo-portal/src/main/resources/static/img/add.png new file mode 100644 index 0000000000000000000000000000000000000000..36c9cf7945bcdec03111b4bdfa05c23d6d036b12 Binary files /dev/null and b/apollo-portal/src/main/resources/static/img/add.png differ diff --git a/apollo-portal/src/main/resources/static/img/clippy.svg b/apollo-portal/src/main/resources/static/img/clippy.svg deleted file mode 100644 index e1b17035905df02cbdca2fbb8417ca48dc4842e2..0000000000000000000000000000000000000000 --- a/apollo-portal/src/main/resources/static/img/clippy.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apollo-portal/src/main/resources/static/img/manage.png b/apollo-portal/src/main/resources/static/img/manage.png new file mode 100644 index 0000000000000000000000000000000000000000..8b10fff2f85f210e50df22b9e7ea97e55cc8b679 Binary files /dev/null and b/apollo-portal/src/main/resources/static/img/manage.png differ diff --git a/apollo-portal/src/main/resources/static/img/plus-orange.png b/apollo-portal/src/main/resources/static/img/plus-orange.png deleted file mode 100644 index 644bdf1ec9aba887f2bc74700309168755b51a3d..0000000000000000000000000000000000000000 Binary files a/apollo-portal/src/main/resources/static/img/plus-orange.png and /dev/null differ diff --git a/apollo-portal/src/main/resources/static/img/user_manage.png b/apollo-portal/src/main/resources/static/img/user_manage.png deleted file mode 100644 index ae2350b85568f8b608678560b466cba2f5e2f811..0000000000000000000000000000000000000000 Binary files a/apollo-portal/src/main/resources/static/img/user_manage.png and /dev/null differ diff --git a/apollo-portal/src/main/resources/static/scripts/AppUtils.js b/apollo-portal/src/main/resources/static/scripts/AppUtils.js index a089de55841efab0de6321ae19565e94f5d7d1bd..2def0cabc8181b105fb2c73862b64005e96b10a8 100644 --- a/apollo-portal/src/main/resources/static/scripts/AppUtils.js +++ b/apollo-portal/src/main/resources/static/scripts/AppUtils.js @@ -28,6 +28,12 @@ appUtil.service('AppUtil', ['toastr', '$window', function (toastr, $window) { if (query.indexOf('/') == 0) { query = query.substring(1, query.length); } + + var anchorIndex = query.indexOf('#'); + if (anchorIndex >= 0) { + query = query.substring(0, anchorIndex); + } + var params = query.split("&"); var result = {}; params.forEach(function (param) { diff --git a/apollo-portal/src/main/resources/static/scripts/app.js b/apollo-portal/src/main/resources/static/scripts/app.js index 979a02d17dd8124da1d629a15affbaf1b94e81d9..8a5f8a39515b93a52eec490defb31d2e32ad596c 100644 --- a/apollo-portal/src/main/resources/static/scripts/app.js +++ b/apollo-portal/src/main/resources/static/scripts/app.js @@ -20,6 +20,8 @@ var sync_item_module = angular.module('sync_item', ['app.service', 'apollo.direc var namespace_module = angular.module('namespace', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar', 'valdr']); //server config var server_config_module = angular.module('server_config', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']); +//setting +var setting_module = angular.module('setting', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar', 'valdr']); //role var role_module = angular.module('role', ['app.service', 'apollo.directive', 'app.util', 'toastr', 'angular-loading-bar']); //cluster diff --git a/apollo-portal/src/main/resources/static/scripts/controller/AppController.js b/apollo-portal/src/main/resources/static/scripts/controller/AppController.js index 32fe9adfe7a4f36b796f95a6afc40f5e0ac511c1..e09deba9e42004ee39427c061501c481125509b2 100644 --- a/apollo-portal/src/main/resources/static/scripts/controller/AppController.js +++ b/apollo-portal/src/main/resources/static/scripts/controller/AppController.js @@ -51,7 +51,7 @@ function createAppController($scope, $window, toastr, AppService, AppUtil, Organ // owner var owner = $('.ownerSelector').select2('data')[0]; if (!owner) { - toastr.warning("请输入应用负责人"); + toastr.warning("请选择应用负责人"); return; } $scope.app.ownerName = owner.id; diff --git a/apollo-portal/src/main/resources/static/scripts/controller/SettingController.js b/apollo-portal/src/main/resources/static/scripts/controller/SettingController.js new file mode 100644 index 0000000000000000000000000000000000000000..1c85e4b8da95007e5d0f66403dcf36cfbddcce65 --- /dev/null +++ b/apollo-portal/src/main/resources/static/scripts/controller/SettingController.js @@ -0,0 +1,191 @@ +setting_module.controller('SettingController', + ['$scope', '$location', 'toastr', + 'AppService', 'AppUtil', 'PermissionService', + 'OrganizationService', + SettingController]); + +function SettingController($scope, $location, toastr, + AppService, AppUtil, PermissionService, + OrganizationService) { + + var params = AppUtil.parseParams($location.$$url); + var $orgWidget = $('#organization'); + + $scope.pageContext = { + appId: params.appid + }; + $scope.display = { + app: { + edit: false + } + }; + + $scope.submitBtnDisabled = false; + $scope.userSelectWidgetId = 'toAssignMasterRoleUser'; + + $scope.assignMasterRoleToUser = assignMasterRoleToUser; + $scope.removeMasterRoleFromUser = removeMasterRoleFromUser; + $scope.toggleEditStatus = toggleEditStatus; + $scope.updateAppInfo = updateAppInfo; + + init(); + + function init() { + initOrganization(); + initPermission(); + initAdmins(); + initApplication(); + + } + + function initOrganization() { + OrganizationService.find_organizations().then(function (result) { + var organizations = []; + result.forEach(function (item) { + var org = {}; + org.id = item.orgId; + org.text = item.orgName + '(' + item.orgId + ')'; + org.name = item.orgName; + organizations.push(org); + }); + $orgWidget.select2({ + placeholder: '请选择部门', + width: '100%', + data: organizations + }); + }, function (result) { + toastr.error(AppUtil.errorMsg(result), "load organizations error"); + }); + } + + function initPermission() { + PermissionService.has_assign_user_permission($scope.pageContext.appId) + .then(function (result) { + $scope.hasAssignUserPermission = result.hasPermission; + }); + } + + function initAdmins() { + PermissionService.get_app_role_users($scope.pageContext.appId) + .then(function (result) { + $scope.appRoleUsers = result; + $scope.admins = []; + $scope.appRoleUsers.masterUsers.forEach(function (user) { + $scope.admins.push(user.userId); + }); + + }); + } + + function initApplication() { + AppService.load($scope.pageContext.appId).then(function (app) { + $scope.app = app; + $scope.viewApp = _.clone(app); + initAppForm(app); + $('.project-setting .panel').removeClass('hidden'); + }) + + } + + function initAppForm(app) { + $orgWidget.val(app.orgId).trigger("change"); + + var $ownerSelector = $('.ownerSelector'); + var defaultSelectedDOM = ''; + $ownerSelector.append(defaultSelectedDOM); + $ownerSelector.trigger('change'); + } + + function assignMasterRoleToUser() { + var user = $('.' + $scope.userSelectWidgetId).select2('data')[0]; + if (!user) { + toastr.warning("请选择用户"); + return; + } + var toAssignMasterRoleUser = user.id; + $scope.submitBtnDisabled = true; + PermissionService.assign_master_role($scope.pageContext.appId, + toAssignMasterRoleUser) + .then(function (result) { + $scope.submitBtnDisabled = false; + toastr.success("添加成功"); + $scope.appRoleUsers.masterUsers.push({userId: toAssignMasterRoleUser}); + $('.' + $scope.userSelectWidgetId).select2("val", ""); + }, function (result) { + $scope.submitBtnDisabled = false; + toastr.error(AppUtil.errorMsg(result), "添加失败"); + }); + } + + function removeMasterRoleFromUser(user) { + if ($scope.appRoleUsers.masterUsers.length <= 1) { + $('#warning').modal('show'); + return; + } + PermissionService.remove_master_role($scope.pageContext.appId, user) + .then(function (result) { + toastr.success("删除成功"); + removeUserFromList($scope.appRoleUsers.masterUsers, user); + }, function (result) { + toastr.error(AppUtil.errorMsg(result), "删除失败"); + }); + } + + function removeUserFromList(list, user) { + var index = 0; + for (var i = 0; i < list.length; i++) { + if (list[i].userId == user) { + index = i; + break; + } + } + list.splice(index, 1); + } + + function toggleEditStatus() { + if ($scope.display.app.edit) {//cancel edit + $scope.viewApp = _.clone($scope.app); + initAppForm($scope.viewApp); + } else {//edit + + } + + $scope.display.app.edit = !$scope.display.app.edit; + + } + + function updateAppInfo() { + $scope.submitBtnDisabled = true; + var app = $scope.viewApp; + + var selectedOrg = $orgWidget.select2('data')[0]; + + if (!selectedOrg.id) { + toastr.warning("请选择部门"); + return; + } + + app.orgId = selectedOrg.id; + app.orgName = selectedOrg.name; + + // owner + var owner = $('.ownerSelector').select2('data')[0]; + if (!owner) { + toastr.warning("请选择应用负责人"); + return; + } + app.ownerName = owner.id; + + AppService.update(app).then(function (app) { + toastr.success("修改成功"); + initApplication(); + $scope.display.app.edit = false; + $scope.submitBtnDisabled = false; + }, function (result) { + AppUtil.showErrorMsg(result); + $scope.submitBtnDisabled = false; + }) + + } +} diff --git a/apollo-portal/src/main/resources/static/scripts/controller/role/AppRoleController.js b/apollo-portal/src/main/resources/static/scripts/controller/role/AppRoleController.js deleted file mode 100644 index 7635cdc2d40788ebf0f91da8d743d8fa32eccb4c..0000000000000000000000000000000000000000 --- a/apollo-portal/src/main/resources/static/scripts/controller/role/AppRoleController.js +++ /dev/null @@ -1,75 +0,0 @@ -role_module.controller('AppRoleController', - ['$scope', '$location', '$window', 'toastr', 'AppService', 'AppUtil', 'PermissionService', - function ($scope, $location, $window, toastr, AppService, AppUtil, PermissionService) { - - var params = AppUtil.parseParams($location.$$url); - $scope.pageContext = { - appId: params.appid - }; - - $scope.submitBtnDisabled = false; - - $scope.userSelectWidgetId = 'toAssignMasterRoleUser'; - - PermissionService.has_assign_user_permission($scope.pageContext.appId) - .then(function (result) { - $scope.hasAssignUserPermission = result.hasPermission; - }, function (reslt) { - - }); - - PermissionService.get_app_role_users($scope.pageContext.appId) - .then(function (result) { - $scope.appRoleUsers = result; - }, function (result) { - - }); - - - $scope.assignMasterRoleToUser = function () { - var user = $('.' + $scope.userSelectWidgetId).select2('data')[0]; - if (!user){ - toastr.warning("请选择用户"); - return; - } - var toAssignMasterRoleUser = user.id; - $scope.submitBtnDisabled = true; - PermissionService.assign_master_role($scope.pageContext.appId, - toAssignMasterRoleUser) - .then(function (result) { - $scope.submitBtnDisabled = false; - toastr.success("添加成功"); - $scope.appRoleUsers.masterUsers.push({userId: toAssignMasterRoleUser}); - $('.' + $scope.userSelectWidgetId).select2("val", ""); - }, function (result) { - $scope.submitBtnDisabled = false; - toastr.error(AppUtil.errorMsg(result), "添加失败"); - }); - }; - - $scope.removeMasterRoleFromUser = function (user) { - if ($scope.appRoleUsers.masterUsers.length <= 1) { - $('#warning').modal('show'); - return; - } - PermissionService.remove_master_role($scope.pageContext.appId, user) - .then(function (result) { - toastr.success("删除成功"); - removeUserFromList($scope.appRoleUsers.masterUsers, user); - }, function (result) { - toastr.error(AppUtil.errorMsg(result), "删除失败"); - }); - }; - - function removeUserFromList(list, user) { - var index = 0; - for (var i = 0; i < list.length; i++) { - if (list[i].userId == user) { - index = i; - break; - } - } - list.splice(index, 1); - } - - }]); diff --git a/apollo-portal/src/main/resources/static/scripts/directive/directive.js b/apollo-portal/src/main/resources/static/scripts/directive/directive.js index c5d7de5b680dcbedc78594220a4672b65f3f457c..01b002317994d3d1e98fe3d3eb0a334ed5d1a063 100644 --- a/apollo-portal/src/main/resources/static/scripts/directive/directive.js +++ b/apollo-portal/src/main/resources/static/scripts/directive/directive.js @@ -275,13 +275,14 @@ directive_module.directive('apollouserselector', function ($compile, $window) { transclude: true, replace: true, scope: { - id: '=apolloId' + id: '=apolloId', + disabled: '=' }, link: function (scope, element, attrs) { scope.$watch("id", initSelect2); - var searchUsersAjax = { + var select2Options = { ajax: { url: '/users', dataType: 'json', @@ -311,8 +312,9 @@ directive_module.directive('apollouserselector', function ($compile, $window) { }; function initSelect2() { - $('.' + scope.id).select2(searchUsersAjax); + $('.' + scope.id).select2(select2Options); } + } } diff --git a/apollo-portal/src/main/resources/static/scripts/services/AppService.js b/apollo-portal/src/main/resources/static/scripts/services/AppService.js index 6f15f25c32090a0e8704e2bb8b17588c697ef287..14071c07b6695abe0ae928db75799794c5eecbdc 100644 --- a/apollo-portal/src/main/resources/static/scripts/services/AppService.js +++ b/apollo-portal/src/main/resources/static/scripts/services/AppService.js @@ -11,7 +11,7 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) { url: '/apps/by-owner' }, load_navtree: { - methode: 'GET', + method: 'GET', isArray: false, url: '/apps/:appId/navtree' }, @@ -23,6 +23,10 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) { method: 'POST', url: '/apps' }, + update_app: { + method: 'PUT', + url: '/apps/:appId' + }, create_app_remote: { method: 'POST', url: '/apps/envs/:env' @@ -78,6 +82,17 @@ appService.service('AppService', ['$resource', '$q', function ($resource, $q) { }); return d.promise; }, + update: function (app) { + var d = $q.defer(); + app_resource.update_app({ + appId: app.appId + }, app, function (result) { + d.resolve(result); + }, function (result) { + d.reject(result); + }); + return d.promise; + }, create_remote: function (env, app) { var d = $q.defer(); app_resource.create_app_remote({env: env}, app, function (result) { diff --git a/apollo-portal/src/main/resources/static/scripts/valdr.js b/apollo-portal/src/main/resources/static/scripts/valdr.js index 21917708fad51d909f5e07a8f19b1d96b4777316..7f42e522b7de46d52d673f0fb797b54cdc5a7067 100644 --- a/apollo-portal/src/main/resources/static/scripts/valdr.js +++ b/apollo-portal/src/main/resources/static/scripts/valdr.js @@ -1,4 +1,7 @@ -app_module.config(function (valdrProvider) { +app_module.config(appValdr); +setting_module.config(appValdr); + +function appValdr(valdrProvider) { valdrProvider.addConstraints({ 'App': { 'appId': { @@ -21,7 +24,7 @@ app_module.config(function (valdrProvider) { } } }) -}); +} cluster_module.config(function (valdrProvider) { valdrProvider.addConstraints({ diff --git a/apollo-portal/src/main/resources/static/styles/common-style.css b/apollo-portal/src/main/resources/static/styles/common-style.css index e34a1205fb606035a29d149f0ad8e127ef34489b..082af3692ba5093f67d78abaf8910985ad5e455e 100644 --- a/apollo-portal/src/main/resources/static/styles/common-style.css +++ b/apollo-portal/src/main/resources/static/styles/common-style.css @@ -144,6 +144,7 @@ pre { .footer { width: 100%; height: 75px; + margin-top: 50px; padding-top: 25px; } @@ -494,14 +495,15 @@ table th { margin: 0; } -.list-group-item .icon-plus-orange { - background: url(../img/plus-orange.png) no-repeat; +.list-group-item .icon-project-manage { + background: url(../img/manage.png) no-repeat; } -.list-group-item .icon-user-manage { - background: url(../img/user_manage.png) no-repeat; +.list-group-item .icon-plus-orange { + background: url(../img/add.png) no-repeat; } + .list-group-item .icon-text { background-size: 20px; background-position: 5% 50%; @@ -790,3 +792,11 @@ table th { background: #fff; } +.project-setting .panel-body { + padding-top: 35px +} + +.project-setting .panel-body .context { + padding-left: 30px; +} + diff --git a/apollo-portal/src/main/resources/static/views/common/nav.html b/apollo-portal/src/main/resources/static/views/common/nav.html index dd9019620e646b44724096b0a7dc4b111a32b505..5e30e7b4b7a332d588ba7c51e6ee1a7af1a5b057 100644 --- a/apollo-portal/src/main/resources/static/views/common/nav.html +++ b/apollo-portal/src/main/resources/static/views/common/nav.html @@ -22,14 +22,14 @@