summaryrefslogtreecommitdiffstats
path: root/ui/imports
diff options
context:
space:
mode:
Diffstat (limited to 'ui/imports')
-rw-r--r--ui/imports/api/attributes_for_hover_on_data/attributes_for_hover_on_data.js24
-rw-r--r--ui/imports/api/clique-types/methods.js12
-rw-r--r--ui/imports/api/configurations/configurations.js29
-rw-r--r--ui/imports/api/configurations/methods.js39
-rw-r--r--ui/imports/api/configurations/server/publications.js21
-rw-r--r--ui/imports/api/environments/environments.js6
-rw-r--r--ui/imports/api/inventories/server/methods.js28
-rw-r--r--ui/imports/api/links/server/methods.js31
-rw-r--r--ui/imports/api/messages/server/methods.js4
-rw-r--r--ui/imports/api/messages/server/publications.js19
-rw-r--r--ui/imports/lib/images-for-node-type.js63
-rw-r--r--ui/imports/startup/client/index.js1
-rw-r--r--ui/imports/startup/server/register-api.js4
-rw-r--r--ui/imports/ui/components/alarm-icons/alarm-icons.html13
-rw-r--r--ui/imports/ui/components/alarm-icons/alarm-icons.js31
-rw-r--r--ui/imports/ui/components/clique-type/clique-type.js6
-rw-r--r--ui/imports/ui/components/configuration/configuration.html31
-rw-r--r--ui/imports/ui/components/configuration/configuration.js114
-rw-r--r--ui/imports/ui/components/configuration/configuration.styl38
-rw-r--r--ui/imports/ui/components/dashboard/dashboard.js18
-rw-r--r--ui/imports/ui/components/environment-dashboard/environment-dashboard.js15
-rw-r--r--ui/imports/ui/components/environment/environment.js1
-rw-r--r--ui/imports/ui/components/graph-tooltip-window/graph-tooltip-window.html4
-rw-r--r--ui/imports/ui/components/graph-tooltip-window/graph-tooltip-window.js19
-rw-r--r--ui/imports/ui/components/graph-tooltip-window/graph-tooltip-window.styl11
-rw-r--r--ui/imports/ui/components/index.styl1
-rw-r--r--ui/imports/ui/components/messages-modal/messages-modal.js54
-rw-r--r--ui/imports/ui/components/network-graph-manager/network-graph-manager.js48
-rw-r--r--ui/imports/ui/components/network-graph/network-graph.js130
-rw-r--r--ui/imports/ui/components/scans-list/scans-list.html2
-rw-r--r--ui/imports/ui/components/top-navbar-menu/top-navbar-menu.js2
31 files changed, 670 insertions, 149 deletions
diff --git a/ui/imports/api/attributes_for_hover_on_data/attributes_for_hover_on_data.js b/ui/imports/api/attributes_for_hover_on_data/attributes_for_hover_on_data.js
index ec2f6cd..13c877a 100644
--- a/ui/imports/api/attributes_for_hover_on_data/attributes_for_hover_on_data.js
+++ b/ui/imports/api/attributes_for_hover_on_data/attributes_for_hover_on_data.js
@@ -7,6 +7,30 @@
// http://www.apache.org/licenses/LICENSE-2.0 /
/////////////////////////////////////////////////////////////////////////////////////////
import { Mongo } from 'meteor/mongo';
+import * as R from 'ramda';
export const NodeHoverAttr = new Mongo.Collection(
'attributes_for_hover_on_data', { idGeneration: 'MONGO' });
+
+export const calcAttrsForItem = function (node, attrsDefsRec) {
+ if (R.isNil(attrsDefsRec)) {
+ return [];
+ }
+
+ let attrsDefs = attrsDefsRec.attributes;
+
+ return R.reduce((acc, attrDef) => {
+ if (R.is(Array, attrDef)) {
+ let value = R.path(attrDef, node);
+ if (R.isNil(value)) { return acc; }
+ let name = R.join('.', attrDef);
+ return R.append(R.assoc(name, value, {}), acc);
+
+ } else {
+ return R.ifElse(R.isNil,
+ R.always(acc),
+ (attrVal) => R.append(R.assoc(attrDef, attrVal, {}), acc)
+ )(R.prop(attrDef, node));
+ }
+ }, [], attrsDefs);
+};
diff --git a/ui/imports/api/clique-types/methods.js b/ui/imports/api/clique-types/methods.js
index a62c22f..4257291 100644
--- a/ui/imports/api/clique-types/methods.js
+++ b/ui/imports/api/clique-types/methods.js
@@ -96,12 +96,12 @@ export const update = new ValidatedMethod({
'focal_point_type',
'link_types',
'name', ],
- cliqueType), {
- environment,
- focal_point_type,
- link_types,
- name,
- });
+ cliqueType), {
+ environment,
+ focal_point_type,
+ link_types,
+ name,
+ });
CliqueTypes.update({ _id: _id }, { $set: cliqueType });
}
diff --git a/ui/imports/api/configurations/configurations.js b/ui/imports/api/configurations/configurations.js
new file mode 100644
index 0000000..067b69f
--- /dev/null
+++ b/ui/imports/api/configurations/configurations.js
@@ -0,0 +1,29 @@
+/////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others /
+// /
+// All rights reserved. This program and the accompanying materials /
+// are made available under the terms of the Apache License, Version 2.0 /
+// which accompanies this distribution, and is available at /
+// http://www.apache.org/licenses/LICENSE-2.0 /
+/////////////////////////////////////////////////////////////////////////////////////////
+import { Mongo } from 'meteor/mongo';
+import { SimpleSchema } from 'meteor/aldeed:simple-schema';
+//import * as R from 'ramda';
+
+export const Configurations = new Mongo.Collection('configurations', { idGeneration: 'MONGO' });
+
+let schema = {
+ _id: { type: { _str: { type: String, regEx: SimpleSchema.RegEx.Id } } },
+ user_id: {
+ type: String,
+ },
+ messages_view_backward_delta: {
+ type: Number,
+ minCount: 1,
+ defaultValue: '1209600000', // 2 weeks
+ }
+};
+
+let simpleSchema = new SimpleSchema(schema);
+Configurations.schema = simpleSchema;
+Configurations.attachSchema(Configurations.schema);
diff --git a/ui/imports/api/configurations/methods.js b/ui/imports/api/configurations/methods.js
new file mode 100644
index 0000000..7366e3e
--- /dev/null
+++ b/ui/imports/api/configurations/methods.js
@@ -0,0 +1,39 @@
+/////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others /
+// /
+// All rights reserved. This program and the accompanying materials /
+// are made available under the terms of the Apache License, Version 2.0 /
+// which accompanies this distribution, and is available at /
+// http://www.apache.org/licenses/LICENSE-2.0 /
+/////////////////////////////////////////////////////////////////////////////////////////
+import { ValidatedMethod } from 'meteor/mdg:validated-method';
+import { Configurations } from '/imports/api/configurations/configurations';
+import * as R from 'ramda';
+
+export const save = new ValidatedMethod({
+ name: 'configurations.save',
+ validate: Configurations.simpleSchema()
+ .pick([
+ 'messages_view_backward_delta'
+ ]).validator({ clean: true, filter: false }),
+ run({
+ messages_view_backward_delta
+ }) {
+
+ let userId = this.userId;
+ let conf = Configurations.findOne({ user_id: userId });
+
+ if (conf) {
+ Configurations.update({ _id: conf._id}, { $set: {
+ messages_view_backward_delta: messages_view_backward_delta
+ }});
+ } else {
+ let item = Configurations.schema.clean({});
+ item = R.merge(item, {
+ user_id: userId,
+ messages_view_backward_delta: messages_view_backward_delta
+ });
+ Configurations.insert(item);
+ }
+ }
+});
diff --git a/ui/imports/api/configurations/server/publications.js b/ui/imports/api/configurations/server/publications.js
new file mode 100644
index 0000000..fe9f6fd
--- /dev/null
+++ b/ui/imports/api/configurations/server/publications.js
@@ -0,0 +1,21 @@
+/////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others /
+// /
+// All rights reserved. This program and the accompanying materials /
+// are made available under the terms of the Apache License, Version 2.0 /
+// which accompanies this distribution, and is available at /
+// http://www.apache.org/licenses/LICENSE-2.0 /
+/////////////////////////////////////////////////////////////////////////////////////////
+import { Meteor } from 'meteor/meteor';
+
+import { Configurations } from '../configurations.js';
+
+Meteor.publish('configurations?user', function () {
+ console.log('server subscribtion: configurations?user');
+
+ let userId = this.userId;
+
+ let query = { user_id: userId };
+ console.log('-query: ', query);
+ return Configurations.find(query);
+});
diff --git a/ui/imports/api/environments/environments.js b/ui/imports/api/environments/environments.js
index 5e3b4b2..22e49cf 100644
--- a/ui/imports/api/environments/environments.js
+++ b/ui/imports/api/environments/environments.js
@@ -32,7 +32,7 @@ export const requiredConfGroups = [
];
export const optionalConfGroups = [
- // 'NFV_provider',
+ // 'NFV_provider',
'AMQP',
'Monitoring',
'ACI',
@@ -335,8 +335,8 @@ function getSchemaForGroupName(groupName) {
return CLISchema;
case 'AMQP':
return AMQPSchema;
-// case 'NFV_provider':
-// return NfvProviderSchema;
+ // case 'NFV_provider':
+ // return NfvProviderSchema;
case 'ACI':
return AciSchema;
case 'Monitoring':
diff --git a/ui/imports/api/inventories/server/methods.js b/ui/imports/api/inventories/server/methods.js
index 3daf570..d7e3648 100644
--- a/ui/imports/api/inventories/server/methods.js
+++ b/ui/imports/api/inventories/server/methods.js
@@ -11,7 +11,8 @@ import * as R from 'ramda';
import { Inventory } from '../inventories';
import { Environments } from '/imports/api/environments/environments';
import { regexEscape } from '/imports/lib/regex-utils';
-import { NodeHoverAttr } from '/imports/api/attributes_for_hover_on_data/attributes_for_hover_on_data';
+import { NodeHoverAttr, calcAttrsForItem } from '/imports/api/attributes_for_hover_on_data/attributes_for_hover_on_data';
+
const AUTO_COMPLETE_RESULTS_LIMIT = 15;
Meteor.methods({
@@ -125,7 +126,7 @@ Meteor.methods({
let query = { _id: nodeId };
let node = Inventory.findOne(query);
let attrsDefs = NodeHoverAttr.findOne({ 'type': node.type });
- let attributes = calcAttrsForNode(node, attrsDefs);
+ let attributes = calcAttrsForItem(node, attrsDefs);
return {
node: node,
@@ -134,26 +135,3 @@ Meteor.methods({
};
},
});
-
-function calcAttrsForNode(node, attrsDefsRec) {
- if (R.isNil(attrsDefsRec)) {
- return [];
- }
-
- let attrsDefs = attrsDefsRec.attributes;
-
- return R.reduce((acc, attrDef) => {
- if (R.is(Array, attrDef)) {
- let value = R.path(attrDef, node);
- if (R.isNil(value)) { return acc; }
- let name = R.join('.', attrDef);
- return R.append(R.assoc(name, value, {}), acc);
-
- } else {
- return R.ifElse(R.isNil,
- R.always(acc),
- (attrVal) => R.append(R.assoc(attrDef, attrVal, {}), acc)
- )(R.prop(attrDef, node));
- }
- }, [], attrsDefs);
-}
diff --git a/ui/imports/api/links/server/methods.js b/ui/imports/api/links/server/methods.js
new file mode 100644
index 0000000..8d3454b
--- /dev/null
+++ b/ui/imports/api/links/server/methods.js
@@ -0,0 +1,31 @@
+/////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others /
+// /
+// All rights reserved. This program and the accompanying materials /
+// are made available under the terms of the Apache License, Version 2.0 /
+// which accompanies this distribution, and is available at /
+// http://www.apache.org/licenses/LICENSE-2.0 /
+/////////////////////////////////////////////////////////////////////////////////////////
+
+import { Links } from '../links';
+import { NodeHoverAttr, calcAttrsForItem } from '/imports/api/attributes_for_hover_on_data/attributes_for_hover_on_data';
+import * as R from 'ramda';
+
+Meteor.methods({
+ 'linksFind?DataAndAttrs': function (id) {
+ console.log(`method server: linksFind?DataAndAttrs. ${R.toString(id)}`);
+ //check(nodeId, ObjectId);
+ this.unblock();
+
+ let query = { _id: id };
+ let link = Links.findOne(query);
+ let attrsDefs = NodeHoverAttr.findOne({ 'type': 'link' });
+ let attributes = calcAttrsForItem(link, attrsDefs);
+
+ return {
+ link: link,
+ linkName: link.link_name,
+ attributes: attributes
+ };
+ },
+});
diff --git a/ui/imports/api/messages/server/methods.js b/ui/imports/api/messages/server/methods.js
index 119e6b0..540c0a1 100644
--- a/ui/imports/api/messages/server/methods.js
+++ b/ui/imports/api/messages/server/methods.js
@@ -11,7 +11,7 @@ import { Messages } from '/imports/api/messages/messages';
Meteor.methods({
'messages/get?level&env&page&amountPerPage&sortField&sortDirection': function (
- level, env, page, amountPerPage, sortField, sortDirection) {
+ level, env, page, amountPerPage, sortField, sortDirection) {
logMethodCall('messages/get?level&env&page&amountPerPage&sortField&sortDirection',
{level, env, page, amountPerPage});
@@ -27,7 +27,7 @@ Meteor.methods({
query = R.ifElse(R.isNil, R.always(query),R.assoc('level', R.__, query))(level);
sortParams = R.ifElse(R.isNil, R.always(sortParams),
- R.assoc(R.__, sortDirection, sortParams))(sortField);
+ R.assoc(R.__, sortDirection, sortParams))(sortField);
console.log('sort params:', sortParams);
diff --git a/ui/imports/api/messages/server/publications.js b/ui/imports/api/messages/server/publications.js
index 13c7c50..6b147f0 100644
--- a/ui/imports/api/messages/server/publications.js
+++ b/ui/imports/api/messages/server/publications.js
@@ -88,11 +88,28 @@ Meteor.publish('messages/count?level', function (level) {
return new Counter(counterName, Messages.find({ level: level }));
});
+Meteor.publish('messages/count?backDelta&level', function (backDelta, level) {
+ const counterName = `messages/count?backDelta=${backDelta}&level=${level}`;
+ console.log(`subscribe - counter: ${counterName}`);
+
+ let begining = moment().subtract(backDelta);
+ let query = {
+ level: level,
+ timestamp: { $gte: begining.toDate() }
+ };
+
+ console.log(`query: ${R.toString(query)}`);
+
+ return new Counter(counterName, Messages.find(query));
+});
+
Meteor.publish('messages/count?level&env', function (level, env) {
const counterName = `messages/count?level=${level}&env=${env}`;
console.log(`subscribe - counter: ${counterName}`);
let query = { level: level };
query = R.ifElse(R.isNil, R.always(query), R.assoc('environment', R.__, query))(env);
+ console.log(`query: ${R.toString(query)}`);
- return new Counter(counterName, Messages.find(query)); });
+ return new Counter(counterName, Messages.find(query));
+});
diff --git a/ui/imports/lib/images-for-node-type.js b/ui/imports/lib/images-for-node-type.js
index fb8e582..19be6ac 100644
--- a/ui/imports/lib/images-for-node-type.js
+++ b/ui/imports/lib/images-for-node-type.js
@@ -1,14 +1,59 @@
export let imagesForNodeType = {
- 'instance': 'ic_computer_black_48dp_2x.png',
- 'pnic': 'ic_dns_black_48dp_2x.png',
- 'vconnector': 'ic_settings_input_composite_black_48dp_2x.png',
+ 'instance': {
+ default: 'ic_computer_black_48dp_2x.png',
+ ok: 'ic_computer_black_48dp_2x-green.png',
+ warning: 'ic_computer_black_48dp_2x-orange.png',
+ error: 'ic_computer_black_48dp_2x-red.png',
+ },
+ 'pnic': {
+ default: 'ic_dns_black_48dp_2x.png',
+ ok: 'ic_dns_black_48dp_2x-green.png',
+ warning: 'ic_dns_black_48dp_2x-orange.png',
+ error: 'ic_dns_black_48dp_2x-red.png',
+ },
+ 'vconnector': {
+ default: 'ic_settings_input_composite_black_48dp_2x.png',
+ ok: 'ic_settings_input_composite_black_48dp_2x-green.png',
+ warning: 'ic_settings_input_composite_black_48dp_2x-orange.png',
+ error: 'ic_settings_input_composite_black_48dp_2x-red.png',
+ },
// 'network': 'ic_cloud_queue_black_48dp_2x.png',
- 'network': 'ic_cloud_queue_black_48dp_2x.png',
- 'vedge': 'ic_gamepad_black_48dp_2x.png',
- 'vservice': 'ic_storage_black_48dp_2x.png',
- 'vnic': 'ic_settings_input_hdmi_black_48dp_2x.png',
- 'otep':'ic_keyboard_return_black_48dp_2x.png',
+ 'network': {
+ default: 'ic_cloud_queue_black_48dp_2x.png',
+ ok: 'ic_cloud_queue_black_48dp_2x-green.png',
+ warning: 'ic_cloud_queue_black_48dp_2x-orange.png',
+ error: 'ic_cloud_queue_black_48dp_2x-red.png',
+ },
+ 'vedge': {
+ default: 'ic_gamepad_black_48dp_2x.png',
+ ok: 'ic_gamepad_black_48dp_2x-green.png',
+ warning: 'ic_gamepad_black_48dp_2x-orange.png',
+ error: 'ic_gamepad_black_48dp_2x-red.png',
+ },
+ 'vservice': {
+ default: 'ic_storage_black_48dp_2x.png',
+ ok: 'ic_storage_black_48dp_2x-green.png',
+ warning: 'ic_storage_black_48dp_2x-orange.png',
+ error: 'ic_storage_black_48dp_2x-red.png',
+ },
+ 'vnic': {
+ default: 'ic_settings_input_hdmi_black_48dp_2x.png',
+ ok: 'ic_settings_input_hdmi_black_48dp_2x-green.png',
+ warning: 'ic_settings_input_hdmi_black_48dp_2x-orange.png',
+ error: 'ic_settings_input_hdmi_black_48dp_2x-red.png',
+ },
+ 'otep': {
+ default: 'ic_keyboard_return_black_48dp_2x.png',
+ ok: 'ic_keyboard_return_black_48dp_2x-green.png',
+ warning: 'ic_keyboard_return_black_48dp_2x-orange.png',
+ error: 'ic_keyboard_return_black_48dp_2x-red.png',
+ },
};
-export let defaultNodeTypeImage = 'ic_lens_black_48dp_2x.png';
+export let defaultNodeTypeImage = {
+ default: 'ic_lens_black_48dp_2x.png',
+ ok: 'ic_lens_black_48dp_2x-green.png',
+ warning: 'ic_lens_black_48dp_2x-orange.png',
+ error: 'ic_lens_black_48dp_2x-red.png',
+};
diff --git a/ui/imports/startup/client/index.js b/ui/imports/startup/client/index.js
index 93da904..6ac478c 100644
--- a/ui/imports/startup/client/index.js
+++ b/ui/imports/startup/client/index.js
@@ -36,3 +36,4 @@ import '/imports/ui/components/messages-list/messages-list';
import '/imports/ui/components/message/message';
import '/imports/ui/components/dashboard/dashboard';
import '/imports/ui/components/new-scanning/new-scanning';
+import '/imports/ui/components/configuration/configuration';
diff --git a/ui/imports/startup/server/register-api.js b/ui/imports/startup/server/register-api.js
index 3475c53..71d6887 100644
--- a/ui/imports/startup/server/register-api.js
+++ b/ui/imports/startup/server/register-api.js
@@ -31,6 +31,7 @@ import '../../api/cliques/methods.js';
import '../../api/links/server/publications';
import '../../api/links/methods.js';
+import '../../api/links/server/methods';
import '../../api/statistics/server/publications';
import '../../api/statistics/methods.js';
@@ -53,4 +54,7 @@ import '../../api/accounts/methods';
import '../../api/supported_environments/server/publications';
import '../../api/supported_environments/methods';
+import '../../api/configurations/server/publications';
+import '../../api/configurations/methods';
+
import '../../api/migrations/migrations';
diff --git a/ui/imports/ui/components/alarm-icons/alarm-icons.html b/ui/imports/ui/components/alarm-icons/alarm-icons.html
index d584990..e59414e 100644
--- a/ui/imports/ui/components/alarm-icons/alarm-icons.html
+++ b/ui/imports/ui/components/alarm-icons/alarm-icons.html
@@ -15,34 +15,37 @@
<div class="dropdown">
<div class="material-icons mdl-badge mdl-badge--overlap dropdown-toggle"
- data-badge="{{countOf 'messages/count?level=info'}}"
+ data-badge="{{ countOf (msgCounterName 'info') }}"
type="button"
id="dropdownMenu1"
data-toggle="modal"
data-target="#messagesModalGlobal"
data-message-level="info"
+ title="Info messages"
>notifications</div>
</div>
<div class="dropdown">
<div class="material-icons mdl-badge mdl-badge--overlap dropdown-toggle"
- data-badge="{{countOf 'messages/count?level=warning'}}"
+ data-badge="{{ countOf (msgCounterName 'warning') }}"
type="button"
id="dropdownMenu1"
data-toggle="modal"
data-target="#messagesModalGlobal"
data-message-level="warning"
+ title="Warning messages"
>warning</div>
</div>
<div class="dropdown">
<div class="material-icons mdl-badge mdl-badge--overlap dropdown-toggle"
- data-badge="{{countOf 'messages/count?level=error'}}"
+ data-badge="{{ countOf (msgCounterName 'error') }}"
type="button"
id="dropdownMenu1"
data-toggle="modal"
data-target="#messagesModalGlobal"
data-message-level="error"
+ title="Error messages"
>error</div>
</div>
@@ -69,6 +72,10 @@
<a href="{{pathFor route='user-list' query=''}}">Users</a>
</li>
{{/if }}
+
+ <li class="dropdown-header">
+ <a href="{{pathFor route='configuration' query=''}}" >Configuration</a>
+ </li>
</ul>
</div>
diff --git a/ui/imports/ui/components/alarm-icons/alarm-icons.js b/ui/imports/ui/components/alarm-icons/alarm-icons.js
index 5c7af31..e86f8d8 100644
--- a/ui/imports/ui/components/alarm-icons/alarm-icons.js
+++ b/ui/imports/ui/components/alarm-icons/alarm-icons.js
@@ -13,6 +13,9 @@
import '/imports/ui/components/breadcrumb/breadcrumb';
import { Messages } from '/imports/api/messages/messages';
import { Roles } from 'meteor/alanning:roles';
+import { ReactiveDict } from 'meteor/reactive-dict';
+
+import { Configurations } from '/imports/api/configurations/configurations';
import './alarm-icons.html';
@@ -23,10 +26,24 @@ import './alarm-icons.html';
Template.alarmIcons.onCreated(function () {
let instance = this;
+ instance.state = new ReactiveDict();
+ instance.state.setDefault({
+ msgsViewBackDelta: 1
+ });
+
instance.autorun(function () {
- instance.subscribe('messages/count?level', 'info');
- instance.subscribe('messages/count?level', 'warning');
- instance.subscribe('messages/count?level', 'error');
+ instance.subscribe('configurations?user');
+ Configurations.find({user_id: Meteor.userId()}).forEach((conf) => {
+ instance.state.set('msgsViewBackDelta', conf.messages_view_backward_delta);
+ });
+ });
+
+ instance.autorun(function () {
+ let msgsViewBackDelta = instance.state.get('msgsViewBackDelta');
+
+ instance.subscribe('messages/count?backDelta&level', msgsViewBackDelta, 'info');
+ instance.subscribe('messages/count?backDelta&level', msgsViewBackDelta, 'warning');
+ instance.subscribe('messages/count?backDelta&level', msgsViewBackDelta, 'error');
});
});
@@ -50,4 +67,12 @@ Template.alarmIcons.helpers({
errorsCount: function(){
return Messages.find({level:'error'}).count();
},
+
+ msgCounterName: function (level) {
+ let instance = Template.instance();
+ let msgsViewBackDelta = instance.state.get('msgsViewBackDelta');
+ let counterName = `messages/count?backDelta=${msgsViewBackDelta}&level=${level}`;
+
+ return counterName;
+ }
});
diff --git a/ui/imports/ui/components/clique-type/clique-type.js b/ui/imports/ui/components/clique-type/clique-type.js
index ae50b94..9b21442 100644
--- a/ui/imports/ui/components/clique-type/clique-type.js
+++ b/ui/imports/ui/components/clique-type/clique-type.js
@@ -130,7 +130,7 @@ Template.CliqueType.helpers({
objectTypesList: function () {
return R.ifElse(R.isNil, R.always([]), R.prop('data')
- )(Constants.findOne({ name: 'object_types_for_links' }));
+ )(Constants.findOne({ name: 'object_types_for_links' }));
},
linkTypesList: function () {
@@ -280,7 +280,7 @@ function submitItem(
focal_point_type,
link_types,
name
- ) {
+) {
let action = instance.state.get('action');
@@ -316,7 +316,7 @@ function submitItem(
break;
default:
- // todo
+ // todo
break;
}
}
diff --git a/ui/imports/ui/components/configuration/configuration.html b/ui/imports/ui/components/configuration/configuration.html
new file mode 100644
index 0000000..f381453
--- /dev/null
+++ b/ui/imports/ui/components/configuration/configuration.html
@@ -0,0 +1,31 @@
+<template name="Configuration">
+<div class="os-configuration cards white">
+ <h3>Configurations</h3>
+ <form>
+ <div class="cl-field-group">
+ <label class="cl-field-label">Message view backward delta</label>
+ <input name="msgsViewBackDelta"
+ value="{{ getModelField 'messages_view_backward_delta' }}"
+ class="cl-msgs-view-back-delta cl-input"
+ type="number"
+ placeholder="" />
+ <div class="cl-field-desc">Backward duration of {{ durationHumanize (getModelField 'messages_view_backward_delta') }} from current date (miliseconds)</div>
+ </div>
+
+ <button type="button"
+ class="js-submit-button mdl-button mdl-js-button mdl-button--raised
+ mdl-js-ripple-effect mdl-button--colored"
+ >Save</button>
+ </form>
+
+ {{#if (getState 'message') }}
+ <div class="js-message-panel alert
+ {{#if isActionError}}alert-danger{{/if}}
+ {{#if isActionSuccess}}alert-success{{/if}}"
+ role="alert">
+ {{ getState 'message' }}
+ </div>
+ {{/if }}
+
+</div>
+</template>
diff --git a/ui/imports/ui/components/configuration/configuration.js b/ui/imports/ui/components/configuration/configuration.js
new file mode 100644
index 0000000..493cc36
--- /dev/null
+++ b/ui/imports/ui/components/configuration/configuration.js
@@ -0,0 +1,114 @@
+/*
+ * Template Component: Configuration
+ */
+
+//import { Meteor } from 'meteor/meteor';
+import { Template } from 'meteor/templating';
+import { ReactiveDict } from 'meteor/reactive-dict';
+//import { SimpleSchema } from 'meteor/aldeed:simple-schema';
+import * as R from 'ramda';
+
+import { save } from '/imports/api/configurations/methods';
+import { Configurations } from '/imports/api/configurations/configurations';
+
+import './configuration.html';
+
+/*
+ * Lifecycles
+ */
+
+Template.Configuration.onCreated(function() {
+ let instance = this;
+ instance.state = new ReactiveDict();
+ instance.state.setDefault({
+ model: Configurations.schema.clean({}),
+ actionResult: 'none',
+ message: null,
+ });
+
+ /*
+ instance.autorun(function () {
+ let data = Template.currentData();
+
+ new SimpleSchema({
+ }).validate(data);
+ });
+ */
+
+ instance.autorun(function () {
+ instance.subscribe('configurations?user');
+ Configurations.find({user_id: Meteor.userId()}).forEach((conf) => {
+ instance.state.set('model', conf);
+ });
+ });
+});
+
+/*
+Template.Configuration.rendered = function() {
+};
+*/
+
+/*
+ * Events
+ */
+
+Template.Configuration.events({
+ 'click .js-submit-button': function (event, instance) {
+ event.preventDefault();
+ let msgsViewBackDelta = instance.$('.cl-msgs-view-back-delta')[0].value;
+ saveForm(instance, msgsViewBackDelta);
+ }
+});
+
+/*
+ * Helpers
+ */
+
+Template.Configuration.helpers({
+ getModelField: function (fieldName) {
+ let instance = Template.instance();
+ return R.path([fieldName], instance.state.get('model'));
+ },
+
+ getState: function (key) {
+ let instance = Template.instance();
+ return instance.state.get(key);
+ },
+
+ isActionError: function () {
+ let instance = Template.instance();
+ return instance.state.get('actionResult') === 'error';
+ },
+
+ isActionSuccess: function () {
+ let instance = Template.instance();
+ return instance.state.get('actionResult') === 'success';
+ },
+
+ durationHumanize: function (duration) {
+ return moment.duration(duration).humanize();
+ }
+}); // end: helpers
+
+function saveForm(instance, msgsViewBackDelta) {
+ instance.state.set('actionResult', 'none');
+ instance.state.set('message', null);
+
+ save.call({
+ messages_view_backward_delta: msgsViewBackDelta
+ }, (error) => {
+ if (error) {
+ instance.state.set('actionResult', 'error');
+ if (typeof error === 'string') {
+ instance.state.set('message', error);
+ } else {
+ instance.state.set('message', error.message);
+ }
+
+ return;
+ }
+
+ instance.state.set('actionResult', 'success');
+ instance.state.set('message', 'record has been updated succesfuly');
+ });
+}
diff --git a/ui/imports/ui/components/configuration/configuration.styl b/ui/imports/ui/components/configuration/configuration.styl
new file mode 100644
index 0000000..b8be180
--- /dev/null
+++ b/ui/imports/ui/components/configuration/configuration.styl
@@ -0,0 +1,38 @@
+/* Set the component style here */
+// "Configuration"
+.os-configuration
+ display: flex;
+ flex-flow: column nowrap;
+ margin: 20px;
+
+ .cl-field-group
+ display: flex;
+ flex-flow: row nowrap;
+ align-items: center;
+ padding: 5px 0;
+
+ .cl-field-label
+ width: 120px;
+ margin: 0 5px;
+
+ >.cl-input
+ display: block;
+ width: 100%;
+ min-height: 34px;
+ padding: 6px 12px;
+ font-size: 14px;
+ line-height: 1.42857143;
+ color: #555;
+ background-color: #fff;
+ background-image: none;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+ width: 400px;
+ margin: 0 5px;
+
+ .cl-field-desc
+ margin: 0 5px;
+
+ .js-message-panel
+ margin-top: 20px;
diff --git a/ui/imports/ui/components/dashboard/dashboard.js b/ui/imports/ui/components/dashboard/dashboard.js
index 85cede8..6fdc184 100644
--- a/ui/imports/ui/components/dashboard/dashboard.js
+++ b/ui/imports/ui/components/dashboard/dashboard.js
@@ -13,8 +13,8 @@
//import * as R from 'ramda';
import * as _ from 'lodash';
import { Environments } from '/imports/api/environments/environments';
-import { //Messages,
- calcIconForMessageLevel, lastMessageTimestamp, calcColorClassForMessagesInfoBox
+import { //Messages,
+ calcIconForMessageLevel, lastMessageTimestamp, calcColorClassForMessagesInfoBox
} from '/imports/api/messages/messages';
import { Template } from 'meteor/templating';
import { Inventory } from '/imports/api/inventories/inventories';
@@ -27,7 +27,7 @@ import { setMainAppSelectedEnvironment } from '/imports/ui/actions/main-app.acti
import '/imports/ui/components/messages-info-box/messages-info-box';
import '/imports/ui/components/environment-box/environment-box';
-import './dashboard.html';
+import './dashboard.html';
/*
* Lifecycle methods
@@ -212,10 +212,10 @@ Template.Dashboard.helpers({
icon: calcIconForMessageLevel(boxDef.level),
colorClass: calcColorClassForMessagesInfoBox(boxDef.level),
onMoreDetailsReq: function () {
- $('#messagesModalGlobal').modal('show', {
+ $('#messagesModalGlobal').modal('show', {
dataset: {
messageLevel: boxDef.level,
- }
+ }
});
}
};
@@ -223,10 +223,10 @@ Template.Dashboard.helpers({
argsEnvBox: function (
environmentName,
- regionsCount,
- regions,
- projectsCount,
- projects,
+ regionsCount,
+ regions,
+ projectsCount,
+ projects,
instancesCount,
vservicesCount,
vconnectorsCount,
diff --git a/ui/imports/ui/components/environment-dashboard/environment-dashboard.js b/ui/imports/ui/components/environment-dashboard/environment-dashboard.js
index 433096e..82fbb52 100644
--- a/ui/imports/ui/components/environment-dashboard/environment-dashboard.js
+++ b/ui/imports/ui/components/environment-dashboard/environment-dashboard.js
@@ -26,6 +26,7 @@ import { calcIconForMessageLevel, lastMessageTimestamp, calcColorClassForMessage
import { Counts } from 'meteor/tmeasday:publish-counts';
import { Roles } from 'meteor/alanning:roles';
//import { idToStr } from '/imports/lib/utilities';
+import { Counter } from 'meteor/natestrauser:publish-performant-counts';
import '/imports/ui/components/data-cubic/data-cubic';
import '/imports/ui/components/icon/icon';
@@ -123,9 +124,10 @@ Template.EnvironmentDashboard.onCreated(function() {
instance.subscribe('inventory?env+type', env.name, 'vconnector');
instance.subscribe('inventory?env+type', env.name, 'project');
instance.subscribe('inventory?env+type', env.name, 'region');
- instance.subscribe('messages?env+level', env.name, 'info');
- instance.subscribe('messages?env+level', env.name, 'warning');
- instance.subscribe('messages?env+level', env.name, 'error');
+
+ instance.subscribe('messages/count?level&env', 'info', env.name);
+ instance.subscribe('messages/count?level&env', 'warning', env.name);
+ instance.subscribe('messages/count?level&env', 'error', env.name);
let vConnectorCounterName = 'inventory?env+type!counter?env=' +
env.name + '&type=' + 'vconnector';
@@ -316,8 +318,11 @@ Template.EnvironmentDashboard.helpers({
};
}
- let count = Counts.get('messages?env+level!counter?env=' +
- envName + '&level=' + boxDef.level);
+ let counterName = `messages/count?level=${boxDef.level}&env=${envName}`;
+ let count = Counter.get(counterName);
+
+ //let count = Counts.get('messages?env+level!counter?env=' +
+ // envName + '&level=' + boxDef.level);
let title = _.capitalize(boxDef.level);
diff --git a/ui/imports/ui/components/environment/environment.js b/ui/imports/ui/components/environment/environment.js
index 83574f2..1f0e723 100644
--- a/ui/imports/ui/components/environment/environment.js
+++ b/ui/imports/ui/components/environment/environment.js
@@ -157,6 +157,7 @@ Template.Environment.onCreated(function () {
new SimpleSchema({
_id: _idFieldDef,
selectedNodeId: R.assoc('optional', true, _idFieldDef),
+ refresh: { type: String, optional: true },
}).validate(data);
store.dispatch(setEnvEnvId(data._id));
diff --git a/ui/imports/ui/components/graph-tooltip-window/graph-tooltip-window.html b/ui/imports/ui/components/graph-tooltip-window/graph-tooltip-window.html
index 53537ca..4ce9787 100644
--- a/ui/imports/ui/components/graph-tooltip-window/graph-tooltip-window.html
+++ b/ui/imports/ui/components/graph-tooltip-window/graph-tooltip-window.html
@@ -9,8 +9,8 @@
########################################################################################
-->
<template name="GraphTooltipWindow">
- <div class="os-graph-tooltip-window {{#if show}}cl-visible{{/if}}"
- style="top: {{ top }}px; left: {{ left }}px;">
+<div class="os-graph-tooltip-window {{#if show}}cl-visible{{/if}}"
+ style="top: {{ top }}px; left: {{ left }}px;">
<div class="sm-label"><u>{{ label }}</u></div>
<div class="sm-title">{{{ title }}}</div>
</div>
diff --git a/ui/imports/ui/components/graph-tooltip-window/graph-tooltip-window.js b/ui/imports/ui/components/graph-tooltip-window/graph-tooltip-window.js
index 48b1903..dbeb55c 100644
--- a/ui/imports/ui/components/graph-tooltip-window/graph-tooltip-window.js
+++ b/ui/imports/ui/components/graph-tooltip-window/graph-tooltip-window.js
@@ -14,6 +14,8 @@
import { Template } from 'meteor/templating';
//import { ReactiveDict } from 'meteor/reactive-dict';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
+import { store } from '/imports/ui/store/store';
+import { closeGraphTooltipWindow } from '/imports/ui/actions/graph-tooltip-window.actions';
import './graph-tooltip-window.html';
@@ -45,6 +47,23 @@ Template.GraphTooltipWindow.rendered = function() {
*/
Template.GraphTooltipWindow.events({
+ 'mouseout .os-graph-tooltip-window': function(_e, _instance) {
+ /*
+ if (!instance.data.show) { return; }
+
+ e.preventDefault();
+ e.stopPropagation();
+ store.dispatch(closeGraphTooltipWindow());
+ */
+ },
+
+ 'click .os-graph-tooltip-window': function(e, instance) {
+ if (!instance.data.show) { return; }
+
+ e.preventDefault();
+ e.stopPropagation();
+ store.dispatch(closeGraphTooltipWindow());
+ },
});
/*
diff --git a/ui/imports/ui/components/graph-tooltip-window/graph-tooltip-window.styl b/ui/imports/ui/components/graph-tooltip-window/graph-tooltip-window.styl
index ec94023..1bbb9d5 100644
--- a/ui/imports/ui/components/graph-tooltip-window/graph-tooltip-window.styl
+++ b/ui/imports/ui/components/graph-tooltip-window/graph-tooltip-window.styl
@@ -3,23 +3,26 @@
.os-graph-tooltip-window
visibility: hidden;
+ max-height: 300px;
+ overflow: auto;
position: absolute;
text-align: left;
opacity: 0
- font: normal 18px sans-serif !important;
+ font: normal 16px sans-serif;
/* width: 60px; */
/* height: 28px; */
padding: 20px;
- font: 16px sans-serif;
background: dk-gray1;
color white
border: 2px solid stark-blue
- pointer-events: none;
+ // pointer-events: none;
transition: visibility 0.5s, opacity 0.5s linear
+ .sm-label
+ font-weight: bold;
+
.os-graph-tooltip-window.cl-visible
visibility: visible
opacity: 0.9
transition: visibility 0.2s, opacity 0.2s linear
-
diff --git a/ui/imports/ui/components/index.styl b/ui/imports/ui/components/index.styl
index 2b2b2d3..877d68b 100644
--- a/ui/imports/ui/components/index.styl
+++ b/ui/imports/ui/components/index.styl
@@ -56,3 +56,4 @@
@import 'network-graph-manager/*';
@import 'network-graph/*';
@import 'environment-box/*';
+@import 'configuration/*';
diff --git a/ui/imports/ui/components/messages-modal/messages-modal.js b/ui/imports/ui/components/messages-modal/messages-modal.js
index 59a6ec7..713e8e9 100644
--- a/ui/imports/ui/components/messages-modal/messages-modal.js
+++ b/ui/imports/ui/components/messages-modal/messages-modal.js
@@ -7,10 +7,10 @@
// http://www.apache.org/licenses/LICENSE-2.0 /
/////////////////////////////////////////////////////////////////////////////////////////
/*
- * Template Component: MessagesModal
+ * Template Component: MessagesModal
*/
-
-//import { Meteor } from 'meteor/meteor';
+
+//import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import { ReactiveDict } from 'meteor/reactive-dict';
import { Counter } from 'meteor/natestrauser:publish-performant-counts';
@@ -18,15 +18,15 @@ import * as R from 'ramda';
//import { Messages } from '/imports/api/messages/messages';
import { Environments } from '/imports/api/environments/environments';
import { idToStr } from '/imports/lib/utilities';
-
+
import '/imports/ui/components/pager/pager';
-import './messages-modal.html';
-
-/*
+import './messages-modal.html';
+
+/*
* Lifecycles
- */
-
+ */
+
Template.MessagesModal.onCreated(function() {
let instance = this;
instance.state = new ReactiveDict();
@@ -41,7 +41,7 @@ Template.MessagesModal.onCreated(function() {
});
instance.autorun(function () {
-
+
//let amountPerPage = instance.state.get('amountPerPage');
//let page = instance.state.get('page');
let envName = instance.state.get('envName');
@@ -77,11 +77,11 @@ Template.MessagesModal.onCreated(function() {
instance.state.set('messages', res);
});
});
-});
+});
/*
Template.MessagesModal.rendered = function() {
-};
+};
*/
/*
@@ -107,9 +107,9 @@ Template.MessagesModal.events({
], {
wait: false
}, function (err, resp) {
- if (err) {
+ if (err) {
console.error(R.toString(err));
- return;
+ return;
}
if (R.isNil(resp.node)) {
@@ -117,12 +117,12 @@ Template.MessagesModal.events({
return;
}
- Router.go('environment', {
- _id: idToStr(environment._id)
- }, {
+ Router.go('environment', {
+ _id: idToStr(environment._id)
+ }, {
query: {
selectedNodeId: idToStr(resp.node._id)
- }
+ }
});
instance.$('#messagesModalGlobal').modal('hide');
@@ -131,12 +131,12 @@ Template.MessagesModal.events({
}
});
-
-/*
+
+/*
* Helpers
*/
-Template.MessagesModal.helpers({
+Template.MessagesModal.helpers({
iconType: function () {
let instance = Template.instance();
return instance.state.get('iconType');
@@ -186,17 +186,17 @@ Template.MessagesModal.helpers({
return {
disableNext: currentPage * amountPerPage > totalMessages,
disablePrev: currentPage == 1,
- totalPages: totalPages,
+ totalPages: totalPages,
currentPage: currentPage,
onReqNext: function () {
console.log('next');
let page = (currentPage * amountPerPage > totalMessages) ? currentPage : currentPage + 1;
- instance.state.set('page', page);
+ instance.state.set('page', page);
},
onReqPrev: function () {
console.log('prev');
let page = (currentPage == 1) ? currentPage : currentPage - 1;
- instance.state.set('page', page);
+ instance.state.set('page', page);
},
onReqFirst: function () {
console.log('req first');
@@ -209,9 +209,9 @@ Template.MessagesModal.helpers({
onReqPage: function (pageNumber) {
console.log('req page');
let page;
- if (pageNumber <= 1) {
- page = 1;
- } else if (pageNumber > Math.ceil(totalMessages / amountPerPage)) {
+ if (pageNumber <= 1) {
+ page = 1;
+ } else if (pageNumber > Math.ceil(totalMessages / amountPerPage)) {
page = totalPages;
} else {
page = pageNumber;
diff --git a/ui/imports/ui/components/network-graph-manager/network-graph-manager.js b/ui/imports/ui/components/network-graph-manager/network-graph-manager.js
index 16637ea..ed556c0 100644
--- a/ui/imports/ui/components/network-graph-manager/network-graph-manager.js
+++ b/ui/imports/ui/components/network-graph-manager/network-graph-manager.js
@@ -37,7 +37,8 @@ Template.NetworkGraphManager.onCreated(function() {
links: [],
nodes: [],
groups: [],
- }
+ },
+ itemOfInterest: null
};
instance.autorun(function () {
@@ -95,6 +96,13 @@ Template.NetworkGraphManager.helpers({
return;
}
+ if (instance.simpleState.itemOfInterest === nodeId) {
+ instance.simpleState.itemOfInterest = null;
+ return;
+ }
+
+ instance.simpleState.itemOfInterest = nodeId;
+
Meteor.apply('inventoryFindNode?DataAndAttrs', [ nodeId ],
{ wait: false }, function (err, res) {
if (err) {
@@ -103,11 +111,11 @@ Template.NetworkGraphManager.helpers({
}
store.dispatch(
- activateGraphTooltipWindow(res.nodeName, res.attributes, x, y));
+ activateGraphTooltipWindow(res.nodeName, res.attributes, x - 30, y - 10));
});
},
onNodeOut: function (_nodeId) {
- store.dispatch(closeGraphTooltipWindow());
+ //store.dispatch(closeGraphTooltipWindow());
},
onNodeClick: function (_nodeId) {
},
@@ -118,6 +126,33 @@ Template.NetworkGraphManager.helpers({
onDragEnd: function () {
isDragging = false;
},
+ onGroupOver: function () {
+ instance.simpleState.itemOfInterest = null;
+ store.dispatch(closeGraphTooltipWindow());
+ },
+ onLinkOver: function (linkId, x, y) {
+ if (isDragging) {
+ return;
+ }
+
+ if (instance.simpleState.itemOfInterest === linkId) {
+ instance.simpleState.itemOfInterest = null;
+ return;
+ }
+
+ instance.simpleState.itemOfInterest = linkId;
+
+ Meteor.apply('linksFind?DataAndAttrs', [ linkId ],
+ { wait: false }, function (err, res) {
+ if (err) {
+ console.error(`error fetching attrs for link for showing: ${R.toString(err)}`);
+ return;
+ }
+
+ store.dispatch(
+ activateGraphTooltipWindow(res.linkName, res.attributes, x - 30, y - 10));
+ });
+ },
};
},
@@ -180,7 +215,11 @@ function addLinkToGraph(link, graphData) {
sourceId: link.source,
targetId: link.target,
label: link.link_name,
- _osid: link._id
+ _osid: link._id,
+ _osmeta: {
+ status: link.status,
+ linkId: link._id
+ }
};
let links = R.unionWith(R.eqBy(R.prop('_osid')), graphData.links, [newLink]);
@@ -215,6 +254,7 @@ function addNodeToGraph(node, graphData) {
_osmeta: {
type: node.type,
nodeId: node._id,
+ status: node.status,
},
width: 60,
height: 40,
diff --git a/ui/imports/ui/components/network-graph/network-graph.js b/ui/imports/ui/components/network-graph/network-graph.js
index 04a33b0..68b3a57 100644
--- a/ui/imports/ui/components/network-graph/network-graph.js
+++ b/ui/imports/ui/components/network-graph/network-graph.js
@@ -9,6 +9,7 @@ import { SimpleSchema } from 'meteor/aldeed:simple-schema';
import * as R from 'ramda';
import * as cola from 'webcola';
import { imagesForNodeType, defaultNodeTypeImage } from '/imports/lib/images-for-node-type';
+import * as _ from 'lodash';
import './network-graph.html';
@@ -37,6 +38,8 @@ Template.NetworkGraph.onCreated(function() {
onNodeClick: { type: Function, optional: true },
onDragStart: { type: Function, optional: true },
onDragEnd: { type: Function, optional: true },
+ onGroupOver: { type: Function, optional: true },
+ onLinkOver: { type: Function, optional: true },
}).validate(data);
instance.simpleState.graphData = data.graphData;
@@ -46,6 +49,8 @@ Template.NetworkGraph.onCreated(function() {
instance.onNodeClick = R.defaultTo(() => {}, data.onNodeClick);
instance.onDragStart = R.defaultTo(() => {}, data.onDragStart);
instance.onDragEnd = R.defaultTo(() => {}, data.onDragEnd);
+ instance.onGroupOver = R.defaultTo(() => {}, data.onGroupOver);
+ instance.onLinkOver = R.defaultTo(() => {}, data.onLinkOver);
});
});
@@ -66,7 +71,9 @@ Template.NetworkGraph.rendered = function() {
instance.onNodeOut,
instance.onNodeClick,
instance.onDragStart,
- instance.onDragEnd
+ instance.onDragEnd,
+ instance.onGroupOver,
+ instance.onLinkOver
);
});
};
@@ -129,7 +136,9 @@ function renderGraph(
onNodeOut,
onNodeClick,
onDragStart,
- onDragEnd
+ onDragEnd,
+ onGroupOver,
+ onLinkOver
) {
let force = genForceCola(cola, d3, w, h);
@@ -167,10 +176,15 @@ function renderGraph(
nodesEl,
linksEl,
drag, zoom, config,
- onNodeOver, onNodeOut, onNodeClick);
+ onNodeOver,
+ onNodeOut,
+ onNodeClick,
+ onGroupOver,
+ onLinkOver
+ );
}
- // d3.select(window).on('resize', resize);
+// d3.select(window).on('resize', resize);
function genSvg(d3, mainElement) {
let svg = d3.select(mainElement).append('svg');
@@ -183,17 +197,24 @@ function genSvg(d3, mainElement) {
return svg;
}
-function genSvgLinks(g, links, nominal_stroke, default_link_color, initialLinkLabelsFontSize) {
+function genSvgLinks(
+ g,
+ links,
+ nominal_stroke,
+ default_link_color,
+ initialLinkLabelsFontSize,
+ onLinkOver
+) {
let svgLinks = g.selectAll('.link-group')
.data(links, (d) => d._osid);
let svgLinksEnter = svgLinks
.enter()
- .append('g')
- .attr('class', 'link-group')
- .attr('data-link-id', function (d) {
- return d._osid;
- })
+ .append('g')
+ .attr('class', 'link-group')
+ .attr('data-link-id', function (d) {
+ return d._osid;
+ })
;
//let svgLinksExit =
@@ -205,9 +226,24 @@ function genSvgLinks(g, links, nominal_stroke, default_link_color, initialLinkLa
.attr('class', 'link-line')
.style('stroke-width', nominal_stroke)
.style('stroke',
- function(_d) {
- return default_link_color;
- });
+ function(d) {
+ let status = R.defaultTo('', R.path(['_osmeta', 'status'], d));
+ status = _.toLower(status);
+ switch(status) {
+ case 'ok':
+ return 'green';
+ case 'warning':
+ return 'orange';
+ case 'error':
+ return 'red';
+ default:
+ return default_link_color;
+ }
+ })
+ .on('mouseover', function (d) {
+ onLinkOver(d._osmeta.linkId, d3.event.pageX, d3.event.pageY);
+ })
+ ;
let svgLinkLabels = svgLinksEnter
.append('text')
@@ -232,9 +268,9 @@ function genSvgNodes(g, nodes, drag, onNodeOver, onNodeOut, onNodeClick, onGroup
let svgNodesEnter = svgNodes
.enter()
.append('g')
- .attr('class', 'node')
- .attr('data-node-id', (d) => d._osid)
- .call(drag);
+ .attr('class', 'node')
+ .attr('data-node-id', (d) => d._osid)
+ .call(drag);
//let svgNodesExit =
svgNodes
@@ -244,7 +280,9 @@ function genSvgNodes(g, nodes, drag, onNodeOver, onNodeOut, onNodeClick, onGroup
let svgImages = svgNodesEnter.append('image')
.attr('class', 'node-image')
.attr('xlink:href', function(d) {
- return `/${calcImageForNodeType(d._osmeta.type)}`;
+ let status = R.defaultTo('', R.path(['_osmeta', 'status'], d));
+ status = _.toLower(status);
+ return `/${calcImageForNodeType(d._osmeta.type, status)}`;
})
.attr('x', -(Math.floor(imageLength / 2)))
.attr('y', -(Math.floor(imageLength / 2)))
@@ -268,8 +306,13 @@ function genSvgNodes(g, nodes, drag, onNodeOver, onNodeOut, onNodeClick, onGroup
//return [svgNodes];
}
-function calcImageForNodeType(nodeType) {
- return R.defaultTo(defaultNodeTypeImage, R.prop(nodeType, imagesForNodeType));
+function calcImageForNodeType(nodeType, status) {
+ let image = R.defaultTo(defaultNodeTypeImage, R.prop(nodeType, imagesForNodeType));
+ if (typeof image === 'object') {
+ image = R.defaultTo(image.default, image[status]);
+ }
+
+ return image;
}
function genZoomBehavior(d3, config) {
@@ -292,7 +335,7 @@ function genForceD3(d3, w, h) {
function genForceCola(cola, d3, w, h) {
let force = cola.d3adaptor(d3)
.convergenceThreshold(0.1)
- // .convergenceThreshold(1e-9)
+ //.convergenceThreshold(1e-9)
.linkDistance(120)
.size([w,h]);
@@ -308,7 +351,7 @@ function activateForce(force, nodes, links, groups) {
.handleDisconnected(true)
.avoidOverlaps(true)
.start(50, 100, 200);
- //.start();
+ //.start();
}
/*
@@ -340,7 +383,10 @@ function renderView(force,
config,
onNodeOver,
onNodeOut,
- onNodeClick) {
+ onNodeClick,
+ onGroupOver,
+ onLinkOver
+) {
state.viewGraph = calcViewGraph(state.graph, state.viewGraph);
@@ -348,13 +394,14 @@ function renderView(force,
zoom.on('zoom', zoomFn);
- genSvgGroups(groupsEl, state.viewGraph.groups, drag, onRenderViewReq);
+ genSvgGroups(groupsEl, state.viewGraph.groups, drag, onRenderViewReq, onGroupOver);
genSvgLinks(
linksEl, state.viewGraph.links,
config.nominal_stroke,
config.default_link_color,
- config.initialLinkLabelsFontSize
+ config.initialLinkLabelsFontSize,
+ onLinkOver
);
genSvgNodes(
@@ -366,7 +413,7 @@ function renderView(force,
state.viewGraph = renderView(force, state,
mainEl, groupsEl, nodesEl, linksEl,
drag, zoom, config,
- onNodeOver, onNodeOut, onNodeClick);
+ onNodeOver, onNodeOut, onNodeClick, onGroupOver, onLinkOver);
});
force.on('tick', tickFn);
@@ -375,7 +422,7 @@ function renderView(force,
state.viewGraph = renderView(force, state,
mainEl, groupsEl, nodesEl, linksEl,
drag, zoom, config,
- onNodeOver, onNodeOut, onNodeClick);
+ onNodeOver, onNodeOut, onNodeClick, onGroupOver, onLinkOver);
}
function tickFn() {
@@ -477,30 +524,33 @@ function renderView(force,
return state.viewGraph;
}
-function genSvgGroups(g, groups, drag, onRenderViewReq) {
+function genSvgGroups(g, groups, drag, onRenderViewReq, onGroupOver) {
let svgGroups = g.selectAll('.group')
- .data(groups, (d) => d._osid);
+ .data(groups, (d) => d._osid);
let enterGroups = svgGroups.enter();
let groupsContainers =
enterGroups
.append('g')
- .attr('class', 'group')
- .attr('data-group-id', (d) => d._osid)
- .call(drag)
- .on('click', function (d) {
- console.log('click', d);
- d.isExpanded = !d.isExpanded;
- onRenderViewReq();
- });
+ .attr('class', 'group')
+ .attr('data-group-id', (d) => d._osid)
+ .call(drag)
+ .on('mouseover', function (_d) {
+ onGroupOver();
+ })
+ .on('click', function (d) {
+ console.log('click', d);
+ d.isExpanded = !d.isExpanded;
+ onRenderViewReq();
+ });
groupsContainers
.append('rect')
- .attr('class', 'group-shape')
- .attr('rx', 8)
- .attr('ry', 8)
- .style('fill', function (_d, _i) { return 'lightblue'; })
+ .attr('class', 'group-shape')
+ .attr('rx', 8)
+ .attr('ry', 8)
+ .style('fill', function (_d, _i) { return 'lightblue'; })
;
groupsContainers
diff --git a/ui/imports/ui/components/scans-list/scans-list.html b/ui/imports/ui/components/scans-list/scans-list.html
index f8998dd..6466068 100644
--- a/ui/imports/ui/components/scans-list/scans-list.html
+++ b/ui/imports/ui/components/scans-list/scans-list.html
@@ -27,7 +27,6 @@
<th>Scan Only Iventory</th>
<th>Scan Only Links</th>
<th>Scan Only Cliques</th>
- <th>Scan Completed</th>
<th>
<a class="sm-table-header"
data-is-sortable="true"
@@ -63,7 +62,6 @@
<td>{{ scan.scan_only_inventory }}</td>
<td>{{ scan.scan_only_links }}</td>
<td>{{ scan.scan_only_cliques }}</td>
- <td>{{ scan.scan_completed }}</td>
<td>{{ scan.submit_timestamp }}</td>
<td>{{ scan.start_timestamp }}</td>
<td>{{ scan.end_timestamp }}</td>
diff --git a/ui/imports/ui/components/top-navbar-menu/top-navbar-menu.js b/ui/imports/ui/components/top-navbar-menu/top-navbar-menu.js
index 6968060..1b86cad 100644
--- a/ui/imports/ui/components/top-navbar-menu/top-navbar-menu.js
+++ b/ui/imports/ui/components/top-navbar-menu/top-navbar-menu.js
@@ -121,7 +121,7 @@ Template.TopNavbarMenu.helpers({
return {
selectedEnvironment: selectedEnvironment,
onEnvSelected: function (env) {
- Router.go('environment', { _id: idToStr(env._id) }, { });
+ Router.go('environment', { _id: idToStr(env._id) }, { query: `r=${Date.now()}` });
}
};
}