Commit e90fd82a authored by 张乐's avatar 张乐 Committed by GitHub

Merge pull request #274 from nobodyiam/create-app-with-org

Create app with org
parents b1e05ca3 d584851e
package com.ctrip.framework.apollo.common.entity; package com.ctrip.framework.apollo.common.entity;
import com.ctrip.framework.apollo.common.entity.BaseEntity; import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Table; import javax.persistence.Table;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
@Entity @Entity
@Table(name = "App") @Table(name = "App")
@SQLDelete(sql = "Update App set isDeleted = 1 where id = ?") @SQLDelete(sql = "Update App set isDeleted = 1 where id = ?")
...@@ -21,6 +19,12 @@ public class App extends BaseEntity { ...@@ -21,6 +19,12 @@ public class App extends BaseEntity {
@Column(name = "AppId", nullable = false) @Column(name = "AppId", nullable = false)
private String appId; private String appId;
@Column(name = "OrgId", nullable = false)
private String orgId;
@Column(name = "OrgName", nullable = false)
private String orgName;
@Column(name = "OwnerName", nullable = false) @Column(name = "OwnerName", nullable = false)
private String ownerName; private String ownerName;
...@@ -35,6 +39,14 @@ public class App extends BaseEntity { ...@@ -35,6 +39,14 @@ public class App extends BaseEntity {
return name; return name;
} }
public String getOrgId() {
return orgId;
}
public String getOrgName() {
return orgName;
}
public String getOwnerEmail() { public String getOwnerEmail() {
return ownerEmail; return ownerEmail;
} }
...@@ -51,6 +63,14 @@ public class App extends BaseEntity { ...@@ -51,6 +63,14 @@ public class App extends BaseEntity {
this.name = name; this.name = name;
} }
public void setOrgId(String orgId) {
this.orgId = orgId;
}
public void setOrgName(String orgName) {
this.orgName = orgName;
}
public void setOwnerEmail(String ownerEmail) { public void setOwnerEmail(String ownerEmail) {
this.ownerEmail = ownerEmail; this.ownerEmail = ownerEmail;
} }
...@@ -60,7 +80,10 @@ public class App extends BaseEntity { ...@@ -60,7 +80,10 @@ public class App extends BaseEntity {
} }
public String toString() { public String toString() {
return toStringHelper().add("name", name).add("appId", appId).add("ownerName", ownerName) return toStringHelper().add("name", name).add("appId", appId)
.add("orgId", orgId)
.add("orgName", orgName)
.add("ownerName", ownerName)
.add("ownerEmail", ownerEmail).toString(); .add("ownerEmail", ownerEmail).toString();
} }
} }
...@@ -8,6 +8,10 @@ public class AppDTO extends BaseDTO{ ...@@ -8,6 +8,10 @@ public class AppDTO extends BaseDTO{
private String appId; private String appId;
private String orgId;
private String orgName;
private String ownerName; private String ownerName;
private String ownerEmail; private String ownerEmail;
...@@ -28,6 +32,14 @@ public class AppDTO extends BaseDTO{ ...@@ -28,6 +32,14 @@ public class AppDTO extends BaseDTO{
return name; return name;
} }
public String getOrgId() {
return orgId;
}
public String getOrgName() {
return orgName;
}
public String getOwnerEmail() { public String getOwnerEmail() {
return ownerEmail; return ownerEmail;
} }
...@@ -44,6 +56,14 @@ public class AppDTO extends BaseDTO{ ...@@ -44,6 +56,14 @@ public class AppDTO extends BaseDTO{
this.name = name; this.name = name;
} }
public void setOrgId(String orgId) {
this.orgId = orgId;
}
public void setOrgName(String orgName) {
this.orgName = orgName;
}
public void setOwnerEmail(String ownerEmail) { public void setOwnerEmail(String ownerEmail) {
this.ownerEmail = ownerEmail; this.ownerEmail = ownerEmail;
} }
......
package com.ctrip.framework.apollo.portal.controller; package com.ctrip.framework.apollo.portal.controller;
import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.common.http.MultiResponseEntity;
import com.ctrip.framework.apollo.common.http.RichResponseEntity;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.portal.PortalSettings;
import com.ctrip.framework.apollo.portal.entity.vo.EnvClusterInfo;
import com.ctrip.framework.apollo.portal.listener.AppCreationEvent;
import com.ctrip.framework.apollo.portal.service.AppService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
...@@ -12,15 +21,6 @@ import org.springframework.web.bind.annotation.RequestMethod; ...@@ -12,15 +21,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpClientErrorException;
import com.ctrip.framework.apollo.common.entity.App;
import com.ctrip.framework.apollo.common.http.MultiResponseEntity;
import com.ctrip.framework.apollo.common.http.RichResponseEntity;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.portal.PortalSettings;
import com.ctrip.framework.apollo.portal.entity.vo.EnvClusterInfo;
import com.ctrip.framework.apollo.portal.listener.AppCreationEvent;
import com.ctrip.framework.apollo.portal.service.AppService;
import java.util.List; import java.util.List;
import static com.ctrip.framework.apollo.portal.util.RequestPrecondition.checkArgument; import static com.ctrip.framework.apollo.portal.util.RequestPrecondition.checkArgument;
...@@ -53,8 +53,8 @@ public class AppController { ...@@ -53,8 +53,8 @@ public class AppController {
response.addResponseEntity(RichResponseEntity.ok(appService.createEnvNavNode(env, appId))); response.addResponseEntity(RichResponseEntity.ok(appService.createEnvNavNode(env, appId)));
} catch (Exception e) { } catch (Exception e) {
response.addResponseEntity(RichResponseEntity.error(HttpStatus.INTERNAL_SERVER_ERROR, response.addResponseEntity(RichResponseEntity.error(HttpStatus.INTERNAL_SERVER_ERROR,
"load env:" + env.name() + " cluster error." + e "load env:" + env.name() + " cluster error." + e
.getMessage())); .getMessage()));
} }
} }
return response; return response;
...@@ -68,7 +68,8 @@ public class AppController { ...@@ -68,7 +68,8 @@ public class AppController {
@RequestMapping(value = "", method = RequestMethod.POST) @RequestMapping(value = "", method = RequestMethod.POST)
public ResponseEntity<Void> create(@RequestBody App app) { public ResponseEntity<Void> create(@RequestBody App app) {
checkArgument(app.getName(), app.getAppId(), app.getOwnerEmail(), app.getOwnerName()); checkArgument(app.getName(), app.getAppId(), app.getOwnerEmail(), app.getOwnerName(),
app.getOrgId(), app.getOrgName());
appService.enrichUserInfo(app); appService.enrichUserInfo(app);
App createdApp = appService.createOrUpdateAppInLocal(app); App createdApp = appService.createOrUpdateAppInLocal(app);
...@@ -78,10 +79,12 @@ public class AppController { ...@@ -78,10 +79,12 @@ public class AppController {
return ResponseEntity.ok().build(); return ResponseEntity.ok().build();
} }
@RequestMapping(value = "/envs/{env}", method = RequestMethod.POST, consumes = {"application/json"}) @RequestMapping(value = "/envs/{env}", method = RequestMethod.POST, consumes = {
"application/json"})
public ResponseEntity<Void> create(@PathVariable String env, @RequestBody App app) { public ResponseEntity<Void> create(@PathVariable String env, @RequestBody App app) {
checkArgument(app.getName(), app.getAppId(), app.getOwnerEmail(), app.getOwnerName()); checkArgument(app.getName(), app.getAppId(), app.getOwnerEmail(), app.getOwnerName(),
app.getOrgId(), app.getOrgName());
appService.createApp(Env.valueOf(env), app); appService.createApp(Env.valueOf(env), app);
...@@ -107,8 +110,8 @@ public class AppController { ...@@ -107,8 +110,8 @@ public class AppController {
response.addResponseEntity(RichResponseEntity.ok(env)); response.addResponseEntity(RichResponseEntity.ok(env));
} else { } else {
response.addResponseEntity(RichResponseEntity.error(HttpStatus.INTERNAL_SERVER_ERROR, 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())); + e.getMessage()));
} }
} }
......
package com.ctrip.framework.apollo.portal.controller;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ctrip.framework.apollo.portal.entity.po.ServerConfig;
import com.ctrip.framework.apollo.portal.entity.vo.Organization;
import com.ctrip.framework.apollo.portal.repository.ServerConfigRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.lang.reflect.Type;
import java.util.List;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RestController
@RequestMapping("/organizations")
public class OrganizationController {
@Autowired
private ServerConfigRepository serverConfigRepository;
@Autowired
private Gson gson;
private Type responseType = new TypeToken<List<Organization>>() {
}.getType();
@RequestMapping
public List<Organization> loadOrganization() {
ServerConfig config = serverConfigRepository.findByKey("organizations");
return gson.fromJson(config.getValue(), responseType);
}
}
package com.ctrip.framework.apollo.portal.entity.vo;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class Organization {
private String orgId;
private String orgName;
public String getOrgId() {
return orgId;
}
public void setOrgId(String orgId) {
this.orgId = orgId;
}
public String getOrgName() {
return orgName;
}
public void setOrgName(String orgName) {
this.orgName = orgName;
}
}
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
<!-- styles --> <!-- styles -->
<link rel="stylesheet" type="text/css" href="vendor/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="vendor/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="vendor/angular/angular-toastr-1.4.1.min.css"> <link rel="stylesheet" type="text/css" href="vendor/angular/angular-toastr-1.4.1.min.css">
<link rel="stylesheet" type="text/css" href="vendor/select2/select2.min.css">
<link rel="stylesheet" type="text/css" media='all' href="vendor/angular/loading-bar.min.css"> <link rel="stylesheet" type="text/css" media='all' href="vendor/angular/loading-bar.min.css">
<link rel="stylesheet" type="text/css" href="styles/common-style.css"> <link rel="stylesheet" type="text/css" href="styles/common-style.css">
<title>新建项目</title> <title>新建项目</title>
...@@ -25,7 +26,13 @@ ...@@ -25,7 +26,13 @@
<div class="panel-body"> <div class="panel-body">
<form class="form-horizontal" ng-controller="CreateAppController" ng-submit="create()"> <form class="form-horizontal" ng-controller="CreateAppController" ng-submit="create()">
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled> 应用ID</label> <label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled> 部门</label>
<div class="col-sm-3">
<select id="organization"><option></option></select>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled> 应用AppId</label>
<div class="col-sm-3"> <div class="col-sm-3">
<input type="text" class="form-control" name="appAppId" ng-model="app.appId" <input type="text" class="form-control" name="appAppId" ng-model="app.appId"
required> required>
...@@ -38,13 +45,13 @@ ...@@ -38,13 +45,13 @@
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled>应用Owner</label> <label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled> 应用负责人</label>
<div class="col-sm-3"> <div class="col-sm-3">
<input type="text" class="form-control" name="appOwner" ng-model="app.ownerName" required> <input type="text" class="form-control" name="appOwner" ng-model="app.ownerName" required>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled>邮箱地址</label> <label class="col-sm-2 control-label"><apollorequiredfiled></apollorequiredfiled> 邮箱地址</label>
<div class="col-sm-4"> <div class="col-sm-4">
<input type="email" class="form-control" ng-model="app.ownerEmail" required> <input type="email" class="form-control" ng-model="app.ownerEmail" required>
</div> </div>
...@@ -74,6 +81,7 @@ ...@@ -74,6 +81,7 @@
<!-- jquery.js --> <!-- jquery.js -->
<script src="vendor/jquery.min.js" type="text/javascript"></script> <script src="vendor/jquery.min.js" type="text/javascript"></script>
<script src="vendor/select2/select2.min.js" type="text/javascript"></script>
<!-- bootstrap.js --> <!-- bootstrap.js -->
<script src="vendor/bootstrap/js/bootstrap.min.js" type="text/javascript"></script> <script src="vendor/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
...@@ -83,6 +91,7 @@ ...@@ -83,6 +91,7 @@
<script type="application/javascript" src="scripts/services/EnvService.js"></script> <script type="application/javascript" src="scripts/services/EnvService.js"></script>
<script type="application/javascript" src="scripts/services/UserService.js"></script> <script type="application/javascript" src="scripts/services/UserService.js"></script>
<script type="application/javascript" src="scripts/AppUtils.js"></script> <script type="application/javascript" src="scripts/AppUtils.js"></script>
<script type="application/javascript" src="scripts/services/OrganizationService.js"></script>
<script type="application/javascript" src="scripts/directive.js"></script> <script type="application/javascript" src="scripts/directive.js"></script>
<script type="application/javascript" src="scripts/controller/CreateAppController.js"></script> <script type="application/javascript" src="scripts/controller/CreateAppController.js"></script>
......
...@@ -61,9 +61,7 @@ ...@@ -61,9 +61,7 @@
<div class="form-group" ng-show="type == 'link'"> <div class="form-group" ng-show="type == 'link'">
<label class="col-sm-3 control-label"><font style="color: red">*</font>namespace</label> <label class="col-sm-3 control-label"><font style="color: red">*</font>namespace</label>
<div class="col-sm-4"> <div class="col-sm-4">
<select id="namespaces"> <select id="namespaces"><option></option></select>
</select>
</div> </div>
</div> </div>
......
create_app_module.controller('CreateAppController', ['$scope', '$window', 'toastr', 'AppService', 'AppUtil', create_app_module.controller('CreateAppController', ['$scope', '$window', 'toastr', 'AppService', 'AppUtil', 'OrganizationService',
function ($scope, $window, toastr, AppService, AppUtil) { function ($scope, $window, toastr, AppService, AppUtil, OrganizationService) {
OrganizationService.find_organizations().then(function (result) {
var organizations = [];
result.forEach(function (item) {
var org = {};
org.id = item.orgId;
org.text = item.orgName + '(' + item.orgId + ')';
organizations.push(org);
});
$('#organization').select2({
placeholder: '请选择部门',
width: '100%',
data: organizations
});
}, function (result) {
toastr.error(AppUtil.errorMsg(result), "load organizations error");
});
$scope.create = function () { $scope.create = function () {
var selectedOrg = $('#organization').select2('data')[0];
if (!selectedOrg.id) {
toastr.warning("请选择部门");
return;
}
$scope.app.orgId = selectedOrg.id;
$scope.app.orgName = selectedOrg.text;
AppService.create($scope.app).then(function (result) { AppService.create($scope.app).then(function (result) {
toastr.success('添加成功!'); toastr.success('添加成功!');
setInterval(function () { setInterval(function () {
......
...@@ -17,9 +17,10 @@ namespace_module.controller("LinkNamespaceController", ...@@ -17,9 +17,10 @@ namespace_module.controller("LinkNamespaceController",
publicNamespaces.push(namespace); publicNamespaces.push(namespace);
}); });
$('#namespaces').select2({ $('#namespaces').select2({
width: '250px', placeholder: '请选择Namespace',
data: publicNamespaces width: '100%',
}); data: publicNamespaces
});
}, function (result) { }, function (result) {
toastr.error(AppUtil.errorMsg(result), "load public namespace error"); toastr.error(AppUtil.errorMsg(result), "load public namespace error");
}); });
...@@ -42,7 +43,13 @@ namespace_module.controller("LinkNamespaceController", ...@@ -42,7 +43,13 @@ namespace_module.controller("LinkNamespaceController",
} }
if ($scope.namespaceType == 1){ if ($scope.namespaceType == 1){
$scope.namespaceName = $('#namespaces').select2('data')[0].id; var selectedNamespaceName = $('#namespaces').select2('data')[0].id;
if (!selectedNamespaceName) {
toastr.warning("请选择Namespace");
return;
}
$scope.namespaceName = selectedNamespaceName;
} }
var namespaceCreationModels = []; var namespaceCreationModels = [];
......
appService.service("OrganizationService", ['$resource', '$q', function ($resource, $q) {
var organization_source = $resource("", {}, {
find_organizations: {
method: 'GET',
isArray: true,
url: '/organizations'
}
});
return {
find_organizations: function () {
var d = $q.defer();
organization_source.find_organizations({}, function (result) {
d.resolve(result);
}, function (result) {
d.reject(result);
});
return d.promise;
}
}
}]);
...@@ -79,6 +79,8 @@ public class ServiceExceptionTest extends AbstractPortalTest { ...@@ -79,6 +79,8 @@ public class ServiceExceptionTest extends AbstractPortalTest {
App app = new App(); App app = new App();
app.setAppId("someAppId"); app.setAppId("someAppId");
app.setName("someName"); app.setName("someName");
app.setOrgId("someOrgId");
app.setOrgName("someOrgNam");
app.setOwnerName("someOwner"); app.setOwnerName("someOwner");
app.setOwnerEmail("someOwner@ctrip.com"); app.setOwnerEmail("someOwner@ctrip.com");
return app; return app;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment