diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 7826cc9b94a..a980426bdd0 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -32,7 +32,7 @@ //= require bower_components/d3/d3 //= require bower_components/c3/c3 //= require bower_components/lodash/lodash -//= require bower_components/kubernetes-topology-graph/dist/topology-graph +//= require kubernetes-topology-graph/dist/topology-graph //= require ./miq_browser_detect //= require ./miq_application //= require ./miq_flash diff --git a/app/assets/javascripts/services/topology_service.js b/app/assets/javascripts/services/topology_service.js index c39fce49895..00410e98cbe 100644 --- a/app/assets/javascripts/services/topology_service.js +++ b/app/assets/javascripts/services/topology_service.js @@ -257,6 +257,7 @@ ManageIQ.angular.app.service('topologyService', ['$location', '$http', 'miqServi controller.relations = data.data.relations; // NOTE: $scope.kinds is required by kubernetes icons used for filtering controller.kinds = $scope.kinds = data.data.kinds; + controller.filters = $scope.filters = {}; controller.icons = data.data.icons; if (currentSelectedKinds && (Object.keys(currentSelectedKinds).length !== Object.keys(controller.kinds).length)) { controller.kinds = $scope.kinds = currentSelectedKinds; diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index cf860cbae35..e735d52515e 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -11,7 +11,7 @@ *= require ./miq_tree *= require bower_components/codemirror/lib/codemirror *= require bower_components/codemirror/theme/eclipse - *= require bower_components/kubernetes-topology-graph/dist/topology-graph + *= require kubernetes-topology-graph/dist/topology-graph *= require ./wizard *= require ./timeline *= require ./topology diff --git a/app/assets/stylesheets/physical_infra_topology.scss b/app/assets/stylesheets/physical_infra_topology.scss index a934c87117d..36169cd0af8 100644 --- a/app/assets/stylesheets/physical_infra_topology.scss +++ b/app/assets/stylesheets/physical_infra_topology.scss @@ -3,14 +3,22 @@ $topology-colors: ( PhysicalRack: #030303, PhysicalSwitch: #030303, PhysicalChassis: #030303, + Valid: #3f9c35, + Warning: #ec7a08, + Critical: #cc0000, + Unknown: #bbb, ); -@each $component, $color in $topology-colors { - .legend kubernetes-topology-icon[kind="#{$component}"] i{ - color: $color; +@each $filter-value, $color in $topology-colors { + .topology g.#{$filter-value} text.glyph{ + fill: $color !important; } - .topology g.#{$component} text.glyph{ - fill: $color !important; + .legend kubernetes-topology-filter[filter-value="#{$filter-value}"] i{ + color: $color; } } + +.legend kubernetes-topology-filter[filter-value="Unknown,None"] i{ + color: map-get($topology-colors, Unknown) +} diff --git a/app/assets/stylesheets/topology.css b/app/assets/stylesheets/topology.css index 256fb7a4348..7ee01427853 100644 --- a/app/assets/stylesheets/topology.css +++ b/app/assets/stylesheets/topology.css @@ -8,8 +8,7 @@ kubernetes-topology-graph { } .topology .legend { - padding-top: 5px; - font-family: sans-serif; + font-family: "Open Sans", Open Sans, sans-serif; font-size: 15px; display: inline-block; vertical-align: middle; @@ -26,21 +25,28 @@ kubernetes-topology-graph { margin-top: 15px; } +kubernetes-topology-filter, kubernetes-topology-icon { opacity: 0.4; - padding-bottom: 0; + padding: 10px 10px; } +kubernetes-topology-filter.active, kubernetes-topology-icon.active { opacity: 1; } +kubernetes-topology-filter svg, kubernetes-topology-icon svg { width: 39px !important; height: 39px !important; display: inline-block; } +.kube-topology g { + font-family: "Open Sans", Open Sans, sans-serif; +} + .kube-topology g text.attached-label { display: none; } @@ -57,6 +63,8 @@ kubernetes-topology-icon svg { .kube-topology g circle { stroke-width: 2px; + stroke: #aaa; + fill: #fff; } .kube-topology g circle.success { @@ -123,3 +131,19 @@ line.PhysicalServerPhysicalSwitch { stroke : #3f9c35; stroke-dasharray: 5; } + +.topology-filter-group { + float: left; + padding: 0px 10px; + margin: 10px 0px; +} + +.topology-filter-group > label { + vertical-align: middle; + padding: 10px 10px; + cursor: pointer; +} + +.topology-filter-group:not(:first-child) { + border-left: 1px solid #d1d1d1; +} \ No newline at end of file diff --git a/app/services/physical_infra_topology_service.rb b/app/services/physical_infra_topology_service.rb index 55f6c500d5e..d687f6b8017 100644 --- a/app/services/physical_infra_topology_service.rb +++ b/app/services/physical_infra_topology_service.rb @@ -51,6 +51,7 @@ class PhysicalInfraTopologyService < TopologyService ] @kinds = %i(PhysicalInfraManager PhysicalRack PhysicalChassis PhysicalServer Host Vm Tag PhysicalSwitch) + @filter_properties = %i(kind status) def entity_type(entity) if entity.kind_of?(Host) diff --git a/app/services/topology_service.rb b/app/services/topology_service.rb index 35ab3242088..cacd53a5dbb 100644 --- a/app/services/topology_service.rb +++ b/app/services/topology_service.rb @@ -88,12 +88,14 @@ def build_topology preloaded = @providers.includes(included_relations) nodes, edges = map_to_graph(preloaded, build_entity_relationships(included_relations)) filtered_nodes, filtered_edges = rbac_filter_nodes_and_edges(nodes, edges) + filter_properties = self.class.instance_variable_get(:@filter_properties) { - :items => filtered_nodes, - :relations => filtered_edges, - :kinds => build_kinds, - :icons => icons + :items => filtered_nodes, + :relations => filtered_edges, + :kinds => build_kinds, + :filter_properties => filter_properties, + :icons => icons } end diff --git a/app/views/physical_infra_topology/show.html.haml b/app/views/physical_infra_topology/show.html.haml index f4211ff2a94..02d9af0a100 100644 --- a/app/views/physical_infra_topology/show.html.haml +++ b/app/views/physical_infra_topology/show.html.haml @@ -2,31 +2,51 @@ .topology{'ng-controller' => "physicalInfraTopologyController as vm"} .legend %label#selected - %div{'ng-if' => "vm.kinds"} - %kubernetes-topology-icon{tooltipOptions, :kind => "PhysicalRack"} - %label - %i.pficon.pficon-enterprise - = _("Physical Racks") - %kubernetes-topology-icon{tooltipOptions, :kind => "PhysicalChassis"} - %label - %i.pficon.pficon-cluster - = _("Physical Chassis") - %kubernetes-topology-icon{tooltipOptions, :kind => "PhysicalServer"} - %label - %i.pficon.pficon-server-group - = _("Physical Servers") - %kubernetes-topology-icon{tooltipOptions, :kind => "PhysicalSwitch"} - %label - %i.ff.ff-network-switch - = _("Physical Switches") - %kubernetes-topology-icon{tooltipOptions, :kind => "Host"} - %label - %i.pficon.pficon-container-node - = _("Hosts") - %kubernetes-topology-icon{tooltipOptions, :kind => "Vm"} - %label - %i.pficon.pficon-virtual-machine - = _("VMs") + %div{'ng-if' => "vm.filters"} + .topology-filter-group + %kubernetes-topology-filter{tooltipOptions, "filter-property" => "kind", "filter-value" => "PhysicalRack"} + %label + %i.pficon.pficon-enterprise + = _("Physical Racks") + %kubernetes-topology-filter{tooltipOptions, "filter-property" => "kind", "filter-value" => "PhysicalChassis"} + %label + %i.pficon.pficon-cluster + = _("Physical Chassis") + %kubernetes-topology-filter{tooltipOptions, "filter-property" => "kind", "filter-value" => "PhysicalServer"} + %label + %i.pficon.pficon-server-group + = _("Physical Servers") + %kubernetes-topology-filter{tooltipOptions, "filter-property" => "kind", "filter-value" => "PhysicalSwitch"} + %label + %i.ff.ff-network-switch + = _("Physical Switches") + %kubernetes-topology-filter{tooltipOptions, "filter-property" => "kind", "filter-value" => "Host"} + %label + %i.pficon.pficon-container-node + = _("Hosts") + %kubernetes-topology-filter{tooltipOptions, "filter-property" => "kind", "filter-value" => "Vm"} + %label + %i.pficon.pficon-virtual-machine + = _("VMs") + .topology-filter-group + %label#health_state + = _("Health State: ") + %kubernetes-topology-filter{tooltipOptions, "filter-property" => "status", "filter-value" => "Valid"} + %label + %i.fa.fa-circle + = _("Valid") + %kubernetes-topology-filter{tooltipOptions, "filter-property" => "status", "filter-value" => "Warning"} + %label + %i.fa.fa-circle + = _("Warning") + %kubernetes-topology-filter{tooltipOptions, "filter-property" => "status", "filter-value" => "Critical"} + %label + %i.fa.fa-circle + = _("Critical") + %kubernetes-topology-filter{tooltipOptions, "filter-property" => "status", "filter-value" => "Unknown,None"} + %label + %i.fa.fa-circle + = _("Unknown") .alert.alert-info.alert-dismissable %button.close{"aria-hidden" => "true", "data-dismiss" => "alert", :type => "button"} @@ -37,7 +57,7 @@ = render :partial => "shared/topology/not_found_vm" - %kubernetes-topology-graph{:items => "vm.items", :relations => "vm.relations", :kinds => "vm.kinds"} + %kubernetes-topology-graph{:items => "vm.items", :relations => "vm.relations", :kinds => "vm.kinds", :filters => "vm.filters"} :javascript miq_bootstrap('.topology'); diff --git a/bower.json b/bower.json index f519d06d246..d01339ab6d6 100644 --- a/bower.json +++ b/bower.json @@ -32,7 +32,6 @@ "jquery-ui": "jqueryui#~1.12.1", "jquery-ujs": "~1.2.2", "jquery.observe_field": "himdel/jquery.observe_field#~0.1.0", - "kubernetes-topology-graph": "~0.0.23", "lodash": "~3.10.0", "manageiq-ui-components": "bower-dev", "moment-duration-format": "~1.3.0", diff --git a/package.json b/package.json index 81b8b8486a9..f2f6f61b37b 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "graphql": "~0.12.0", "history": "^4.7.2", "jquery": "~2.2.4", + "kubernetes-topology-graph": "~0.0.25", "lodash": "^4.17.4", "patternfly": "~3.54.1", "patternfly-react": "2.10.1", diff --git a/spec/services/cloud_topology_service_spec.rb b/spec/services/cloud_topology_service_spec.rb index ca05c4f55ae..aa745bf5a8d 100644 --- a/spec/services/cloud_topology_service_spec.rb +++ b/spec/services/cloud_topology_service_spec.rb @@ -13,7 +13,7 @@ end it "topology contains only the expected keys" do - expect(subject.keys).to match_array(%i(items kinds relations icons)) + expect(subject.keys).to match_array(%i(items kinds filter_properties relations icons)) end it "provider has unknown status when no authentication exists" do diff --git a/spec/services/container_topology_service_spec.rb b/spec/services/container_topology_service_spec.rb index 7a4a0e5ca70..ea34a5b2a0a 100644 --- a/spec/services/container_topology_service_spec.rb +++ b/spec/services/container_topology_service_spec.rb @@ -5,7 +5,7 @@ subject { container_topology_service.build_topology } it "topology contains only the expected keys" do - expect(subject.keys).to match_array(%i(items kinds relations icons)) + expect(subject.keys).to match_array(%i(items kinds filter_properties relations icons)) end let(:container) { Container.create(:name => "ruby-example", :state => 'running') } diff --git a/spec/services/infra_topology_service_spec.rb b/spec/services/infra_topology_service_spec.rb index e001f325378..84e4b52c84e 100644 --- a/spec/services/infra_topology_service_spec.rb +++ b/spec/services/infra_topology_service_spec.rb @@ -12,7 +12,7 @@ end it "topology contains only the expected keys" do - expect(subject.keys).to match_array(%i(items kinds relations icons)) + expect(subject.keys).to match_array(%i(items kinds filter_properties relations icons)) end it "provider has unknown status when no authentication exists" do diff --git a/spec/services/network_topology_service_spec.rb b/spec/services/network_topology_service_spec.rb index 9e271311db1..377fb98040a 100644 --- a/spec/services/network_topology_service_spec.rb +++ b/spec/services/network_topology_service_spec.rb @@ -32,7 +32,7 @@ end it "topology contains only the expected keys" do - expect(subject.keys).to match_array(%i(items kinds relations icons)) + expect(subject.keys).to match_array(%i(items kinds filter_properties relations icons)) end it "provider has unknown status when no authentication exists" do diff --git a/spec/services/physical_infra_topology_service_spec.rb b/spec/services/physical_infra_topology_service_spec.rb index c450176e2bf..b4ea274ab3e 100644 --- a/spec/services/physical_infra_topology_service_spec.rb +++ b/spec/services/physical_infra_topology_service_spec.rb @@ -61,7 +61,7 @@ subject { physical_infra_topology_service.build_topology } it "topology contains only the expected keys" do - expect(subject.keys).to match_array(%i(items kinds relations icons)) + expect(subject.keys).to match_array(%i(items kinds filter_properties relations icons)) end it "topology contains the expected structure and content" do diff --git a/spec/services/topology_service_spec.rb b/spec/services/topology_service_spec.rb index f679d3b390c..eee178316b4 100644 --- a/spec/services/topology_service_spec.rb +++ b/spec/services/topology_service_spec.rb @@ -67,6 +67,7 @@ expect(topology).to have_key(:relations) expect(topology).to have_key(:kinds) expect(topology).to have_key(:icons) + expect(topology).to have_key(:filter_properties) end end