Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wrr-cat
apollo
提交
8720978c
apollo
项目概览
wrr-cat
/
apollo
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
apollo
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
8720978c
编写于
4月 14, 2016
作者:
L
lepdou
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
create app & release config
上级
f7191bfa
变更
26
隐藏空白更改
内联
并排
Showing
26 changed file
with
799 addition
and
265 deletion
+799
-265
apollo-adminservice/src/main/java/com/ctrip/apollo/adminservice/controller/AppController.java
...m/ctrip/apollo/adminservice/controller/AppController.java
+5
-2
apollo-biz/src/main/java/com/ctrip/apollo/biz/service/AdminService.java
.../main/java/com/ctrip/apollo/biz/service/AdminService.java
+40
-17
apollo-biz/src/main/java/com/ctrip/apollo/biz/service/ItemSetService.java
...ain/java/com/ctrip/apollo/biz/service/ItemSetService.java
+1
-0
apollo-biz/src/main/java/com/ctrip/apollo/biz/service/ReleaseService.java
...ain/java/com/ctrip/apollo/biz/service/ReleaseService.java
+4
-0
apollo-biz/src/test/java/com/ctrip/apollo/biz/service/AdminServiceTest.java
...t/java/com/ctrip/apollo/biz/service/AdminServiceTest.java
+13
-7
apollo-biz/src/test/java/com/ctrip/apollo/biz/service/PrivilegeServiceTest.java
...va/com/ctrip/apollo/biz/service/PrivilegeServiceTest.java
+21
-9
apollo-core/src/main/java/com/ctrip/apollo/core/dto/AppDTO.java
...-core/src/main/java/com/ctrip/apollo/core/dto/AppDTO.java
+32
-0
apollo-core/src/main/java/com/ctrip/apollo/core/dto/ItemDTO.java
...core/src/main/java/com/ctrip/apollo/core/dto/ItemDTO.java
+22
-1
apollo-portal/src/main/java/com/ctrip/apollo/portal/api/AdminServiceAPI.java
...ain/java/com/ctrip/apollo/portal/api/AdminServiceAPI.java
+40
-11
apollo-portal/src/main/java/com/ctrip/apollo/portal/controller/AppController.java
...ava/com/ctrip/apollo/portal/controller/AppController.java
+23
-0
apollo-portal/src/main/java/com/ctrip/apollo/portal/controller/ConfigController.java
.../com/ctrip/apollo/portal/controller/ConfigController.java
+43
-7
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/form/FormModel.java
...n/java/com/ctrip/apollo/portal/entity/form/FormModel.java
+7
-0
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/form/NamespaceModifyModel.java
...ctrip/apollo/portal/entity/form/NamespaceModifyModel.java
+76
-0
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/form/NamespaceReleaseModel.java
...trip/apollo/portal/entity/form/NamespaceReleaseModel.java
+69
-0
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/AppService.java
...main/java/com/ctrip/apollo/portal/service/AppService.java
+26
-6
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/ConfigService.java
...n/java/com/ctrip/apollo/portal/service/ConfigService.java
+72
-35
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/txtresolver/ConfigTextResolver.java
...apollo/portal/service/txtresolver/ConfigTextResolver.java
+2
-2
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/txtresolver/PropertyResolver.java
...p/apollo/portal/service/txtresolver/PropertyResolver.java
+58
-23
apollo-portal/src/main/resources/application.yml
apollo-portal/src/main/resources/application.yml
+1
-1
apollo-portal/src/main/resources/static/img/icon.jpg
apollo-portal/src/main/resources/static/img/icon.jpg
+0
-0
apollo-portal/src/main/resources/static/scripts/controller/CreateAppController.js
...esources/static/scripts/controller/CreateAppController.js
+7
-4
apollo-portal/src/main/resources/static/scripts/controller/app/AppConfigController.js
...rces/static/scripts/controller/app/AppConfigController.js
+111
-56
apollo-portal/src/main/resources/static/scripts/services/ConfigService.js
...c/main/resources/static/scripts/services/ConfigService.js
+33
-10
apollo-portal/src/main/resources/static/styles/common-style.css
...-portal/src/main/resources/static/styles/common-style.css
+9
-5
apollo-portal/src/main/resources/static/views/app.html
apollo-portal/src/main/resources/static/views/app.html
+82
-60
apollo-portal/src/main/resources/static/views/create-app.html
...lo-portal/src/main/resources/static/views/create-app.html
+2
-9
未找到文件。
apollo-adminservice/src/main/java/com/ctrip/apollo/adminservice/controller/AppController.java
浏览文件 @
8720978c
...
...
@@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import
org.springframework.web.bind.annotation.RestController
;
import
com.ctrip.apollo.biz.entity.App
;
import
com.ctrip.apollo.biz.service.AdminService
;
import
com.ctrip.apollo.biz.service.AppService
;
import
com.ctrip.apollo.biz.utils.BeanUtils
;
import
com.ctrip.apollo.core.dto.AppDTO
;
...
...
@@ -25,11 +26,13 @@ public class AppController {
@Autowired
private
AppService
appService
;
@Autowired
private
AdminService
adminService
;
@RequestMapping
(
path
=
"/apps
/
"
,
method
=
RequestMethod
.
POST
)
@RequestMapping
(
path
=
"/apps"
,
method
=
RequestMethod
.
POST
)
public
ResponseEntity
<
AppDTO
>
create
(
@RequestBody
AppDTO
dto
)
{
App
entity
=
BeanUtils
.
transfrom
(
App
.
class
,
dto
);
entity
=
a
ppService
.
save
(
entity
);
entity
=
a
dminService
.
createNewApp
(
entity
);
dto
=
BeanUtils
.
transfrom
(
AppDTO
.
class
,
entity
);
return
ResponseEntity
.
status
(
HttpStatus
.
CREATED
).
body
(
dto
);
}
...
...
apollo-biz/src/main/java/com/ctrip/apollo/biz/service/AdminService.java
浏览文件 @
8720978c
package
com.ctrip.apollo.biz.service
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.actuate.metrics.CounterService
;
import
org.springframework.stereotype.Service
;
import
org.springframework.boot.actuate.metrics.CounterService
;
import
com.ctrip.apollo.biz.entity.App
;
import
com.ctrip.apollo.biz.entity.AppNamespace
;
import
com.ctrip.apollo.biz.entity.Cluster
;
...
...
@@ -12,6 +12,9 @@ import com.ctrip.apollo.biz.repository.AppNamespaceRepository;
import
com.ctrip.apollo.biz.repository.AppRepository
;
import
com.ctrip.apollo.biz.repository.ClusterRepository
;
import
com.ctrip.apollo.biz.repository.NamespaceRepository
;
import
com.ctrip.apollo.core.ConfigConsts
;
import
java.util.Date
;
@Service
public
class
AdminService
{
...
...
@@ -27,36 +30,56 @@ public class AdminService {
@Autowired
private
ClusterRepository
clusterRepository
;
@Autowired
private
CounterService
counter
;
public
App
createNewApp
(
String
appId
,
String
appName
,
String
ownerName
,
String
ownerEmail
,
String
namespace
)
{
public
App
createNewApp
(
App
app
)
{
counter
.
increment
(
"admin.createNewApp.start"
);
App
app
=
new
App
();
app
.
setAppId
(
appId
);
app
.
setName
(
appName
);
app
.
setOwnerName
(
ownerName
);
app
.
setOwnerEmail
(
ownerEmail
);
appRepository
.
save
(
app
);
String
createBy
=
app
.
getDataChangeCreatedBy
();
App
createdApp
=
appRepository
.
save
(
app
);
String
appId
=
createdApp
.
getAppId
();
createDefaultAppNamespace
(
appId
,
createBy
);
createDefaultCluster
(
appId
,
createBy
);
createDefaultNamespace
(
appId
,
createBy
);
counter
.
increment
(
"admin.createNewApp.success"
);
return
app
;
}
private
void
createDefaultAppNamespace
(
String
appId
,
String
createBy
){
AppNamespace
appNs
=
new
AppNamespace
();
appNs
.
setAppId
(
appId
);
appNs
.
setName
(
namespace
);
appNs
.
setName
(
ConfigConsts
.
NAMESPACE_APPLICATION
);
appNs
.
setComment
(
"default app namespace"
);
appNs
.
setDataChangeCreatedBy
(
createBy
);
appNs
.
setDataChangeCreatedTime
(
new
Date
());
appNs
.
setDataChangeLastModifiedBy
(
createBy
);
appNamespaceRepository
.
save
(
appNs
);
}
private
void
createDefaultCluster
(
String
appId
,
String
createBy
){
Cluster
cluster
=
new
Cluster
();
cluster
.
setName
(
"default"
);
cluster
.
setName
(
ConfigConsts
.
CLUSTER_NAME_DEFAULT
);
cluster
.
setAppId
(
appId
);
cluster
.
setDataChangeCreatedBy
(
createBy
);
cluster
.
setDataChangeCreatedTime
(
new
Date
());
cluster
.
setDataChangeLastModifiedBy
(
createBy
);
clusterRepository
.
save
(
cluster
);
}
private
void
createDefaultNamespace
(
String
appId
,
String
createBy
){
Namespace
ns
=
new
Namespace
();
ns
.
setAppId
(
appId
);
ns
.
setClusterName
(
cluster
.
getName
());
ns
.
setNamespaceName
(
namespace
);
ns
.
setClusterName
(
ConfigConsts
.
CLUSTER_NAME_DEFAULT
);
ns
.
setNamespaceName
(
ConfigConsts
.
NAMESPACE_APPLICATION
);
ns
.
setDataChangeCreatedBy
(
createBy
);
ns
.
setDataChangeCreatedTime
(
new
Date
());
ns
.
setDataChangeLastModifiedBy
(
createBy
);
namespaceRepository
.
save
(
ns
);
counter
.
increment
(
"admin.createNewApp.success"
);
return
app
;
}
}
apollo-biz/src/main/java/com/ctrip/apollo/biz/service/ItemSetService.java
浏览文件 @
8720978c
...
...
@@ -20,6 +20,7 @@ public class ItemSetService {
for
(
ItemDTO
item
:
changeSet
.
getCreateItems
())
{
Item
entity
=
BeanUtils
.
transfrom
(
Item
.
class
,
item
);
entity
.
setDataChangeCreatedBy
(
changeSet
.
getModifyBy
());
entity
.
setDataChangeLastModifiedBy
(
changeSet
.
getModifyBy
());
itemRepository
.
save
(
entity
);
}
}
...
...
apollo-biz/src/main/java/com/ctrip/apollo/biz/service/ReleaseService.java
浏览文件 @
8720978c
package
com.ctrip.apollo.biz.service
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
...
...
@@ -53,6 +54,9 @@ public class ReleaseService {
}
Release
release
=
new
Release
();
release
.
setDataChangeCreatedTime
(
new
Date
());
release
.
setDataChangeCreatedBy
(
name
);
release
.
setDataChangeLastModifiedBy
(
name
);
release
.
setName
(
name
);
release
.
setComment
(
comment
);
release
.
setAppId
(
appId
);
...
...
apollo-biz/src/test/java/com/ctrip/apollo/biz/service/AdminServiceTest.java
浏览文件 @
8720978c
package
com.ctrip.apollo.biz.service
;
import
java.util.Date
;
import
java.util.List
;
import
org.junit.Assert
;
...
...
@@ -27,12 +28,17 @@ public class AdminServiceTest {
@Test
public
void
testCreateNewApp
()
{
String
appId
=
"someAppId"
;
String
appName
=
"someAppName"
;
String
ownerName
=
"someOwnerName"
;
String
ownerEmail
=
"someOwnerName@ctrip.com"
;
String
namespace
=
"someNamespace"
;
App
app
=
adminService
.
createNewApp
(
appId
,
appName
,
ownerName
,
ownerEmail
,
namespace
);
App
app
=
new
App
();
app
.
setAppId
(
appId
);
app
.
setName
(
"someAppName"
);
String
owner
=
"someOwnerName"
;
app
.
setOwnerName
(
owner
);
app
.
setOwnerEmail
(
"someOwnerName@ctrip.com"
);
app
.
setDataChangeCreatedBy
(
owner
);
app
.
setDataChangeLastModifiedBy
(
owner
);
app
.
setDataChangeCreatedTime
(
new
Date
());
app
=
adminService
.
createNewApp
(
app
);
Assert
.
assertEquals
(
appId
,
app
.
getAppId
());
List
<
Cluster
>
clusters
=
viewService
.
findClusters
(
app
.
getAppId
());
...
...
@@ -41,6 +47,6 @@ public class AdminServiceTest {
List
<
Namespace
>
namespaces
=
viewService
.
findNamespaces
(
appId
,
clusters
.
get
(
0
).
getName
());
Assert
.
assertEquals
(
1
,
namespaces
.
size
());
Assert
.
assertEquals
(
namespace
,
namespaces
.
get
(
0
).
getNamespaceName
());
Assert
.
assertEquals
(
"application"
,
namespaces
.
get
(
0
).
getNamespaceName
());
}
}
apollo-biz/src/test/java/com/ctrip/apollo/biz/service/PrivilegeServiceTest.java
浏览文件 @
8720978c
package
com.ctrip.apollo.biz.service
;
import
java.util.Date
;
import
java.util.List
;
import
org.junit.Assert
;
...
...
@@ -30,10 +31,16 @@ public class PrivilegeServiceTest {
@Test
public
void
testAddAndRemovePrivilege
()
{
App
newApp
=
adminService
.
createNewApp
(
String
.
valueOf
(
System
.
currentTimeMillis
()),
"new app "
+
System
.
currentTimeMillis
(),
"owner "
+
System
.
currentTimeMillis
(),
"owner "
+
System
.
currentTimeMillis
()
+
"@ctrip.com"
,
"namespace "
+
System
.
currentTimeMillis
());
App
app
=
new
App
();
app
.
setAppId
(
String
.
valueOf
(
System
.
currentTimeMillis
()));
app
.
setName
(
"new app "
+
System
.
currentTimeMillis
());
String
owner
=
"owner "
+
System
.
currentTimeMillis
();
app
.
setOwnerName
(
owner
);
app
.
setOwnerEmail
(
"owner "
+
System
.
currentTimeMillis
()
+
"@ctrip.com"
);
app
.
setDataChangeCreatedBy
(
owner
);
app
.
setDataChangeLastModifiedBy
(
owner
);
app
.
setDataChangeCreatedTime
(
new
Date
());
App
newApp
=
adminService
.
createNewApp
(
app
);
List
<
Cluster
>
clusters
=
viewService
.
findClusters
(
newApp
.
getAppId
());
List
<
Namespace
>
namespaces
=
...
...
@@ -55,11 +62,16 @@ public class PrivilegeServiceTest {
@Test
public
void
testCheckPrivilege
()
{
App
newApp
=
adminService
.
createNewApp
(
String
.
valueOf
(
System
.
currentTimeMillis
()),
"new app "
+
System
.
currentTimeMillis
(),
"owner "
+
System
.
currentTimeMillis
(),
"owner "
+
System
.
currentTimeMillis
()
+
"@ctrip.com"
,
"namespace "
+
System
.
currentTimeMillis
());
App
app
=
new
App
();
app
.
setAppId
(
String
.
valueOf
(
System
.
currentTimeMillis
()));
app
.
setName
(
"new app "
+
System
.
currentTimeMillis
());
String
owner
=
"owner "
+
System
.
currentTimeMillis
();
app
.
setOwnerName
(
owner
);
app
.
setOwnerEmail
(
"owner "
+
System
.
currentTimeMillis
()
+
"@ctrip.com"
);
app
.
setDataChangeCreatedBy
(
owner
);
app
.
setDataChangeLastModifiedBy
(
owner
);
app
.
setDataChangeCreatedTime
(
new
Date
());
App
newApp
=
adminService
.
createNewApp
(
app
);
List
<
Cluster
>
clusters
=
viewService
.
findClusters
(
newApp
.
getAppId
());
List
<
Namespace
>
namespaces
=
viewService
.
findNamespaces
(
newApp
.
getAppId
(),
clusters
.
get
(
0
).
getName
());
...
...
apollo-core/src/main/java/com/ctrip/apollo/core/dto/AppDTO.java
浏览文件 @
8720978c
package
com.ctrip.apollo.core.dto
;
import
java.util.Date
;
public
class
AppDTO
{
private
long
id
;
...
...
@@ -12,6 +14,12 @@ public class AppDTO {
private
String
ownerEmail
;
private
String
dataChangeCreatedBy
;
private
Date
dataChangeCreatedTime
;
private
String
dataChangeLastModifiedBy
;
public
String
getAppId
()
{
return
appId
;
}
...
...
@@ -51,4 +59,28 @@ public class AppDTO {
public
void
setOwnerName
(
String
ownerName
)
{
this
.
ownerName
=
ownerName
;
}
public
String
getDataChangeCreatedBy
()
{
return
dataChangeCreatedBy
;
}
public
void
setDataChangeCreatedBy
(
String
dataChangeCreatedBy
)
{
this
.
dataChangeCreatedBy
=
dataChangeCreatedBy
;
}
public
Date
getDataChangeCreatedTime
()
{
return
dataChangeCreatedTime
;
}
public
void
setDataChangeCreatedTime
(
Date
dataChangeCreatedTime
)
{
this
.
dataChangeCreatedTime
=
dataChangeCreatedTime
;
}
public
String
getDataChangeLastModifiedBy
()
{
return
dataChangeLastModifiedBy
;
}
public
void
setDataChangeLastModifiedBy
(
String
dataChangeLastModifiedBy
)
{
this
.
dataChangeLastModifiedBy
=
dataChangeLastModifiedBy
;
}
}
apollo-core/src/main/java/com/ctrip/apollo/core/dto/ItemDTO.java
浏览文件 @
8720978c
...
...
@@ -16,6 +16,10 @@ public class ItemDTO{
private
int
lineNum
;
private
String
dataChangeCreatedBy
;
private
Date
dataChangeCreatedTime
;
private
String
dataChangeLastModifiedBy
;
private
Date
dataChangeLastModifiedTime
;
...
...
@@ -93,6 +97,22 @@ public class ItemDTO{
this
.
dataChangeLastModifiedTime
=
dataChangeLastModifiedTime
;
}
public
String
getDataChangeCreatedBy
()
{
return
dataChangeCreatedBy
;
}
public
void
setDataChangeCreatedBy
(
String
dataChangeCreatedBy
)
{
this
.
dataChangeCreatedBy
=
dataChangeCreatedBy
;
}
public
Date
getDataChangeCreatedTime
()
{
return
dataChangeCreatedTime
;
}
public
void
setDataChangeCreatedTime
(
Date
dataChangeCreatedTime
)
{
this
.
dataChangeCreatedTime
=
dataChangeCreatedTime
;
}
@Override
public
String
toString
()
{
return
"ItemDTO{"
+
...
...
@@ -102,9 +122,10 @@ public class ItemDTO{
", value='"
+
value
+
'\''
+
", comment='"
+
comment
+
'\''
+
", lineNum="
+
lineNum
+
", dataChangeCreatedBy='"
+
dataChangeCreatedBy
+
'\''
+
", dataChangeCreatedTime="
+
dataChangeCreatedTime
+
", dataChangeLastModifiedBy='"
+
dataChangeLastModifiedBy
+
'\''
+
", dataChangeLastModifiedTime="
+
dataChangeLastModifiedTime
+
'}'
;
}
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/api/AdminServiceAPI.java
浏览文件 @
8720978c
...
...
@@ -12,9 +12,13 @@ import com.ctrip.apollo.core.utils.StringUtils;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.LinkedMultiValueMap
;
import
org.springframework.util.MultiValueMap
;
import
org.springframework.web.client.HttpClientErrorException
;
import
org.springframework.web.client.HttpServerErrorException
;
import
java.util.Arrays
;
import
java.util.List
;
...
...
@@ -22,6 +26,7 @@ import java.util.List;
@Service
public
class
AdminServiceAPI
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
AdminServiceAPI
.
class
);
@Service
...
...
@@ -32,6 +37,10 @@ public class AdminServiceAPI {
public
List
<
AppDTO
>
getApps
(
Apollo
.
Env
env
)
{
return
Arrays
.
asList
(
restTemplate
.
getForObject
(
getAdminServiceHost
(
env
)
+
APP_API
,
AppDTO
[].
class
));
}
public
AppDTO
save
(
Apollo
.
Env
env
,
AppDTO
app
)
{
return
restTemplate
.
postForEntity
(
getAdminServiceHost
(
env
)
+
APP_API
,
app
,
AppDTO
.
class
).
getBody
();
}
}
...
...
@@ -76,11 +85,12 @@ public class AdminServiceAPI {
public
void
updateItems
(
String
appId
,
Apollo
.
Env
env
,
String
clusterName
,
String
namespace
,
ItemChangeSets
changeSets
)
{
if
(
StringUtils
.
isContainEmpty
(
appId
,
clusterName
,
namespace
)){
if
(
StringUtils
.
isContainEmpty
(
appId
,
clusterName
,
namespace
))
{
return
;
}
restTemplate
.
postForEntity
(
getAdminServiceHost
(
env
)
+
String
.
format
(
"apps/%s/clusters/%s/namespaces/%s/itemset"
,
appId
,
clusterName
,
namespace
),
changeSets
,
Void
.
class
);
appId
,
clusterName
,
namespace
),
changeSets
,
Void
.
class
);
}
...
...
@@ -107,14 +117,33 @@ public class AdminServiceAPI {
if
(
StringUtils
.
isContainEmpty
(
appId
,
clusterName
,
namespace
))
{
return
null
;
}
try
{
ReleaseDTO
releaseDTO
=
restTemplate
.
getForObject
(
getAdminServiceHost
(
env
)
+
String
.
format
(
"apps/%s/clusters/%s/namespaces/%s/releases/latest"
,
appId
,
clusterName
,
namespace
),
ReleaseDTO
.
class
);
return
releaseDTO
;
}
catch
(
HttpClientErrorException
e
){
logger
.
warn
(
" call [ReleaseAPI.loadLatestRelease] and return not fount exception.app id:{}, env:{}, clusterName:{}, namespace:{}"
,
appId
,
env
,
clusterName
,
namespace
);
try
{
ReleaseDTO
releaseDTO
=
restTemplate
.
getForObject
(
getAdminServiceHost
(
env
)
+
String
.
format
(
"apps/%s/clusters/%s/namespaces/%s/releases/latest"
,
appId
,
clusterName
,
namespace
),
ReleaseDTO
.
class
);
return
releaseDTO
;
}
catch
(
HttpClientErrorException
e
)
{
logger
.
warn
(
" call [ReleaseAPI.loadLatestRelease] and return not fount exception.app id:{}, env:{}, clusterName:{}, namespace:{}"
,
appId
,
env
,
clusterName
,
namespace
);
return
null
;
}
}
public
ReleaseDTO
release
(
String
appId
,
Apollo
.
Env
env
,
String
clusterName
,
String
namespace
,
String
releaseBy
,
String
comment
)
{
MultiValueMap
<
String
,
String
>
parameters
=
new
LinkedMultiValueMap
<
String
,
String
>();
parameters
.
add
(
"name"
,
releaseBy
);
parameters
.
add
(
"comment"
,
comment
);
HttpEntity
<
MultiValueMap
<
String
,
String
>>
entity
=
new
HttpEntity
<
MultiValueMap
<
String
,
String
>>(
parameters
,
null
);
ResponseEntity
<
ReleaseDTO
>
response
=
restTemplate
.
postForEntity
(
getAdminServiceHost
(
env
)
+
String
.
format
(
"apps/%s/clusters/%s/namespaces/%s/releases"
,
appId
,
clusterName
,
namespace
),
entity
,
ReleaseDTO
.
class
);
if
(
response
.
getStatusCode
()
==
HttpStatus
.
OK
){
return
response
.
getBody
();
}
else
{
logger
.
error
(
"release fail.id:{}, env:{}, clusterName:{}, namespace:{},releaseBy{}"
,
appId
,
env
,
clusterName
,
namespace
,
releaseBy
);
return
null
;
}
}
...
...
apollo-portal/src/main/java/com/ctrip/apollo/portal/controller/AppController.java
浏览文件 @
8720978c
...
...
@@ -2,12 +2,18 @@ package com.ctrip.apollo.portal.controller;
import
com.google.common.base.Strings
;
import
com.ctrip.apollo.core.dto.AppDTO
;
import
com.ctrip.apollo.core.utils.StringUtils
;
import
com.ctrip.apollo.portal.entity.ClusterNavTree
;
import
com.ctrip.apollo.portal.service.AppService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.RestController
;
@RestController
...
...
@@ -26,6 +32,23 @@ public class AppController {
return
appService
.
buildClusterNavTree
(
appId
);
}
@RequestMapping
(
value
=
""
,
method
=
RequestMethod
.
POST
,
consumes
=
{
"application/json"
})
public
ResponseEntity
<
AppDTO
>
create
(
@RequestBody
AppDTO
app
)
{
if
(
isInvalidApp
(
app
)){
return
ResponseEntity
.
badRequest
().
body
(
null
);
}
AppDTO
createdApp
=
appService
.
save
(
app
);
if
(
createdApp
!=
null
){
return
ResponseEntity
.
ok
().
body
(
createdApp
);
}
else
{
return
ResponseEntity
.
status
(
HttpStatus
.
INTERNAL_SERVER_ERROR
).
body
(
null
);
}
}
private
boolean
isInvalidApp
(
AppDTO
app
)
{
return
StringUtils
.
isContainEmpty
(
app
.
getName
(),
app
.
getAppId
(),
app
.
getOwnerEmail
(),
app
.
getOwnerName
());
}
}
...
...
apollo-portal/src/main/java/com/ctrip/apollo/portal/controller/ConfigController.java
浏览文件 @
8720978c
...
...
@@ -2,15 +2,20 @@ package com.ctrip.apollo.portal.controller;
import
com.ctrip.apollo.Apollo
;
import
com.ctrip.apollo.core.dto.ReleaseDTO
;
import
com.ctrip.apollo.core.utils.StringUtils
;
import
com.ctrip.apollo.portal.entity.form.NamespaceModifyModel
;
import
com.ctrip.apollo.portal.entity.NamespaceVO
;
import
com.ctrip.apollo.portal.entity.SimpleMsg
;
import
com.ctrip.apollo.portal.entity.form.NamespaceReleaseModel
;
import
com.ctrip.apollo.portal.service.ConfigService
;
import
com.ctrip.apollo.portal.service.txtresolver.TextResolverResult
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.RestController
;
...
...
@@ -34,13 +39,22 @@ public class ConfigController {
return
configService
.
findNampspaces
(
appId
,
Apollo
.
Env
.
valueOf
(
env
),
clusterName
);
}
@RequestMapping
(
value
=
"/apps/{appId}/env/{env}/clusters/{clusterName}/namespaces/{namespaceName}/modify"
,
method
=
RequestMethod
.
GET
)
public
ResponseEntity
<
SimpleMsg
>
modifyConfigs
(
@PathVariable
String
appId
,
@PathVariable
String
env
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespaceName
,
String
configText
)
{
TextResolverResult
result
=
configService
.
resolve
(
appId
,
Apollo
.
Env
.
valueOf
(
env
),
clusterName
,
namespaceName
,
configText
);
@RequestMapping
(
value
=
"/apps/{appId}/env/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items"
,
method
=
RequestMethod
.
PUT
,
consumes
=
{
"application/json"
})
public
ResponseEntity
<
SimpleMsg
>
modifyItems
(
@PathVariable
String
appId
,
@PathVariable
String
env
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespaceName
,
@RequestBody
NamespaceModifyModel
model
)
{
model
.
setAppId
(
appId
);
model
.
setClusterName
(
clusterName
);
model
.
setEnv
(
env
);
model
.
setNamespaceName
(
namespaceName
);
if
(
model
==
null
||
model
.
isInvalid
()){
return
ResponseEntity
.
badRequest
().
body
(
new
SimpleMsg
(
"form data exception."
));
}
TextResolverResult
result
=
configService
.
resolveConfigText
(
model
);
if
(
result
.
isResolveSuccess
())
{
return
ResponseEntity
.
ok
().
body
(
new
SimpleMsg
(
"success"
));
}
else
{
...
...
@@ -48,4 +62,26 @@ public class ConfigController {
}
}
@RequestMapping
(
value
=
"/apps/{appId}/env/{env}/clusters/{clusterName}/namespaces/{namespaceName}/release"
,
method
=
RequestMethod
.
POST
,
consumes
=
{
"application/json"
})
public
ResponseEntity
<
SimpleMsg
>
createRelease
(
@PathVariable
String
appId
,
@PathVariable
String
env
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespaceName
,
@RequestBody
NamespaceReleaseModel
model
){
model
.
setAppId
(
appId
);
model
.
setClusterName
(
clusterName
);
model
.
setEnv
(
env
);
model
.
setNamespaceName
(
namespaceName
);
if
(
model
==
null
||
model
.
isInvalid
()){
return
ResponseEntity
.
badRequest
().
body
(
new
SimpleMsg
(
"form data exception."
));
}
ReleaseDTO
release
=
configService
.
release
(
model
);
if
(
release
==
null
){
return
ResponseEntity
.
status
(
HttpStatus
.
INTERNAL_SERVER_ERROR
).
body
(
new
SimpleMsg
(
"oops! some error in server."
));
}
else
{
return
ResponseEntity
.
ok
().
body
(
new
SimpleMsg
(
"success"
));
}
}
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/form/FormModel.java
0 → 100644
浏览文件 @
8720978c
package
com.ctrip.apollo.portal.entity.form
;
public
interface
FormModel
{
boolean
isInvalid
();
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/form/NamespaceModifyModel.java
0 → 100644
浏览文件 @
8720978c
package
com.ctrip.apollo.portal.entity.form
;
import
com.ctrip.apollo.Apollo
;
import
com.ctrip.apollo.core.utils.StringUtils
;
public
class
NamespaceModifyModel
implements
FormModel
{
private
String
appId
;
private
String
env
;
private
String
clusterName
;
private
String
namespaceName
;
private
int
namespaceId
;
private
String
configText
;
private
String
modifyBy
;
@Override
public
boolean
isInvalid
(){
return
StringUtils
.
isContainEmpty
(
appId
,
env
,
clusterName
,
namespaceName
,
configText
,
modifyBy
)
||
namespaceId
<=
0
;
}
public
String
getAppId
()
{
return
appId
;
}
public
void
setAppId
(
String
appId
)
{
this
.
appId
=
appId
;
}
public
Apollo
.
Env
getEnv
()
{
return
Apollo
.
Env
.
valueOf
(
env
);
}
public
void
setEnv
(
String
env
)
{
this
.
env
=
env
;
}
public
String
getClusterName
()
{
return
clusterName
;
}
public
void
setClusterName
(
String
clusterName
)
{
this
.
clusterName
=
clusterName
;
}
public
String
getNamespaceName
()
{
return
namespaceName
;
}
public
void
setNamespaceName
(
String
namespaceName
)
{
this
.
namespaceName
=
namespaceName
;
}
public
int
getNamespaceId
()
{
return
namespaceId
;
}
public
void
setNamespaceId
(
int
namespaceId
)
{
this
.
namespaceId
=
namespaceId
;
}
public
String
getConfigText
()
{
return
configText
;
}
public
void
setConfigText
(
String
configText
)
{
this
.
configText
=
configText
;
}
public
String
getModifyBy
()
{
return
modifyBy
;
}
public
void
setModifyBy
(
String
modifyBy
)
{
this
.
modifyBy
=
modifyBy
;
}
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/entity/form/NamespaceReleaseModel.java
0 → 100644
浏览文件 @
8720978c
package
com.ctrip.apollo.portal.entity.form
;
import
com.ctrip.apollo.Apollo
;
import
com.ctrip.apollo.core.utils.StringUtils
;
public
class
NamespaceReleaseModel
implements
FormModel
{
private
String
appId
;
private
String
env
;
private
String
clusterName
;
private
String
namespaceName
;
private
String
releaseBy
;
private
String
releaseComment
;
@Override
public
boolean
isInvalid
()
{
return
StringUtils
.
isContainEmpty
(
appId
,
env
,
clusterName
,
namespaceName
,
releaseBy
);
}
public
String
getAppId
()
{
return
appId
;
}
public
void
setAppId
(
String
appId
)
{
this
.
appId
=
appId
;
}
public
Apollo
.
Env
getEnv
()
{
return
Apollo
.
Env
.
valueOf
(
env
);
}
public
void
setEnv
(
String
env
)
{
this
.
env
=
env
;
}
public
String
getClusterName
()
{
return
clusterName
;
}
public
void
setClusterName
(
String
clusterName
)
{
this
.
clusterName
=
clusterName
;
}
public
String
getNamespaceName
()
{
return
namespaceName
;
}
public
void
setNamespaceName
(
String
namespaceName
)
{
this
.
namespaceName
=
namespaceName
;
}
public
String
getReleaseBy
()
{
return
releaseBy
;
}
public
void
setReleaseBy
(
String
releaseBy
)
{
this
.
releaseBy
=
releaseBy
;
}
public
String
getReleaseComment
()
{
return
releaseComment
;
}
public
void
setReleaseComment
(
String
releaseComment
)
{
this
.
releaseComment
=
releaseComment
;
}
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/AppService.java
浏览文件 @
8720978c
package
com.ctrip.apollo.portal.service
;
import
java.util.Date
;
import
java.util.List
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
com.ctrip.apollo.Apollo.Env
;
import
com.ctrip.apollo.core.dto.AppDTO
;
import
com.ctrip.apollo.core.utils.StringUtils
;
import
com.ctrip.apollo.portal.PortalSettings
;
import
com.ctrip.apollo.portal.api.AdminServiceAPI
;
import
com.ctrip.apollo.portal.entity.ClusterNavTree
;
import
com.ctrip.apollo.portal.entity.SimpleMsg
;
@Service
public
class
AppService
{
private
Logger
logger
=
LoggerFactory
.
getLogger
(
AppService
.
class
);
@Autowired
private
ClusterService
clusterService
;
@Autowired
private
PortalSettings
portalSettings
;
@Autowired
private
AdminServiceAPI
.
AppAPI
appAPI
;
public
ClusterNavTree
buildClusterNavTree
(
String
appId
)
{
ClusterNavTree
tree
=
new
ClusterNavTree
();
...
...
@@ -28,12 +40,20 @@ public class AppService {
clusterNode
.
setClusters
(
clusterService
.
findClusters
(
env
,
appId
));
tree
.
addNode
(
clusterNode
);
}
// ClusterNavTree.Node uatNode = new ClusterNavTree.Node(Apollo.Env.UAT);
// List<ClusterDTO> uatClusters = new LinkedList<>();
// uatClusters.add(defaultCluster);
// uatNode.setClusters(uatClusters);
// tree.addNode(uatNode);
return
tree
;
}
public
AppDTO
save
(
AppDTO
app
)
{
String
createBy
=
app
.
getOwnerName
();
try
{
app
.
setDataChangeCreatedBy
(
createBy
);
app
.
setDataChangeCreatedTime
(
new
Date
());
app
.
setDataChangeLastModifiedBy
(
createBy
);
return
appAPI
.
save
(
Env
.
LOCAL
,
app
);
}
catch
(
Exception
e
)
{
logger
.
error
(
"oops! save app error. app id:{}"
,
app
.
getAppId
(),
e
);
return
null
;
}
}
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/ConfigService.java
浏览文件 @
8720978c
...
...
@@ -11,14 +11,18 @@ import com.ctrip.apollo.core.dto.ItemChangeSets;
import
com.ctrip.apollo.core.dto.ItemDTO
;
import
com.ctrip.apollo.core.dto.NamespaceDTO
;
import
com.ctrip.apollo.core.dto.ReleaseDTO
;
import
com.ctrip.apollo.core.utils.StringUtils
;
import
com.ctrip.apollo.portal.api.AdminServiceAPI
;
import
com.ctrip.apollo.portal.entity.form.NamespaceModifyModel
;
import
com.ctrip.apollo.portal.entity.NamespaceVO
;
import
com.ctrip.apollo.portal.entity.form.NamespaceReleaseModel
;
import
com.ctrip.apollo.portal.service.txtresolver.ConfigTextResolver
;
import
com.ctrip.apollo.portal.service.txtresolver.TextResolverResult
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
java.io.IOException
;
import
java.util.Collections
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.LinkedList
;
import
java.util.List
;
...
...
@@ -41,6 +45,13 @@ public class ConfigService {
private
ObjectMapper
objectMapper
=
new
ObjectMapper
();
/**
* load cluster all namespace info with items
* @param appId
* @param env
* @param clusterName
* @return
*/
public
List
<
NamespaceVO
>
findNampspaces
(
String
appId
,
Apollo
.
Env
env
,
String
clusterName
)
{
List
<
NamespaceDTO
>
namespaces
=
groupAPI
.
findGroupsByAppAndCluster
(
appId
,
env
,
clusterName
);
...
...
@@ -65,39 +76,6 @@ public class ConfigService {
return
namespaceVOs
;
}
public
TextResolverResult
resolve
(
String
appId
,
Apollo
.
Env
env
,
String
clusterName
,
String
namespaceName
,
String
configText
)
{
TextResolverResult
result
=
new
TextResolverResult
();
try
{
result
=
resolver
.
resolve
(
configText
,
itemAPI
.
findItems
(
appId
,
env
,
clusterName
,
namespaceName
));
}
catch
(
Exception
e
)
{
logger
.
error
(
"resolve config text error. app id:{}, env:{}, clusterName:{}, namespace:{}"
,
appId
,
env
,
clusterName
,
namespaceName
,
e
);
result
.
setResolveSuccess
(
false
);
result
.
setMsg
(
"oops! server resolve config text error."
);
return
result
;
}
if
(
result
.
isResolveSuccess
())
{
try
{
// TODO: 16/4/13
result
.
getChangeSets
().
setModifyBy
(
"lepdou"
);
itemAPI
.
updateItems
(
appId
,
env
,
clusterName
,
namespaceName
,
result
.
getChangeSets
());
}
catch
(
Exception
e
)
{
logger
.
error
(
"resolve config text error. app id:{}, env:{}, clusterName:{}, namespace:{}"
,
appId
,
env
,
clusterName
,
namespaceName
,
e
);
result
.
setResolveSuccess
(
false
);
result
.
setMsg
(
"oops! server update config error."
);
return
result
;
}
}
else
{
logger
.
warn
(
"resolve config text error by format error. app id:{}, env:{}, clusterName:{}, namespace:{},cause:{}"
,
appId
,
env
,
clusterName
,
namespaceName
,
result
.
getMsg
());
}
return
result
;
}
private
NamespaceVO
parseNamespace
(
String
appId
,
Apollo
.
Env
env
,
String
clusterName
,
NamespaceDTO
namespace
)
{
NamespaceVO
namespaceVO
=
new
NamespaceVO
();
...
...
@@ -140,16 +118,75 @@ public class ConfigService {
}
private
NamespaceVO
.
ItemVO
parseItemVO
(
ItemDTO
itemDTO
,
Map
<
String
,
String
>
releaseItems
)
{
String
key
=
itemDTO
.
getKey
();
NamespaceVO
.
ItemVO
itemVO
=
new
NamespaceVO
.
ItemVO
();
itemVO
.
setItem
(
itemDTO
);
String
key
=
itemDTO
.
getKey
();
String
newValue
=
itemDTO
.
getValue
();
String
oldValue
=
releaseItems
.
get
(
key
);
if
(
oldValue
==
null
||
!
newValue
.
equals
(
oldValue
))
{
if
(
!
StringUtils
.
isEmpty
(
key
)
&&
(
oldValue
==
null
||
!
newValue
.
equals
(
oldValue
)
))
{
itemVO
.
setModified
(
true
);
itemVO
.
setOldValue
(
oldValue
==
null
?
""
:
oldValue
);
itemVO
.
setNewValue
(
newValue
);
}
return
itemVO
;
}
/**
* parse config text and update config items
* @return parse result
*/
public
TextResolverResult
resolveConfigText
(
NamespaceModifyModel
model
)
{
String
appId
=
model
.
getAppId
();
Apollo
.
Env
env
=
model
.
getEnv
();
String
clusterName
=
model
.
getClusterName
();
String
namespaceName
=
model
.
getNamespaceName
();
long
namespaceId
=
model
.
getNamespaceId
();
String
configText
=
model
.
getConfigText
();
TextResolverResult
result
=
new
TextResolverResult
();
try
{
result
=
resolver
.
resolve
(
namespaceId
,
configText
,
itemAPI
.
findItems
(
appId
,
env
,
clusterName
,
namespaceName
));
}
catch
(
Exception
e
)
{
logger
.
error
(
"resolve config text error. app id:{}, env:{}, clusterName:{}, namespace:{}"
,
appId
,
env
,
clusterName
,
namespaceName
,
e
);
result
.
setResolveSuccess
(
false
);
result
.
setMsg
(
"oops! server resolveConfigText config text error."
);
return
result
;
}
if
(
result
.
isResolveSuccess
())
{
try
{
ItemChangeSets
changeSets
=
result
.
getChangeSets
();
changeSets
.
setModifyBy
(
model
.
getModifyBy
());
enrichChangeSetBaseInfo
(
changeSets
);
itemAPI
.
updateItems
(
appId
,
env
,
clusterName
,
namespaceName
,
changeSets
);
}
catch
(
Exception
e
)
{
logger
.
error
(
"resolve config text error. app id:{}, env:{}, clusterName:{}, namespace:{}"
,
appId
,
env
,
clusterName
,
namespaceName
,
e
);
result
.
setResolveSuccess
(
false
);
result
.
setMsg
(
"oops! server update config error."
);
return
result
;
}
}
else
{
logger
.
warn
(
"resolve config text error by format error. app id:{}, env:{}, clusterName:{}, namespace:{},cause:{}"
,
appId
,
env
,
clusterName
,
namespaceName
,
result
.
getMsg
());
}
return
result
;
}
private
void
enrichChangeSetBaseInfo
(
ItemChangeSets
changeSets
){
for
(
ItemDTO
item:
changeSets
.
getCreateItems
()){
item
.
setDataChangeCreatedTime
(
new
Date
());
}
}
/**
* release config items
* @return
*/
public
ReleaseDTO
release
(
NamespaceReleaseModel
model
){
return
releaseAPI
.
release
(
model
.
getAppId
(),
model
.
getEnv
(),
model
.
getClusterName
(),
model
.
getNamespaceName
(),
model
.
getReleaseBy
(),
model
.
getReleaseComment
());
}
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/txtresolver/ConfigTextResolver.java
浏览文件 @
8720978c
...
...
@@ -5,10 +5,10 @@ import com.ctrip.apollo.core.dto.ItemDTO;
import
java.util.List
;
/**
* users can modify config in text mode.so need resolve text.
* users can modify config in text mode.so need resolve
ConfigText
text.
*/
public
interface
ConfigTextResolver
{
TextResolverResult
resolve
(
String
configText
,
List
<
ItemDTO
>
baseItems
);
TextResolverResult
resolve
(
long
namespaceId
,
String
configText
,
List
<
ItemDTO
>
baseItems
);
}
apollo-portal/src/main/java/com/ctrip/apollo/portal/service/txtresolver/PropertyResolver.java
浏览文件 @
8720978c
...
...
@@ -8,8 +8,10 @@ import com.ctrip.apollo.portal.util.BeanUtils;
import
org.springframework.stereotype.Component
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
/**
* normal property file resolver.
...
...
@@ -23,7 +25,7 @@ public class PropertyResolver implements ConfigTextResolver {
private
static
final
String
ITEM_SEPARATOR
=
"\n"
;
@Override
public
TextResolverResult
resolve
(
String
configText
,
List
<
ItemDTO
>
baseItems
)
{
public
TextResolverResult
resolve
(
long
namespaceId
,
String
configText
,
List
<
ItemDTO
>
baseItems
)
{
TextResolverResult
result
=
new
TextResolverResult
();
if
(
StringUtils
.
isEmpty
(
configText
)){
...
...
@@ -40,6 +42,12 @@ public class PropertyResolver implements ConfigTextResolver {
String
[]
newItems
=
configText
.
split
(
ITEM_SEPARATOR
);
if
(
isHasRepeatKey
(
newItems
)){
result
.
setResolveSuccess
(
false
);
result
.
setMsg
(
"config text has repeat key please check."
);
return
result
;
}
ItemChangeSets
changeSets
=
new
ItemChangeSets
();
result
.
setChangeSets
(
changeSets
);
Map
<
Integer
,
String
>
newLineNumMapItem
=
new
HashMap
();
//use for delete blank and comment item
...
...
@@ -52,16 +60,16 @@ public class PropertyResolver implements ConfigTextResolver {
//comment item
if
(
isCommentItem
(
newItem
))
{
handleCommentLine
(
oldItemByLine
,
newItem
,
lineCounter
,
changeSets
);
handleCommentLine
(
namespaceId
,
oldItemByLine
,
newItem
,
lineCounter
,
changeSets
);
//blank item
}
else
if
(
isBlankItem
(
newItem
))
{
handleBlankLine
(
oldItemByLine
,
lineCounter
,
changeSets
);
handleBlankLine
(
namespaceId
,
oldItemByLine
,
lineCounter
,
changeSets
);
//normal
line
//normal
item
}
else
{
if
(!
handleNormalLine
(
oldKeyMapItem
,
newItem
,
lineCounter
,
result
))
{
if
(!
handleNormalLine
(
namespaceId
,
oldKeyMapItem
,
newItem
,
lineCounter
,
result
))
{
return
result
;
}
}
...
...
@@ -77,42 +85,68 @@ public class PropertyResolver implements ConfigTextResolver {
return
result
;
}
private
void
handleCommentLine
(
ItemDTO
oldItemByLine
,
String
newItem
,
int
lineCounter
,
ItemChangeSets
changeSets
)
{
private
boolean
isHasRepeatKey
(
String
[]
newItems
){
Set
<
String
>
keys
=
new
HashSet
<>();
int
keyCount
=
0
;
for
(
String
item:
newItems
){
if
(!
isCommentItem
(
item
)
&&
!
isBlankItem
(
item
)){
keyCount
++;
keys
.
add
(
parseKeyValueFromItem
(
item
)[
0
]);
}
}
return
keyCount
>
keys
.
size
();
}
private
String
[]
parseKeyValueFromItem
(
String
item
){
int
kvSeparator
=
item
.
indexOf
(
KV_SEPARATOR
);
if
(
kvSeparator
==
-
1
)
{
return
null
;
}
String
[]
kv
=
new
String
[
2
];
kv
[
0
]
=
item
.
substring
(
0
,
kvSeparator
).
trim
();
kv
[
1
]
=
item
.
substring
(
kvSeparator
+
1
,
item
.
length
()).
trim
();
return
kv
;
}
private
void
handleCommentLine
(
Long
namespaceId
,
ItemDTO
oldItemByLine
,
String
newItem
,
int
lineCounter
,
ItemChangeSets
changeSets
)
{
String
oldComment
=
oldItemByLine
==
null
?
""
:
oldItemByLine
.
getComment
();
//create comment. implement update comment by delete old comment and create new comment
if
(!(
isCommentItem
(
oldItemByLine
)
&&
newItem
.
equals
(
oldComment
)))
{
changeSets
.
addCreateItem
(
buildCommentItem
(
0
l
,
newItem
,
lineCounter
));
changeSets
.
addCreateItem
(
buildCommentItem
(
0
l
,
n
amespaceId
,
n
ewItem
,
lineCounter
));
}
}
private
void
handleBlankLine
(
ItemDTO
oldItem
,
int
lineCounter
,
ItemChangeSets
changeSets
)
{
private
void
handleBlankLine
(
Long
namespaceId
,
ItemDTO
oldItem
,
int
lineCounter
,
ItemChangeSets
changeSets
)
{
if
(!
isBlankItem
(
oldItem
))
{
changeSets
.
addCreateItem
(
buildBlankItem
(
0
l
,
lineCounter
));
changeSets
.
addCreateItem
(
buildBlankItem
(
0
l
,
namespaceId
,
lineCounter
));
}
}
private
boolean
handleNormalLine
(
Map
<
String
,
ItemDTO
>
keyMapOldItem
,
String
newItem
,
private
boolean
handleNormalLine
(
Long
namespaceId
,
Map
<
String
,
ItemDTO
>
keyMapOldItem
,
String
newItem
,
int
lineCounter
,
TextResolverResult
result
)
{
ItemChangeSets
changeSets
=
result
.
getChangeSets
();
int
kvSeparator
=
newItem
.
indexOf
(
KV_SEPARATOR
);
if
(
kvSeparator
==
-
1
)
{
String
[]
kv
=
parseKeyValueFromItem
(
newItem
);
if
(
kv
==
null
)
{
result
.
setResolveSuccess
(
false
);
result
.
setMsg
(
" line:"
+
lineCounter
+
" key value must separate by '='"
);
return
false
;
}
String
newKey
=
newItem
.
substring
(
0
,
kvSeparator
).
trim
()
;
String
newValue
=
newItem
.
substring
(
kvSeparator
+
1
,
newItem
.
length
()).
trim
()
;
String
newKey
=
kv
[
0
]
;
String
newValue
=
kv
[
1
]
;
ItemDTO
oldItem
=
keyMapOldItem
.
get
(
newKey
);
if
(
oldItem
==
null
)
{
//new item
changeSets
.
addCreateItem
(
buildNormalItem
(
0
l
,
newKey
,
newValue
,
""
,
lineCounter
));
}
else
if
(!
newValue
.
equals
(
oldItem
.
getValue
())){
//update item
changeSets
.
addCreateItem
(
buildNormalItem
(
0
l
,
n
amespaceId
,
n
ewKey
,
newValue
,
""
,
lineCounter
));
}
else
if
(!
newValue
.
equals
(
oldItem
.
getValue
())
||
lineCounter
!=
oldItem
.
getLineNum
()
){
//update item
changeSets
.
addUpdateItem
(
buildNormalItem
(
oldItem
.
getId
(),
newKey
,
newValue
,
oldItem
.
getComment
(),
buildNormalItem
(
oldItem
.
getId
(),
n
amespaceId
,
n
ewKey
,
newValue
,
oldItem
.
getComment
(),
lineCounter
));
}
keyMapOldItem
.
remove
(
newKey
);
...
...
@@ -154,23 +188,24 @@ public class PropertyResolver implements ConfigTextResolver {
//1. old is blank by now is not
//2.old is comment by now is not exist or modified
if
((
isBlankItem
(
oldItem
)
&&
!
isBlankItem
(
newItem
))
||
isCommentItem
(
oldItem
)
&&
(
newItem
==
null
||
!
newItem
.
equals
(
oldItem
)))
{
||
isCommentItem
(
oldItem
)
&&
(
newItem
==
null
||
!
newItem
.
equals
(
oldItem
.
getComment
()
)))
{
changeSets
.
addDeleteItem
(
oldItem
);
}
}
}
private
ItemDTO
buildCommentItem
(
Long
id
,
String
comment
,
int
lineNum
)
{
return
buildNormalItem
(
id
,
""
,
""
,
comment
,
lineNum
);
private
ItemDTO
buildCommentItem
(
Long
id
,
Long
namespaceId
,
String
comment
,
int
lineNum
)
{
return
buildNormalItem
(
id
,
namespaceId
,
""
,
""
,
comment
,
lineNum
);
}
private
ItemDTO
buildBlankItem
(
Long
id
,
int
lineNum
)
{
return
buildNormalItem
(
id
,
""
,
""
,
""
,
lineNum
);
private
ItemDTO
buildBlankItem
(
Long
id
,
Long
namespaceId
,
int
lineNum
)
{
return
buildNormalItem
(
id
,
namespaceId
,
""
,
""
,
""
,
lineNum
);
}
private
ItemDTO
buildNormalItem
(
Long
id
,
String
key
,
String
value
,
String
comment
,
int
lineNum
)
{
private
ItemDTO
buildNormalItem
(
Long
id
,
Long
namespaceId
,
String
key
,
String
value
,
String
comment
,
int
lineNum
)
{
ItemDTO
item
=
new
ItemDTO
();
item
.
setId
(
id
);
item
.
setNamespaceId
(
namespaceId
);
item
.
setKey
(
key
);
item
.
setValue
(
value
);
item
.
setComment
(
comment
);
...
...
apollo-portal/src/main/resources/application.yml
浏览文件 @
8720978c
...
...
@@ -15,4 +15,4 @@ ctrip:
apollo
:
portal
:
env
:
local
,dev
env
:
local
apollo-portal/src/main/resources/static/img/icon.jpg
已删除
100644 → 0
浏览文件 @
f7191bfa
56.4 KB
apollo-portal/src/main/resources/static/scripts/controller/CreateAppController.js
浏览文件 @
8720978c
...
...
@@ -5,9 +5,8 @@ create_app_module.controller('CreateAppController', ['$scope', '$window', 'toast
$scope
.
app
=
{
appId
:
1001
,
name
:
'
lepdou
'
,
ownerPhone
:
'
1111
'
,
ownerMail
:
'
qqq@qq.com
'
,
owner
:
'
le
'
ownerEmail
:
'
qqq@qq.com
'
,
ownerName
:
'
le
'
};
$scope
.
save
=
function
()
{
...
...
@@ -17,7 +16,11 @@ create_app_module.controller('CreateAppController', ['$scope', '$window', 'toast
$window
.
location
.
href
=
'
/views/app.html?#appid=
'
+
result
.
appId
;
},
1000
);
},
function
(
result
)
{
toastr
.
error
(
'
添加失败!
'
);
if
(
result
.
status
==
400
){
toastr
.
error
(
'
params error
'
,
'
添加失败!
'
);
}
else
{
toastr
.
error
(
'
server error
'
,
'
添加失败!
'
);
}
});
};
...
...
apollo-portal/src/main/resources/static/scripts/controller/app/AppConfigController.js
浏览文件 @
8720978c
...
...
@@ -3,29 +3,34 @@ application_module.controller("AppConfigController",
function
(
$scope
,
$location
,
toastr
,
AppService
,
ConfigService
)
{
var
appId
=
$location
.
$$url
.
split
(
"
=
"
)[
1
];
var
currentUser
=
'
lepdou
'
;
var
pageContext
=
{
appId
:
appId
,
env
:
'
LOCAL
'
,
clusterName
:
'
default
'
};
$scope
.
pageEnv
=
pageContext
;
/////////////
$scope
.
pageContext
=
pageContext
;
///////////// load cluster nav tree /////////
AppService
.
load_nav_tree
(
$scope
.
page
Env
.
appId
).
then
(
function
(
result
)
{
AppService
.
load_nav_tree
(
$scope
.
page
Context
.
appId
).
then
(
function
(
result
)
{
var
navTree
=
[];
var
nodes
=
result
.
nodes
;
nodes
.
forEach
(
function
(
item
)
{
var
node
=
{};
//first nav
node
.
text
=
item
.
env
;
node
.
selectable
=
false
;
//second nav
var
clusterNodes
=
[];
item
.
clusters
.
forEach
(
function
(
item
)
{
var
clusterNode
=
{};
var
clusterNode
=
{},
parentNode
=
[];
clusterNode
.
text
=
item
.
name
;
parentNode
.
push
(
node
.
text
);
clusterNode
.
tags
=
parentNode
;
clusterNodes
.
push
(
clusterNode
);
});
...
...
@@ -36,33 +41,86 @@ application_module.controller("AppConfigController",
color
:
"
#428bca
"
,
showBorder
:
true
,
data
:
navTree
,
levels
:
99
levels
:
99
,
onNodeSelected
:
function
(
event
,
data
)
{
$scope
.
pageContext
.
env
=
data
.
tags
[
0
];
$scope
.
pageContext
.
clusterName
=
data
.
text
;
refreshNamespaces
();
}
});
},
function
(
result
)
{
toastr
.
error
(
"
加载导航出错:
"
+
result
);
});
///////////
/////////// namespace ////////////
var
namespace_view_type
=
{
TEXT
:
'
text
'
,
TABLE
:
'
table
'
,
LOG
:
'
log
'
};
refreshNamespaces
();
function
refreshNamespaces
(
viewType
)
{
ConfigService
.
load_all_namespaces
(
$scope
.
pageContext
.
appId
,
$scope
.
pageContext
.
env
,
$scope
.
pageContext
.
clusterName
,
viewType
).
then
(
function
(
result
)
{
$scope
.
namespaces
=
result
;
//初始化视图
if
(
$scope
.
namespaces
)
{
$scope
.
namespaces
.
forEach
(
function
(
item
)
{
item
.
isModify
=
false
;
if
(
!
viewType
){
//default text view
$scope
.
switchView
(
item
,
namespace_view_type
.
TEXT
);
}
else
if
(
viewType
==
namespace_view_type
.
TABLE
){
item
.
viewType
=
namespace_view_type
.
TABLE
;
}
item
.
isTextEditing
=
false
;
})
}
},
function
(
result
)
{
toastr
.
error
(
"
加载配置信息出错
"
);
});
}
////////////global view oper /////////////
$scope
.
switchView
=
function
(
namespace
,
viewType
)
{
ConfigService
.
load_all_namespaces
(
$scope
.
pageEnv
.
appId
,
$scope
.
pageEnv
.
env
,
$scope
.
pageEnv
.
clusterName
).
then
(
function
(
result
)
{
$scope
.
namespaces
=
result
;
if
(
namespace_view_type
.
TEXT
==
viewType
)
{
namespace
.
text
=
parseModel2Text
(
namespace
);
}
else
if
(
namespace_view_type
.
TABLE
==
viewType
)
{
//初始化视图
if
(
$scope
.
namespaces
)
{
$scope
.
namespaces
.
forEach
(
function
(
item
)
{
item
.
isModify
=
false
;
item
.
viewType
=
'
table
'
;
item
.
isTextEditing
=
false
;
})
}
namespace
.
viewType
=
viewType
;
};
//把表格内容解析成文本
function
parseModel2Text
(
namespace
)
{
if
(
!
namespace
.
items
)
{
return
"
无配置信息
"
;
}
var
result
=
""
;
namespace
.
items
.
forEach
(
function
(
item
)
{
if
(
item
.
item
.
key
)
{
result
+=
item
.
item
.
key
+
"
=
"
+
item
.
item
.
value
+
"
\n
"
;
}
else
{
result
+=
item
.
item
.
comment
+
"
\n
"
;
}
},
function
(
result
)
{
toastr
.
error
(
"
加载配置信息出错
"
);
});
return
result
;
}
////////// text view oper /////////
$scope
.
draft
=
{};
//保存草稿
$scope
.
saveDraft
=
function
(
namespace
)
{
...
...
@@ -71,12 +129,17 @@ application_module.controller("AppConfigController",
//更新配置
$scope
.
commitChange
=
function
()
{
ConfigService
.
modify_items
(
$scope
.
pageEnv
.
appId
,
$scope
.
pageEnv
.
env
,
$scope
.
pageEnv
.
clusterName
,
$scope
.
draft
.
namespace
.
namespaceName
,
$scope
.
draft
.
text
).
then
(
ConfigService
.
modify_items
(
$scope
.
pageContext
.
appId
,
$scope
.
pageContext
.
env
,
$scope
.
pageContext
.
clusterName
,
$scope
.
draft
.
namespace
.
namespaceName
,
$scope
.
draft
.
text
,
$scope
.
draft
.
namespace
.
id
,
'
lepdou
'
).
then
(
function
(
result
)
{
toastr
.
success
(
"
更新成功
"
);
//refresh all namespace items
refreshNamespaces
();
$scope
.
draft
.
backupText
=
''
;
//清空备份文本
$scope
.
toggleTextEditStatus
(
$scope
.
draft
);
},
function
(
result
)
{
toastr
.
error
(
result
.
data
.
msg
,
"
更新失败
"
);
...
...
@@ -84,7 +147,6 @@ application_module.controller("AppConfigController",
);
};
/////////
//文本编辑框状态切换
$scope
.
toggleTextEditStatus
=
function
(
namespace
)
{
namespace
.
isTextEditing
=
!
namespace
.
isTextEditing
;
...
...
@@ -96,7 +158,10 @@ application_module.controller("AppConfigController",
}
}
};
////////// table view oper /////////
//查看旧值
$scope
.
queryOldValue
=
function
(
key
,
oldValue
)
{
$scope
.
queryKey
=
key
;
if
(
oldValue
==
''
)
{
...
...
@@ -105,40 +170,30 @@ application_module.controller("AppConfigController",
$scope
.
OldValue
=
oldValue
;
}
};
$scope
.
switchView
=
function
(
namespace
,
viewType
)
{
if
(
'
textarea
'
==
viewType
)
{
namespace
.
text
=
parseTableModel2Text
(
namespace
);
}
else
if
(
'
table
'
==
viewType
)
{
}
namespace
.
viewType
=
viewType
;
/////// release ///////
var
releaseNamespace
=
{};
$scope
.
prepareReleaseNamespace
=
function
(
namespace
)
{
releaseNamespace
=
namespace
;
};
$scope
.
releaseComment
=
''
;
$scope
.
release
=
function
()
{
ConfigService
.
release
(
$scope
.
pageContext
.
appId
,
$scope
.
pageContext
.
env
,
$scope
.
pageContext
.
clusterName
,
releaseNamespace
.
namespace
.
namespaceName
,
currentUser
,
$scope
.
releaseComment
).
then
(
function
(
result
)
{
toastr
.
success
(
"
发布成功
"
);
//refresh all namespace items
refreshNamespaces
();
//把表格内容解析成文本
function
parseTableModel2Text
(
namespace
)
{
if
(
!
namespace
.
items
)
{
return
"
无配置信息
"
;
}
var
result
=
""
;
namespace
.
items
.
forEach
(
function
(
item
)
{
// if (item.modified) {
// result += "**";
// }
if
(
item
.
item
.
key
)
{
result
+=
item
.
item
.
key
+
"
=
"
+
item
.
item
.
value
+
"
\n
"
;
}
else
{
result
+=
item
.
item
.
comment
+
"
\n
"
;
}
});
},
function
(
result
)
{
toastr
.
error
(
result
.
data
.
msg
,
"
发布失败
"
);
return
result
;
}
);
}
//把文本内容解析成表格
}]);
apollo-portal/src/main/resources/static/scripts/services/ConfigService.js
浏览文件 @
8720978c
...
...
@@ -6,12 +6,12 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
url
:
'
/apps/:appId/env/:env/clusters/:clusterName/namespaces
'
},
modify_items
:
{
method
:
'
GE
T
'
,
isArray
:
false
,
url
:
'
/apps/:appId/env/:env/clusters/:clusterName/namespaces/:namespaceName/modify
'
,
params
:
{
configText
:
'
@configText
'
}
method
:
'
PU
T
'
,
url
:
'
/apps/:appId/env/:env/clusters/:clusterName/namespaces/:namespaceName/items
'
}
,
release
:
{
method
:
'
POST
'
,
url
:
'
/apps/:appId/env/:env/clusters/:clusterName/namespaces/:namespaceName/release
'
}
});
...
...
@@ -29,17 +29,40 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
});
return
d
.
promise
;
},
modify_items
:
function
(
appId
,
env
,
clusterName
,
namespaceName
,
configText
)
{
modify_items
:
function
(
appId
,
env
,
clusterName
,
namespaceName
,
configText
,
namespaceId
,
modifyBy
)
{
var
d
=
$q
.
defer
();
config_source
.
modify_items
({
appId
:
appId
,
env
:
env
,
clusterName
:
clusterName
,
namespaceName
:
namespaceName
,
configText
:
configText
namespaceName
:
namespaceName
},
{
configText
:
configText
,
namespaceId
:
namespaceId
,
modifyBy
:
modifyBy
},
function
(
result
)
{
d
.
resolve
(
result
);
d
.
resolve
(
result
);
},
function
(
result
)
{
d
.
reject
(
result
);
});
return
d
.
promise
;
},
release
:
function
(
appId
,
env
,
clusterName
,
namespaceName
,
releaseBy
,
comment
)
{
var
d
=
$q
.
defer
();
config_source
.
release
({
appId
:
appId
,
env
:
env
,
clusterName
:
clusterName
,
namespaceName
:
namespaceName
},
{
releaseBy
:
releaseBy
,
releaseComment
:
comment
},
function
(
result
)
{
d
.
resolve
(
result
);
},
function
(
result
)
{
d
.
reject
(
result
);
});
...
...
apollo-portal/src/main/resources/static/styles/common-style.css
浏览文件 @
8720978c
...
...
@@ -72,27 +72,31 @@ table th {
height
:
500px
;
overflow
:
scroll
;
}
.namespace-view-table
{
max-height
:
700px
;
overflow
:
scroll
;
}
.historyview
{
.history
-
view
{
padding
:
50px
20px
;
}
.historyview
.commit
{
.history
-
view
.commit
{
padding
:
5px
15px
;
border
:
1px
solid
#ddd
;
}
.historyview
img
{
.history
-
view
img
{
position
:
absolute
;
left
:
-28px
;
}
.historyview
.media
.row
{
.history
-
view
.media
.row
{
padding-left
:
35px
;
}
.historyview
.list
{
.history
-
view
.list
{
position
:
relative
;
border-left
:
3px
solid
#ddd
;
}
...
...
apollo-portal/src/main/resources/static/views/app.html
浏览文件 @
8720978c
...
...
@@ -41,8 +41,10 @@
<div
class=
"col-md-7"
>
<div
class=
"btn-toolbar"
role=
"toolbar"
aria-label=
"..."
>
<div
class=
"btn-group"
role=
"group"
aria-label=
"..."
>
<button
type=
"button"
class=
"btn btn-default btn-sm J_tableview_btn"
>
发布
<button
type=
"button"
data-toggle=
"modal"
data-target=
"#releaseModal"
class=
"btn btn-default btn-sm J_tableview_btn"
ng-disabled=
"namespace.isTextEditing"
ng-click=
"prepareReleaseNamespace(namespace)"
>
发布
</button>
<button
type=
"button"
class=
"btn btn-default btn-sm J_tableview_btn"
>
回滚
...
...
@@ -65,7 +67,7 @@
<div
class=
"btn-group"
role=
"group"
aria-label=
"..."
>
<button
type=
"button"
class=
"btn btn-default btn-sm J_tableview_btn"
ng-click=
"switchView(namespace, 'text
area
')"
>
文本
ng-click=
"switchView(namespace, 'text')"
>
文本
</button>
<button
type=
"button"
class=
"btn btn-default btn-sm J_tableview_btn"
...
...
@@ -86,7 +88,7 @@
<span
class=
"glyphicon glyphicon-remove"
aria-hidden=
"true"
></span>
</a>
<a
data-toggle=
"tooltip"
data-placement=
"top"
title=
"修改配置"
ng-show=
"!namespace.isTextEditing"
ng-show=
"!namespace.isTextEditing
&& namespace.viewType == 'text'
"
ng-click=
"toggleTextEditStatus(namespace)"
>
<span
class=
"glyphicon glyphicon-pencil"
aria-hidden=
"true"
></span>
</a>
...
...
@@ -99,65 +101,66 @@
</div>
</header>
<div
ng-show=
"namespace.viewType == 'text
area
'"
>
<textarea
class=
"form-control"
rows=
"
2
0"
ng-model=
"namespace.text"
<div
ng-show=
"namespace.viewType == 'text'"
>
<textarea
class=
"form-control"
rows=
"
3
0"
ng-model=
"namespace.text"
ng-disabled=
"!namespace.isTextEditing"
>
{{namespace.text}}
</textarea>
</div>
<table
class=
"table table-bordered text-center table-hover"
ng-show=
"namespace.viewType == 'table'"
>
<thead>
<tr>
<th>
Key
</th>
<th>
value
</th>
<th>
备注
</th>
<th>
最后修改人
</th>
<th>
最后修改时间
</th>
</tr>
</thead>
<tbody
ng-repeat=
"config in namespace.items"
>
<tr
ng-class=
"{warning:config.modified}"
ng-if=
"config.item.key"
>
<td>
{{config.item.key}}
</td>
<td>
<button
data-placement=
"top"
title=
"查看旧值"
class=
"glyphicon glyphicon-eye-open"
aria-hidden=
"true"
data-toggle=
"modal"
data-target=
"#oldValueModal"
ng-show=
"config.modified"
ng-click=
"queryOldValue(config.item.key, config.oldValue)"
></button>
{{config.item.value}}
</td>
<td>
{{config.item.comment}}
</td>
<td>
{{config.item.dataChangeLastModifiedBy}}
</td>
<td>
{{config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'}}
</td>
</tr>
</tbody>
</table>
<div
class=
"namespace-view-table"
>
<table
class=
"table table-bordered text-center table-hover"
ng-show=
"namespace.viewType == 'table'"
>
<thead>
<tr>
<th>
Key
</th>
<th>
value
</th>
<th>
备注
</th>
<th>
最后修改人
</th>
<th>
最后修改时间
</th>
</tr>
</thead>
<tbody
ng-repeat=
"config in namespace.items"
>
<tr
ng-class=
"{warning:config.modified}"
ng-if=
"config.item.key"
>
<td>
{{config.item.key}}
</td>
<td>
<button
data-placement=
"top"
title=
"查看旧值"
class=
"glyphicon glyphicon-eye-open"
aria-hidden=
"true"
data-toggle=
"modal"
data-target=
"#oldValueModal"
ng-show=
"config.modified"
ng-click=
"queryOldValue(config.item.key, config.oldValue)"
></button>
{{config.item.value}}
</td>
<td>
{{config.item.comment}}
</td>
<td>
{{config.item.dataChangeLastModifiedBy}}
</td>
<td>
{{config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'}}
</td>
</tr>
</tbody>
</table>
</div>
<!--历史修改视图-->
<div
class=
"J_historyview historyview"
ng-show=
"namespace.viewType == 'history'"
>
<div
class=
"J_historyview history
-
view"
ng-show=
"namespace.viewType == 'history'"
>
<div
class=
"row"
>
<div
class=
"col-md-11 col-md-offset-1 list"
style=
""
>
<div
class=
"media"
>
...
...
@@ -208,7 +211,7 @@
</div>
<!-- Modal -->
<!--
view old value
Modal -->
<div
class=
"modal fade "
id=
"oldValueModal"
tabindex=
"-1"
role=
"dialog"
aria-labelledby=
"myModalLabel"
>
<div
class=
"modal-dialog modal-sm"
role=
"document"
>
<div
class=
"modal-content"
>
...
...
@@ -228,7 +231,7 @@
</div>
<!-- commi
nt modify config
-->
<!-- commi
t modify config modal
-->
<div
class=
"modal fade"
id=
"commitModal"
tabindex=
"-1"
role=
"dialog"
aria-labelledby=
"myModalLabel2"
>
<div
class=
"modal-dialog"
role=
"document"
>
<div
class=
"modal-content"
>
...
...
@@ -238,10 +241,29 @@
<h4
class=
"modal-title"
id=
"myModalLabel2"
>
Commit changes
</h4>
</div>
<div
class=
"modal-body"
>
<textarea
rows=
"4"
style=
"width:570px;"
placeholder=
"input change log...."
></textarea>
<textarea
rows=
"4"
class=
"form-control"
style=
"width:570px;"
placeholder=
"input change log...."
></textarea>
</div>
<div
class=
"modal-footer"
>
<button
type=
"button"
class=
"btn btn-primary"
data-dismiss=
"modal"
ng-click=
"commitChange()"
>
提交
</button>
</div>
</div>
</div>
</div>
<!--release modal-->
<div
class=
"modal fade"
id=
"releaseModal"
tabindex=
"-1"
role=
"dialog"
aria-labelledby=
"myModalLabel3"
>
<div
class=
"modal-dialog"
role=
"document"
>
<div
class=
"modal-content"
>
<div
class=
"modal-header panel-primary"
>
<button
type=
"button"
class=
"close"
data-dismiss=
"modal"
aria-label=
"Close"
><span
aria-hidden=
"true"
>
×
</span></button>
<h4
class=
"modal-title"
id=
"myModalLabel3"
>
发布
</h4>
</div>
<div
class=
"modal-body"
>
<textarea
rows=
"4"
class=
"form-control"
style=
"width:570px;"
ng-model =
"releaseComment"
placeholder=
"input release log...."
></textarea>
</div>
<div
class=
"modal-footer"
>
<button
type=
"button"
class=
"btn btn-
default"
data-dismiss=
"modal"
ng-click=
"commitChang
e()"
>
提交
</button>
<button
type=
"button"
class=
"btn btn-
primary"
data-dismiss=
"modal"
ng-click=
"releas
e()"
>
提交
</button>
</div>
</div>
</div>
...
...
apollo-portal/src/main/resources/static/views/create-app.html
浏览文件 @
8720978c
...
...
@@ -43,20 +43,13 @@
<div
class=
"form-group"
>
<label
class=
"col-sm-2 control-label"
>
Owner
</label>
<div
class=
"col-sm-3"
>
<input
type=
"text"
class=
"form-control"
name=
"appOwner"
ng-model=
"app.owner"
>
</div>
</div>
<div
class=
"form-group"
>
<label
class=
"col-sm-2 control-label"
>
手机号
</label>
<div
class=
"col-sm-3"
>
<input
type=
"text"
class=
"form-control"
name=
"appOwnerPhone"
ng-model=
"app.ownerPhone"
>
<input
type=
"text"
class=
"form-control"
name=
"appOwner"
ng-model=
"app.ownerName"
>
</div>
</div>
<div
class=
"form-group"
>
<label
class=
"col-sm-2 control-label"
>
邮箱地址
</label>
<div
class=
"col-sm-4"
>
<input
type=
"email"
class=
"form-control"
ng-model=
"app.owner
M
ail"
>
<input
type=
"email"
class=
"form-control"
ng-model=
"app.owner
Em
ail"
>
</div>
</div>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录