зеркало из https://github.com/github/vitess-gh.git
web/vtctld: Implement topology browser.
This commit is contained in:
Родитель
592d676f5c
Коммит
3ec559166c
|
@ -71,6 +71,12 @@ func HandleExplorer(name, url, templateName string, exp Explorer) {
|
|||
panic(fmt.Sprintf("Only one Explorer can be registered in vtctld. Trying to register %q, but %q was already registered.", name, explorerName))
|
||||
}
|
||||
|
||||
// Topo explorer API for client-side vtctld app.
|
||||
handleCollection("topodata", func(r *http.Request) (interface{}, error) {
|
||||
return exp.HandlePath(actionRepo, path.Clean(url+getItemPath(r.URL.Path)), r), nil
|
||||
})
|
||||
|
||||
// Old server-side explorer.
|
||||
explorer = exp
|
||||
explorerName = name
|
||||
indexContent.ToplevelLinks[name+" Explorer"] = url
|
||||
|
|
|
@ -61,3 +61,18 @@ md-toolbar h1 {
|
|||
.card-table-row {
|
||||
padding: 8px 0px 8px 0px;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
color: #E8EAF6;
|
||||
background-color: #3F51B5;
|
||||
padding: 0px 12px 0px 12px;
|
||||
}
|
||||
|
||||
.breadcrumb md-icon {
|
||||
color: #E8EAF6;
|
||||
}
|
||||
|
||||
.breadcrumb-divider {
|
||||
font-size: 1.5em;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@ app.constant('routes', [
|
|||
urlPattern: '/keyspaces/',
|
||||
templateUrl: 'keyspaces.html',
|
||||
controller: 'KeyspacesCtrl',
|
||||
showInNav: true
|
||||
showInNav: true,
|
||||
icon: 'dashboard'
|
||||
},
|
||||
{
|
||||
name: 'shard',
|
||||
|
@ -34,7 +35,8 @@ app.constant('routes', [
|
|||
urlPattern: '/schema/',
|
||||
templateUrl: 'schema.html',
|
||||
controller: 'SchemaCtrl',
|
||||
showInNav: true
|
||||
showInNav: true,
|
||||
icon: 'storage'
|
||||
},
|
||||
{
|
||||
name: 'topo',
|
||||
|
@ -43,7 +45,8 @@ app.constant('routes', [
|
|||
urlPattern: '/topo/:path*?',
|
||||
templateUrl: 'topo.html',
|
||||
controller: 'TopoCtrl',
|
||||
showInNav: true
|
||||
showInNav: true,
|
||||
icon: 'folder'
|
||||
},
|
||||
]);
|
||||
|
||||
|
@ -247,8 +250,21 @@ app.controller('ShardCtrl', function($scope, $routeParams, $timeout,
|
|||
app.controller('SchemaCtrl', function() {
|
||||
});
|
||||
|
||||
app.controller('TopoCtrl', function($scope, $routeParams) {
|
||||
$scope.path = $routeParams.path;
|
||||
app.controller('TopoCtrl', function($scope, $routeParams, topodata) {
|
||||
var path = $routeParams.path;
|
||||
|
||||
$scope.path = path;
|
||||
$scope.node = topodata.get({path: path});
|
||||
|
||||
var crumbs = [];
|
||||
if (path) {
|
||||
var elems = path.split('/');
|
||||
while (elems.length > 0) {
|
||||
var elemPath = elems.join('/');
|
||||
crumbs.unshift({name: elems.pop(), path: elemPath});
|
||||
}
|
||||
}
|
||||
$scope.breadcrumbs = crumbs;
|
||||
});
|
||||
|
||||
app.factory('actions', function($mdDialog, keyspaces, shards, tablets) {
|
||||
|
@ -355,3 +371,7 @@ app.factory('tabletinfo', function($resource) {
|
|||
app.factory('endpoints', function($resource) {
|
||||
return $resource('/api/endpoints/:cell/:keyspace/:shard/:tabletType');
|
||||
});
|
||||
|
||||
app.factory('topodata', function($resource) {
|
||||
return $resource('/api/topodata/:path');
|
||||
});
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
<md-list>
|
||||
<md-list-item ng-repeat="route in routes | filter:{showInNav:true}">
|
||||
<md-button ng-class="{ 'selected': navIsSelected(route) }" ng-href="#{{route.urlBase}}">
|
||||
<md-icon md-font-set="material-icons" ng-bind="route.icon"></md-icon>
|
||||
{{route.title}}
|
||||
</md-button>
|
||||
</md-list-item>
|
||||
|
@ -38,14 +39,14 @@
|
|||
|
||||
<div flex layout="column" tabIndex="-1" role="main" class="md-whiteframe-z2">
|
||||
|
||||
<md-toolbar layout="row" class="md-whiteframe-z1">
|
||||
<md-button hide-gt-md ng-click="toggleNav()" aria-label="Toggle Nav Bar">
|
||||
<md-toolbar layout="row" class="md-whiteframe-z1" layout-align="space-between center">
|
||||
<md-button class="md-icon-button" hide-gt-md ng-click="toggleNav()" aria-label="Toggle Nav Bar">
|
||||
<md-icon md-font-set="material-icons">menu</md-icon>
|
||||
</md-button>
|
||||
|
||||
<h1 ng-bind="navTitle()"></h1>
|
||||
|
||||
<md-button ng-click="refreshRoute()" aria-label="Refresh">
|
||||
<md-button class="md-icon-button" ng-click="refreshRoute()" aria-label="Refresh">
|
||||
<md-icon md-font-set="material-icons">refresh</md-icon>
|
||||
</md-button>
|
||||
</md-toolbar>
|
||||
|
|
|
@ -1 +1,37 @@
|
|||
<h1 ng-bind="path"></h1>
|
||||
<div ng-if="!node.$resolved" flex layout="column" layout-align="center center">
|
||||
<md-progress-circular md-mode="indeterminate"></md-progress-circular>
|
||||
<h3>Loading...</h3>
|
||||
</div>
|
||||
|
||||
<md-content ng-if="node.$resolved" class="md-padding">
|
||||
|
||||
<div class="breadcrumb md-whiteframe-z1">
|
||||
<md-button href="#/topo/">
|
||||
<md-icon md-font-set="material-icons">folder</md-icon>
|
||||
</md-button>
|
||||
<span class="breadcrumb-divider">/</span>
|
||||
<span ng-repeat="elem in breadcrumbs">
|
||||
<md-button ng-href="#/topo/{{elem.path}}">{{elem.name}}</md-button>
|
||||
<span ng-if="!$last" class="breadcrumb-divider">/</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<h2 ng-bind="node.Path"></h2>
|
||||
|
||||
<md-list ng-if="node.Children">
|
||||
<md-list-item class="md-whiteframe-z1" ng-repeat="child in node.Children" ng-click="navigate('/topo/' + (path ? path+'/' : '') + child)">
|
||||
<md-icon md-font-set="material-icons">folder</md-icon>
|
||||
<h3 flex>{{child}}</h3>
|
||||
</md-list-item>
|
||||
</md-list>
|
||||
|
||||
<md-content ng-if="node.Data" class="md-padding md-whiteframe-z2">
|
||||
<pre>{{node.Data}}</pre>
|
||||
</md-content>
|
||||
|
||||
<div ng-if="node.Error">
|
||||
<h2>Error</h2>
|
||||
<p>{{node.Error}}</p>
|
||||
</div>
|
||||
|
||||
</md-content>
|
||||
|
|
Загрузка…
Ссылка в новой задаче