From 0caaa722864de0f3110c5809d8c7ef95617f87ae Mon Sep 17 00:00:00 2001 From: Rob Cresswell Date: Mon, 19 Oct 2015 17:25:21 +0100 Subject: [PATCH] Add a panel and table to display Containers Change-Id: I52f36e3a6f02a83e11d717ac4d247f04fdb3a177 Implements: blueprint containers-table-view --- magnum_ui/api/rest/magnum.py | 2 +- magnum_ui/containers/__init__.py | 0 magnum_ui/containers/panel.py | 25 +++ .../templates/containers/index.html | 14 ++ magnum_ui/containers/tests.py | 30 ++++ magnum_ui/containers/urls.py | 21 +++ magnum_ui/containers/views.py | 21 +++ magnum_ui/dashboard.py | 2 +- .../dashboard/containers/containers.module.js | 3 +- .../containers/containers.module.js | 32 ++++ .../containers/containers.module.spec.js | 25 +++ .../containers/table/table.controller.js | 80 +++++++++ .../containers/containers/table/table.html | 164 ++++++++++++++++++ .../dashboard/containers/magnum.service.js | 32 +++- 14 files changed, 447 insertions(+), 4 deletions(-) create mode 100644 magnum_ui/containers/__init__.py create mode 100644 magnum_ui/containers/panel.py create mode 100644 magnum_ui/containers/templates/containers/index.html create mode 100644 magnum_ui/containers/tests.py create mode 100644 magnum_ui/containers/urls.py create mode 100644 magnum_ui/containers/views.py create mode 100644 magnum_ui/static/dashboard/containers/containers/containers.module.js create mode 100644 magnum_ui/static/dashboard/containers/containers/containers.module.spec.js create mode 100644 magnum_ui/static/dashboard/containers/containers/table/table.controller.js create mode 100644 magnum_ui/static/dashboard/containers/containers/table/table.html diff --git a/magnum_ui/api/rest/magnum.py b/magnum_ui/api/rest/magnum.py index bae23a2e..18ad280d 100644 --- a/magnum_ui/api/rest/magnum.py +++ b/magnum_ui/api/rest/magnum.py @@ -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): diff --git a/magnum_ui/containers/__init__.py b/magnum_ui/containers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/magnum_ui/containers/panel.py b/magnum_ui/containers/panel.py new file mode 100644 index 00000000..46d7d663 --- /dev/null +++ b/magnum_ui/containers/panel.py @@ -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) diff --git a/magnum_ui/containers/templates/containers/index.html b/magnum_ui/containers/templates/containers/index.html new file mode 100644 index 00000000..7ee76b0a --- /dev/null +++ b/magnum_ui/containers/templates/containers/index.html @@ -0,0 +1,14 @@ +{% extends 'base.html' %} +{% load i18n %} + +{% block title %} + {% trans "Containers" %} +{% endblock %} + +{% block page_header %} + +{% endblock page_header %} + +{% block main %} + +{% endblock %} diff --git a/magnum_ui/containers/tests.py b/magnum_ui/containers/tests.py new file mode 100644 index 00000000..66bb2307 --- /dev/null +++ b/magnum_ui/containers/tests.py @@ -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') diff --git a/magnum_ui/containers/urls.py b/magnum_ui/containers/urls.py new file mode 100644 index 00000000..30b46f0e --- /dev/null +++ b/magnum_ui/containers/urls.py @@ -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'), +] diff --git a/magnum_ui/containers/views.py b/magnum_ui/containers/views.py new file mode 100644 index 00000000..bf811ec8 --- /dev/null +++ b/magnum_ui/containers/views.py @@ -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' diff --git a/magnum_ui/dashboard.py b/magnum_ui/dashboard.py index 847b2ea7..d2591df8 100644 --- a/magnum_ui/dashboard.py +++ b/magnum_ui/dashboard.py @@ -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) diff --git a/magnum_ui/static/dashboard/containers/containers.module.js b/magnum_ui/static/dashboard/containers/containers.module.js index bd2e7a92..ce35df91 100644 --- a/magnum_ui/static/dashboard/containers/containers.module.js +++ b/magnum_ui/static/dashboard/containers/containers.module.js @@ -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); diff --git a/magnum_ui/static/dashboard/containers/containers/containers.module.js b/magnum_ui/static/dashboard/containers/containers/containers.module.js new file mode 100644 index 00000000..4cb7a905 --- /dev/null +++ b/magnum_ui/static/dashboard/containers/containers/containers.module.js @@ -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', []); + +})(); diff --git a/magnum_ui/static/dashboard/containers/containers/containers.module.spec.js b/magnum_ui/static/dashboard/containers/containers/containers.module.spec.js new file mode 100644 index 00000000..82d98020 --- /dev/null +++ b/magnum_ui/static/dashboard/containers/containers/containers.module.spec.js @@ -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(); + }); + }); + +})(); diff --git a/magnum_ui/static/dashboard/containers/containers/table/table.controller.js b/magnum_ui/static/dashboard/containers/containers/table/table.controller.js new file mode 100644 index 00000000..c29df04e --- /dev/null +++ b/magnum_ui/static/dashboard/containers/containers/table/table.controller.js @@ -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 = {}; + }); + } + } + +})(); diff --git a/magnum_ui/static/dashboard/containers/containers/table/table.html b/magnum_ui/static/dashboard/containers/containers/table/table.html new file mode 100644 index 00000000..6607e9a9 --- /dev/null +++ b/magnum_ui/static/dashboard/containers/containers/table/table.html @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + Delete Containers + + + + +
+ + + Name + + UUID + + Status + + Bay UUID + + Image + + Memory + + Actions +
+ + + + + {$ c.name $}{$ c.id $}{$ c.status $}{$ c.bay_uuid $}{$ c.image $}{$ c.memory $} + + + + + + Delete + + + +
+
+ +
Name
+
{$ c.name $}
+ +
UUID
+
{$ c.id $}
+ +
Status
+
{$ c.status $}
+ +
Bay UUID
+
{$ c.bay_uuid $}
+ +
Image
+
{$ c.image $}
+ +
Memory
+
{$ c.memory $}
+ +
Command
+
{$ c.command $}
+ +
+
+ {$ table.icontainers.length|itemCount $} +
+
diff --git a/magnum_ui/static/dashboard/containers/magnum.service.js b/magnum_ui/static/dashboard/containers/magnum.service.js index 083fa18a..314c0eb1 100644 --- a/magnum_ui/static/dashboard/containers/magnum.service.js +++ b/magnum_ui/static/dashboard/containers/magnum.service.js @@ -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.')); + }); + } } }());