Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
apollo
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
apollo
Commits
f5218b17
Commit
f5218b17
authored
Dec 12, 2016
by
lepdou
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
link namespace show public namespace's item & refactor bean & improve log
parent
b6996c0a
Changes
29
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
1777 additions
and
1277 deletions
+1777
-1277
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/NamespaceController.java
...k/apollo/adminservice/controller/NamespaceController.java
+11
-0
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceService.java
.../ctrip/framework/apollo/biz/service/NamespaceService.java
+19
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/util/OpenApiBeanUtils.java
...ctrip/framework/apollo/openapi/util/OpenApiBeanUtils.java
+15
-14
apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/NamespaceController.java
...ork/apollo/openapi/v1/controller/NamespaceController.java
+5
-5
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java
...om/ctrip/framework/apollo/portal/api/AdminServiceAPI.java
+13
-6
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/components/PortalSettings.java
...ip/framework/apollo/portal/components/PortalSettings.java
+13
-7
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/components/RetryableRestTemplate.java
...ework/apollo/portal/components/RetryableRestTemplate.java
+13
-5
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceBranchController.java
...k/apollo/portal/controller/NamespaceBranchController.java
+2
-2
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceController.java
...amework/apollo/portal/controller/NamespaceController.java
+15
-6
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ReleaseController.java
...framework/apollo/portal/controller/ReleaseController.java
+2
-2
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/ItemBO.java
...a/com/ctrip/framework/apollo/portal/entity/bo/ItemBO.java
+53
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/KVEntity.java
...com/ctrip/framework/apollo/portal/entity/bo/KVEntity.java
+1
-1
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/NamespaceBO.java
.../ctrip/framework/apollo/portal/entity/bo/NamespaceBO.java
+5
-56
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/ReleaseBO.java
...om/ctrip/framework/apollo/portal/entity/bo/ReleaseBO.java
+3
-2
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/Change.java
...a/com/ctrip/framework/apollo/portal/entity/vo/Change.java
+1
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/ReleaseCompareResult.java
...amework/apollo/portal/entity/vo/ReleaseCompareResult.java
+1
-0
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceBranchService.java
...amework/apollo/portal/service/NamespaceBranchService.java
+4
-4
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceService.java
...rip/framework/apollo/portal/service/NamespaceService.java
+51
-41
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ReleaseService.java
...ctrip/framework/apollo/portal/service/ReleaseService.java
+5
-5
apollo-portal/src/main/resources/static/scripts/controller/config/ConfigNamespaceController.js
...ic/scripts/controller/config/ConfigNamespaceController.js
+3
-3
apollo-portal/src/main/resources/static/scripts/directive/namespace-panel-directive.js
...ces/static/scripts/directive/namespace-panel-directive.js
+48
-6
apollo-portal/src/main/resources/static/scripts/services/ConfigService.js
...c/main/resources/static/scripts/services/ConfigService.js
+18
-0
apollo-portal/src/main/resources/static/scripts/services/ReleaseService.js
.../main/resources/static/scripts/services/ReleaseService.js
+24
-0
apollo-portal/src/main/resources/static/styles/common-style.css
...-portal/src/main/resources/static/styles/common-style.css
+19
-0
apollo-portal/src/main/resources/static/views/component/namespace-panel-branch-tab.html
...es/static/views/component/namespace-panel-branch-tab.html
+521
-0
apollo-portal/src/main/resources/static/views/component/namespace-panel-header.html
...ources/static/views/component/namespace-panel-header.html
+41
-0
apollo-portal/src/main/resources/static/views/component/namespace-panel-master-tab.html
...es/static/views/component/namespace-panel-master-tab.html
+864
-0
apollo-portal/src/main/resources/static/views/component/namespace-panel.html
...ain/resources/static/views/component/namespace-panel.html
+4
-1109
apollo-portal/src/test/java/com/ctrip/framework/apollo/portal/service/NamespaceServiceTest.java
...framework/apollo/portal/service/NamespaceServiceTest.java
+3
-3
No files found.
apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/NamespaceController.java
View file @
f5218b17
...
...
@@ -78,4 +78,15 @@ public class NamespaceController {
return
BeanUtils
.
transfrom
(
NamespaceDTO
.
class
,
namespace
);
}
@RequestMapping
(
"/clusters/{clusterName}/namespaces/{namespaceName}/public"
)
public
NamespaceDTO
findPublicNamespace
(
@PathVariable
String
clusterName
,
@PathVariable
String
namespaceName
)
{
Namespace
namespace
=
namespaceService
.
findPublicNamespace
(
clusterName
,
namespaceName
);
if
(
namespace
==
null
)
{
throw
new
NotFoundException
(
String
.
format
(
"public namespace not found. namespace:%s"
,
namespaceName
));
}
return
BeanUtils
.
transfrom
(
NamespaceDTO
.
class
,
namespace
);
}
}
apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceService.java
View file @
f5218b17
...
...
@@ -6,8 +6,10 @@ import com.ctrip.framework.apollo.biz.entity.Namespace;
import
com.ctrip.framework.apollo.biz.repository.NamespaceRepository
;
import
com.ctrip.framework.apollo.common.constants.NamespaceBranchStatus
;
import
com.ctrip.framework.apollo.common.entity.AppNamespace
;
import
com.ctrip.framework.apollo.common.exception.BadRequestException
;
import
com.ctrip.framework.apollo.common.exception.ServiceException
;
import
com.ctrip.framework.apollo.common.utils.BeanUtils
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
...
...
@@ -57,6 +59,23 @@ public class NamespaceService {
namespaceName
);
}
public
Namespace
findPublicNamespace
(
String
clusterName
,
String
namespaceName
)
{
AppNamespace
appNamespace
=
appNamespaceService
.
findPublicNamespaceByName
(
namespaceName
);
if
(
appNamespace
==
null
)
{
throw
new
BadRequestException
(
"namespace not exist"
);
}
String
appId
=
appNamespace
.
getAppId
();
Namespace
namespace
=
findOne
(
appId
,
clusterName
,
namespaceName
);
if
(
namespace
==
null
)
{
namespace
=
findOne
(
appId
,
ConfigConsts
.
CLUSTER_NAME_DEFAULT
,
namespaceName
);
}
return
namespace
;
}
public
List
<
Namespace
>
findNamespaces
(
String
appId
,
String
clusterName
)
{
List
<
Namespace
>
namespaces
=
namespaceRepository
.
findByAppIdAndClusterNameOrderByIdAsc
(
appId
,
clusterName
);
if
(
namespaces
==
null
)
{
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/util/OpenApiBeanUtils.java
View file @
f5218b17
...
...
@@ -12,7 +12,8 @@ import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO;
import
com.ctrip.framework.apollo.openapi.dto.OpenNamespaceDTO
;
import
com.ctrip.framework.apollo.openapi.dto.OpenNamespaceLockDTO
;
import
com.ctrip.framework.apollo.openapi.dto.OpenReleaseDTO
;
import
com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO
;
import
com.ctrip.framework.apollo.portal.entity.bo.ItemBO
;
import
com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO
;
import
org.springframework.util.CollectionUtils
;
...
...
@@ -51,22 +52,22 @@ public class OpenApiBeanUtils {
return
openReleaseDTO
;
}
public
static
OpenNamespaceDTO
transformFromNamespace
VO
(
NamespaceVO
namespaceV
O
)
{
Preconditions
.
checkArgument
(
namespace
V
O
!=
null
);
public
static
OpenNamespaceDTO
transformFromNamespace
BO
(
NamespaceBO
namespaceB
O
)
{
Preconditions
.
checkArgument
(
namespace
B
O
!=
null
);
OpenNamespaceDTO
openNamespaceDTO
=
BeanUtils
.
transfrom
(
OpenNamespaceDTO
.
class
,
namespace
V
O
OpenNamespaceDTO
openNamespaceDTO
=
BeanUtils
.
transfrom
(
OpenNamespaceDTO
.
class
,
namespace
B
O
.
getBaseInfo
());
//app namespace info
openNamespaceDTO
.
setFormat
(
namespace
V
O
.
getFormat
());
openNamespaceDTO
.
setComment
(
namespace
V
O
.
getComment
());
openNamespaceDTO
.
setPublic
(
namespace
V
O
.
isPublic
());
openNamespaceDTO
.
setFormat
(
namespace
B
O
.
getFormat
());
openNamespaceDTO
.
setComment
(
namespace
B
O
.
getComment
());
openNamespaceDTO
.
setPublic
(
namespace
B
O
.
isPublic
());
//items
List
<
OpenItemDTO
>
items
=
new
LinkedList
<>();
List
<
NamespaceVO
.
ItemVO
>
itemVOs
=
namespaceV
O
.
getItems
();
if
(!
CollectionUtils
.
isEmpty
(
item
V
Os
))
{
items
.
addAll
(
item
VOs
.
stream
().
map
(
itemVO
->
transformFromItemDTO
(
itemV
O
.
getItem
())).
collect
List
<
ItemBO
>
itemBOs
=
namespaceB
O
.
getItems
();
if
(!
CollectionUtils
.
isEmpty
(
item
B
Os
))
{
items
.
addAll
(
item
BOs
.
stream
().
map
(
itemBO
->
transformFromItemDTO
(
itemB
O
.
getItem
())).
collect
(
Collectors
.
toList
()));
}
openNamespaceDTO
.
setItems
(
items
);
...
...
@@ -74,14 +75,14 @@ public class OpenApiBeanUtils {
}
public
static
List
<
OpenNamespaceDTO
>
batchTransformFromNamespace
VOs
(
List
<
NamespaceV
O
>
namespace
V
Os
)
{
if
(
CollectionUtils
.
isEmpty
(
namespace
V
Os
))
{
public
static
List
<
OpenNamespaceDTO
>
batchTransformFromNamespace
BOs
(
List
<
NamespaceB
O
>
namespace
B
Os
)
{
if
(
CollectionUtils
.
isEmpty
(
namespace
B
Os
))
{
return
Collections
.
emptyList
();
}
List
<
OpenNamespaceDTO
>
openNamespaceDTOs
=
namespace
VOs
.
stream
().
map
(
OpenApiBeanUtils:
:
transformFromNamespaceV
O
)
namespace
BOs
.
stream
().
map
(
OpenApiBeanUtils:
:
transformFromNamespaceB
O
)
.
collect
(
Collectors
.
toCollection
(
LinkedList:
:
new
));
return
openNamespaceDTOs
;
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/NamespaceController.java
View file @
f5218b17
...
...
@@ -7,7 +7,7 @@ import com.ctrip.framework.apollo.core.enums.Env;
import
com.ctrip.framework.apollo.openapi.dto.OpenNamespaceDTO
;
import
com.ctrip.framework.apollo.openapi.dto.OpenNamespaceLockDTO
;
import
com.ctrip.framework.apollo.openapi.util.OpenApiBeanUtils
;
import
com.ctrip.framework.apollo.portal.entity.
vo.NamespaceV
O
;
import
com.ctrip.framework.apollo.portal.entity.
bo.NamespaceB
O
;
import
com.ctrip.framework.apollo.portal.service.NamespaceLockService
;
import
com.ctrip.framework.apollo.portal.service.NamespaceService
;
...
...
@@ -33,7 +33,7 @@ public class NamespaceController {
@PathVariable
String
clusterName
)
{
return
OpenApiBeanUtils
.
batchTransformFromNamespace
VOs
(
namespaceService
.
findNamespace
s
(
appId
,
Env
.
batchTransformFromNamespace
BOs
(
namespaceService
.
findNamespaceBO
s
(
appId
,
Env
.
fromString
(
env
),
clusterName
));
}
...
...
@@ -41,12 +41,12 @@ public class NamespaceController {
public
OpenNamespaceDTO
loadNamespace
(
@PathVariable
String
appId
,
@PathVariable
String
env
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespaceName
)
{
Namespace
VO
namespaceVO
=
namespaceService
.
loadNamespace
(
appId
,
Env
.
fromString
Namespace
BO
namespaceBO
=
namespaceService
.
loadNamespaceBO
(
appId
,
Env
.
fromString
(
env
),
clusterName
,
namespaceName
);
if
(
namespace
V
O
==
null
)
{
if
(
namespace
B
O
==
null
)
{
return
null
;
}
return
OpenApiBeanUtils
.
transformFromNamespace
VO
(
namespaceV
O
);
return
OpenApiBeanUtils
.
transformFromNamespace
BO
(
namespaceB
O
);
}
@RequestMapping
(
value
=
"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/lock"
,
method
=
RequestMethod
.
GET
)
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java
View file @
f5218b17
...
...
@@ -71,12 +71,16 @@ public class AdminServiceAPI {
public
NamespaceDTO
loadNamespace
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
)
{
NamespaceDTO
dto
=
return
restTemplate
.
get
(
env
,
"apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}"
,
NamespaceDTO
.
class
,
appId
,
clusterName
,
namespaceName
);
return
dto
;
}
public
NamespaceDTO
loadPublicNamespace
(
Env
env
,
String
clusterName
,
String
namespaceName
)
{
return
restTemplate
.
get
(
env
,
"/clusters/{clusterName}/namespaces/{namespaceName}/public"
,
NamespaceDTO
.
class
,
clusterName
,
namespaceName
);
}
public
NamespaceDTO
createNamespace
(
Env
env
,
NamespaceDTO
namespace
)
{
return
restTemplate
...
...
@@ -378,23 +382,26 @@ public class AdminServiceAPI {
public
static
class
ReleaseHistoryAPI
extends
API
{
private
ParameterizedTypeReference
<
PageDTO
<
ReleaseHistoryDTO
>>
type
=
new
ParameterizedTypeReference
<
PageDTO
<
ReleaseHistoryDTO
>>()
{};
new
ParameterizedTypeReference
<
PageDTO
<
ReleaseHistoryDTO
>>()
{
};
public
PageDTO
<
ReleaseHistoryDTO
>
findReleaseHistoriesByNamespace
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
,
int
page
,
int
size
)
{
String
namespaceName
,
int
page
,
int
size
)
{
return
restTemplate
.
get
(
env
,
"/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/histories?page={page}&size={size}"
,
type
,
appId
,
clusterName
,
namespaceName
,
page
,
size
).
getBody
();
}
public
PageDTO
<
ReleaseHistoryDTO
>
findByReleaseIdAndOperation
(
Env
env
,
long
releaseId
,
int
operation
,
int
page
,
int
size
)
{
public
PageDTO
<
ReleaseHistoryDTO
>
findByReleaseIdAndOperation
(
Env
env
,
long
releaseId
,
int
operation
,
int
page
,
int
size
)
{
return
restTemplate
.
get
(
env
,
"/releases/histories/by_release_id_and_operation?releaseId={releaseId}&operation={operation}&page={page}&size={size}"
,
type
,
releaseId
,
operation
,
page
,
size
).
getBody
();
}
public
PageDTO
<
ReleaseHistoryDTO
>
findByPreviousReleaseIdAndOperation
(
Env
env
,
long
previousReleaseId
,
int
operation
,
int
page
,
int
size
)
{
public
PageDTO
<
ReleaseHistoryDTO
>
findByPreviousReleaseIdAndOperation
(
Env
env
,
long
previousReleaseId
,
int
operation
,
int
page
,
int
size
)
{
return
restTemplate
.
get
(
env
,
"/releases/histories/by_previous_release_id_and_operation?previousReleaseId={releaseId}&operation={operation}&page={page}&size={size}"
,
type
,
previousReleaseId
,
operation
,
page
,
size
).
getBody
();
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/components/PortalSettings.java
View file @
f5218b17
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
components
;
import
com.ctrip.framework.apollo.core.MetaDomainConsts
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.core.utils.ApolloThreadFactory
;
import
com.ctrip.framework.apollo.portal.api.AdminServiceAPI
;
...
...
@@ -110,13 +111,15 @@ public class PortalSettings {
logger
.
info
(
"Env revived because env health check success. env: {}"
,
env
);
}
}
else
{
logger
.
warn
(
"Env health check failed, maybe because of admin server down. env: {}"
,
env
);
logger
.
error
(
"Env health check failed, maybe because of admin server down. env: {}, meta server address: {}"
,
env
,
MetaDomainConsts
.
getDomain
(
env
));
handleEnvDown
(
env
);
}
}
catch
(
Exception
e
)
{
logger
.
warn
(
"Env health check failed, maybe because of meta server down "
+
"or config error meta server address. env: {}"
,
env
);
logger
.
error
(
"Env health check failed, maybe because of meta server down "
+
"or configure wrong meta server address. env: {}, meta server address: {}"
,
env
,
MetaDomainConsts
.
getDomain
(
env
),
e
);
handleEnvDown
(
env
);
}
}
...
...
@@ -133,15 +136,18 @@ public class PortalSettings {
healthCheckFailedCounter
.
put
(
env
,
++
failedTimes
);
if
(!
envStatusMark
.
get
(
env
))
{
logger
.
error
(
"Env is down. env: {}, failed times: {}"
,
env
,
failedTimes
);
logger
.
error
(
"Env is down. env: {}, failed times: {}, meta server address: {}"
,
env
,
failedTimes
,
MetaDomainConsts
.
getDomain
(
env
));
}
else
{
if
(
failedTimes
>=
ENV_DOWN_THRESHOLD
)
{
envStatusMark
.
put
(
env
,
false
);
logger
.
error
(
"Env is down because health check failed for {} times, "
+
"which equals to down threshold. env: {}"
,
ENV_DOWN_THRESHOLD
,
env
);
+
"which equals to down threshold. env: {}, meta server address: {}"
,
ENV_DOWN_THRESHOLD
,
env
,
MetaDomainConsts
.
getDomain
(
env
));
}
else
{
logger
.
warn
(
"Env health check failed for {} times which less than down threshold. down threshold:{}, env: {}"
,
failedTimes
,
ENV_DOWN_THRESHOLD
,
env
);
logger
.
error
(
"Env health check failed for {} times which less than down threshold. down threshold:{}, env: {}, meta server address: {}"
,
failedTimes
,
ENV_DOWN_THRESHOLD
,
env
,
MetaDomainConsts
.
getDomain
(
env
));
}
}
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/components/RetryableRestTemplate.java
View file @
f5218b17
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
components
;
import
com.ctrip.framework.apollo.common.exception.ServiceException
;
import
com.ctrip.framework.apollo.core.MetaDomainConsts
;
import
com.ctrip.framework.apollo.core.dto.ServiceDTO
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.portal.constant.CatEventType
;
...
...
@@ -109,7 +110,9 @@ public class RetryableRestTemplate {
}
//all admin server down
ServiceException
e
=
new
ServiceException
(
"No available admin service"
);
ServiceException
e
=
new
ServiceException
(
String
.
format
(
"Admin servers are unresponsive. meta server address: %s, admin servers: %s"
,
MetaDomainConsts
.
getDomain
(
env
),
services
));
ct
.
setStatus
(
e
);
ct
.
complete
();
throw
e
;
...
...
@@ -138,9 +141,9 @@ public class RetryableRestTemplate {
}
catch
(
Throwable
t
)
{
logger
.
error
(
"Http request failed, uri: {}, method: {}"
,
uri
,
HttpMethod
.
GET
,
t
);
Tracer
.
logError
(
t
);
if
(
canRetry
(
t
,
HttpMethod
.
GET
)){
if
(
canRetry
(
t
,
HttpMethod
.
GET
))
{
Tracer
.
logEvent
(
CatEventType
.
API_RETRY
,
uri
);
}
else
{
// biz exception rethrow
}
else
{
// biz exception rethrow
ct
.
setStatus
(
t
);
ct
.
complete
();
throw
t
;
...
...
@@ -150,7 +153,9 @@ public class RetryableRestTemplate {
}
//all admin server down
ServiceException
e
=
new
ServiceException
(
"No available admin service"
);
ServiceException
e
=
new
ServiceException
(
String
.
format
(
"Admin servers are unresponsive. meta server address: %s, admin servers: %s"
,
MetaDomainConsts
.
getDomain
(
env
),
services
));
ct
.
setStatus
(
e
);
ct
.
complete
();
throw
e
;
...
...
@@ -162,7 +167,10 @@ public class RetryableRestTemplate {
List
<
ServiceDTO
>
services
=
adminServiceAddressLocator
.
getServiceList
(
env
);
if
(
CollectionUtils
.
isEmpty
(
services
))
{
ServiceException
e
=
new
ServiceException
(
"No available admin service"
);
ServiceException
e
=
new
ServiceException
(
String
.
format
(
"No available admin server."
+
" Maybe because of meta server down or all admin server down. "
+
"Meta server address: %s"
,
MetaDomainConsts
.
getDomain
(
env
)));
ct
.
setStatus
(
e
);
ct
.
complete
();
throw
e
;
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceBranchController.java
View file @
f5218b17
...
...
@@ -6,7 +6,7 @@ import com.ctrip.framework.apollo.common.dto.ReleaseDTO;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.portal.components.PermissionValidator
;
import
com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel
;
import
com.ctrip.framework.apollo.portal.entity.
vo.NamespaceV
O
;
import
com.ctrip.framework.apollo.portal.entity.
bo.NamespaceB
O
;
import
com.ctrip.framework.apollo.portal.listener.ConfigPublishEvent
;
import
com.ctrip.framework.apollo.portal.service.NamespaceBranchService
;
import
com.ctrip.framework.apollo.portal.service.ReleaseService
;
...
...
@@ -35,7 +35,7 @@ public class NamespaceBranchController {
private
ApplicationEventPublisher
publisher
;
@RequestMapping
(
"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/branches"
)
public
Namespace
V
O
findBranch
(
@PathVariable
String
appId
,
public
Namespace
B
O
findBranch
(
@PathVariable
String
appId
,
@PathVariable
String
env
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespaceName
)
{
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/NamespaceController.java
View file @
f5218b17
...
...
@@ -13,7 +13,7 @@ import com.ctrip.framework.apollo.core.enums.Env;
import
com.ctrip.framework.apollo.core.utils.StringUtils
;
import
com.ctrip.framework.apollo.portal.constant.RoleType
;
import
com.ctrip.framework.apollo.portal.entity.model.NamespaceCreationModel
;
import
com.ctrip.framework.apollo.portal.entity.
vo.NamespaceV
O
;
import
com.ctrip.framework.apollo.portal.entity.
bo.NamespaceB
O
;
import
com.ctrip.framework.apollo.portal.listener.AppNamespaceCreationEvent
;
import
com.ctrip.framework.apollo.portal.service.AppNamespaceService
;
import
com.ctrip.framework.apollo.portal.service.AppService
;
...
...
@@ -35,6 +35,7 @@ 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.RequestParam
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.util.List
;
...
...
@@ -67,17 +68,25 @@ public class NamespaceController {
}
@RequestMapping
(
"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces"
)
public
List
<
Namespace
V
O
>
findNamespaces
(
@PathVariable
String
appId
,
@PathVariable
String
env
,
public
List
<
Namespace
B
O
>
findNamespaces
(
@PathVariable
String
appId
,
@PathVariable
String
env
,
@PathVariable
String
clusterName
)
{
return
namespaceService
.
findNamespaces
(
appId
,
Env
.
valueOf
(
env
),
clusterName
);
return
namespaceService
.
findNamespace
BO
s
(
appId
,
Env
.
valueOf
(
env
),
clusterName
);
}
@RequestMapping
(
"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName:.+}"
)
public
Namespace
VO
findNamespaces
(
@PathVariable
String
appId
,
@PathVariable
String
env
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespaceName
)
{
public
Namespace
BO
findNamespace
(
@PathVariable
String
appId
,
@PathVariable
String
env
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespaceName
)
{
return
namespaceService
.
loadNamespace
(
appId
,
Env
.
valueOf
(
env
),
clusterName
,
namespaceName
);
return
namespaceService
.
loadNamespaceBO
(
appId
,
Env
.
valueOf
(
env
),
clusterName
,
namespaceName
);
}
@RequestMapping
(
"/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/public"
)
public
NamespaceBO
findPublicNamespace
(
@PathVariable
String
env
,
@PathVariable
String
namespaceName
,
@PathVariable
String
clusterName
)
{
return
namespaceService
.
loadPublicNamespaceBO
(
Env
.
valueOf
(
env
),
clusterName
,
namespaceName
);
}
@PreAuthorize
(
value
=
"@permissionValidator.hasCreateNamespacePermission(#appId)"
)
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ReleaseController.java
View file @
f5218b17
...
...
@@ -5,7 +5,7 @@ import com.ctrip.framework.apollo.common.utils.RequestPrecondition;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel
;
import
com.ctrip.framework.apollo.portal.entity.vo.ReleaseCompareResult
;
import
com.ctrip.framework.apollo.portal.entity.
vo.ReleaseV
O
;
import
com.ctrip.framework.apollo.portal.entity.
bo.ReleaseB
O
;
import
com.ctrip.framework.apollo.portal.listener.ConfigPublishEvent
;
import
com.ctrip.framework.apollo.portal.service.ReleaseService
;
...
...
@@ -89,7 +89,7 @@ public class ReleaseController {
@RequestMapping
(
value
=
"/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/releases/all"
)
public
List
<
Release
V
O
>
findAllReleases
(
@PathVariable
String
appId
,
public
List
<
Release
B
O
>
findAllReleases
(
@PathVariable
String
appId
,
@PathVariable
String
env
,
@PathVariable
String
clusterName
,
@PathVariable
String
namespaceName
,
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/bo/ItemBO.java
0 → 100644
View file @
f5218b17
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
entity
.
bo
;
import
com.ctrip.framework.apollo.common.dto.ItemDTO
;
public
class
ItemBO
{
private
ItemDTO
item
;
private
boolean
isModified
;
private
boolean
isDeleted
;
private
String
oldValue
;
private
String
newValue
;
public
ItemDTO
getItem
()
{
return
item
;
}
public
void
setItem
(
ItemDTO
item
)
{
this
.
item
=
item
;
}
public
boolean
isDeleted
()
{
return
isDeleted
;
}
public
void
setDeleted
(
boolean
deleted
)
{
isDeleted
=
deleted
;
}
public
boolean
isModified
()
{
return
isModified
;
}
public
void
setModified
(
boolean
isModified
)
{
this
.
isModified
=
isModified
;
}
public
String
getOldValue
()
{
return
oldValue
;
}
public
void
setOldValue
(
String
oldValue
)
{
this
.
oldValue
=
oldValue
;
}
public
String
getNewValue
()
{
return
newValue
;
}
public
void
setNewValue
(
String
newValue
)
{
this
.
newValue
=
newValue
;
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/
v
o/KVEntity.java
→
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/
b
o/KVEntity.java
View file @
f5218b17
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
entity
.
v
o
;
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
entity
.
b
o
;
public
class
KVEntity
{
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/
vo/NamespaceV
O.java
→
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/
bo/NamespaceB
O.java
View file @
f5218b17
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
entity
.
v
o
;
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
entity
.
b
o
;
import
com.ctrip.framework.apollo.common.dto.ItemDTO
;
import
com.ctrip.framework.apollo.common.dto.NamespaceDTO
;
import
java.util.List
;
public
class
Namespace
V
O
{
public
class
Namespace
B
O
{
private
NamespaceDTO
baseInfo
;
private
int
itemModifiedCnt
;
private
List
<
Item
V
O
>
items
;
private
List
<
Item
B
O
>
items
;
private
String
format
;
private
boolean
isPublic
;
private
String
parentAppId
;
...
...
@@ -31,11 +30,11 @@ public class NamespaceVO {
this
.
itemModifiedCnt
=
itemModifiedCnt
;
}
public
List
<
Item
V
O
>
getItems
()
{
public
List
<
Item
B
O
>
getItems
()
{
return
items
;
}
public
void
setItems
(
List
<
Item
V
O
>
items
)
{
public
void
setItems
(
List
<
Item
B
O
>
items
)
{
this
.
items
=
items
;
}
...
...
@@ -71,54 +70,4 @@ public class NamespaceVO {
this
.
comment
=
comment
;
}
public
static
class
ItemVO
{
private
ItemDTO
item
;
private
boolean
isModified
;
private
boolean
isDeleted
;
private
String
oldValue
;
private
String
newValue
;
public
ItemDTO
getItem
()
{
return
item
;
}
public
void
setItem
(
ItemDTO
item
)
{
this
.
item
=
item
;
}
public
boolean
isDeleted
()
{
return
isDeleted
;
}
public
void
setDeleted
(
boolean
deleted
)
{
isDeleted
=
deleted
;
}
public
boolean
isModified
()
{
return
isModified
;
}
public
void
setModified
(
boolean
isModified
)
{
this
.
isModified
=
isModified
;
}
public
String
getOldValue
()
{
return
oldValue
;
}
public
void
setOldValue
(
String
oldValue
)
{
this
.
oldValue
=
oldValue
;
}
public
String
getNewValue
()
{
return
newValue
;
}
public
void
setNewValue
(
String
newValue
)
{
this
.
newValue
=
newValue
;
}
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/
vo/ReleaseV
O.java
→
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/
bo/ReleaseB
O.java
View file @
f5218b17
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
entity
.
v
o
;
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
entity
.
b
o
;
import
com.ctrip.framework.apollo.common.dto.ReleaseDTO
;
import
com.ctrip.framework.apollo.portal.entity.bo.KVEntity
;
import
java.util.Set
;
public
class
Release
V
O
{
public
class
Release
B
O
{
private
ReleaseDTO
baseInfo
;
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/Change.java
View file @
f5218b17
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
entity
.
vo
;
import
com.ctrip.framework.apollo.common.entity.EntityPair
;
import
com.ctrip.framework.apollo.portal.entity.bo.KVEntity
;
import
com.ctrip.framework.apollo.portal.enums.ChangeType
;
public
class
Change
{
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/entity/vo/ReleaseCompareResult.java
View file @
f5218b17
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
entity
.
vo
;
import
com.ctrip.framework.apollo.common.entity.EntityPair
;
import
com.ctrip.framework.apollo.portal.entity.bo.KVEntity
;
import
com.ctrip.framework.apollo.portal.enums.ChangeType
;
import
java.util.LinkedList
;
...
...
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceBranchService.java
View file @
f5218b17
...
...
@@ -11,7 +11,7 @@ import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import
com.ctrip.framework.apollo.portal.components.ItemsComparator
;
import
com.ctrip.framework.apollo.portal.components.PermissionValidator
;
import
com.ctrip.framework.apollo.portal.constant.CatEventType
;
import
com.ctrip.framework.apollo.portal.entity.
vo.NamespaceV
O
;
import
com.ctrip.framework.apollo.portal.entity.
bo.NamespaceB
O
;
import
com.ctrip.framework.apollo.portal.spi.UserInfoHolder
;
import
com.ctrip.framework.apollo.tracer.Tracer
;
...
...
@@ -100,7 +100,7 @@ public class NamespaceBranchService {
private
ItemChangeSets
calculateBranchChangeSet
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
,
String
branchName
)
{
Namespace
VO
parentNamespace
=
namespaceService
.
loadNamespace
(
appId
,
env
,
clusterName
,
namespaceName
);
Namespace
BO
parentNamespace
=
namespaceService
.
loadNamespaceBO
(
appId
,
env
,
clusterName
,
namespaceName
);
if
(
parentNamespace
==
null
)
{
throw
new
BadRequestException
(
"base namespace not existed"
);
...
...
@@ -125,12 +125,12 @@ public class NamespaceBranchService {
return
namespaceBranchAPI
.
findBranch
(
appId
,
env
,
clusterName
,
namespaceName
);
}
public
Namespace
V
O
findBranch
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
)
{
public
Namespace
B
O
findBranch
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
)
{
NamespaceDTO
namespaceDTO
=
findBranchBaseInfo
(
appId
,
env
,
clusterName
,
namespaceName
);
if
(
namespaceDTO
==
null
)
{
return
null
;
}
return
namespaceService
.
loadNamespace
(
appId
,
env
,
namespaceDTO
.
getClusterName
(),
namespaceName
);
return
namespaceService
.
loadNamespace
BO
(
appId
,
env
,
namespaceDTO
.
getClusterName
(),
namespaceName
);
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/NamespaceService.java
View file @
f5218b17
package
com
.
ctrip
.
framework
.
apollo
.
portal
.
service
;
import
com.google.gson.Gson
;
import
com.google.gson.reflect.TypeToken
;
import
com.ctrip.framework.apollo.common.constants.GsonType
;
import
com.ctrip.framework.apollo.common.dto.ItemDTO
;
import
com.ctrip.framework.apollo.common.dto.NamespaceDTO
;
import
com.ctrip.framework.apollo.common.dto.ReleaseDTO
;
import
com.ctrip.framework.apollo.common.entity.AppNamespace
;
import
com.ctrip.framework.apollo.common.exception.BadRequestException
;
import
com.ctrip.framework.apollo.common.utils.BeanUtils
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.core.utils.StringUtils
;
import
com.ctrip.framework.apollo.portal.api.AdminServiceAPI
;
import
com.ctrip.framework.apollo.portal.constant.CatEventType
;
import
com.ctrip.framework.apollo.portal.entity.vo.NamespaceVO
;
import
com.ctrip.framework.apollo.portal.entity.bo.ItemBO
;
import
com.ctrip.framework.apollo.portal.entity.bo.NamespaceBO
;
import
com.ctrip.framework.apollo.portal.spi.UserInfoHolder
;
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.http.HttpStatus
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.web.client.HttpClientErrorException
;
import
java.lang.reflect.Type
;
import
java.util.HashMap
;
import
java.util.LinkedList
;
import
java.util.List
;
...
...
@@ -35,8 +38,6 @@ public class NamespaceService {
private
Logger
logger
=
LoggerFactory
.
getLogger
(
NamespaceService
.
class
);
private
Gson
gson
=
new
Gson
();
private
static
Type
mapType
=
new
TypeToken
<
Map
<
String
,
String
>>()
{
}.
getType
();
@Autowired
private
UserInfoHolder
userInfoHolder
;
...
...
@@ -58,8 +59,8 @@ public class NamespaceService {
NamespaceDTO
createdNamespace
=
namespaceAPI
.
createNamespace
(
env
,
namespace
);
Tracer
.
logEvent
(
CatEventType
.
CREATE_NAMESPACE
,
String
.
format
(
"%s+%s+%s+%s"
,
namespace
.
getAppId
(),
env
,
namespace
.
getClusterName
(),
namespace
.
getNamespaceName
()));
String
.
format
(
"%s+%s+%s+%s"
,
namespace
.
getAppId
(),
env
,
namespace
.
getClusterName
(),
namespace
.
getNamespaceName
()));
return
createdNamespace
;
}
...
...
@@ -68,7 +69,7 @@ public class NamespaceService {
public
void
deleteNamespace
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
)
{
AppNamespace
appNamespace
=
appNamespaceService
.
findByAppIdAndName
(
appId
,
namespaceName
);
if
(
appNamespace
!=
null
&&
!
appNamespace
.
isPublic
()){
if
(
appNamespace
!=
null
&&
!
appNamespace
.
isPublic
())
{
throw
new
BadRequestException
(
"private namespace can not be deleted"
);
}
...
...
@@ -89,20 +90,20 @@ public class NamespaceService {
/**
* load cluster all namespace info with items
*/
public
List
<
Namespace
VO
>
findNamespace
s
(
String
appId
,
Env
env
,
String
clusterName
)
{
public
List
<
Namespace
BO
>
findNamespaceBO
s
(
String
appId
,
Env
env
,
String
clusterName
)
{
List
<
NamespaceDTO
>
namespaces
=
namespaceAPI
.
findNamespaceByCluster
(
appId
,
env
,
clusterName
);
if
(
namespaces
==
null
||
namespaces
.
size
()
==
0
)
{
throw
new
BadRequestException
(
"namespaces not exist"
);
}
List
<
Namespace
VO
>
namespaceV
Os
=
new
LinkedList
<>();
List
<
Namespace
BO
>
namespaceB
Os
=
new
LinkedList
<>();
for
(
NamespaceDTO
namespace
:
namespaces
)
{
Namespace
VO
namespaceV
O
=
null
;
Namespace
BO
namesapceB
O
=
null
;
try
{
names
paceVO
=
parseNamespace
(
appId
,
env
,
clusterName
,
namespace
);
namespace
VOs
.
add
(
namespaceV
O
);
names
apceBO
=
transformNamespace2BO
(
appId
,
env
,
clusterName
,
namespace
);
namespace
BOs
.
add
(
namesapceB
O
);
}
catch
(
Exception
e
)
{
logger
.
error
(
"parse namespace error. app id:{}, env:{}, clusterName:{}, namespace:{}"
,
appId
,
env
,
clusterName
,
namespace
.
getNamespaceName
(),
e
);
...
...
@@ -110,25 +111,34 @@ public class NamespaceService {
}
}
return
namespace
V
Os
;
return
namespace
B
Os
;
}
public
Namespace
VO
loadNamespace
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
)
{
public
Namespace
BO
loadNamespaceBO
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
)
{
NamespaceDTO
namespace
=
namespaceAPI
.
loadNamespace
(
appId
,
env
,
clusterName
,
namespaceName
);
if
(
namespace
==
null
)
{
throw
new
BadRequestException
(
"namespaces not exist"
);
}
return
parseNamespace
(
appId
,
env
,
clusterName
,
namespace
);
return
transformNamespace2BO
(
appId
,
env
,
clusterName
,
namespace
);
}
private
NamespaceVO
parseNamespace
(
String
appId
,
Env
env
,
String
clusterName
,
NamespaceDTO
namespace
)
{
NamespaceVO
namespaceVO
=
new
NamespaceVO
();
namespaceVO
.
setBaseInfo
(
namespace
);
public
NamespaceBO
loadPublicNamespaceBO
(
Env
env
,
String
clusterName
,
String
namespaceName
)
{
NamespaceDTO
namespace
=
namespaceAPI
.
loadPublicNamespace
(
env
,
clusterName
,
namespaceName
);
fillAppNamespaceProperties
(
namespaceVO
);
String
appId
=
namespace
.
getAppId
();
String
actualClusterName
=
namespace
.
getClusterName
();
List
<
NamespaceVO
.
ItemVO
>
itemVos
=
new
LinkedList
<>();
namespaceVO
.
setItems
(
itemVos
);
return
transformNamespace2BO
(
appId
,
env
,
actualClusterName
,
namespace
);
}
private
NamespaceBO
transformNamespace2BO
(
String
appId
,
Env
env
,
String
clusterName
,
NamespaceDTO
namespace
)
{
NamespaceBO
namespaceBO
=
new
NamespaceBO
();
namespaceBO
.
setBaseInfo
(
namespace
);
fillAppNamespaceProperties
(
namespaceBO
);
List
<
ItemBO
>
itemBOs
=
new
LinkedList
<>();
namespaceBO
.
setItems
(
itemBOs
);
String
namespaceName
=
namespace
.
getNamespaceName
();
...
...
@@ -137,7 +147,7 @@ public class NamespaceService {
Map
<
String
,
String
>
releaseItems
=
new
HashMap
<>();
latestRelease
=
releaseService
.
loadLatestRelease
(
appId
,
env
,
clusterName
,
namespaceName
);
if
(
latestRelease
!=
null
)
{
releaseItems
=
gson
.
fromJson
(
latestRelease
.
getConfigurations
(),
mapType
);
releaseItems
=
gson
.
fromJson
(
latestRelease
.
getConfigurations
(),
GsonType
.
CONFIG
);
}
//not Release config items
...
...
@@ -145,26 +155,26 @@ public class NamespaceService {
int
modifiedItemCnt
=
0
;
for
(
ItemDTO
itemDTO
:
items
)
{
NamespaceVO
.
ItemVO
itemVO
=
parseItemV
O
(
itemDTO
,
releaseItems
);
ItemBO
itemBO
=
transformItem2B
O
(
itemDTO
,
releaseItems
);
if
(
item
V
O
.
isModified
())
{
if
(
item
B
O
.
isModified
())
{
modifiedItemCnt
++;
}
item
Vos
.
add
(
itemV
O
);
item
BOs
.
add
(
itemB
O
);
}
//deleted items
List
<
NamespaceVO
.
ItemV
O
>
deletedItems
=
parseDeletedItems
(
items
,
releaseItems
);
item
Vo
s
.
addAll
(
deletedItems
);
List
<
ItemB
O
>
deletedItems
=
parseDeletedItems
(
items
,
releaseItems
);
item
BO
s
.
addAll
(
deletedItems
);
modifiedItemCnt
+=
deletedItems
.
size
();
namespace
V
O
.
setItemModifiedCnt
(
modifiedItemCnt
);
namespace
B
O
.
setItemModifiedCnt
(
modifiedItemCnt
);
return
namespace
V
O
;
return
namespace
B
O
;
}
private
void
fillAppNamespaceProperties
(
Namespace
V
O
namespace
)
{
private
void
fillAppNamespaceProperties
(
Namespace
B
O
namespace
)
{
NamespaceDTO
namespaceDTO
=
namespace
.
getBaseInfo
();
//先从当前appId下面找,包含私有的和公共的
...
...
@@ -190,14 +200,14 @@ public class NamespaceService {
namespace
.
setPublic
(
isPublic
);
}
private
List
<
NamespaceVO
.
ItemV
O
>
parseDeletedItems
(
List
<
ItemDTO
>
newItems
,
Map
<
String
,
String
>
releaseItems
)
{
private
List
<
ItemB
O
>
parseDeletedItems
(
List
<
ItemDTO
>
newItems
,
Map
<
String
,
String
>
releaseItems
)
{
Map
<
String
,
ItemDTO
>
newItemMap
=
BeanUtils
.
mapByKey
(
"key"
,
newItems
);
List
<
NamespaceVO
.
ItemV
O
>
deletedItems
=
new
LinkedList
<>();
List
<
ItemB
O
>
deletedItems
=
new
LinkedList
<>();
for
(
Map
.
Entry
<
String
,
String
>
entry
:
releaseItems
.
entrySet
())
{
String
key
=
entry
.
getKey
();
if
(
newItemMap
.
get
(
key
)
==
null
)
{
NamespaceVO
.
ItemVO
deletedItem
=
new
NamespaceVO
.
ItemV
O
();
ItemBO
deletedItem
=
new
ItemB
O
();
deletedItem
.
setDeleted
(
true
);
ItemDTO
deletedItemDto
=
new
ItemDTO
();
...
...
@@ -215,19 +225,19 @@ public class NamespaceService {
return
deletedItems
;
}
private
NamespaceVO
.
ItemVO
parseItemV
O
(
ItemDTO
itemDTO
,
Map
<
String
,
String
>
releaseItems
)
{
private
ItemBO
transformItem2B
O
(
ItemDTO
itemDTO
,
Map
<
String
,
String
>
releaseItems
)
{
String
key
=
itemDTO
.
getKey
();
NamespaceVO
.
ItemVO
itemVO
=
new
NamespaceVO
.
ItemV
O
();
item
V
O
.
setItem
(
itemDTO
);
ItemBO
itemBO
=
new
ItemB
O
();
item
B
O
.
setItem
(
itemDTO
);
String
newValue
=
itemDTO
.
getValue
();
String
oldValue
=
releaseItems
.
get
(
key
);
//new item or modified
if
(!
StringUtils
.
isEmpty
(
key
)
&&
(
oldValue
==
null
||
!
newValue
.
equals
(
oldValue
)))
{
item
V
O
.
setModified
(
true
);
item
V
O
.
setOldValue
(
oldValue
==
null
?
""
:
oldValue
);
item
V
O
.
setNewValue
(
newValue
);
item
B
O
.
setModified
(
true
);
item
B
O
.
setOldValue
(
oldValue
==
null
?
""
:
oldValue
);
item
B
O
.
setNewValue
(
newValue
);
}
return
item
V
O
;
return
item
B
O
;
}
}
apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ReleaseService.java
View file @
f5218b17
...
...
@@ -11,9 +11,9 @@ import com.ctrip.framework.apollo.core.utils.StringUtils;
import
com.ctrip.framework.apollo.portal.api.AdminServiceAPI
;
import
com.ctrip.framework.apollo.portal.constant.CatEventType
;
import
com.ctrip.framework.apollo.portal.entity.model.NamespaceReleaseModel
;
import
com.ctrip.framework.apollo.portal.entity.
v
o.KVEntity
;
import
com.ctrip.framework.apollo.portal.entity.
b
o.KVEntity
;
import
com.ctrip.framework.apollo.portal.entity.vo.ReleaseCompareResult
;
import
com.ctrip.framework.apollo.portal.entity.
vo.ReleaseV
O
;
import
com.ctrip.framework.apollo.portal.entity.
bo.ReleaseB
O
;
import
com.ctrip.framework.apollo.portal.enums.ChangeType
;
import
com.ctrip.framework.apollo.portal.spi.UserInfoHolder
;
import
com.ctrip.framework.apollo.tracer.Tracer
;
...
...
@@ -65,7 +65,7 @@ public class ReleaseService {
deleteBranch
,
changeSets
);
}
public
List
<
Release
V
O
>
findAllReleases
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
,
int
page
,
public
List
<
Release
B
O
>
findAllReleases
(
String
appId
,
Env
env
,
String
clusterName
,
String
namespaceName
,
int
page
,
int
size
)
{
List
<
ReleaseDTO
>
releaseDTOs
=
releaseAPI
.
findAllReleases
(
appId
,
env
,
clusterName
,
namespaceName
,
page
,
size
);
...
...
@@ -73,9 +73,9 @@ public class ReleaseService {
return
Collections
.
emptyList
();
}
List
<
Release
V
O
>
releases
=
new
LinkedList
<>();
List
<
Release
B
O
>
releases
=
new
LinkedList
<>();
for
(
ReleaseDTO
releaseDTO
:
releaseDTOs
)
{
Release
VO
release
=
new
ReleaseV
O
();
Release
BO
release
=
new
ReleaseB
O
();
release
.
setBaseInfo
(
releaseDTO
);
Set
<
KVEntity
>
kvEntities
=
new
LinkedHashSet
<>();
...
...
apollo-portal/src/main/resources/static/scripts/controller/config/ConfigNamespaceController.js
View file @
f5218b17
...
...
@@ -62,6 +62,7 @@ function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigSer
function
(
result
)
{
$scope
.
namespaces
=
result
;
$
(
'
.config-item-container
'
).
removeClass
(
'
hide
'
);
},
function
(
result
)
{
toastr
.
error
(
AppUtil
.
errorMsg
(
result
),
"
加载配置信息出错
"
);
...
...
@@ -138,10 +139,9 @@ function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigSer
$scope
.
item
=
_
.
clone
(
toEditItem
);
if
(
namespace
.
isBranch
)
{
if
(
namespace
.
isBranch
||
namespace
.
isLinkedNamespace
)
{
var
existedItem
=
false
;
namespace
.
items
.
forEach
(
function
(
item
)
{
//branch items contain the item
if
(
!
item
.
isDeleted
&&
item
.
item
.
key
==
toEditItem
.
key
)
{
existedItem
=
true
;
}
...
...
@@ -270,7 +270,7 @@ function controller($rootScope, $scope, toastr, AppUtil, EventManager, ConfigSer
$
(
'
.config-item-container
'
).
removeClass
(
'
hide
'
);
new
Clipboard
(
'
.clipboard
'
);
}
...
...
apollo-portal/src/main/resources/static/scripts/directive/namespace-panel-directive.js
View file @
f5218b17
...
...
@@ -40,7 +40,6 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
ALL
:
'
all
'
};
var
operate_branch_storage_key
=
'
OperateBranch
'
;
scope
.
switchView
=
switchView
;
...
...
@@ -101,6 +100,7 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
initNamespaceLock
(
namespace
);
initNamespaceInstancesCount
(
namespace
);
initPermission
(
namespace
);
initLinkedNamespace
(
namespace
);
function
initNamespaceBranch
(
namespace
)
{
NamespaceBranchService
.
findNamespaceBranch
(
scope
.
appId
,
scope
.
env
,
...
...
@@ -221,6 +221,44 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
});
}
function
initLinkedNamespace
(
namespace
)
{
if
(
!
namespace
.
isPublic
||
!
namespace
.
isLinkedNamespace
)
{
return
;
}
//load public namespace
ConfigService
.
load_public_namespace
(
scope
.
env
,
scope
.
cluster
,
namespace
.
baseInfo
.
namespaceName
)
.
then
(
function
(
result
)
{
var
publicNamespace
=
result
;
namespace
.
publicNamespace
=
publicNamespace
;
var
linkNamespaceItemKeys
=
[];
namespace
.
items
.
forEach
(
function
(
item
)
{
var
key
=
item
.
item
.
key
;
linkNamespaceItemKeys
.
push
(
key
);
});
publicNamespace
.
viewItems
=
[];
publicNamespace
.
items
.
forEach
(
function
(
item
)
{
var
key
=
item
.
item
.
key
;
if
(
key
){
publicNamespace
.
viewItems
.
push
(
item
);
}
item
.
covered
=
linkNamespaceItemKeys
.
indexOf
(
key
)
>=
0
;
if
(
item
.
isModified
||
item
.
isDeleted
)
{
publicNamespace
.
isModified
=
true
;
}
else
if
(
key
){
publicNamespace
.
hasPublishedItem
=
true
;
}
});
});
}
function
initNamespaceViewName
(
namespace
)
{
//namespace view name hide suffix
namespace
.
viewName
=
...
...
@@ -270,7 +308,7 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
switchBranch
(
operateBranchStorage
[
namespaceId
]);
}
}
function
initNamespaceInstancesCount
(
namespace
)
{
...
...
@@ -497,11 +535,11 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
scope
.
namespace
.
baseInfo
.
namespaceName
,
branch
.
baseInfo
.
clusterName
)
.
then
(
function
(
result
)
{
if
(
result
.
appId
)
{
branch
.
rules
=
result
;
}
},
function
(
result
)
{
toastr
.
error
(
AppUtil
.
errorMsg
(
result
),
"
加载灰度规则出错
"
);
});
...
...
@@ -684,7 +722,7 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
namespace
.
itemCnt
=
itemCnt
;
return
result
;
}
function
toggleItemSearchInput
(
namespace
)
{
namespace
.
showSearchInput
=
!
namespace
.
showSearchInput
;
}
...
...
@@ -727,7 +765,7 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
var
parentNamespace
=
branch
.
parentNamespace
;
if
(
!
parentNamespace
.
hasReleasePermission
)
{
AppUtil
.
showModal
(
'
#releaseNoPermissionDialog
'
);
}
else
if
(
branch
.
lockOwner
&&
scope
.
user
==
branch
.
lockOwner
)
{
}
else
if
(
branch
.
lockOwner
&&
scope
.
user
==
branch
.
lockOwner
)
{
AppUtil
.
showModal
(
'
#releaseDenyDialog
'
);
}
else
if
(
parentNamespace
.
itemModifiedCnt
>
0
)
{
AppUtil
.
showModal
(
'
#mergeAndReleaseDenyDialog
'
);
...
...
@@ -741,6 +779,10 @@ function directive($window, toastr, AppUtil, EventManager, PermissionService, Na
EventManager
.
emit
(
EventManager
.
EventType
.
PRE_ROLLBACK_NAMESPACE
,
{
namespace
:
namespace
});
}
setTimeout
(
function
()
{
scope
.
namespace
.
show
=
true
;
},
200
);
}
}
}
...
...
apollo-portal/src/main/resources/static/scripts/services/ConfigService.js
View file @
f5218b17
...
...
@@ -5,6 +5,11 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
isArray
:
false
,
url
:
'
/apps/:appId/envs/:env/clusters/:clusterName/namespaces/:namespaceName
'
},
load_public_namespace
:
{
method
:
'
GET
'
,
isArray
:
false
,
url
:
'
/envs/:env/clusters/:clusterName/namespaces/:namespaceName/public
'
},
load_all_namespaces
:
{
method
:
'
GET
'
,
isArray
:
true
,
...
...
@@ -58,6 +63,19 @@ appService.service("ConfigService", ['$resource', '$q', function ($resource, $q)
});
return
d
.
promise
;
},
load_public_namespace
:
function
(
env
,
clusterName
,
namespaceName
)
{
var
d
=
$q
.
defer
();
config_source
.
load_public_namespace
({
env
:
env
,
clusterName
:
clusterName
,
namespaceName
:
namespaceName
},
function
(
result
)
{
d
.
resolve
(
result
);
},
function
(
result
)
{
d
.
reject
(
result
);
});
return
d
.
promise
;
},
load_all_namespaces
:
function
(
appId
,
env
,
clusterName
)
{
var
d
=
$q
.
defer
();
config_source
.
load_all_namespaces
({
...
...
apollo-portal/src/main/resources/static/scripts/services/ReleaseService.js
View file @
f5218b17
...
...
@@ -98,6 +98,29 @@ appService.service('ReleaseService', ['$resource', '$q', function ($resource, $q
});
return
d
.
promise
;
}
function
findLatestActiveRelease
(
appId
,
env
,
clusterName
,
namespaceName
)
{
var
d
=
$q
.
defer
();
resource
.
find_active_releases
({
appId
:
appId
,
env
:
env
,
clusterName
:
clusterName
,
namespaceName
:
namespaceName
,
page
:
0
,
size
:
1
},
function
(
result
)
{
if
(
result
&&
result
.
length
){
d
.
resolve
(
result
[
0
]);
}
d
.
resolve
(
undefined
);
},
function
(
result
)
{
d
.
reject
(
result
);
});
return
d
.
promise
;
}
function
compare
(
env
,
baseReleaseId
,
toCompareReleaseId
)
{
var
d
=
$q
.
defer
();
...
...
@@ -133,6 +156,7 @@ appService.service('ReleaseService', ['$resource', '$q', function ($resource, $q
grayPublish
:
createGrayRelease
,
findAllRelease
:
findAllReleases
,
findActiveReleases
:
findActiveReleases
,
findLatestActiveRelease
:
findLatestActiveRelease
,
compare
:
compare
,
rollback
:
rollback
}
...
...
apollo-portal/src/main/resources/static/styles/common-style.css
View file @
f5218b17
...
...
@@ -50,6 +50,14 @@ p, td, span {
border
:
solid
1px
#c3c3c3
;
}
.padding-top-5
{
padding-top
:
5px
;
}
.border-top
{
border-top
:
1px
solid
#ddd
;
}
.active
{
background
:
#f5f5f5
;
}
...
...
@@ -336,6 +344,7 @@ table th {
.namespace-panel
{
border-top
:
0
;
border-bottom
:
0
;
}
.namespace-panel
.namespace-name
{
...
...
@@ -388,6 +397,10 @@ table th {
}
.namespace-panel
.no-config-panel
{
padding
:
15px
0
;
}
.namespace-panel
.history-view
{
padding
:
10px
20px
;
...
...
@@ -724,4 +737,10 @@ table th {
width
:
auto
!important
;
}
.search-onblur
{
background
:
#f5f5f5
;
}
.search-focus
{
background
:
#fff
;
}
apollo-portal/src/main/resources/static/views/component/namespace-panel-branch-tab.html
0 → 100644
View file @
f5218b17
<section
class=
"branch-panel-body"
ng-if=
"namespace.hasBranch && namespace.currentOperateBranch != 'master'"
>
<!--main header-->
<header
class=
"panel-heading"
>
<div
class=
"row"
>
<div
class=
"col-md-6 header-namespace"
>
<b
class=
"namespace-name"
ng-bind=
"namespace.viewName"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"{{namespace.comment}}"
></b>
<span
class=
"label label-info no-radius namespace-label"
ng-bind=
"namespace.format"
></span>
<span
class=
"label label-warning no-radius namespace-label"
ng-show=
"namespace.branch.itemModifiedCnt > 0"
>
有修改
<span
class=
"badge label badge-white namespace-label"
ng-bind=
"namespace.branch.itemModifiedCnt"
></span>
</span>
<span
class=
"label label-primary no-radius namespace-label"
ng-show=
"namespace.branch.lockOwner"
>
当前修改者:
<span
ng-bind=
"namespace.branch.lockOwner"
></span>
</span>
</div>
<div
class=
"col-md-6 text-right header-buttons"
>
<a
type=
"button"
class=
"btn btn-success btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"继续灰度发布"
ng-show=
"(namespace.hasReleasePermission || namespace.hasModifyPermission)"
ng-click=
"publish(namespace.branch)"
>
灰度发布
</a>
<a
type=
"button"
class=
"btn btn-primary btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"合并到主版本并发布主版本配置"
ng-show=
"(namespace.hasReleasePermission || namespace.hasModifyPermission)"
ng-click=
"mergeAndPublish(namespace.branch)"
>
全量发布
</a>
<a
type=
"button"
class=
"btn btn-warning btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"废弃灰度版本"
ng-show=
"(namespace.hasReleasePermission
|| (!namespace.branch.latestRelease && namespace.hasModifyPermission))"
ng-click=
"preDeleteBranch(namespace.branch)"
>
放弃灰度
</a>
</div>
</div>
</header>
<!--second header-->
<header
class=
"panel-heading second-panel-heading"
>
<div
class=
"row"
>
<div
class=
"col-md-8 pull-left"
>
<ul
class=
"nav nav-tabs"
>
<li
role=
"presentation"
ng-click=
"switchView(namespace.branch, 'table')"
ng-show=
"namespace.isPropertiesFormat"
>
<a
ng-class=
"{node_active:namespace.branch.viewType == 'table'}"
>
<img
src=
"img/table.png"
>
配置
</a>
</li>
<li
role=
"presentation"
ng-click=
"switchView(namespace.branch, 'rule')"
>
<a
ng-class=
"{node_active:namespace.branch.viewType == 'rule'}"
>
<img
src=
"img/rule.png"
>
灰度规则
<span
class=
"badge badge-grey"
ng-bind=
"namespace.branch.grayIps.length + namespace.branch.grayApps.length"
></span>
</a>
</li>
<li
role=
"presentation"
ng-click=
"switchView(namespace.branch, 'instance')"
>
<a
ng-class=
"{node_active:namespace.branch.viewType == 'instance'}"
>
<img
src=
"img/machine.png"
>
灰度实例列表
<span
class=
"badge badge-grey"
ng-bind=
"namespace.branch.latestReleaseInstances.total"
></span>
</a>
</li>
<li
role=
"presentation"
ng-click=
"switchView(namespace.branch, 'history')"
>
<a
ng-class=
"{node_active:namespace.branch.viewType == 'history'}"
>
<img
src=
"img/change.png"
>
更改历史
</a>
</li>
</ul>
</div>
</div>
</header>
<section>
<!--items-->
<div
class=
"namespace-view-table"
ng-show=
"namespace.branch.viewType == 'table'"
>
<div
class=
"panel panel-default"
ng-if=
"namespace.hasBranch"
>
<div
class=
"panel-heading"
>
灰度的配置
<button
type=
"button"
class=
"btn btn-primary btn-sm pull-right"
style=
"margin-top: -4px;"
ng-show=
"namespace.hasModifyPermission"
ng-click=
"createItem(namespace.branch)"
>
<img
src=
"img/plus.png"
>
新增灰度配置
</button>
</div>
<table
class=
"table table-bordered table-striped table-hover"
>
<thead>
<tr>
<th>
发布状态
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.key';desc=!desc;"
>
Key
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
主版本的值
</th>
<th>
灰度的值
</th>
<th>
备注
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedBy';desc=!desc;"
>
最后修改人
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedTime';desc=!desc;"
>
最后修改时间
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
操作
</th>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"config in namespace.branch.branchItems |orderBy:col:desc"
ng-if=
"config.item.key"
>
<td
width=
"7%"
class=
"text-center"
>
<span
class=
"label label-warning no-radius cursor-pointer"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"点击查看已发布的值"
ng-if=
"config.isModified || config.isDeleted"
ng-click=
"showText(config.oldValue)"
>
未发布
</span>
<span
class=
"label label-default-light no-radius"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"已生效的配置"
ng-if=
"!config.isModified"
>
已发布
</span>
</td>
<td
width=
"15%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.key)"
>
<span
ng-bind=
"config.item.key | limitTo: 250"
></span>
<span
ng-bind=
"config.item.key.length > 250 ? '...' :''"
></span>
<span
class=
"label label-danger"
ng-if=
"config.isDeleted"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"删除的配置"
>
删
</span>
<span
class=
"label label-info"
ng-if=
"!config.isDeleted && config.masterReleaseValue"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改主版本的配置"
>
改
</span>
<span
class=
"label label-success"
ng-if=
"!config.isDeleted && !config.masterReleaseValue"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"灰度版本特有的配置"
>
新
</span>
</td>
<td
width=
"20%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.masterReleaseValue)"
>
<span
ng-bind=
"config.masterReleaseValue | limitTo: 250"
></span>
<span
ng-bind=
"config.item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"20%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.value)"
>
<span
ng-bind=
"config.item.value | limitTo: 250"
></span>
<span
ng-bind=
"config.item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"10%"
title=
"{{config.item.comment}}"
>
<span
ng-bind=
"config.item.comment | limitTo: 250"
></span>
<span
ng-bind=
"config.item.comment.length > 250 ?'...' : ''"
></span>
</td>
<td
width=
"10%"
ng-bind=
"config.item.dataChangeLastModifiedBy"
>
</td>
<td
width=
"10%"
ng-bind=
"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'"
>
</td>
<td
width=
"9%"
class=
"text-center"
>
<img
src=
"img/edit.png"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改"
ng-if=
"!config.isDeleted"
ng-click=
"editItem(namespace.branch, config.item)"
ng-show=
"namespace.hasModifyPermission"
>
<img
style=
"margin-left: 5px;"
src=
"img/cancel.png"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"删除"
ng-if=
"!config.isDeleted"
ng-click=
"preDeleteItem(namespace.branch, config.item.id)"
ng-show=
"namespace.hasModifyPermission"
>
</td>
</tr>
</tbody>
</table>
</div>
<div
class=
"panel panel-default"
ng-if=
"namespace.branch.masterItems && namespace.branch.masterItems.length > 0"
>
<div
class=
"panel-heading"
>
主版本的配置
</div>
<table
class=
"table table-bordered table-striped table-hover"
>
<thead>
<tr>
<th>
发布状态
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.key';desc=!desc;"
>
Key
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
Value
</th>
<th>
备注
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedBy';desc=!desc;"
>
最后修改人
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedTime';desc=!desc;"
>
最后修改时间
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
操作
</th>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"config in namespace.branch.masterItems |orderBy:col:desc"
ng-if=
"config.item.key"
>
<td
width=
"8%"
class=
"text-center"
>
<span
class=
"label label-warning no-radius cursor-pointer"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"点击查看已发布的值"
ng-if=
"config.isModified || config.isDeleted"
ng-click=
"showText(config.oldValue)"
>
未发布
</span>
<span
class=
"label label-default-light no-radius"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"已生效的配置"
ng-if=
"!config.isModified"
>
已发布
</span>
</td>
<td
width=
"15%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.key)"
>
<span
ng-bind=
"config.item.key | limitTo: 250"
></span>
<span
ng-bind=
"config.item.key.length > 250 ? '...' :''"
></span>
<span
class=
"label label-success"
ng-if=
"config.isModified && !config.oldValue"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"新增的配置"
>
新
</span>
<span
class=
"label label-info"
ng-if=
"config.isModified && config.oldValue && !config.isDeleted"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改的配置"
>
改
</span>
<span
class=
"label label-danger"
ng-if=
"config.isDeleted"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"删除的配置"
>
删
</span>
</td>
<td
width=
"35%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.value)"
>
<span
ng-bind=
"config.item.value | limitTo: 250"
></span>
<span
ng-bind=
"config.item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"12%"
title=
"{{config.item.comment}}"
>
<span
ng-bind=
"config.item.comment | limitTo: 250"
></span>
<span
ng-bind=
"config.item.comment.length > 250 ?'...' : ''"
></span>
</td>
<td
width=
"10%"
ng-bind=
"config.item.dataChangeLastModifiedBy"
>
</td>
<td
width=
"15%"
ng-bind=
"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'"
>
</td>
<td
width=
"5%"
class=
"text-center"
>
<img
src=
"img/gray.png"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"对此配置灰度"
ng-if=
"!config.isDeleted"
ng-click=
"editItem(namespace.branch, config.item)"
ng-show=
"namespace.hasModifyPermission"
>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!--gray rules-->
<div
class=
"rules-manage-view row"
ng-show=
"namespace.branch.viewType == 'rule'"
>
<div
class=
"alert alert-warning no-radius"
ng-show=
"!namespace.hasModifyPermission && !namespace.hasReleasePermission"
>
<strong>
Tips:
</strong>
您没有权限编辑灰度规则, 具有namespace修改权或者发布权的人员才可以编辑灰度规则. 如需要编辑灰度规则,请找项目管理员申请权限.
</div>
<table
class=
"table table-bordered table-hover"
>
<thead>
<tr>
<th>
灰度的AppId
</th>
<th>
灰度的IP列表
</th>
<th>
操作
</th>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"ruleItem in namespace.branch.rules.ruleItems"
>
<td
width=
"20%"
ng-bind=
"ruleItem.clientAppId"
></td>
<td
width=
"70%"
ng-show=
"!ruleItem.ApplyToAllInstances"
ng-bind=
"ruleItem.clientIpList.join(', ')"
></td>
<td
width=
"70%"
ng-show=
"ruleItem.ApplyToAllInstances"
>
ALL
</td>
<td
class=
"text-center"
width=
"10%"
>
<img
src=
"img/edit.png"
class=
"i-20 hover"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改"
ng-show=
"namespace.hasModifyPermission || namespace.hasReleasePermission"
ng-click=
"editRuleItem(namespace.branch, ruleItem)"
>
<img
src=
"img/cancel.png"
class=
"i-20 hover"
style=
"margin-left: 5px;"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"删除"
ng-show=
"namespace.hasModifyPermission || namespace.hasReleasePermission"
ng-click=
"deleteRuleItem(namespace.branch, ruleItem)"
>
</td>
</tr>
</tbody>
</table>
<button
class=
"btn btn-primary"
ng-if=
"namespace.hasModifyPermission || namespace.hasReleasePermission"
ng-show=
"(namespace.isPublic && !namespace.isLinkedNamespace) ||
((!namespace.isPublic || namespace.isLinkedNamespace)
&& (!namespace.branch.rules
|| !namespace.branch.rules.ruleItems
|| !namespace.branch.rules.ruleItems.length))"
ng-click=
"addRuleItem(namespace.branch)"
>
新增规则
</button>
</div>
<!--instances -->
<div
class=
"panel panel-default"
ng-show=
"namespace.branch.viewType == 'instance'"
>
<div
class=
"panel-heading text-right"
>
<button
class=
"btn btn-default btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"刷新列表"
ng-click=
"refreshInstancesInfo(namespace.branch)"
>
<img
src=
"../../img/refresh.png"
/>
</button>
</div>
<div
class=
"panel-body"
>
<div
class=
"panel-default"
ng-if=
"namespace.branch.latestReleaseInstances.total > 0"
>
<div
class=
"panel-heading"
>
<a
target=
"_blank"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"查看配置"
href=
"/config/history.html?#/appid={{appId}}&env={{env}}&clusterName={{namespace.baseInfo.clusterName}}&namespaceName={{namespace.baseInfo.namespaceName}}&releaseId={{namespace.branch.latestRelease.id}}"
>
{{namespace.branch.latestRelease.name}}
</a>
</div>
<table
class=
"table table-bordered table-striped"
>
<thead>
<tr>
<td>
App ID
</td>
<td>
Cluster Name
</td>
<td>
Data Center
</td>
<td>
IP
</td>
<td>
配置获取时间
</td>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"instance in namespace.branch.latestReleaseInstances.content"
>
<td
width=
"20%"
ng-bind=
"instance.appId"
></td>
<td
width=
"20%"
ng-bind=
"instance.clusterName"
></td>
<td
width=
"20%"
ng-bind=
"instance.dataCenter"
></td>
<td
width=
"20%"
ng-bind=
"instance.ip"
></td>
<td
width=
"20%"
>
{{instance.configs
&&
instance.configs.length ?
(instance.configs[0].releaseDeliveryTime | date: 'yyyy-MM-dd HH:mm:ss') : ''}}
</td>
</tr>
</tbody>
</table>
<div
class=
"row text-center"
ng-show=
"namespace.branch.latestReleaseInstances.content.length < namespace.branch.latestReleaseInstances.total"
>
<button
class=
"btn btn-default"
ng-click=
"loadInstanceInfo(namespace.branch)"
>
加载更多
</button>
</div>
</div>
<div
class=
"text-center"
ng-if=
"namespace.branch.latestReleaseInstances.total == 0"
>
无实例信息
</div>
</div>
</div>
<!--history view-->
<div
class=
"J_historyview history-view"
ng-show=
"namespace.branch.viewType == 'history'"
>
<div
class=
"media"
ng-repeat=
"commits in namespace.branch.commits"
>
<div
class=
"media-body"
>
<div
class=
"row"
>
<div
class=
"col-md-6"
><h3
class=
"media-heading"
ng-bind=
"commits.dataChangeCreatedBy"
></h3>
</div>
<div
class=
"col-md-6 text-right"
>
<h5
class=
"media-heading"
ng-bind=
"commits.dataChangeCreatedTime | date: 'yyyy-MM-dd HH:mm:ss'"
></h5>
</div>
</div>
<!--properties format-->
<table
class=
"table table-bordered table-striped text-center table-hover"
style=
"margin-top: 5px;"
ng-if=
"namespace.isPropertiesFormat"
>
<thead>
<tr>
<th>
Type
</th>
<th>
Key
</th>
<th>
Old Value
</th>
<th>
New Value
</th>
<th>
Comment
</th>
</tr>
</thead>
<tbody>
<!--兼容老数据,不显示item类型为空行和注释的item-->
<tr
ng-repeat=
"item in commits.changeSets.createItems"
ng-show=
"item.key"
>
<td
width=
"2%"
>
新增
</td>
<td
width=
"20%"
title=
"{{item.key}}"
>
<span
ng-bind=
"item.key | limitTo: 250"
></span>
<span
ng-bind=
"item.key.length > 250 ? '...' :''"
></span>
</td>
<td
width=
"30%"
>
</td>
<td
width=
"30%"
class=
"cursor-pointer"
title=
"{{item.value}}"
ng-click=
"showText(item.value)"
>
<span
ng-bind=
"item.value | limitTo: 250"
></span>
<span
ng-bind=
"item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"18%"
title=
"{{item.comment}}"
>
<span
ng-bind=
"item.comment | limitTo: 250"
></span>
<span
ng-bind=
"item.comment.length > 250 ?'...' : ''"
></span>
</td>
</tr>
<tr
ng-repeat=
"item in commits.changeSets.updateItems"
>
<td
width=
"2%"
>
更新
</td>
<td
width=
"20%"
title=
"{{item.newItem.key}}"
>
<span
ng-bind=
"item.newItem.key | limitTo: 250"
></span>
<span
ng-bind=
"item.newItem.key.length > 250 ? '...' :''"
></span>
</td>
<td
width=
"30%"
class=
"cursor-pointer"
title=
"{{item.oldItem.value}}"
ng-click=
"showText(item.oldItem.value)"
>
<span
ng-bind=
"item.oldItem.value | limitTo: 250"
></span>
<span
ng-bind=
"item.oldItem.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"30%"
class=
"cursor-pointer"
title=
"{{item.newItem.value}}"
ng-click=
"showText(item.newItem.value)"
>
<span
ng-bind=
"item.newItem.value | limitTo: 250"
></span>
<span
ng-bind=
"item.newItem.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"18%"
title=
"{{item.newItem.comment}}"
>
<span
ng-bind=
"item.newItem.comment | limitTo: 250"
></span>
<span
ng-bind=
"item.newItem.comment.length > 250 ?'...' : ''"
></span>
</td>
</tr>
<tr
ng-repeat=
"item in commits.changeSets.deleteItems"
ng-show=
"item.key || item.comment"
>
<td
width=
"2%"
>
删除
</td>
<td
width=
"20%"
title=
"{{item.key}}"
>
<span
ng-bind=
"item.key | limitTo: 250"
></span>
<span
ng-bind=
"item.key.length > 250 ? '...' :''"
></span>
</td>
<td
width=
"30%"
title=
"{{item.value}}"
>
<span
ng-bind=
"item.value | limitTo: 250"
></span>
<span
ng-bind=
"item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"30%"
>
</td>
<td
width=
"18%"
title=
"{{item.comment}}"
>
<span
ng-bind=
"item.comment | limitTo: 250"
></span>
<span
ng-bind=
"item.comment.length > 250 ?'...' : ''"
></span>
</td>
</tr>
</tbody>
</table>
<!--not properties format-->
<div
ng-if=
"!namespace.isPropertiesFormat"
>
<div
ng-repeat=
"item in commits.changeSets.createItems"
>
<textarea
class=
"form-control no-radius"
rows=
"20"
ng-disabled=
"true"
ng-bind=
"item.value"
>
</textarea>
</div>
<div
ng-repeat=
"item in commits.changeSets.updateItems"
>
<textarea
class=
"form-control no-radius"
rows=
"20"
ng-disabled=
"true"
ng-bind=
"item.newItem.value"
>
</textarea>
</div>
</div>
</div>
<hr>
</div>
<div
class=
"text-center"
>
<button
type=
"button"
class=
"btn btn-default"
ng-show=
"!namespace.branch.hasLoadAllCommit"
ng-click=
"loadCommitHistory(namespace.branch)"
>
加载更多
<span
class=
"glyphicon glyphicon-menu-down"
></span></button>
</div>
</div>
</section>
</section>
apollo-portal/src/main/resources/static/views/component/namespace-panel-header.html
0 → 100644
View file @
f5218b17
<header
class=
"row namespace-attribute-panel"
>
<div
class=
"text-center namespace-attribute-public"
>
<span
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"私有namespace({{namespace.baseInfo.namespaceName}})的配置只能被AppId为{{appId}}的客户端读取到"
ng-show=
"!namespace.isPublic"
>
私有
</span>
<span
data-tooltip=
"tooltip"
data-placement=
"top"
title=
"namespace({{namespace.baseInfo.namespaceName}})的配置能被任何客户端读取到"
ng-show=
"namespace.isPublic && namespace.parentAppId == namespace.baseInfo.appId"
>
公共
</span>
<span
data-tooltip=
"tooltip"
data-placement=
"top"
title=
"namespace({{namespace.baseInfo.namespaceName}})的配置将会覆盖公共namespace的配置, 且合并之后的配置只能被AppId为{{appId}}的客户端读取到"
ng-show=
"namespace.isPublic && namespace.isLinkedNamespace"
ng-click=
"goToParentAppConfigPage(namespace)"
>
关联
</span>
</div>
</header>
<!--branch nav-->
<header
class=
"panel-heading second-panel-heading"
ng-show=
"namespace.hasBranch"
>
<div
class=
"row"
>
<div
class=
"col-md-8 pull-left"
>
<ul
class=
"nav nav-tabs"
>
<li
role=
"presentation"
>
<a
ng-class=
"{'node_active': namespace.currentOperateBranch == 'master'}"
ng-click=
"switchBranch('master')"
>
<img
src=
"img/branch.png"
>
主版本
</a>
</li>
<li
role=
"presentation"
>
<a
ng-class=
"{'node_active': namespace.currentOperateBranch != 'master'}"
ng-click=
"switchBranch(namespace.branchName)"
>
<img
src=
"img/branch.png"
>
灰度版本
</a>
</li>
</ul>
</div>
</div>
</header>
apollo-portal/src/main/resources/static/views/component/namespace-panel-master-tab.html
0 → 100644
View file @
f5218b17
<!--master panel body-->
<section
class=
"master-panel-body"
ng-if=
"namespace.hasBranch
&& namespace.currentOperateBranch == 'master' ||
!namespace.hasBranch"
>
<!--main header-->
<header
class=
"panel-heading"
>
<div
class=
"row"
>
<div
class=
"col-md-6 header-namespace"
>
<b
class=
"namespace-name"
ng-bind=
"namespace.viewName"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"{{namespace.comment}}"
></b>
<span
class=
"label label-info no-radius namespace-label"
ng-bind=
"namespace.format"
></span>
<span
class=
"label label-warning no-radius namespace-label"
ng-show=
"namespace.itemModifiedCnt > 0"
>
有修改
<span
class=
"badge label badge-white namespace-label"
ng-bind=
"namespace.itemModifiedCnt"
></span>
</span>
<span
class=
"label label-primary no-radius namespace-label"
ng-show=
"namespace.lockOwner"
>
当前修改者:{{namespace.lockOwner}}
</span>
</div>
<div
class=
"col-md-6 text-right header-buttons"
>
<button
type=
"button"
class=
"btn btn-success btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"发布配置"
ng-show=
"(namespace.hasReleasePermission || namespace.hasModifyPermission)"
ng-disabled=
"namespace.isTextEditing"
ng-click=
"publish(namespace)"
>
<img
src=
"img/release.png"
>
发布
</button>
<button
type=
"button"
class=
"btn btn-default btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"回滚已发布配置"
ng-show=
"namespace.hasReleasePermission"
ng-click=
"rollback(namespace)"
>
<img
src=
"img/rollback.png"
>
回滚
</button>
<a
type=
"button"
class=
"btn btn-default btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"查看发布历史"
href=
"/config/history.html?#/appid={{appId}}&env={{env}}&clusterName={{cluster}}&namespaceName={{namespace.baseInfo.namespaceName}}"
>
<img
src=
"img/release-history.png"
>
发布历史
</a>
<a
type=
"button"
class=
"btn btn-default btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"配置修改、发布权限"
href=
"/namespace/role.html?#/appid={{appId}}&namespaceName={{namespace.baseInfo.namespaceName}}"
ng-show=
"hasAssignUserPermission"
>
<img
src=
"img/assign.png"
>
授权
</a>
<a
type=
"button"
class=
"btn btn-default btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"创建测试版本"
ng-show=
"!namespace.hasBranch && namespace.isPropertiesFormat && namespace.hasModifyPermission"
ng-click=
"preCreateBranch(namespace)"
>
<img
src=
"img/test.png"
>
创建灰度
</a>
<a
type=
"button"
class=
"btn btn-default btn-sm J_tableview_btn"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"您没有任何配置权限,请申请"
ng-click=
"showNoModifyPermissionDialog()"
ng-show=
"!namespace.hasModifyPermission && !namespace.hasReleasePermission"
>
申请配置权限
</a>
</div>
</div>
</header>
<!--second header-->
<header
class=
"panel-heading second-panel-heading"
>
<div
class=
"row"
>
<div
class=
"col-md-8 pull-left"
>
<!--master branch nav tabs-->
<ul
class=
"nav nav-tabs"
>
<li
role=
"presentation"
ng-click=
"switchView(namespace, 'table')"
ng-show=
"namespace.isPropertiesFormat"
>
<a
ng-class=
"{node_active:namespace.viewType == 'table'}"
>
<img
src=
"img/table.png"
>
表格
</a>
</li>
<li
role=
"presentation"
ng-click=
"switchView(namespace, 'text')"
>
<a
ng-class=
"{node_active:namespace.viewType == 'text'}"
>
<img
src=
"img/text.png"
>
文本
</a>
</li>
<li
role=
"presentation"
ng-click=
"switchView(namespace, 'history')"
>
<a
ng-class=
"{node_active:namespace.viewType == 'history'}"
>
<img
src=
"img/change.png"
>
更改历史
</a>
</li>
<li
role=
"presentation"
ng-click=
"switchView(namespace, 'instance')"
>
<a
ng-class=
"{node_active:namespace.viewType == 'instance'}"
>
<img
src=
"img/machine.png"
>
实例列表
<span
class=
"badge badge-grey"
ng-bind=
"namespace.instancesCount"
></span>
</a>
</li>
</ul>
</div>
<div
class=
"col-md-4 text-right"
>
<a
class=
"clipboard"
data-clipboard-text=
"{{namespace.text}}"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"复制文本"
ng-show=
"!namespace.isTextEditing && namespace.viewType == 'text' && namespace.hasModifyPermission"
>
<img
src=
"img/copy.png"
class=
"ns_btn"
>
</a>
<a
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"取消修改"
ng-show=
"namespace.isTextEditing && namespace.viewType == 'text'"
ng-click=
"toggleTextEditStatus(namespace)"
>
<img
src=
"img/cancel.png"
class=
"ns_btn"
>
</a>
<a
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改配置"
ng-show=
"!namespace.isTextEditing && namespace.viewType == 'text' && namespace.hasModifyPermission"
ng-click=
"toggleTextEditStatus(namespace)"
>
<img
src=
"img/edit.png"
class=
"ns_btn"
>
</a>
<a
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"提交修改"
data-toggle=
"modal"
data-target=
"#commitModal"
ng-show=
"namespace.isTextEditing && namespace.viewType == 'text'"
ng-click=
"modifyByText(namespace)"
>
<img
src=
"img/submit.png"
class=
"ns_btn"
>
</a>
<button
type=
"button"
class=
"btn btn-default btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"按Key过滤配置"
ng-show=
"namespace.viewType == 'table' && namespace.currentOperateBranch == 'master'
&& !namespace.isLinkedNamespace"
ng-click=
"toggleItemSearchInput(namespace)"
>
<span
class=
"glyphicon glyphicon-filter"
></span>
过滤配置
</button>
<button
type=
"button"
class=
"btn btn-default btn-sm J_tableview_btn"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"同步各环境间配置"
ng-click=
"goToSyncPage(namespace)"
ng-show=
"namespace.viewType == 'table' && namespace.currentOperateBranch == 'master'
&& namespace.hasModifyPermission && namespace.isPropertiesFormat"
>
<img
src=
"img/sync.png"
>
同步配置
</button>
<button
type=
"button"
class=
"btn btn-primary btn-sm"
ng-show=
"!namespace.isLinkedNamespace
&& namespace.viewType == 'table'
&& namespace.currentOperateBranch == 'master'
&& namespace.hasModifyPermission"
ng-click=
"createItem(namespace)"
>
<img
src=
"img/plus.png"
>
新增配置
</button>
</div>
</div>
</header>
<section>
<!--table view-->
<div
class=
"namespace-view-table"
ng-show=
"namespace.viewType == 'table'"
>
<!--not link namespace-->
<div
ng-if=
"!namespace.isLinkedNamespace"
>
<div
class=
"col-md-8 col-lg-offset-2 search-input"
ng-show=
"namespace.showSearchInput"
>
<input
type=
"text"
class=
"form-control"
placeholder=
"输入key过滤"
ng-model=
"namespace.searchKey"
ng-change=
"searchItems(namespace)"
>
</div>
<table
class=
"table table-bordered table-striped table-hover"
>
<thead>
<tr>
<th>
发布状态
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.key';desc=!desc;"
>
Key
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
Value
</th>
<th>
备注
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedBy';desc=!desc;"
>
最后修改人
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedTime';desc=!desc;"
>
最后修改时间
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
操作
</th>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"config in namespace.viewItems |orderBy:col:desc"
ng-if=
"config.item.key"
>
<td
width=
"8%"
class=
"text-center"
>
<span
class=
"label label-warning no-radius cursor-pointer"
ng-if=
"config.isModified"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"点击查看已发布的值"
ng-click=
"showText(config.oldValue?config.oldValue:'新增的配置,无发布的值')"
>
未发布
</span>
<span
class=
"label label-default-light no-radius"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"已生效的配置"
ng-if=
"!config.isModified"
>
已发布
</span>
</td>
<td
width=
"15%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.key)"
>
<span
ng-bind=
"config.item.key | limitTo: 250"
></span>
<span
ng-bind=
"config.item.key.length > 250 ? '...' :''"
></span>
<span
class=
"label label-default cursor-pointer"
ng-if=
"config.hasBranchValue"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"该配置有灰度配置,点击查看灰度的值"
ng-click=
"namespace.currentOperateBranch=namespace.branchName;namespace.branch.viewType='table'"
>
灰
</span>
<span
class=
"label label-success"
ng-if=
"config.isModified && !config.oldValue"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"新增的配置"
>
新
</span>
<span
class=
"label label-info"
ng-if=
"config.isModified && config.oldValue && !config.isDeleted"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改的配置"
>
改
</span>
<span
class=
"label label-danger"
ng-if=
"config.isDeleted"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"删除的配置"
>
删
</span>
</td>
<td
width=
"30%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.value)"
>
<span
ng-bind=
"config.item.value | limitTo: 250"
></span>
<span
ng-bind=
"config.item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"13%"
title=
"{{config.item.comment}}"
>
<span
ng-bind=
"config.item.comment | limitTo: 250"
></span>
<span
ng-bind=
"config.item.comment.length > 250 ?'...' : ''"
></span>
</td>
<td
width=
"10%"
ng-bind=
"config.item.dataChangeLastModifiedBy"
>
</td>
<td
width=
"16%"
ng-bind=
"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'"
>
</td>
<td
width=
"8%"
class=
"text-center"
ng-if=
"!config.isDeleted"
>
<img
src=
"img/edit.png"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改"
ng-click=
"editItem(namespace, config.item)"
ng-show=
"namespace.hasModifyPermission"
>
<img
style=
"margin-left: 5px;"
src=
"img/cancel.png"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"删除"
ng-click=
"preDeleteItem(namespace, config.item.id)"
ng-show=
"namespace.hasModifyPermission"
>
</td>
<td
width=
"6%"
class=
"text-center"
ng-if=
"config.isDeleted"
>
</td>
</tr>
</tbody>
</table>
</div>
<!--link namespace-->
<div
class=
"panel panel-default"
ng-if=
"namespace.isLinkedNamespace"
>
<div
class=
"panel-heading"
>
<div
class=
"row"
>
<div
class=
"padding-top-5 col-md-4"
>
覆盖的配置
</div>
<div
class=
"col-md-2 col-lg-offset-6 text-right"
>
<input
type=
"text"
class=
"form-control"
placeholder=
"filter by key ..."
ng-class=
"{'search-onblur': namespace.searchStatus == 'OFF' || !namespace.searchStatus,
'search-focus': namespace.searchStatus == 'ON'}"
ng-model=
"namespace.searchKey"
ng-change=
"searchItems(namespace)"
ng-focus=
"namespace.searchStatus='ON'"
ng-blur=
"namespace.searchStatus='OFF'"
>
</div>
</div>
</div>
<table
class=
"table table-bordered table-striped table-hover"
ng-if=
"namespace.viewItems && namespace.viewItems.length"
>
<thead>
<tr>
<th>
发布状态
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.key';desc=!desc;"
>
Key
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
Value
</th>
<th>
备注
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedBy';desc=!desc;"
>
最后修改人
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedTime';desc=!desc;"
>
最后修改时间
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
操作
</th>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"config in namespace.viewItems |orderBy:col:desc"
ng-if=
"config.item.key"
>
<td
width=
"8%"
class=
"text-center"
>
<span
class=
"label label-warning no-radius cursor-pointer"
ng-if=
"config.isModified"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"点击查看已发布的值"
ng-click=
"showText(config.oldValue?config.oldValue:'新增的配置,无发布的值')"
>
未发布
</span>
<span
class=
"label label-default-light no-radius"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"已生效的配置"
ng-if=
"!config.isModified"
>
已发布
</span>
</td>
<td
width=
"15%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.key)"
>
<span
ng-bind=
"config.item.key | limitTo: 250"
></span>
<span
ng-bind=
"config.item.key.length > 250 ? '...' :''"
></span>
<span
class=
"label label-default cursor-pointer"
ng-if=
"config.hasBranchValue"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"该配置有灰度配置,点击查看灰度的值"
ng-click=
"namespace.currentOperateBranch=namespace.branchName;namespace.branch.viewType='table'"
>
灰
</span>
<span
class=
"label label-success"
ng-if=
"config.isModified && !config.oldValue"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"新增的配置"
>
新
</span>
<span
class=
"label label-info"
ng-if=
"config.isModified && config.oldValue && !config.isDeleted"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改的配置"
>
改
</span>
<span
class=
"label label-danger"
ng-if=
"config.isDeleted"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"删除的配置"
>
删
</span>
</td>
<td
width=
"30%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.value)"
>
<span
ng-bind=
"config.item.value | limitTo: 250"
></span>
<span
ng-bind=
"config.item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"13%"
title=
"{{config.item.comment}}"
>
<span
ng-bind=
"config.item.comment | limitTo: 250"
></span>
<span
ng-bind=
"config.item.comment.length > 250 ?'...' : ''"
></span>
</td>
<td
width=
"10%"
ng-bind=
"config.item.dataChangeLastModifiedBy"
>
</td>
<td
width=
"16%"
ng-bind=
"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'"
>
</td>
<td
width=
"8%"
class=
"text-center"
ng-if=
"!config.isDeleted"
>
<img
src=
"img/edit.png"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改"
ng-click=
"editItem(namespace, config.item)"
ng-show=
"namespace.hasModifyPermission"
>
<img
style=
"margin-left: 5px;"
src=
"img/cancel.png"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"删除"
ng-click=
"preDeleteItem(namespace, config.item.id)"
ng-show=
"namespace.hasModifyPermission"
>
</td>
<td
width=
"6%"
class=
"text-center"
ng-if=
"config.isDeleted"
>
</td>
</tr>
</tbody>
</table>
<div
class=
"text-center no-config-panel"
ng-if=
"!namespace.viewItems || !namespace.viewItems.length"
>
<h5>
无覆盖的配置
</h5>
</div>
</div>
<!--link namespace's public namespace-->
<div
class=
"panel panel-default"
ng-if=
"namespace.isLinkedNamespace"
>
<div
class=
"panel-heading"
>
<div
class=
"row"
>
<div
class=
"padding-top-5 col-md-4"
>
公共的配置
<a
href=
"/config.html?#/appid={{namespace.publicNamespace.baseInfo.appId}}"
target=
"_blank"
>
<small>
(AppId:{{namespace.publicNamespace.baseInfo.appId}},
Cluster:{{namespace.publicNamespace.baseInfo.clusterName}})
</small>
</a>
</div>
<div
class=
"col-md-4 text-center"
>
<div
class=
"btn-group btn-group-sm"
role=
"group"
ng-show=
"namespace.publicNamespace.isModified"
>
<button
type=
"button"
class=
"btn btn-default"
ng-class=
"{'active':namespace.publicNamespaceViewType == 'RELEASE'
|| !namespace.publicNamespaceViewType}"
ng-click=
"namespace.publicNamespaceViewType = 'RELEASE'"
>
已发布的配置
</button>
<button
type=
"button"
class=
"btn btn-default"
ng-class=
"{'active':namespace.publicNamespaceViewType == 'NOT_RELEASE'}"
ng-click=
"namespace.publicNamespaceViewType = 'NOT_RELEASE'"
>
未发布的配置
</button>
</div>
</div>
<div
class=
"col-md-2 col-lg-offset-2 text-right"
>
<input
type=
"text"
class=
"form-control"
placeholder=
"filter by key ..."
ng-class=
"{'search-onblur': namespace.publicNamespace.searchStatus == 'OFF'
|| !namespace.publicNamespace.searchStatus,
'search-focus': namespace.publicNamespace.searchStatus == 'ON'}"
ng-model=
"namespace.publicNamespace.searchKey"
ng-change=
"searchItems(namespace.publicNamespace)"
ng-blur=
"namespace.publicNamespace.searchStatus='OFF'"
ng-focus=
"namespace.publicNamespace.searchStatus='ON'"
/>
</div>
</div>
</div>
<!--published items-->
<div
ng-show=
"!namespace.publicNamespaceViewType || namespace.publicNamespaceViewType == 'RELEASE'"
>
<table
class=
"table table-bordered table-striped table-hover"
ng-show=
"namespace.publicNamespace.hasPublishedItem"
>
<thead>
<tr>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.key';desc=!desc;"
>
Key
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
Value
</th>
<th>
备注
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedBy';desc=!desc;"
>
最后修改人
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedTime';desc=!desc;"
>
最后修改时间
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
操作
</th>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"config in namespace.publicNamespace.viewItems |orderBy:col:desc"
ng-if=
"config.item.key && !config.isModified && !config.isDeleted"
>
<td
width=
"15%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.key)"
>
<span
ng-bind=
"config.item.key | limitTo: 250"
></span>
<span
ng-bind=
"config.item.key.length > 250 ? '...' :''"
></span>
</td>
<td
width=
"35%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.value)"
>
<span
ng-bind=
"config.item.value | limitTo: 250"
></span>
<span
ng-bind=
"config.item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"15%"
title=
"{{config.item.comment}}"
>
<span
ng-bind=
"config.item.comment | limitTo: 250"
></span>
<span
ng-bind=
"config.item.comment.length > 250 ?'...' : ''"
></span>
</td>
<td
width=
"10%"
ng-bind=
"config.item.dataChangeLastModifiedBy"
>
</td>
<td
width=
"15%"
ng-bind=
"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'"
>
</td>
<td
width=
"10%"
class=
"text-center"
ng-if=
"!config.isDeleted"
>
<img
src=
"img/gray.png"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"覆盖此配置"
ng-click=
"editItem(namespace, config.item)"
ng-show=
"namespace.hasModifyPermission && !config.covered"
>
</td>
<td
width=
"6%"
class=
"text-center"
ng-if=
"config.isDeleted"
>
</td>
</tr>
</tbody>
</table>
<div
class=
"text-center no-config-panel"
ng-if=
"namespace.publicNamespace.viewItems
&& namespace.publicNamespace.viewItems.length
&& !namespace.publicNamespace.hasPublishedItem"
>
<h5>
无发布的配置
</h5>
</div>
</div>
<!--not published items-->
<table
class=
"table table-bordered table-striped table-hover"
ng-show=
"namespace.publicNamespaceViewType == 'NOT_RELEASE'"
>
<thead>
<tr>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.key';desc=!desc;"
>
Key
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
Old Value
</th>
<th>
New Value
</th>
<th>
备注
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedTime';desc=!desc;"
>
最后修改时间
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
操作
</th>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"config in namespace.publicNamespace.viewItems |orderBy:col:desc"
ng-if=
"config.item.key && (config.isModified || config.isDeleted)"
>
<td
width=
"20%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.key)"
>
<span
ng-bind=
"config.item.key | limitTo: 250"
></span>
<span
ng-bind=
"config.item.key.length > 250 ? '...' :''"
></span>
<span
class=
"label label-success"
ng-if=
"config.isModified && !config.oldValue"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"新增的配置"
>
新
</span>
<span
class=
"label label-info"
ng-if=
"config.isModified && config.oldValue && !config.isDeleted"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改的配置"
>
改
</span>
<span
class=
"label label-danger"
ng-if=
"config.isDeleted"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"删除的配置"
>
删
</span>
</td>
<td
width=
"25%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.oldValue)"
>
<span
ng-bind=
"config.oldValue | limitTo: 250"
></span>
<span
ng-bind=
"config.oldValue.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"25%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.value)"
>
<span
ng-bind=
"config.item.value | limitTo: 250"
></span>
<span
ng-bind=
"config.item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"10%"
title=
"{{config.item.comment}}"
>
<span
ng-bind=
"config.item.comment | limitTo: 250"
></span>
<span
ng-bind=
"config.item.comment.length > 250 ?'...' : ''"
></span>
</td>
<td
width=
"15%"
ng-bind=
"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'"
>
</td>
<td
width=
"5%"
class=
"text-center"
ng-if=
"!config.isDeleted"
>
<img
src=
"img/gray.png"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"覆盖此配置"
ng-click=
"editItem(namespace, config.item)"
ng-show=
"namespace.hasModifyPermission && !config.covered"
>
</td>
</tr>
</tbody>
</table>
<div
class=
"text-center no-config-panel"
ng-if=
"!namespace.publicNamespace.viewItems || !namespace.publicNamespace.viewItems.length"
>
<h5>
无公共的配置
</h5>
</div>
</div>
</div>
<!--text view-->
<!--只读模式下的文本内容,不替换换行符-->
<textarea
class=
"form-control no-radius"
rows=
"{{namespace.itemCnt < 10 ? 10: namespace.itemCnt>20 ? 20:namespace.itemCnt}}"
ng-show=
"namespace.viewType == 'text' && !namespace.isTextEditing"
ng-disabled=
"!namespace.isTextEditing"
ng-bind=
"namespace.text"
>
</textarea>
<!--编辑状态下的文本内容,会过滤掉换行符-->
<textarea
class=
"form-control no-radius"
rows=
"{{namespace.itemCnt < 10 ? 10: namespace.itemCnt>20 ? 20:namespace.itemCnt}}"
ng-show=
"namespace.viewType == 'text' && namespace.isTextEditing"
ng-disabled=
"!namespace.isTextEditing"
ng-model=
"namespace.editText"
>
</textarea>
<!--history view-->
<div
class=
"J_historyview history-view"
ng-show=
"namespace.viewType == 'history'"
>
<div
class=
"media"
ng-repeat=
"commits in namespace.commits"
>
<div
class=
"media-body"
>
<div
class=
"row"
>
<div
class=
"col-md-6"
><h3
class=
"media-heading"
ng-bind=
"commits.dataChangeCreatedBy"
></h3>
</div>
<div
class=
"col-md-6 text-right"
><h5
class=
"media-heading"
ng-bind=
"commits.dataChangeCreatedTime | date: 'yyyy-MM-dd HH:mm:ss'"
></h5>
</div>
</div>
<!--properties format-->
<table
class=
"table table-bordered table-striped text-center table-hover"
style=
"margin-top: 5px;"
ng-if=
"namespace.isPropertiesFormat"
>
<thead>
<tr>
<th>
Type
</th>
<th>
Key
</th>
<th>
Old Value
</th>
<th>
New Value
</th>
<th>
Comment
</th>
</tr>
</thead>
<tbody>
<!--兼容老数据,不显示item类型为空行和注释的item-->
<tr
ng-repeat=
"item in commits.changeSets.createItems"
ng-show=
"item.key"
>
<td
width=
"2%"
>
新增
</td>
<td
width=
"20%"
title=
"{{item.key}}"
>
<span
ng-bind=
"item.key | limitTo: 250"
></span>
<span
ng-bind=
"item.key.length > 250 ? '...' :''"
></span>
</td>
<td
width=
"30%"
>
</td>
<td
width=
"30%"
class=
"cursor-pointer"
title=
"{{item.value}}"
ng-click=
"showText(item.value)"
>
<span
ng-bind=
"item.value | limitTo: 250"
></span>
<span
ng-bind=
"item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"18%"
title=
"{{item.comment}}"
>
<span
ng-bind=
"item.comment | limitTo: 250"
></span>
<span
ng-bind=
"item.comment.length > 250 ?'...' : ''"
></span>
</td>
</tr>
<tr
ng-repeat=
"item in commits.changeSets.updateItems"
>
<td
width=
"2%"
>
更新
</td>
<td
width=
"20%"
title=
"{{item.newItem.key}}"
>
<span
ng-bind=
"item.newItem.key | limitTo: 250"
></span>
<span
ng-bind=
"item.newItem.key.length > 250 ? '...' :''"
></span>
</td>
<td
width=
"30%"
class=
"cursor-pointer"
title=
"{{item.oldItem.value}}"
ng-click=
"showText(item.oldItem.value)"
>
<span
ng-bind=
"item.oldItem.value | limitTo: 250"
></span>
<span
ng-bind=
"item.oldItem.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"30%"
class=
"cursor-pointer"
title=
"{{item.newItem.value}}"
ng-click=
"showText(item.newItem.value)"
>
<span
ng-bind=
"item.newItem.value | limitTo: 250"
></span>
<span
ng-bind=
"item.newItem.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"18%"
title=
"{{item.newItem.comment}}"
>
<span
ng-bind=
"item.newItem.comment | limitTo: 250"
></span>
<span
ng-bind=
"item.newItem.comment.length > 250 ?'...' : ''"
></span>
</td>
</tr>
<tr
ng-repeat=
"item in commits.changeSets.deleteItems"
ng-show=
"item.key || item.comment"
>
<td
width=
"2%"
>
删除
</td>
<td
width=
"20%"
title=
"{{item.key}}"
>
<span
ng-bind=
"item.key | limitTo: 250"
></span>
<span
ng-bind=
"item.key.length > 250 ? '...' :''"
></span>
</td>
<td
width=
"30%"
title=
"{{item.value}}"
>
<span
ng-bind=
"item.value | limitTo: 250"
></span>
<span
ng-bind=
"item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"30%"
>
</td>
<td
width=
"18%"
title=
"{{item.comment}}"
>
<span
ng-bind=
"item.comment | limitTo: 250"
></span>
<span
ng-bind=
"item.comment.length > 250 ?'...' : ''"
></span>
</td>
</tr>
</tbody>
</table>
<!--not properties format-->
<div
ng-if=
"!namespace.isPropertiesFormat"
>
<div
ng-repeat=
"item in commits.changeSets.createItems"
>
<textarea
class=
"form-control no-radius"
rows=
"20"
ng-disabled=
"true"
ng-bind=
"item.value"
>
</textarea>
</div>
<div
ng-repeat=
"item in commits.changeSets.updateItems"
>
<textarea
class=
"form-control no-radius"
rows=
"20"
ng-disabled=
"true"
ng-bind=
"item.newItem.value"
>
</textarea>
</div>
</div>
</div>
<hr>
</div>
<div
class=
"text-center"
>
<button
type=
"button"
class=
"btn btn-default"
ng-show=
"!namespace.hasLoadAllCommit"
ng-click=
"loadCommitHistory(namespace)"
>
加载更多
<span
class=
"glyphicon glyphicon-menu-down"
></span></button>
</div>
</div>
<!--instance view-->
<div
class=
"panel panel-default instance-view"
ng-show=
"namespace.viewType == 'instance'"
>
<div
class=
"panel-heading"
>
<div
class=
"row text-right"
style=
"padding-right: 15px;"
>
<div
class=
"btn-group btn-group-sm"
role=
"group"
>
<button
type=
"button"
class=
"btn btn-default"
ng-class=
"{'btn-primary':namespace.instanceViewType == 'latest_release'}"
ng-click=
"switchInstanceViewType(namespace, 'latest_release')"
>
使用最新配置的实例
<span
class=
"badge"
ng-bind=
"namespace.latestReleaseInstances.total"
></span>
</button>
<button
type=
"button"
class=
"btn btn-default"
ng-class=
"{'btn-primary':namespace.instanceViewType == 'not_latest_release'}"
ng-click=
"switchInstanceViewType(namespace, 'not_latest_release')"
>
使用非最新配置的实例
<span
class=
"badge"
ng-bind=
"namespace.instancesCount - namespace.latestReleaseInstances.total"
></span>
</button>
<button
type=
"button"
class=
"btn btn-default"
ng-class=
"{'btn-primary':namespace.instanceViewType == 'all'}"
ng-click=
"switchInstanceViewType(namespace, 'all')"
>
所有实例
<span
class=
"badge"
ng-bind=
"namespace.instancesCount"
></span>
</button>
</div>
<button
class=
"btn btn-default btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"刷新列表"
ng-click=
"refreshInstancesInfo(namespace)"
>
<img
src=
"../../img/refresh.png"
/>
</button>
</div>
</div>
<!--latest release instances-->
<div
class=
"panel-body"
ng-show=
"namespace.instanceViewType == 'latest_release'"
>
<div
class=
"panel-default"
ng-if=
"namespace.latestReleaseInstances.total > 0"
>
<div
class=
"panel-heading"
>
<a
target=
"_blank"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"查看配置"
href=
"/config/history.html?#/appid={{appId}}&env={{env}}&clusterName={{cluster}}&namespaceName={{namespace.baseInfo.namespaceName}}&releaseId={{namespace.latestRelease.id}}"
>
{{namespace.latestRelease.name}}
</a>
</div>
<table
class=
"table table-bordered table-striped"
>
<thead>
<tr>
<td>
App ID
</td>
<td>
Cluster Name
</td>
<td>
Data Center
</td>
<td>
IP
</td>
<td>
配置获取时间
</td>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"instance in namespace.latestReleaseInstances.content"
>
<td
width=
"20%"
ng-bind=
"instance.appId"
></td>
<td
width=
"20%"
ng-bind=
"instance.clusterName"
></td>
<td
width=
"20%"
ng-bind=
"instance.dataCenter"
></td>
<td
width=
"20%"
ng-bind=
"instance.ip"
></td>
<td
width=
"20%"
>
{{instance.configs
&&
instance.configs.length ?
(instance.configs[0].releaseDeliveryTime | date: 'yyyy-MM-dd HH:mm:ss') : ''}}
</td>
</tr>
</tbody>
</table>
<div
class=
"row text-center"
ng-show=
"namespace.latestReleaseInstances.content.length < namespace.latestReleaseInstances.total"
>
<button
class=
"btn btn-default"
ng-click=
"loadInstanceInfo(namespace)"
>
加载更多
</button>
</div>
</div>
<div
class=
"text-center"
ng-if=
"namespace.latestReleaseInstances.total == 0"
>
无实例信息
</div>
</div>
<!--not latest release instances-->
<div
class=
"panel-body"
ng-show=
"namespace.instanceViewType == 'not_latest_release'"
>
<div
class=
"panel-default"
ng-if=
"namespace.instancesCount - namespace.latestReleaseInstances.total > 0"
ng-repeat=
"release in namespace.notLatestReleases"
>
<div
class=
"panel-heading"
>
<a
target=
"_blank"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"查看配置"
href=
"/config/history.html?#/appid={{appId}}&env={{env}}&clusterName={{cluster}}&namespaceName={{namespace.baseInfo.namespaceName}}&releaseId={{release.id}}"
>
{{release.name}}
</a>
</div>
<table
class=
"table table-bordered table-striped"
>
<thead>
<tr>
<td>
App ID
</td>
<td>
Cluster Name
</td>
<td>
Data Center
</td>
<td>
IP
</td>
<td>
配置获取时间
</td>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"instance in namespace.notLatestReleaseInstances[release.id]"
>
<td
width=
"20%"
ng-bind=
"instance.appId"
></td>
<td
width=
"20%"
ng-bind=
"instance.clusterName"
></td>
<td
width=
"20%"
ng-bind=
"instance.dataCenter"
></td>
<td
width=
"20%"
ng-bind=
"instance.ip"
></td>
<td
width=
"20%"
>
{{instance.configs
&&
instance.configs.length ?
(instance.configs[0].releaseDeliveryTime | date: 'yyyy-MM-dd HH:mm:ss') : ''}}
</td>
</tr>
</tbody>
</table>
</div>
<div
class=
"text-center"
ng-if=
"namespace.instancesCount - namespace.latestReleaseInstances.total == 0"
>
无实例信息
</div>
</div>
<!--all instances-->
<div
class=
"panel-body"
ng-show=
"namespace.instanceViewType == 'all'"
>
<div
class=
"panel-default"
ng-if=
"namespace.instancesCount > 0"
>
<table
class=
"table table-bordered table-striped"
ng-if=
"namespace.allInstances"
>
<thead>
<tr>
<td>
App ID
</td>
<td>
Cluster Name
</td>
<td>
Data Center
</td>
<td>
IP
</td>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"instance in namespace.allInstances"
>
<td
width=
"25%"
ng-bind=
"instance.appId"
></td>
<td
width=
"25%"
ng-bind=
"instance.clusterName"
></td>
<td
width=
"25%"
ng-bind=
"instance.dataCenter"
></td>
<td
width=
"25%"
ng-bind=
"instance.ip"
></td>
</tr>
</tbody>
</table>
<div
class=
"row text-center"
ng-show=
"namespace.allInstances.length < namespace.instancesCount"
>
<button
class=
"btn btn-default"
ng-click=
"loadInstanceInfo(namespace)"
>
加载更多
</button>
</div>
</div>
<div
class=
"text-center"
ng-if=
"namespace.instancesCount == 0"
>
无实例信息
</div>
</div>
</div>
</section>
</section>
apollo-portal/src/main/resources/static/views/component/namespace-panel.html
View file @
f5218b17
<section
class=
"panel namespace-panel"
>
<section
class=
"panel namespace-panel"
ng-class=
"{'hidden': !namespace.show}"
>
<!--public or link label-->
<header
class=
"row namespace-attribute-panel"
>
<div
class=
"text-center namespace-attribute-public"
>
<span
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"私有namespace({{namespace.baseInfo.namespaceName}})的配置只能被AppId为{{appId}}的客户端读取到"
ng-show=
"!namespace.isPublic"
>
私有
</span>
<ng-include
src=
"'views/component/namespace-panel-header.html'"
></ng-include>
<span
data-tooltip=
"tooltip"
data-placement=
"top"
title=
"namespace({{namespace.baseInfo.namespaceName}})的配置能被任何客户端读取到"
ng-show=
"namespace.isPublic && namespace.parentAppId == namespace.baseInfo.appId"
>
公共
</span>
<span
data-tooltip=
"tooltip"
data-placement=
"top"
title=
"namespace({{namespace.baseInfo.namespaceName}})的配置将会覆盖公共namespace的配置, 且合并之后的配置只能被AppId为{{appId}}的客户端读取到"
ng-show=
"namespace.isPublic && namespace.isLinkedNamespace"
ng-click=
"goToParentAppConfigPage(namespace)"
>
关联
</span>
</div>
</header>
<!--branch nav-->
<header
class=
"panel-heading second-panel-heading"
ng-show=
"namespace.hasBranch"
>
<div
class=
"row"
>
<div
class=
"col-md-8 pull-left"
>
<ul
class=
"nav nav-tabs"
>
<li
role=
"presentation"
>
<a
ng-class=
"{'node_active': namespace.currentOperateBranch == 'master'}"
ng-click=
"switchBranch('master')"
>
<img
src=
"img/branch.png"
>
主版本
</a>
</li>
<li
role=
"presentation"
>
<a
ng-class=
"{'node_active': namespace.currentOperateBranch != 'master'}"
ng-click=
"switchBranch(namespace.branchName)"
>
<img
src=
"img/branch.png"
>
灰度版本
</a>
</li>
</ul>
</div>
</div>
</header>
<!--master panel body-->
<section
class=
"master-panel-body"
ng-if=
"namespace.hasBranch && namespace.currentOperateBranch == 'master' || !namespace.hasBranch"
>
<!--main header-->
<header
class=
"panel-heading"
>
<div
class=
"row"
>
<div
class=
"col-md-6 header-namespace"
>
<b
class=
"namespace-name"
ng-bind=
"namespace.viewName"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"{{namespace.comment}}"
></b>
<span
class=
"label label-info no-radius namespace-label"
ng-bind=
"namespace.format"
></span>
<span
class=
"label label-warning no-radius namespace-label"
ng-show=
"namespace.itemModifiedCnt > 0"
>
有修改
<span
class=
"badge label badge-white namespace-label"
ng-bind=
"namespace.itemModifiedCnt"
></span>
</span>
<span
class=
"label label-primary no-radius namespace-label"
ng-show=
"namespace.lockOwner"
>
当前修改者:{{namespace.lockOwner}}
</span>
</div>
<div
class=
"col-md-6 text-right header-buttons"
>
<button
type=
"button"
class=
"btn btn-success btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"发布配置"
ng-show=
"(namespace.hasReleasePermission || namespace.hasModifyPermission)"
ng-disabled=
"namespace.isTextEditing"
ng-click=
"publish(namespace)"
>
<img
src=
"img/release.png"
>
发布
</button>
<button
type=
"button"
class=
"btn btn-default btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"回滚已发布配置"
ng-show=
"namespace.hasReleasePermission"
ng-click=
"rollback(namespace)"
>
<img
src=
"img/rollback.png"
>
回滚
</button>
<a
type=
"button"
class=
"btn btn-default btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"查看发布历史"
href=
"/config/history.html?#/appid={{appId}}&env={{env}}&clusterName={{cluster}}&namespaceName={{namespace.baseInfo.namespaceName}}"
>
<img
src=
"img/release-history.png"
>
发布历史
</a>
<a
type=
"button"
class=
"btn btn-default btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"配置修改、发布权限"
href=
"/namespace/role.html?#/appid={{appId}}&namespaceName={{namespace.baseInfo.namespaceName}}"
ng-show=
"hasAssignUserPermission"
>
<img
src=
"img/assign.png"
>
授权
</a>
<a
type=
"button"
class=
"btn btn-default btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"创建测试版本"
ng-show=
"!namespace.hasBranch && namespace.isPropertiesFormat && namespace.hasModifyPermission"
ng-click=
"preCreateBranch(namespace)"
>
<img
src=
"img/test.png"
>
创建灰度
</a>
<a
type=
"button"
class=
"btn btn-default btn-sm J_tableview_btn"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"您没有任何配置权限,请申请"
ng-click=
"showNoModifyPermissionDialog()"
ng-show=
"!namespace.hasModifyPermission && !namespace.hasReleasePermission"
>
申请配置权限
</a>
</div>
</div>
</header>
<!--second header-->
<header
class=
"panel-heading second-panel-heading"
>
<div
class=
"row"
>
<div
class=
"col-md-8 pull-left"
>
<!--master branch nav tabs-->
<ul
class=
"nav nav-tabs"
>
<li
role=
"presentation"
ng-click=
"switchView(namespace, 'table')"
ng-show=
"namespace.isPropertiesFormat"
>
<a
ng-class=
"{node_active:namespace.viewType == 'table'}"
>
<img
src=
"img/table.png"
>
表格
</a>
</li>
<li
role=
"presentation"
ng-click=
"switchView(namespace, 'text')"
>
<a
ng-class=
"{node_active:namespace.viewType == 'text'}"
>
<img
src=
"img/text.png"
>
文本
</a>
</li>
<li
role=
"presentation"
ng-click=
"switchView(namespace, 'history')"
>
<a
ng-class=
"{node_active:namespace.viewType == 'history'}"
>
<img
src=
"img/change.png"
>
更改历史
</a>
</li>
<li
role=
"presentation"
ng-click=
"switchView(namespace, 'instance')"
>
<a
ng-class=
"{node_active:namespace.viewType == 'instance'}"
>
<img
src=
"img/machine.png"
>
实例列表
<span
class=
"badge badge-grey"
ng-bind=
"namespace.instancesCount"
></span>
</a>
</li>
</ul>
</div>
<div
class=
"col-md-4 text-right"
>
<a
class=
"clipboard"
data-clipboard-text=
"{{namespace.text}}"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"复制文本"
ng-show=
"!namespace.isTextEditing && namespace.viewType == 'text' && namespace.hasModifyPermission"
>
<img
src=
"img/copy.png"
class=
"ns_btn"
>
</a>
<a
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"取消修改"
ng-show=
"namespace.isTextEditing && namespace.viewType == 'text'"
ng-click=
"toggleTextEditStatus(namespace)"
>
<img
src=
"img/cancel.png"
class=
"ns_btn"
>
</a>
<a
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改配置"
ng-show=
"!namespace.isTextEditing && namespace.viewType == 'text' && namespace.hasModifyPermission"
ng-click=
"toggleTextEditStatus(namespace)"
>
<img
src=
"img/edit.png"
class=
"ns_btn"
>
</a>
<a
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"提交修改"
data-toggle=
"modal"
data-target=
"#commitModal"
ng-show=
"namespace.isTextEditing && namespace.viewType == 'text'"
ng-click=
"modifyByText(namespace)"
>
<img
src=
"img/submit.png"
class=
"ns_btn"
>
</a>
<button
type=
"button"
class=
"btn btn-default btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"按Key过滤配置"
ng-show=
"namespace.viewType == 'table' && namespace.currentOperateBranch == 'master'"
ng-click=
"toggleItemSearchInput(namespace)"
>
<span
class=
"glyphicon glyphicon-filter"
></span>
过滤配置
</button>
<button
type=
"button"
class=
"btn btn-default btn-sm J_tableview_btn"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"同步各环境间配置"
ng-click=
"goToSyncPage(namespace)"
ng-show=
"namespace.viewType == 'table' && namespace.currentOperateBranch == 'master'
&& namespace.hasModifyPermission && namespace.isPropertiesFormat"
>
<img
src=
"img/sync.png"
>
同步配置
</button>
<button
type=
"button"
class=
"btn btn-primary btn-sm"
ng-show=
"namespace.viewType == 'table' && namespace.currentOperateBranch == 'master'
&& namespace.hasModifyPermission"
ng-click=
"createItem(namespace)"
>
<img
src=
"img/plus.png"
>
新增配置
</button>
</div>
</div>
</header>
<section>
<!--table view-->
<div
class=
"namespace-view-table"
ng-show=
"namespace.viewType == 'table'"
>
<div
class=
"col-md-8 col-lg-offset-2 search-input"
ng-show=
"namespace.showSearchInput"
>
<input
type=
"text"
class=
"form-control"
placeholder=
"输入key过滤"
ng-model=
"namespace.searchKey"
ng-change=
"searchItems(namespace)"
>
</div>
<table
class=
"table table-bordered table-striped table-hover"
>
<thead>
<tr>
<th>
发布状态
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.key';desc=!desc;"
>
Key
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
Value
</th>
<th>
备注
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedBy';desc=!desc;"
>
最后修改人
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedTime';desc=!desc;"
>
最后修改时间
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
操作
</th>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"config in namespace.viewItems |orderBy:col:desc"
ng-if=
"config.item.key"
>
<td
width=
"8%"
class=
"text-center"
>
<span
class=
"label label-warning no-radius cursor-pointer"
ng-if=
"config.isModified"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"点击查看已发布的值"
ng-click=
"showText(config.oldValue?config.oldValue:'新增的配置,无发布的值')"
>
未发布
</span>
<span
class=
"label label-default-light no-radius"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"已生效的配置"
ng-if=
"!config.isModified"
>
已发布
</span>
</td>
<td
width=
"15%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.key)"
>
<span
ng-bind=
"config.item.key | limitTo: 250"
></span>
<span
ng-bind=
"config.item.key.length > 250 ? '...' :''"
></span>
<span
class=
"label label-default cursor-pointer"
ng-if=
"config.hasBranchValue"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"该配置有灰度配置,点击查看灰度的值"
ng-click=
"namespace.currentOperateBranch=namespace.branchName;namespace.branch.viewType='table'"
>
灰
</span>
<span
class=
"label label-success"
ng-if=
"config.isModified && !config.oldValue"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"新增的配置"
>
新
</span>
<span
class=
"label label-info"
ng-if=
"config.isModified && config.oldValue && !config.isDeleted"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改的配置"
>
改
</span>
<span
class=
"label label-danger"
ng-if=
"config.isDeleted"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"删除的配置"
>
删
</span>
</td>
<td
width=
"33%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.value)"
>
<span
ng-bind=
"config.item.value | limitTo: 250"
></span>
<span
ng-bind=
"config.item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"15%"
title=
"{{config.item.comment}}"
>
<span
ng-bind=
"config.item.comment | limitTo: 250"
></span>
<span
ng-bind=
"config.item.comment.length > 250 ?'...' : ''"
></span>
</td>
<td
width=
"10%"
ng-bind=
"config.item.dataChangeLastModifiedBy"
>
</td>
<td
width=
"11%"
ng-bind=
"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'"
>
</td>
<td
width=
"8%"
class=
"text-center"
ng-if=
"!config.isDeleted"
>
<img
src=
"img/edit.png"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改"
ng-click=
"editItem(namespace, config.item)"
ng-show=
"namespace.hasModifyPermission"
>
<img
style=
"margin-left: 5px;"
src=
"img/cancel.png"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"删除"
ng-click=
"preDeleteItem(namespace, config.item.id)"
ng-show=
"namespace.hasModifyPermission"
>
</td>
<td
width=
"6%"
class=
"text-center"
ng-if=
"config.isDeleted"
>
</td>
</tr>
</tbody>
</table>
</div>
<!--text view-->
<!--只读模式下的文本内容,不替换换行符-->
<textarea
class=
"form-control no-radius"
rows=
"{{namespace.itemCnt < 10 ? 10: namespace.itemCnt>20 ? 20:namespace.itemCnt}}"
ng-show=
"namespace.viewType == 'text' && !namespace.isTextEditing"
ng-disabled=
"!namespace.isTextEditing"
ng-bind=
"namespace.text"
>
</textarea>
<!--编辑状态下的文本内容,会过滤掉换行符-->
<textarea
class=
"form-control no-radius"
rows=
"{{namespace.itemCnt < 10 ? 10: namespace.itemCnt>20 ? 20:namespace.itemCnt}}"
ng-show=
"namespace.viewType == 'text' && namespace.isTextEditing"
ng-disabled=
"!namespace.isTextEditing"
ng-model=
"namespace.editText"
>
</textarea>
<!--history view-->
<div
class=
"J_historyview history-view"
ng-show=
"namespace.viewType == 'history'"
>
<div
class=
"media"
ng-repeat=
"commits in namespace.commits"
>
<div
class=
"media-body"
>
<div
class=
"row"
>
<div
class=
"col-md-6"
><h3
class=
"media-heading"
ng-bind=
"commits.dataChangeCreatedBy"
></h3>
</div>
<div
class=
"col-md-6 text-right"
><h5
class=
"media-heading"
ng-bind=
"commits.dataChangeCreatedTime | date: 'yyyy-MM-dd HH:mm:ss'"
></h5>
</div>
</div>
<!--properties format-->
<table
class=
"table table-bordered table-striped text-center table-hover"
style=
"margin-top: 5px;"
ng-if=
"namespace.isPropertiesFormat"
>
<thead>
<tr>
<th>
Type
</th>
<th>
Key
</th>
<th>
Old Value
</th>
<th>
New Value
</th>
<th>
Comment
</th>
</tr>
</thead>
<tbody>
<!--兼容老数据,不显示item类型为空行和注释的item-->
<tr
ng-repeat=
"item in commits.changeSets.createItems"
ng-show=
"item.key"
>
<td
width=
"2%"
>
新增
</td>
<td
width=
"20%"
title=
"{{item.key}}"
>
<span
ng-bind=
"item.key | limitTo: 250"
></span>
<span
ng-bind=
"item.key.length > 250 ? '...' :''"
></span>
</td>
<td
width=
"30%"
>
</td>
<td
width=
"30%"
class=
"cursor-pointer"
title=
"{{item.value}}"
ng-click=
"showText(item.value)"
>
<span
ng-bind=
"item.value | limitTo: 250"
></span>
<span
ng-bind=
"item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"18%"
title=
"{{item.comment}}"
>
<span
ng-bind=
"item.comment | limitTo: 250"
></span>
<span
ng-bind=
"item.comment.length > 250 ?'...' : ''"
></span>
</td>
</tr>
<tr
ng-repeat=
"item in commits.changeSets.updateItems"
>
<td
width=
"2%"
>
更新
</td>
<td
width=
"20%"
title=
"{{item.newItem.key}}"
>
<span
ng-bind=
"item.newItem.key | limitTo: 250"
></span>
<span
ng-bind=
"item.newItem.key.length > 250 ? '...' :''"
></span>
</td>
<td
width=
"30%"
class=
"cursor-pointer"
title=
"{{item.oldItem.value}}"
ng-click=
"showText(item.oldItem.value)"
>
<span
ng-bind=
"item.oldItem.value | limitTo: 250"
></span>
<span
ng-bind=
"item.oldItem.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"30%"
class=
"cursor-pointer"
title=
"{{item.newItem.value}}"
ng-click=
"showText(item.newItem.value)"
>
<span
ng-bind=
"item.newItem.value | limitTo: 250"
></span>
<span
ng-bind=
"item.newItem.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"18%"
title=
"{{item.newItem.comment}}"
>
<span
ng-bind=
"item.newItem.comment | limitTo: 250"
></span>
<span
ng-bind=
"item.newItem.comment.length > 250 ?'...' : ''"
></span>
</td>
</tr>
<tr
ng-repeat=
"item in commits.changeSets.deleteItems"
ng-show=
"item.key || item.comment"
>
<td
width=
"2%"
>
删除
</td>
<td
width=
"20%"
title=
"{{item.key}}"
>
<span
ng-bind=
"item.key | limitTo: 250"
></span>
<span
ng-bind=
"item.key.length > 250 ? '...' :''"
></span>
</td>
<td
width=
"30%"
title=
"{{item.value}}"
>
<span
ng-bind=
"item.value | limitTo: 250"
></span>
<span
ng-bind=
"item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"30%"
>
</td>
<td
width=
"18%"
title=
"{{item.comment}}"
>
<span
ng-bind=
"item.comment | limitTo: 250"
></span>
<span
ng-bind=
"item.comment.length > 250 ?'...' : ''"
></span>
</td>
</tr>
</tbody>
</table>
<!--not properties format-->
<div
ng-if=
"!namespace.isPropertiesFormat"
>
<div
ng-repeat=
"item in commits.changeSets.createItems"
>
<textarea
class=
"form-control no-radius"
rows=
"20"
ng-disabled=
"true"
ng-bind=
"item.value"
>
</textarea>
</div>
<div
ng-repeat=
"item in commits.changeSets.updateItems"
>
<textarea
class=
"form-control no-radius"
rows=
"20"
ng-disabled=
"true"
ng-bind=
"item.newItem.value"
>
</textarea>
</div>
</div>
</div>
<hr>
</div>
<div
class=
"text-center"
>
<button
type=
"button"
class=
"btn btn-default"
ng-show=
"!namespace.hasLoadAllCommit"
ng-click=
"loadCommitHistory(namespace)"
>
加载更多
<span
class=
"glyphicon glyphicon-menu-down"
></span></button>
</div>
</div>
<!--instance view-->
<div
class=
"panel panel-default instance-view"
ng-show=
"namespace.viewType == 'instance'"
>
<div
class=
"panel-heading"
>
<div
class=
"row text-right"
style=
"padding-right: 15px;"
>
<div
class=
"btn-group btn-group-sm"
role=
"group"
>
<button
type=
"button"
class=
"btn btn-default"
ng-class=
"{'btn-primary':namespace.instanceViewType == 'latest_release'}"
ng-click=
"switchInstanceViewType(namespace, 'latest_release')"
>
使用最新配置的实例
<span
class=
"badge"
ng-bind=
"namespace.latestReleaseInstances.total"
></span>
</button>
<button
type=
"button"
class=
"btn btn-default"
ng-class=
"{'btn-primary':namespace.instanceViewType == 'not_latest_release'}"
ng-click=
"switchInstanceViewType(namespace, 'not_latest_release')"
>
使用非最新配置的实例
<span
class=
"badge"
ng-bind=
"namespace.instancesCount - namespace.latestReleaseInstances.total"
></span>
</button>
<button
type=
"button"
class=
"btn btn-default"
ng-class=
"{'btn-primary':namespace.instanceViewType == 'all'}"
ng-click=
"switchInstanceViewType(namespace, 'all')"
>
所有实例
<span
class=
"badge"
ng-bind=
"namespace.instancesCount"
></span>
</button>
</div>
<button
class=
"btn btn-default btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"刷新列表"
ng-click=
"refreshInstancesInfo(namespace)"
>
<img
src=
"../../img/refresh.png"
/>
</button>
</div>
</div>
<!--latest release instances-->
<div
class=
"panel-body"
ng-show=
"namespace.instanceViewType == 'latest_release'"
>
<div
class=
"panel-default"
ng-if=
"namespace.latestReleaseInstances.total > 0"
>
<div
class=
"panel-heading"
>
<a
target=
"_blank"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"查看配置"
href=
"/config/history.html?#/appid={{appId}}&env={{env}}&clusterName={{cluster}}&namespaceName={{namespace.baseInfo.namespaceName}}&releaseId={{namespace.latestRelease.id}}"
>
{{namespace.latestRelease.name}}
</a>
</div>
<table
class=
"table table-bordered table-striped"
>
<thead>
<tr>
<td>
App ID
</td>
<td>
Cluster Name
</td>
<td>
Data Center
</td>
<td>
IP
</td>
<td>
配置获取时间
</td>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"instance in namespace.latestReleaseInstances.content"
>
<td
width=
"20%"
ng-bind=
"instance.appId"
></td>
<td
width=
"20%"
ng-bind=
"instance.clusterName"
></td>
<td
width=
"20%"
ng-bind=
"instance.dataCenter"
></td>
<td
width=
"20%"
ng-bind=
"instance.ip"
></td>
<td
width=
"20%"
>
{{instance.configs
&&
instance.configs.length ?
(instance.configs[0].releaseDeliveryTime | date: 'yyyy-MM-dd HH:mm:ss') : ''}}
</td>
</tr>
</tbody>
</table>
<div
class=
"row text-center"
ng-show=
"namespace.latestReleaseInstances.content.length < namespace.latestReleaseInstances.total"
>
<button
class=
"btn btn-default"
ng-click=
"loadInstanceInfo(namespace)"
>
加载更多
</button>
</div>
</div>
<div
class=
"text-center"
ng-if=
"namespace.latestReleaseInstances.total == 0"
>
无实例信息
</div>
</div>
<!--not latest release instances-->
<div
class=
"panel-body"
ng-show=
"namespace.instanceViewType == 'not_latest_release'"
>
<div
class=
"panel-default"
ng-if=
"namespace.instancesCount - namespace.latestReleaseInstances.total > 0"
ng-repeat=
"release in namespace.notLatestReleases"
>
<div
class=
"panel-heading"
>
<a
target=
"_blank"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"查看配置"
href=
"/config/history.html?#/appid={{appId}}&env={{env}}&clusterName={{cluster}}&namespaceName={{namespace.baseInfo.namespaceName}}&releaseId={{release.id}}"
>
{{release.name}}
</a>
</div>
<table
class=
"table table-bordered table-striped"
>
<thead>
<tr>
<td>
App ID
</td>
<td>
Cluster Name
</td>
<td>
Data Center
</td>
<td>
IP
</td>
<td>
配置获取时间
</td>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"instance in namespace.notLatestReleaseInstances[release.id]"
>
<td
width=
"20%"
ng-bind=
"instance.appId"
></td>
<td
width=
"20%"
ng-bind=
"instance.clusterName"
></td>
<td
width=
"20%"
ng-bind=
"instance.dataCenter"
></td>
<td
width=
"20%"
ng-bind=
"instance.ip"
></td>
<td
width=
"20%"
>
{{instance.configs
&&
instance.configs.length ?
(instance.configs[0].releaseDeliveryTime | date: 'yyyy-MM-dd HH:mm:ss') : ''}}
</td>
</tr>
</tbody>
</table>
</div>
<div
class=
"text-center"
ng-if=
"namespace.instancesCount - namespace.latestReleaseInstances.total == 0"
>
无实例信息
</div>
</div>
<!--all instances-->
<div
class=
"panel-body"
ng-show=
"namespace.instanceViewType == 'all'"
>
<div
class=
"panel-default"
ng-if=
"namespace.instancesCount > 0"
>
<table
class=
"table table-bordered table-striped"
ng-if=
"namespace.allInstances"
>
<thead>
<tr>
<td>
App ID
</td>
<td>
Cluster Name
</td>
<td>
Data Center
</td>
<td>
IP
</td>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"instance in namespace.allInstances"
>
<td
width=
"25%"
ng-bind=
"instance.appId"
></td>
<td
width=
"25%"
ng-bind=
"instance.clusterName"
></td>
<td
width=
"25%"
ng-bind=
"instance.dataCenter"
></td>
<td
width=
"25%"
ng-bind=
"instance.ip"
></td>
</tr>
</tbody>
</table>
<div
class=
"row text-center"
ng-show=
"namespace.allInstances.length < namespace.instancesCount"
>
<button
class=
"btn btn-default"
ng-click=
"loadInstanceInfo(namespace)"
>
加载更多
</button>
</div>
</div>
<div
class=
"text-center"
ng-if=
"namespace.instancesCount == 0"
>
无实例信息
</div>
</div>
</div>
</section>
</section>
<ng-include
src=
"'views/component/namespace-panel-master-tab.html'"
></ng-include>
<!--branch panel body-->
<section
class=
"branch-panel-body"
ng-if=
"namespace.hasBranch && namespace.currentOperateBranch != 'master'"
>
<!--main header-->
<header
class=
"panel-heading"
>
<div
class=
"row"
>
<div
class=
"col-md-6 header-namespace"
>
<b
class=
"namespace-name"
ng-bind=
"namespace.viewName"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"{{namespace.comment}}"
></b>
<span
class=
"label label-info no-radius namespace-label"
ng-bind=
"namespace.format"
></span>
<span
class=
"label label-warning no-radius namespace-label"
ng-show=
"namespace.branch.itemModifiedCnt > 0"
>
有修改
<span
class=
"badge label badge-white namespace-label"
ng-bind=
"namespace.branch.itemModifiedCnt"
></span>
</span>
<span
class=
"label label-primary no-radius namespace-label"
ng-show=
"namespace.branch.lockOwner"
>
当前修改者:
<span
ng-bind=
"namespace.branch.lockOwner"
></span>
</span>
</div>
<div
class=
"col-md-6 text-right header-buttons"
>
<a
type=
"button"
class=
"btn btn-success btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"继续灰度发布"
ng-show=
"(namespace.hasReleasePermission || namespace.hasModifyPermission)"
ng-click=
"publish(namespace.branch)"
>
灰度发布
</a>
<a
type=
"button"
class=
"btn btn-primary btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"合并到主版本并发布主版本配置"
ng-show=
"(namespace.hasReleasePermission || namespace.hasModifyPermission)"
ng-click=
"mergeAndPublish(namespace.branch)"
>
全量发布
</a>
<a
type=
"button"
class=
"btn btn-warning btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"废弃灰度版本"
ng-show=
"(namespace.hasReleasePermission
|| (!namespace.branch.latestRelease && namespace.hasModifyPermission))"
ng-click=
"preDeleteBranch(namespace.branch)"
>
放弃灰度
</a>
</div>
</div>
</header>
<!--second header-->
<header
class=
"panel-heading second-panel-heading"
>
<div
class=
"row"
>
<div
class=
"col-md-8 pull-left"
>
<ul
class=
"nav nav-tabs"
>
<li
role=
"presentation"
ng-click=
"switchView(namespace.branch, 'table')"
ng-show=
"namespace.isPropertiesFormat"
>
<a
ng-class=
"{node_active:namespace.branch.viewType == 'table'}"
>
<img
src=
"img/table.png"
>
配置
</a>
</li>
<li
role=
"presentation"
ng-click=
"switchView(namespace.branch, 'rule')"
>
<a
ng-class=
"{node_active:namespace.branch.viewType == 'rule'}"
>
<img
src=
"img/rule.png"
>
灰度规则
<span
class=
"badge badge-grey"
ng-bind=
"namespace.branch.grayIps.length + namespace.branch.grayApps.length"
></span>
</a>
</li>
<li
role=
"presentation"
ng-click=
"switchView(namespace.branch, 'instance')"
>
<a
ng-class=
"{node_active:namespace.branch.viewType == 'instance'}"
>
<img
src=
"img/machine.png"
>
灰度实例列表
<span
class=
"badge badge-grey"
ng-bind=
"namespace.branch.latestReleaseInstances.total"
></span>
</a>
</li>
<li
role=
"presentation"
ng-click=
"switchView(namespace.branch, 'history')"
>
<a
ng-class=
"{node_active:namespace.branch.viewType == 'history'}"
>
<img
src=
"img/change.png"
>
更改历史
</a>
</li>
</ul>
</div>
</div>
</header>
<section>
<!--items-->
<div
class=
"namespace-view-table"
ng-show=
"namespace.branch.viewType == 'table'"
>
<div
class=
"panel panel-default"
ng-if=
"namespace.hasBranch"
>
<div
class=
"panel-heading"
>
灰度的配置
<button
type=
"button"
class=
"btn btn-primary btn-sm pull-right"
style=
"margin-top: -4px;"
ng-show=
"namespace.hasModifyPermission"
ng-click=
"createItem(namespace.branch)"
>
<img
src=
"img/plus.png"
>
新增灰度配置
</button>
</div>
<table
class=
"table table-bordered table-striped table-hover"
>
<thead>
<tr>
<th>
发布状态
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.key';desc=!desc;"
>
Key
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
主版本的值
</th>
<th>
灰度的值
</th>
<th>
备注
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedBy';desc=!desc;"
>
最后修改人
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedTime';desc=!desc;"
>
最后修改时间
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
操作
</th>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"config in namespace.branch.branchItems |orderBy:col:desc"
ng-if=
"config.item.key"
>
<td
width=
"7%"
class=
"text-center"
>
<span
class=
"label label-warning no-radius cursor-pointer"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"点击查看已发布的值"
ng-if=
"config.isModified || config.isDeleted"
ng-click=
"showText(config.oldValue)"
>
未发布
</span>
<span
class=
"label label-default-light no-radius"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"已生效的配置"
ng-if=
"!config.isModified"
>
已发布
</span>
</td>
<td
width=
"15%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.key)"
>
<span
ng-bind=
"config.item.key | limitTo: 250"
></span>
<span
ng-bind=
"config.item.key.length > 250 ? '...' :''"
></span>
<span
class=
"label label-danger"
ng-if=
"config.isDeleted"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"删除的配置"
>
删
</span>
<span
class=
"label label-info"
ng-if=
"!config.isDeleted && config.masterReleaseValue"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改主版本的配置"
>
改
</span>
<span
class=
"label label-success"
ng-if=
"!config.isDeleted && !config.masterReleaseValue"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"灰度版本特有的配置"
>
新
</span>
</td>
<td
width=
"20%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.masterReleaseValue)"
>
<span
ng-bind=
"config.masterReleaseValue | limitTo: 250"
></span>
<span
ng-bind=
"config.item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"20%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.value)"
>
<span
ng-bind=
"config.item.value | limitTo: 250"
></span>
<span
ng-bind=
"config.item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"10%"
title=
"{{config.item.comment}}"
>
<span
ng-bind=
"config.item.comment | limitTo: 250"
></span>
<span
ng-bind=
"config.item.comment.length > 250 ?'...' : ''"
></span>
</td>
<td
width=
"10%"
ng-bind=
"config.item.dataChangeLastModifiedBy"
>
</td>
<td
width=
"10%"
ng-bind=
"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'"
>
</td>
<td
width=
"9%"
class=
"text-center"
>
<img
src=
"img/edit.png"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改"
ng-if=
"!config.isDeleted"
ng-click=
"editItem(namespace.branch, config.item)"
ng-show=
"namespace.hasModifyPermission"
>
<img
style=
"margin-left: 5px;"
src=
"img/cancel.png"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"删除"
ng-if=
"!config.isDeleted"
ng-click=
"preDeleteItem(namespace.branch, config.item.id)"
ng-show=
"namespace.hasModifyPermission"
>
</td>
</tr>
</tbody>
</table>
</div>
<div
class=
"panel panel-default"
ng-if=
"namespace.branch.masterItems && namespace.branch.masterItems.length > 0"
>
<div
class=
"panel-heading"
>
主版本的配置
</div>
<table
class=
"table table-bordered table-striped table-hover"
>
<thead>
<tr>
<th>
发布状态
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.key';desc=!desc;"
>
Key
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
Value
</th>
<th>
备注
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedBy';desc=!desc;"
>
最后修改人
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th
class=
"hover"
title=
"排序"
ng-click=
"col='item.dataChangeLastModifiedTime';desc=!desc;"
>
最后修改时间
<span
class=
"glyphicon glyphicon-sort"
></span>
</th>
<th>
操作
</th>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"config in namespace.branch.masterItems |orderBy:col:desc"
ng-if=
"config.item.key"
>
<td
width=
"8%"
class=
"text-center"
>
<span
class=
"label label-warning no-radius cursor-pointer"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"点击查看已发布的值"
ng-if=
"config.isModified || config.isDeleted"
ng-click=
"showText(config.oldValue)"
>
未发布
</span>
<span
class=
"label label-default-light no-radius"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"已生效的配置"
ng-if=
"!config.isModified"
>
已发布
</span>
</td>
<td
width=
"15%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.key)"
>
<span
ng-bind=
"config.item.key | limitTo: 250"
></span>
<span
ng-bind=
"config.item.key.length > 250 ? '...' :''"
></span>
<span
class=
"label label-success"
ng-if=
"config.isModified && !config.oldValue"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"新增的配置"
>
新
</span>
<span
class=
"label label-info"
ng-if=
"config.isModified && config.oldValue && !config.isDeleted"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改的配置"
>
改
</span>
<span
class=
"label label-danger"
ng-if=
"config.isDeleted"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"删除的配置"
>
删
</span>
</td>
<td
width=
"35%"
class=
"cursor-pointer"
title=
"点击查看"
ng-click=
"showText(config.item.value)"
>
<span
ng-bind=
"config.item.value | limitTo: 250"
></span>
<span
ng-bind=
"config.item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"15%"
title=
"{{config.item.comment}}"
>
<span
ng-bind=
"config.item.comment | limitTo: 250"
></span>
<span
ng-bind=
"config.item.comment.length > 250 ?'...' : ''"
></span>
</td>
<td
width=
"10%"
ng-bind=
"config.item.dataChangeLastModifiedBy"
>
</td>
<td
width=
"12%"
ng-bind=
"config.item.dataChangeLastModifiedTime | date: 'yyyy-MM-dd HH:mm:ss'"
>
</td>
<td
width=
"5%"
class=
"text-center"
>
<img
src=
"img/gray.png"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"对此配置灰度"
ng-if=
"!config.isDeleted"
ng-click=
"editItem(namespace.branch, config.item)"
ng-show=
"namespace.hasModifyPermission"
>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!--gray rules-->
<div
class=
"rules-manage-view row"
ng-show=
"namespace.branch.viewType == 'rule'"
>
<div
class=
"alert alert-warning no-radius"
ng-show=
"!namespace.hasModifyPermission && !namespace.hasReleasePermission"
>
<strong>
Tips:
</strong>
您没有权限编辑灰度规则, 具有namespace修改权或者发布权的人员才可以编辑灰度规则. 如需要编辑灰度规则,请找项目管理员申请权限.
</div>
<table
class=
"table table-bordered table-hover"
>
<thead>
<tr>
<th>
灰度的AppId
</th>
<th>
灰度的IP列表
</th>
<th>
操作
</th>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"ruleItem in namespace.branch.rules.ruleItems"
>
<td
width=
"20%"
ng-bind=
"ruleItem.clientAppId"
></td>
<td
width=
"70%"
ng-show=
"!ruleItem.ApplyToAllInstances"
ng-bind=
"ruleItem.clientIpList.join(', ')"
></td>
<td
width=
"70%"
ng-show=
"ruleItem.ApplyToAllInstances"
>
ALL
</td>
<td
class=
"text-center"
width=
"10%"
>
<img
src=
"img/edit.png"
class=
"i-20 hover"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"修改"
ng-show=
"namespace.hasModifyPermission || namespace.hasReleasePermission"
ng-click=
"editRuleItem(namespace.branch, ruleItem)"
>
<img
src=
"img/cancel.png"
class=
"i-20 hover"
style=
"margin-left: 5px;"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"删除"
ng-show=
"namespace.hasModifyPermission || namespace.hasReleasePermission"
ng-click=
"deleteRuleItem(namespace.branch, ruleItem)"
>
</td>
</tr>
</tbody>
</table>
<button
class=
"btn btn-primary"
ng-if=
"namespace.hasModifyPermission || namespace.hasReleasePermission"
ng-show=
"(namespace.isPublic && !namespace.isLinkedNamespace) ||
((!namespace.isPublic || namespace.isLinkedNamespace)
&& (!namespace.branch.rules
|| !namespace.branch.rules.ruleItems
|| !namespace.branch.rules.ruleItems.length))"
ng-click=
"addRuleItem(namespace.branch)"
>
新增规则
</button>
</div>
<!--instances -->
<div
class=
"panel panel-default"
ng-show=
"namespace.branch.viewType == 'instance'"
>
<div
class=
"panel-heading text-right"
>
<button
class=
"btn btn-default btn-sm"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"刷新列表"
ng-click=
"refreshInstancesInfo(namespace.branch)"
>
<img
src=
"../../img/refresh.png"
/>
</button>
</div>
<div
class=
"panel-body"
>
<div
class=
"panel-default"
ng-if=
"namespace.branch.latestReleaseInstances.total > 0"
>
<div
class=
"panel-heading"
>
<a
target=
"_blank"
data-tooltip=
"tooltip"
data-placement=
"bottom"
title=
"查看配置"
href=
"/config/history.html?#/appid={{appId}}&env={{env}}&clusterName={{namespace.baseInfo.clusterName}}&namespaceName={{namespace.baseInfo.namespaceName}}&releaseId={{namespace.branch.latestRelease.id}}"
>
{{namespace.branch.latestRelease.name}}
</a>
</div>
<table
class=
"table table-bordered table-striped"
>
<thead>
<tr>
<td>
App ID
</td>
<td>
Cluster Name
</td>
<td>
Data Center
</td>
<td>
IP
</td>
<td>
配置获取时间
</td>
</tr>
</thead>
<tbody>
<tr
ng-repeat=
"instance in namespace.branch.latestReleaseInstances.content"
>
<td
width=
"20%"
ng-bind=
"instance.appId"
></td>
<td
width=
"20%"
ng-bind=
"instance.clusterName"
></td>
<td
width=
"20%"
ng-bind=
"instance.dataCenter"
></td>
<td
width=
"20%"
ng-bind=
"instance.ip"
></td>
<td
width=
"20%"
>
{{instance.configs
&&
instance.configs.length ?
(instance.configs[0].releaseDeliveryTime | date: 'yyyy-MM-dd HH:mm:ss') : ''}}
</td>
</tr>
</tbody>
</table>
<div
class=
"row text-center"
ng-show=
"namespace.branch.latestReleaseInstances.content.length < namespace.branch.latestReleaseInstances.total"
>
<button
class=
"btn btn-default"
ng-click=
"loadInstanceInfo(namespace.branch)"
>
加载更多
</button>
</div>
</div>
<div
class=
"text-center"
ng-if=
"namespace.branch.latestReleaseInstances.total == 0"
>
无实例信息
</div>
</div>
</div>
<!--history view-->
<div
class=
"J_historyview history-view"
ng-show=
"namespace.branch.viewType == 'history'"
>
<div
class=
"media"
ng-repeat=
"commits in namespace.branch.commits"
>
<div
class=
"media-body"
>
<div
class=
"row"
>
<div
class=
"col-md-6"
><h3
class=
"media-heading"
ng-bind=
"commits.dataChangeCreatedBy"
></h3>
</div>
<div
class=
"col-md-6 text-right"
>
<h5
class=
"media-heading"
ng-bind=
"commits.dataChangeCreatedTime | date: 'yyyy-MM-dd HH:mm:ss'"
></h5>
</div>
</div>
<!--properties format-->
<table
class=
"table table-bordered table-striped text-center table-hover"
style=
"margin-top: 5px;"
ng-if=
"namespace.isPropertiesFormat"
>
<thead>
<tr>
<th>
Type
</th>
<th>
Key
</th>
<th>
Old Value
</th>
<th>
New Value
</th>
<th>
Comment
</th>
</tr>
</thead>
<tbody>
<!--兼容老数据,不显示item类型为空行和注释的item-->
<tr
ng-repeat=
"item in commits.changeSets.createItems"
ng-show=
"item.key"
>
<td
width=
"2%"
>
新增
</td>
<td
width=
"20%"
title=
"{{item.key}}"
>
<span
ng-bind=
"item.key | limitTo: 250"
></span>
<span
ng-bind=
"item.key.length > 250 ? '...' :''"
></span>
</td>
<td
width=
"30%"
>
</td>
<td
width=
"30%"
class=
"cursor-pointer"
title=
"{{item.value}}"
ng-click=
"showText(item.value)"
>
<span
ng-bind=
"item.value | limitTo: 250"
></span>
<span
ng-bind=
"item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"18%"
title=
"{{item.comment}}"
>
<span
ng-bind=
"item.comment | limitTo: 250"
></span>
<span
ng-bind=
"item.comment.length > 250 ?'...' : ''"
></span>
</td>
</tr>
<tr
ng-repeat=
"item in commits.changeSets.updateItems"
>
<td
width=
"2%"
>
更新
</td>
<td
width=
"20%"
title=
"{{item.newItem.key}}"
>
<span
ng-bind=
"item.newItem.key | limitTo: 250"
></span>
<span
ng-bind=
"item.newItem.key.length > 250 ? '...' :''"
></span>
</td>
<td
width=
"30%"
class=
"cursor-pointer"
title=
"{{item.oldItem.value}}"
ng-click=
"showText(item.oldItem.value)"
>
<span
ng-bind=
"item.oldItem.value | limitTo: 250"
></span>
<span
ng-bind=
"item.oldItem.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"30%"
class=
"cursor-pointer"
title=
"{{item.newItem.value}}"
ng-click=
"showText(item.newItem.value)"
>
<span
ng-bind=
"item.newItem.value | limitTo: 250"
></span>
<span
ng-bind=
"item.newItem.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"18%"
title=
"{{item.newItem.comment}}"
>
<span
ng-bind=
"item.newItem.comment | limitTo: 250"
></span>
<span
ng-bind=
"item.newItem.comment.length > 250 ?'...' : ''"
></span>
</td>
</tr>
<tr
ng-repeat=
"item in commits.changeSets.deleteItems"
ng-show=
"item.key || item.comment"
>
<td
width=
"2%"
>
删除
</td>
<td
width=
"20%"
title=
"{{item.key}}"
>
<span
ng-bind=
"item.key | limitTo: 250"
></span>
<span
ng-bind=
"item.key.length > 250 ? '...' :''"
></span>
</td>
<td
width=
"30%"
title=
"{{item.value}}"
>
<span
ng-bind=
"item.value | limitTo: 250"
></span>
<span
ng-bind=
"item.value.length > 250 ? '...': ''"
></span>
</td>
<td
width=
"30%"
>
</td>
<td
width=
"18%"
title=
"{{item.comment}}"
>
<span
ng-bind=
"item.comment | limitTo: 250"
></span>
<span
ng-bind=
"item.comment.length > 250 ?'...' : ''"
></span>
</td>
</tr>
</tbody>
</table>
<!--not properties format-->
<div
ng-if=
"!namespace.isPropertiesFormat"
>
<div
ng-repeat=
"item in commits.changeSets.createItems"
>
<textarea
class=
"form-control no-radius"
rows=
"20"
ng-disabled=
"true"
ng-bind=
"item.value"
>
</textarea>
</div>
<div
ng-repeat=
"item in commits.changeSets.updateItems"
>
<textarea
class=
"form-control no-radius"
rows=
"20"
ng-disabled=
"true"
ng-bind=
"item.newItem.value"
>
</textarea>
</div>
</div>
</div>
<hr>
</div>
<div
class=
"text-center"
>
<button
type=
"button"
class=
"btn btn-default"
ng-show=
"!namespace.branch.hasLoadAllCommit"
ng-click=
"loadCommitHistory(namespace.branch)"
>
加载更多
<span
class=
"glyphicon glyphicon-menu-down"
></span></button>
</div>
</div>
</section>
</section>
<ng-include
src=
"'views/component/namespace-panel-branch-tab.html'"
></ng-include>
</section>
apollo-portal/src/test/java/com/ctrip/framework/apollo/portal/service/NamespaceServiceTest.java
View file @
f5218b17
...
...
@@ -8,7 +8,7 @@ import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
import
com.ctrip.framework.apollo.core.enums.Env
;
import
com.ctrip.framework.apollo.portal.api.AdminServiceAPI
;
import
com.ctrip.framework.apollo.portal.components.txtresolver.PropertyResolver
;
import
com.ctrip.framework.apollo.portal.entity.
vo.NamespaceV
O
;
import
com.ctrip.framework.apollo.portal.entity.
bo.NamespaceB
O
;
import
org.junit.Before
;
import
org.junit.Test
;
...
...
@@ -87,9 +87,9 @@ public class NamespaceServiceTest {
when
(
releaseService
.
loadLatestRelease
(
appId
,
Env
.
DEV
,
clusterName
,
"hermes"
)).
thenReturn
(
someRelease
);
when
(
itemService
.
findItems
(
appId
,
Env
.
DEV
,
clusterName
,
namespaceName
)).
thenReturn
(
someItems
);
List
<
Namespace
VO
>
namespaceVOs
=
namespaceService
.
findNamespace
s
(
appId
,
Env
.
DEV
,
clusterName
);
List
<
Namespace
BO
>
namespaceVOs
=
namespaceService
.
findNamespaceBO
s
(
appId
,
Env
.
DEV
,
clusterName
);
assertEquals
(
2
,
namespaceVOs
.
size
());
Namespace
V
O
namespaceVO
=
namespaceVOs
.
get
(
0
);
Namespace
B
O
namespaceVO
=
namespaceVOs
.
get
(
0
);
assertEquals
(
4
,
namespaceVO
.
getItems
().
size
());
assertEquals
(
"a"
,
namespaceVO
.
getItems
().
get
(
0
).
getItem
().
getKey
());
assertEquals
(
2
,
namespaceVO
.
getItemModifiedCnt
());
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment