Add a panel and table to display Containers
Change-Id: I52f36e3a6f02a83e11d717ac4d247f04fdb3a177 Implements: blueprint containers-table-view
This commit is contained in:
parent
564f9c2e18
commit
0caaa72286
@ -118,7 +118,7 @@ class Containers(generic.View):
|
||||
item under this is a Container.
|
||||
"""
|
||||
result = magnum.container_list(request)
|
||||
return {'items': [n.to_dict() for n in result]}
|
||||
return {'items': [change_to_id(n.to_dict()) for n in result]}
|
||||
|
||||
@rest_utils.ajax(data_required=True)
|
||||
def delete(self, request):
|
||||
|
0
magnum_ui/containers/__init__.py
Normal file
0
magnum_ui/containers/__init__.py
Normal file
25
magnum_ui/containers/panel.py
Normal file
25
magnum_ui/containers/panel.py
Normal file
@ -0,0 +1,25 @@
|
||||
# Copyright 2015 Cisco Systems
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
import horizon
|
||||
from magnum_ui import dashboard
|
||||
|
||||
|
||||
class Containers(horizon.Panel):
|
||||
name = _("Containers")
|
||||
slug = "containers"
|
||||
|
||||
|
||||
dashboard.Containers.register(Containers)
|
14
magnum_ui/containers/templates/containers/index.html
Normal file
14
magnum_ui/containers/templates/containers/index.html
Normal file
@ -0,0 +1,14 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}
|
||||
{% trans "Containers" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
<hz-page-header header="'Containers' | translate"/>
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<ng-include src="'{{ STATIC_URL }}dashboard/containers/containers/table/table.html'"></ng-include>
|
||||
{% endblock %}
|
30
magnum_ui/containers/tests.py
Normal file
30
magnum_ui/containers/tests.py
Normal file
@ -0,0 +1,30 @@
|
||||
# Copyright 2015 Cisco Systems, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
import horizon
|
||||
from magnum_ui.containers.panel import Containers as containers_panel
|
||||
from openstack_dashboard.test import helpers as test
|
||||
|
||||
|
||||
class ContainerTests(test.TestCase):
|
||||
def test_registration(self):
|
||||
dashboard = horizon.get_dashboard('containers')
|
||||
registered_panel = dashboard.get_panel('containers')
|
||||
self.assertEqual(registered_panel.slug, containers_panel.slug)
|
||||
|
||||
def test_index(self):
|
||||
index = reverse('horizon:containers:containers:index')
|
||||
res = self.client.get(index)
|
||||
self.assertTemplateUsed(res, 'containers/containers/index.html')
|
21
magnum_ui/containers/urls.py
Normal file
21
magnum_ui/containers/urls.py
Normal file
@ -0,0 +1,21 @@
|
||||
# Copyright 2015 Cisco Systems, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.conf.urls import url
|
||||
from magnum_ui.containers import views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', views.IndexView.as_view(), name='index'),
|
||||
]
|
21
magnum_ui/containers/views.py
Normal file
21
magnum_ui/containers/views.py
Normal file
@ -0,0 +1,21 @@
|
||||
# Copyright 2015 Cisco Systems
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from horizon import views
|
||||
|
||||
from magnum_ui.api.rest import magnum # noqa
|
||||
|
||||
|
||||
class IndexView(views.APIView):
|
||||
template_name = 'containers/containers/index.html'
|
@ -20,7 +20,7 @@ import horizon
|
||||
class Containers(horizon.Dashboard):
|
||||
name = _("Containers")
|
||||
slug = "containers"
|
||||
panels = ('bay', 'baymodel')
|
||||
panels = ('bay', 'baymodel', 'containers')
|
||||
default_panel = 'bay'
|
||||
|
||||
horizon.register(Containers)
|
||||
|
@ -27,7 +27,8 @@
|
||||
angular
|
||||
.module('horizon.dashboard.containers', [
|
||||
'horizon.dashboard.containers.bay',
|
||||
'horizon.dashboard.containers.baymodel'
|
||||
'horizon.dashboard.containers.baymodel',
|
||||
'horizon.dashboard.containers.containers'
|
||||
])
|
||||
.config(config);
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright 2015 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @name horizon.dashboard.containers.containers
|
||||
* @ngModule
|
||||
*
|
||||
* @description
|
||||
* Provides all the services and widgets require to display the containers
|
||||
* panel
|
||||
*/
|
||||
angular
|
||||
.module('horizon.dashboard.containers.containers', []);
|
||||
|
||||
})();
|
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright 2015 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
describe('horizon.dashboard.containers.containers', function() {
|
||||
it('should exist', function() {
|
||||
expect(angular.module('horizon.dashboard.containers.containers')).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Copyright 2015 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc overview
|
||||
* @name containersContainersTableController
|
||||
* @ngController
|
||||
*
|
||||
* @description
|
||||
* Controller for the Magnum containers table
|
||||
*/
|
||||
angular
|
||||
.module('horizon.dashboard.containers.containers')
|
||||
.controller('containersContainersTableController', containersContainersTableController);
|
||||
|
||||
containersContainersTableController.$inject = [
|
||||
'$scope',
|
||||
'horizon.app.core.openstack-service-api.magnum'
|
||||
];
|
||||
|
||||
function containersContainersTableController($scope, magnum) {
|
||||
var ctrl = this;
|
||||
ctrl.icontainers = [];
|
||||
ctrl.containers = [];
|
||||
|
||||
ctrl.singleDelete = singleDelete;
|
||||
ctrl.batchDelete = batchDelete;
|
||||
|
||||
init();
|
||||
|
||||
function init() {
|
||||
magnum.getContainers().success(getContainersSuccess);
|
||||
}
|
||||
|
||||
function getContainersSuccess(response) {
|
||||
ctrl.containers = response.items;
|
||||
}
|
||||
|
||||
function singleDelete(container) {
|
||||
magnum.deleteContainer(container.id).success(function() {
|
||||
ctrl.containers.splice(ctrl.containers.indexOf(container), 1);
|
||||
});
|
||||
}
|
||||
|
||||
function batchDelete() {
|
||||
var ids = [];
|
||||
for (var id in $scope.selected) {
|
||||
if ($scope.selected[id].checked) {
|
||||
ids.push(id);
|
||||
}
|
||||
}
|
||||
magnum.deleteContainers(ids).success(function() {
|
||||
for (var c in ids) {
|
||||
var todelete = ctrl.containers.filter(function(obj) {
|
||||
return obj.id == ids[c];
|
||||
});
|
||||
ctrl.containers.splice(ctrl.containers.indexOf(todelete[0]), 1);
|
||||
}
|
||||
$scope.selected = {};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,164 @@
|
||||
<table ng-controller="containersContainersTableController as table"
|
||||
hz-table ng-cloak
|
||||
st-table="table.icontainers"
|
||||
st-safe-src="table.containers"
|
||||
default-sort="name"
|
||||
default-sort-reverse="false"
|
||||
class="table-striped table-rsp table-detail modern">
|
||||
|
||||
<thead>
|
||||
<!--
|
||||
Table-batch-actions:
|
||||
This is where batch actions like searching, creating, and deleting.
|
||||
-->
|
||||
<tr>
|
||||
<th colspan="100" class="search-header">
|
||||
<hz-search-bar group-classes="input-group-sm" icon-classes="fa-search">
|
||||
|
||||
<action-list class="btn-addon">
|
||||
<action
|
||||
action-classes="'btn btn-default btn-sm btn-danger'"
|
||||
disabled="numSelected === 0"
|
||||
callback="table.batchDelete">
|
||||
<i class="fa fa-trash-o"></i>
|
||||
<translate>Delete Containers</translate>
|
||||
</action>
|
||||
</action-list>
|
||||
|
||||
</hz-search-bar>
|
||||
</th>
|
||||
</tr>
|
||||
<!--
|
||||
Table-column-headers:
|
||||
The headers for the table columns
|
||||
-->
|
||||
<tr>
|
||||
<th class=select-col>
|
||||
<input type="checkbox" hz-select-all="table.icontainers">
|
||||
</th>
|
||||
|
||||
<th class="expander"></th>
|
||||
|
||||
<th class="rsp-p1" st-sort="name" st-sort-default>
|
||||
<translate>Name</translate>
|
||||
</th>
|
||||
|
||||
<th class="rsp-p1" st-sort="id" >
|
||||
<translate>UUID</translate>
|
||||
</th>
|
||||
|
||||
<th class="rsp-p1" st-sort="status" >
|
||||
<translate>Status</translate>
|
||||
</th>
|
||||
|
||||
<th class="rsp-p3" st-sort="bay" >
|
||||
<translate>Bay UUID</translate>
|
||||
</th>
|
||||
|
||||
<th class="rsp-p2" st-sort="image" >
|
||||
<translate>Image</translate>
|
||||
</th>
|
||||
|
||||
<th class="rsp-p3" st-sort="memory" >
|
||||
<translate>Memory</translate>
|
||||
</th>
|
||||
|
||||
<th class="action-col">
|
||||
<translate>Actions</translate>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!--
|
||||
Table-rows:
|
||||
This is where we declaratively define the table columns.
|
||||
Include select-col if you want to select all.
|
||||
Include expander if you want to inline details.
|
||||
Include action-col if you want to perform actions.
|
||||
rsp-p1 rsp-p2 are responsive priority as user resizes window.
|
||||
-->
|
||||
|
||||
<tr ng-repeat-start="c in table.icontainers track by c.id"
|
||||
nt-class="{'st-selected': checked[c.id]}">
|
||||
|
||||
<td class="select-col">
|
||||
<input type="checkbox"
|
||||
ng-model="selected[c.id].checked"
|
||||
hz-select="c">
|
||||
</td>
|
||||
|
||||
<td class="expander">
|
||||
<i class="fa fa-chevron-right"
|
||||
hz-expand-detail
|
||||
duration="200">
|
||||
</i>
|
||||
</td>
|
||||
|
||||
<td class="rsp-p1">{$ c.name $}</td>
|
||||
<td class="rsp-p1">{$ c.id $}</td>
|
||||
<td class="rsp-p1">{$ c.status $}</td>
|
||||
<td class="rsp-p3">{$ c.bay_uuid $}</td>
|
||||
<td class="rsp-p2">{$ c.image $}</td>
|
||||
<td class="rsp-p3">{$ c.memory $}</td>
|
||||
|
||||
<td class="action-col">
|
||||
<!--
|
||||
Table-row-action-column:
|
||||
Actions taken here applies to a single item/row.
|
||||
-->
|
||||
|
||||
<action-list dropdown>
|
||||
|
||||
<action
|
||||
button-type="split-button"
|
||||
action-classes="'btn btn-default btn-danger btn-sm'"
|
||||
callback="table.singleDelete" item="c">
|
||||
<translate>Delete</translate>
|
||||
</action>
|
||||
|
||||
</action-list>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-repeat-end class="detail-row">
|
||||
<!--
|
||||
Table-row-details:
|
||||
Provides detail view of specific view, with more information than can be
|
||||
displayed in the table alone.
|
||||
-->
|
||||
|
||||
<td class="detail" colspan="100">
|
||||
<dl class=dl-horizontal>
|
||||
|
||||
<dt><translate>Name</translate></dt>
|
||||
<dd>{$ c.name $}</dd>
|
||||
|
||||
<dt><translate>UUID</translate></dt>
|
||||
<dd>{$ c.id $}</dd>
|
||||
|
||||
<dt><translate>Status</translate></dt>
|
||||
<dd>{$ c.status $}</dd>
|
||||
|
||||
<dt><translate>Bay UUID</translate></dt>
|
||||
<dd>{$ c.bay_uuid $}</dd>
|
||||
|
||||
<dt><translate>Image</translate></dt>
|
||||
<dd>{$ c.image $}</dd>
|
||||
|
||||
<dt><translate>Memory</translate></dt>
|
||||
<dd>{$ c.memory $}</dd>
|
||||
|
||||
<dt><translate>Command</translate></dt>
|
||||
<dd>{$ c.command $}</dd>
|
||||
|
||||
</dl>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<td colspan="100">
|
||||
<span class="display">{$ table.icontainers.length|itemCount $}</span>
|
||||
<div st-pagination="" st-items-by-page="10"
|
||||
st-displayed-pages="10"></div>
|
||||
</td>
|
||||
</tfoot>
|
||||
</table>
|
@ -33,7 +33,11 @@
|
||||
deleteBays: deleteBays,
|
||||
getBayModels: getBayModels,
|
||||
deleteBayModel: deleteBayModel,
|
||||
deleteBayModels: deleteBayModels
|
||||
deleteBayModels: deleteBayModels,
|
||||
getContainers: getContainers,
|
||||
deleteContainer: deleteContainer,
|
||||
deleteContainers: deleteContainers,
|
||||
|
||||
};
|
||||
|
||||
return service;
|
||||
@ -94,6 +98,32 @@
|
||||
toastService.add('error', gettext('Unable to delete the BayModels.'))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
////////////////
|
||||
// Containers //
|
||||
////////////////
|
||||
|
||||
function getContainers() {
|
||||
return apiService.get('/api/containers/containers/')
|
||||
.error(function() {
|
||||
toastService.add('error', gettext('Unable to retrieve the Containers.'));
|
||||
});
|
||||
}
|
||||
|
||||
function deleteContainer(id) {
|
||||
return apiService.delete('/api/containers/containers/', [id])
|
||||
.error(function() {
|
||||
toastService.add('error', gettext('Unable to delete the Container.'));
|
||||
});
|
||||
}
|
||||
|
||||
function deleteContainers(ids) {
|
||||
return apiService.delete('/api/containers/containers/', ids)
|
||||
.error(function() {
|
||||
toastService.add('error', gettext('Unable to delete the Containers.'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}());
|
||||
|
Loading…
x
Reference in New Issue
Block a user