Cleaning up gui plugin

- fixing bug url
- removing limit action and custom alarm query code
- simplifying logger setup in settings
- removing unused rickshaw enhancements
- deleting deprecated styling overrides from theme

Change-Id: I26de161295e37235419054aa350ffd868dd9586d
Signed-off-by: Tyler Smith <tyler.smith@windriver.com>
This commit is contained in:
Tyler Smith 2019-10-31 15:46:05 -04:00
parent 161e69480f
commit 5627f93254
12 changed files with 48 additions and 1160 deletions

View File

@ -15,4 +15,4 @@ Pull requests submitted through GitHub will be ignored.
Bugs should be filed on Launchpad, not GitHub:
https://bugs.launchpad.net/horizon
https://bugs.launchpad.net/starlingx

View File

@ -8,61 +8,18 @@
#
# PBR should always appear first
pbr>=1.6 # Apache-2.0
# Horizon Core Requirements
Babel>=2.3.4 # BSD
Django<1.9,>=1.8 # BSD
Pint>=0.5 # BSD
django-babel>=0.5.1 # BSD
django-compressor>=2.0 # MIT
django-openstack-auth>=2.4.0 # Apache-2.0
django-pyscss>=2.0.2 # BSD License (2 clause)
httplib2>=0.7.5 # MIT
iso8601>=0.1.11 # MIT
netaddr!=0.7.16,>=0.7.13 # BSD
oslo.concurrency>=3.8.0 # Apache-2.0
oslo.config>=3.14.0 # Apache-2.0
oslo.i18n>=2.1.0 # Apache-2.0
oslo.policy>=1.9.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0
oslo.utils>=3.16.0 # Apache-2.0
pyScss!=1.3.5,>=1.3.4 # MIT License
python-ceilometerclient>=2.5.0 # Apache-2.0
python-cinderclient!=1.7.0,!=1.7.1,>=1.6.0 # Apache-2.0
python-glanceclient!=2.4.0,>=2.3.0 # Apache-2.0
python-heatclient>=1.4.0 # Apache-2.0
python-keystoneclient!=2.1.0,>=2.0.0 # Apache-2.0
python-neutronclient>=5.1.0 # Apache-2.0
python-novaclient!=2.33.0,>=2.29.0 # Apache-2.0
python-swiftclient>=2.2.0 # Apache-2.0
fmclient>=1.0
cgcs-patch>=1.0
distributedcloud-client>=1.0.0
cgtsclient1.0
sysinv>=1.0
nfv-client>=1.0.0
sm-client>=1.0.0
python-cephclient>=13.2.2.0
pytz>=2013.6 # MIT
PyYAML>=3.1.0 # MIT
requests-toolbelt>=0.5
six>=1.9.0 # MIT
XStatic>=1.0.0 # MIT License
XStatic-Angular>=1.3.7 # MIT License
XStatic-Angular-Bootstrap>=0.11.0.2 # MIT License
XStatic-Angular-FileUpload>=12.0.4.0 # MIT License
XStatic-Angular-Gettext>=2.1.0.2 # MIT License
XStatic-Angular-lrdragndrop>=1.0.2.2 # MIT License
XStatic-Angular-Schema-Form>=0.8.13.0 # MIT
XStatic-Bootstrap-Datepicker>=1.3.1.0 # Apache 2.0 License
XStatic-Bootstrap-SCSS>=3 # Apache 2.0 License
XStatic-bootswatch>=3.3.5.3 # MIT License
XStatic-D3>=3.1.6.2 # BSD License (3 clause)
XStatic-Hogan>=2.0.0.2 # Apache 2.0 License
XStatic-Font-Awesome>=4.3.0 # SIL OFL 1.1 License, MIT License
XStatic-Jasmine>=2.1.2.0 # MIT License
XStatic-jQuery>=1.7.2 # MIT License
XStatic-JQuery-Migrate>=1.2.1.1 # MIT License
XStatic-JQuery.quicksearch>=2.0.3.1 # MIT License
XStatic-JQuery.TableSorter>=2.14.5.1 # MIT License
XStatic-jquery-ui>=1.10.1 # MIT License
XStatic-JSEncrypt>=2.0.0.2 # MIT License
XStatic-mdi>=1.4.57.0 # SIL OPEN FONT LICENSE Version 1.1
XStatic-objectpath>=1.2.1.0 # MIT
XStatic-Rickshaw>=1.5.0 # BSD License (prior)
XStatic-roboto-fontface>=0.4.3.2 # Apache 2.0 License
XStatic-smart-table!=1.4.13.0,>=1.4.5.3 # MIT License
XStatic-Spin>=1.2.5.2 # MIT License
XStatic-term.js>=0.0.4 # MIT License
XStatic-tv4>=1.2.7.0 # MIT

View File

@ -1,2 +0,0 @@
from starlingx_dashboard.horizon.tables.actions import FixedWithQueryFilter # noqa
from starlingx_dashboard.horizon.tables.actions import LimitAction # noqa

View File

@ -1,201 +0,0 @@
#
# Copyright (c) 2018 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
from collections import OrderedDict
from django.conf import settings
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon.tables.actions import BaseAction
from horizon.tables import FilterAction
DEFAULT_TABLE_LIMITS = [10, 20, 50, 100, 500, 1000]
class FixedWithQueryFilter(FilterAction):
"""FilterAction
A FilterAction that visually renders like a combination
FixedFilterAction and a FilterAction of type query.
Before extracting data from the filter, always ensure to first call
the method updateFromRequestDataToSession(..) which will copy current
request data to the session
Use get_filter_string(self, request) method to extract the current
filter string
Use get_filter_field(self,request) method to extract the current
"choice" value
"""
def __init__(self, **kwargs):
super(FixedWithQueryFilter, self).__init__(**kwargs)
self.filter_type = "fixedwithquery"
self.filter_choices = []
self.default_value = ''
self.grouped_choices = []
self.disabled_choices = []
def _get_fieldFromGETorPOSTorSESSION(self, request, param_name):
"""Utility method
Utility method for getting 'named" data (param_name) from either
GET/POST or Session .
IMPORTANT NOTE: Has the side-effect of storing the data into
the session
TODO: In the future, this method should really live in some
utility module.
:param request:
:param param_name:
:return: value of data referenced by param_name
"""
the_field = None
if param_name in request.GET:
the_field = request.GET.get(param_name, '')
if the_field is None and param_name in request.POST:
the_field = request.POST.get(param_name, '')
if the_field is None and param_name in request.session:
the_field = request.session.get(param_name, '')
if the_field is not None:
request.session[param_name] = the_field
return the_field
def get_filter_field(self, request):
param_name = '%s_field' % self.get_param_name()
filter_field = self._get_fieldFromGETorPOSTorSESSION(request,
param_name)
self.filter_field = filter_field \
if filter_field \
else self.default_value
return filter_field
def get_filter_string(self, request):
param_name = self.get_param_name()
filter_string = self._get_fieldFromGETorPOSTorSESSION(request,
param_name)
self.filter_string = filter_string if filter_string else ''
self.build_grouped_choices()
return filter_string
def updateFromRequestDataToSession(self, request):
# The desired side-effect of calling the following 2 functions
# will update the filter field and filter string into
# the session so that they are 'remembered' across requests
self.get_filter_field(request)
self.get_filter_string(request)
def set_disabled_filter_field_for_group(self, grpNo, disabled_status):
self.disabled_choices[grpNo] = disabled_status
def get_filter_field_for_group(self, grpNo):
splitted = self.filter_field.split("|")
if len(splitted) <= grpNo:
raise Exception("get_filter_field_for_group: grpNo out of \
range! grpNo={}".format(grpNo))
value = splitted[grpNo]
if not value:
value = self.default_value.split("|")[grpNo]
return value
def build_grouped_choices(self):
grps = []
grpNo = 0
for choices_in_group in self.filter_choices:
currentGrpValue = self.get_filter_field_for_group(grpNo)
disable_status = self.disabled_choices[grpNo]
grps.append(
{
"grpNo": grpNo,
"filter_choices": choices_in_group,
"value": currentGrpValue,
"disabled": disable_status
}
)
grpNo = grpNo + 1
self.grouped_choices = grps
return grps
class LimitAction(BaseAction):
"""A base class representing a count limit action for a table.
.. attribute:: name
The short name or "slug" representing this action. Defaults to
``"limit"``.
.. attribute:: limits
A set of table entry limits. Default: ``"settings.TABLE_LIMITS"``.
.. attribute:: limit_format
A default format sting used do format the verbose
name of each limit count.
Default: ``"%(count)s %(name)s"``.
.. attribute:: verbose_name
A descriptive entity name to be used . Default: ``"Entries"``.
"""
# class attribute name is used for ordering of Actions in table
name = "limit"
verbose_name = _("Entries")
limit_format = _("%(count)s %(name)s")
limits = set(getattr(settings, 'TABLE_LIMITS', DEFAULT_TABLE_LIMITS))
def __init__(self, **kwargs):
super(LimitAction, self).__init__(**kwargs)
self.name = kwargs.get('name', self.name)
self.limits = kwargs.get('limits', self.limits)
self.limit_format = kwargs.get('limit_format', self.limit_format)
self.verbose_name = kwargs.get('verbose_name', self.verbose_name)
def get_param_name(self):
"""Returns the limit parameter name for this table action."""
return self.table._meta.limit_param
def get_default_classes(self):
classes = super(LimitAction, self).get_default_classes()
classes += ("btn", "btn-default", "btn-sm",
"btn-limit", "dropdown-toggle")
return classes
def get_limit_display(self):
"""Default formatter for each limit entry."""
count = self.table.get_limit_count()
return self.get_limit_name(count)
def get_limit_name(self, count):
"""Default formatter for each limit entry."""
if count is None:
return "Default Limit"
return str(self.limit_format % {'count': count,
'name': self.verbose_name})
def get_limit_count(self):
"""Return the current table limit for tables that support paging."""
count = self.table.get_limit_count()
return count
def get_limits(self):
""""Return the set of limits supported by the action."""
limits = {}
for count in self.limits:
limits[count] = self.get_limit_name(count)
return OrderedDict(sorted(limits.items(), key=lambda limit: limit[0]))

View File

@ -142,149 +142,45 @@ except Exception:
pass
LOGGING = {
'version': 1,
# When set to True this will disable all logging except
# for loggers specified in this configuration dictionary. Note that
# if nothing is specified here and disable_existing_loggers is True,
# django.db.backends will still log unless it is disabled explicitly.
'disable_existing_loggers': False,
'formatters': {
'simple': {
'format': '%(levelno)s %(levelname)s %(message)s',
},
'standard': {
'format': '%(levelno)s %(asctime)s [%(levelname)s] '
'%(name)s: %(message)s',
},
'verbose': {
'format': '%(levelno)s %(levelname)s %(asctime)s %(module)s '
'%(process)d %(thread)d %(message)s',
},
'operation': {
# The format of "%(message)s" is defined by
# OPERATION_LOG_OPTIONS['format']
'format': '%(asctime)s %(message)s',
},
},
'handlers': {
'null': {
'level': 'DEBUG',
'class': 'logging.NullHandler',
},
'console': {
# Set the level to "DEBUG" for verbose output logging.
'level': 'INFO',
'class': 'logging.StreamHandler',
},
'syslog': {
# Set the level to "DEBUG" for verbose output logging.
'level': 'INFO',
'formatter': 'standard',
'class': 'logging.handlers.SysLogHandler',
'facility': 'local7',
'address': '/dev/log',
},
'operation': {
'level': 'INFO',
'formatter': 'operation',
'class': 'logging.handlers.SysLogHandler',
'facility': 'local7',
'address': '/dev/log',
},
},
'loggers': {
# Logging from django.db.backends is VERY verbose, send to null
# by default.
'django.db.backends': {
'handlers': ['null'],
'propagate': False,
},
'requests': {
'handlers': ['null'],
'propagate': False,
},
'horizon': {
'handlers': ['syslog'],
'level': 'DEBUG',
'propagate': False,
},
'horizon.operation_log': {
'handlers': ['syslog'],
'level': 'INFO',
'propagate': False,
},
'openstack_dashboard': {
'handlers': ['syslog'],
'level': 'DEBUG',
'propagate': False,
},
'starlingx_dashboard': {
'handlers': ['syslog'],
'level': 'DEBUG',
'propagate': False,
},
'novaclient': {
'handlers': ['syslog'],
'level': 'DEBUG',
'propagate': False,
},
'cinderclient': {
'handlers': ['syslog'],
'level': 'DEBUG',
'propagate': False,
},
'keystoneclient': {
'handlers': ['syslog'],
'level': 'DEBUG',
'propagate': False,
},
'glanceclient': {
'handlers': ['syslog'],
'level': 'DEBUG',
'propagate': False,
},
'neutronclient': {
'handlers': ['syslog'],
'level': 'DEBUG',
'propagate': False,
},
'heatclient': {
'handlers': ['syslog'],
'level': 'DEBUG',
'propagate': False,
},
'swiftclient': {
'handlers': ['null'],
'level': 'DEBUG',
'propagate': False,
},
'openstack_auth': {
'handlers': ['syslog'],
'level': 'DEBUG',
'propagate': False,
},
'nose.plugins.manager': {
'handlers': ['syslog'],
'level': 'DEBUG',
'propagate': False,
},
'django': {
'handlers': ['syslog'],
'level': 'DEBUG',
'propagate': False,
},
'iso8601': {
'handlers': ['null'],
'propagate': False,
},
'scss': {
'handlers': ['null'],
'propagate': False,
},
},
# Override LOGGING settings
LOGGING['formatters']['standard'] = { # noqa
'format':
'%(levelno)s %(asctime)s [%(levelname)s] %(name)s: %(message)s'
}
LOGGING['formatters']['operation'] = { # noqa
# The format of "%(message)s" is defined by
# OPERATION_LOG_OPTIONS['format']
'format': '%(asctime)s %(message)s',
}
# Overwrite the console handler to send to syslog
LOGGING['handlers']['console'] = { # noqa
'level': 'DEBUG' if DEBUG else 'INFO', # noqa
'formatter': 'standard',
'class': 'logging.handlers.SysLogHandler',
'facility': 'local7',
'address': '/dev/log',
}
# Overwrite the operation handler to send to syslog
LOGGING['handlers']['operation'] = { # noqa
'level': 'INFO',
'formatter': 'operation',
'class': 'logging.handlers.SysLogHandler',
'facility': 'local7',
'address': '/dev/log',
}
LOGGING['loggers'].update({ # noqa
'starlingx_dashboard': {
'handlers': ['console'],
'level': 'DEBUG',
'propagate': False,
}
})
# Session overrides
SESSION_ENGINE = 'django.contrib.sessions.backends.file'
SESSION_FILE_PATH = '/var/tmp'

View File

@ -1,513 +0,0 @@
Rickshaw.namespace('Rickshaw.Series.FixedDuration.ExtendedData');
Rickshaw.Series.FixedDuration.ExtendedData = Rickshaw.Class.create(Rickshaw.Series.FixedDuration, {
initialize: function ($super, data, palette, options) {
$super(data, palette, options);
this.lastTimestamp = 0;
},
addData: function($super, data, x) {
var index = this.getIndex();
Rickshaw.keys(data).forEach(function(name) {
if (!this.itemByName(name)) {
this.addItem({name: name});
}
}, this);
var count = 0;
this.forEach(function(item) {
count = 0;
var points = (Array.isArray(data[item.name])) ? data[item.name] : [data[item.name]];
points.forEach(function(point) {
var datum = Object.create(point);
datum.x = x || this.getTimestamp(datum.x) || ((index * this.timeInterval || 1) + this.timeBase);
datum.y = (datum.y || 0);
item.data.push(datum);
count++;
if (datum.x > this.lastTimestamp) {
this.lastTimestamp = datum.x;
}
}, this);
}, this);
this.currentSize += count;
this.currentIndex += count;
if (this.maxDataPoints !== undefined) {
while (this.currentSize > this.maxDataPoints) {
this.dropData();
}
}
},
zeroData: function() {
this.forEach(function(item) {
item.data.forEach(function(datum) {
datum.y = 0;
});
}, this);
},
/* timestamp rounded down to the nearest interval time */
getTimestamp: function(timestamp) {
return Math.floor(timestamp / this.timeInterval) * this.timeInterval;
},
getLastTimestamp: function() {
return this.lastTimestamp;
}
});
Rickshaw.namespace('Rickshaw.Fixtures.Number');
Rickshaw.Fixtures.Number.formatBinaryBytes = function(y) {
//CGCS addition
var abs_y = Math.abs(y);
if (abs_y >= 1125899906842624) { return (y / 1125899906842624).toFixed(0) + "P"; }
else if (abs_y >= 1099511627776){ return (y / 1099511627776).toFixed(0) + "T"; }
else if (abs_y >= 1073741824) { return (y / 1073741824).toFixed(0) + "G"; }
else if (abs_y >= 1048576) { return (y / 1048576).toFixed(0) + "M"; }
else if (abs_y >= 1024) { return (y / 1024).toFixed(0) + "K"; }
else if (abs_y < 1 && y > 0) { return y.toFixed(0); }
else if (abs_y === 0) { return '0'; }
else { return y.toFixed(0); }
};
Rickshaw.namespace('Rickshaw.Graph.Behavior.Series.Toggle');
Rickshaw.Graph.Behavior.Series.Toggle = function(args) {
this.graph = args.graph;
this.legend = args.legend;
var self = this;
this.addAnchor = function(line) {
var anchor = document.createElement('a');
anchor.innerHTML = '&#10004;';
anchor.classList.add('action');
line.element.insertBefore(anchor, line.element.firstChild);
anchor.onclick = function(e) {
if (line.series.disabled) {
line.series.enable();
line.element.classList.remove('disabled');
} else {
if (this.graph.series.filter(function(s) { return !s.disabled }).length <= 1) return;
line.series.disable();
line.element.classList.add('disabled');
}
}.bind(this);
var label = line.element.getElementsByTagName('span')[0];
label.onclick = function(e){
var disableAllOtherLines = line.series.disabled;
if ( ! disableAllOtherLines ) {
for ( var i = 0; i < self.legend.lines.length; i++ ) {
var l = self.legend.lines[i];
if ( line.series === l.series ) {
// noop
} else if ( l.series.disabled ) {
// noop
} else {
disableAllOtherLines = true;
break;
}
}
}
// show all or none
if ( disableAllOtherLines ) {
// these must happen first or else we try ( and probably fail ) to make a no line graph
line.series.enable(false);
line.element.classList.remove('disabled');
self.legend.lines.forEach(function(l){
if ( line.series === l.series ) {
// noop
} else {
l.series.disable(false);
l.element.classList.add('disabled');
}
});
} else {
self.legend.lines.forEach(function(l){
l.series.enable(false);
l.element.classList.remove('disabled');
});
}
self.graph.update();
};
};
if (this.legend) {
var $ = jQuery;
if (typeof $ != 'undefined' && $(this.legend.list).sortable) {
$(this.legend.list).sortable( {
start: function(event, ui) {
ui.item.bind('no.onclick',
function(event) {
event.preventDefault();
}
);
},
stop: function(event, ui) {
setTimeout(function(){
ui.item.unbind('no.onclick');
}, 250);
}
});
}
this.legend.lines.forEach( function(l) {
self.addAnchor(l);
} );
}
this._addBehavior = function() {
this.graph.series.forEach( function(s) {
// Update parameter is CGCS addition
s.disable = function(update) {
if (self.graph.series.length <= 1) {
throw('only one series left');
}
s.disabled = true;
if (update !== false) {
self.graph.update();
}
};
s.enable = function(update) {
s.disabled = false;
if (update !== false) {
self.graph.update();
}
};
} );
};
this._addBehavior();
this.updateBehaviour = function () { this._addBehavior() };
};
Rickshaw.namespace('Rickshaw.Graph.HoverDetail');
Rickshaw.Graph.HoverDetail = Rickshaw.Class.create({
initialize: function(args) {
var graph = this.graph = args.graph;
this.xFormatter = args.xFormatter || function(x) {
return new Date( x * 1000 ).toUTCString();
};
this.yFormatter = args.yFormatter || function(y) {
return y === null ? y : y.toFixed(2);
};
var element = this.element = document.createElement('div');
element.className = 'detail';
this.visible = true;
graph.element.appendChild(element);
this.lastEvent = null;
this._addListeners();
this.onShow = args.onShow;
this.onHide = args.onHide;
this.onRender = args.onRender;
this.formatter = args.formatter || this.formatter;
},
formatter: function(series, x, y, formattedX, formattedY, d) {
return series.name + ':&nbsp;' + formattedY;
},
update: function(e) {
e = e || this.lastEvent;
if (!e) return;
this.lastEvent = e;
if (!e.target.nodeName.match(/^(path|svg|rect|circle)$/)) return;
var graph = this.graph;
var eventX = e.offsetX || e.layerX;
var eventY = e.offsetY || e.layerY;
var j = 0;
var points = [];
var nearestPoint;
this.graph.series.active().forEach( function(series) {
var data = this.graph.stackedData[j++];
if (!data.length)
return;
var domainX = graph.x.invert(eventX);
var domainIndexScale = d3.scale.linear()
.domain([data[0].x, data.slice(-1)[0].x])
.range([0, data.length - 1]);
var approximateIndex = Math.round(domainIndexScale(domainX));
if (approximateIndex == data.length - 1) approximateIndex--;
var dataIndex = Math.min(approximateIndex || 0, data.length - 1);
for (var i = approximateIndex; i < data.length - 1;) {
if (!data[i] || !data[i + 1]) break;
if (data[i].x <= domainX && data[i + 1].x > domainX) {
dataIndex = Math.abs(domainX - data[i].x) < Math.abs(domainX - data[i + 1].x) ? i : i + 1;
break;
}
if (data[i + 1].x <= domainX) { i++ } else { i-- }
}
if (dataIndex < 0) dataIndex = 0;
var value = data[dataIndex];
var distance = Math.sqrt(
Math.pow(Math.abs(graph.x(value.x) - eventX), 2) +
Math.pow(Math.abs(graph.y(value.y + value.y0) - eventY), 2)
);
var xFormatter = series.xFormatter || this.xFormatter;
var yFormatter = series.yFormatter || this.yFormatter;
var point = {
formattedXValue: xFormatter(value.x),
formattedYValue: yFormatter(series.scale ? series.scale.invert(value.y) : value.y),
series: series,
value: value,
distance: distance,
order: j,
name: series.name
};
if (!nearestPoint || distance < nearestPoint.distance) {
nearestPoint = point;
}
points.push(point);
}, this );
if (!nearestPoint)
return;
nearestPoint.active = true;
var domainX = nearestPoint.value.x;
var formattedXValue = nearestPoint.formattedXValue;
this.element.innerHTML = '';
this.element.style.left = graph.x(domainX) + 'px';
this.visible && this.render( {
points: points,
detail: points, // for backwards compatibility
mouseX: eventX,
mouseY: eventY,
formattedXValue: formattedXValue,
domainX: domainX
} );
},
hide: function() {
this.visible = false;
this.element.classList.add('inactive');
if (typeof this.onHide == 'function') {
this.onHide();
}
},
show: function() {
this.visible = true;
this.element.classList.remove('inactive');
if (typeof this.onShow == 'function') {
this.onShow();
}
},
render: function(args) {
var graph = this.graph;
var points = args.points;
var point = points.filter( function(p) { return p.active } ).shift();
if (point.value.y === null) return;
var formattedXValue = point.formattedXValue;
var formattedYValue = point.formattedYValue;
this.element.innerHTML = '';
this.element.style.left = graph.x(point.value.x) + 'px';
var xLabel = document.createElement('div');
xLabel.className = 'x_label';
xLabel.innerHTML = formattedXValue;
this.element.appendChild(xLabel);
var item = document.createElement('div');
item.className = 'item';
// invert the scale if this series displays using a scale
var series = point.series;
var actualY = series.scale ? series.scale.invert(point.value.y) : point.value.y;
item.innerHTML = this.formatter(series, point.value.x, actualY, formattedXValue, formattedYValue, point);
item.style.top = this.graph.y(point.value.y0 + point.value.y) + 'px';
this.element.appendChild(item);
var dot = document.createElement('div');
dot.className = 'dot';
dot.style.top = item.style.top;
dot.style.borderColor = series.color;
this.element.appendChild(dot);
if (point.active) {
item.classList.add('active');
dot.classList.add('active');
}
// Assume left alignment until the element has been displayed and
// bounding box calculations are possible.
var alignables = [xLabel, item];
alignables.forEach(function(el) {
el.classList.add('left');
});
this.show();
// If left-alignment results in any error, try right-alignment.
var leftAlignError = this._calcLayoutError(alignables);
if (leftAlignError > 0) {
alignables.forEach(function(el) {
el.classList.remove('left');
el.classList.add('right');
});
// If right-alignment is worse than left alignment, switch back.
var rightAlignError = this._calcLayoutError(alignables);
if (rightAlignError > leftAlignError) {
alignables.forEach(function(el) {
el.classList.remove('right');
el.classList.add('left');
});
}
}
if (typeof this.onRender == 'function') {
this.onRender(args);
}
},
_calcLayoutError: function(alignables) {
// Layout error is calculated as the number of linear pixels by which
// an alignable extends past the left or right edge of the parent.
// CGCS addition
try {
var parentRect = this.element.parentNode.getBoundingClientRect();
} catch(e) {
var parentRect = this.element.getBoundingClientRect();
}
// CGCS addition
try { parent.subclasses.push(klass) } catch(e) {}
var error = 0;
var alignRight = alignables.forEach(function(el) {
var rect = el.getBoundingClientRect();
if (!rect.width) {
return;
}
if (rect.right > parentRect.right) {
error += rect.right - parentRect.right;
}
if (rect.left < parentRect.left) {
error += parentRect.left - rect.left;
}
});
return error;
},
_addListeners: function() {
this.graph.element.addEventListener(
'mousemove',
function(e) {
this.visible = true;
this.update(e);
}.bind(this),
false
);
this.graph.onUpdate( function() { this.update() }.bind(this) );
this.graph.element.addEventListener(
'mouseout',
function(e) {
if (e.relatedTarget && !(e.relatedTarget.compareDocumentPosition(this.graph.element) & Node.DOCUMENT_POSITION_CONTAINS)) {
this.hide();
}
}.bind(this),
false
);
}
});
Rickshaw.namespace('Rickshaw.Series.HoverDetail.Panel');
Rickshaw.Graph.HoverDetail.Panel = Rickshaw.Class.create(Rickshaw.Graph.HoverDetail, {
// CGCS addition
formatter: function(series, x, y, formattedX, formattedY, d) {
if (d.value.formattedY !== undefined) {
formattedY = d.value.formattedY;
}
var date = '<span class="date">' + new Date(x * 1000).toLocaleString() + '</span>';
var swatch = '<span class="swatch" style="background-color: ' + series.color + '"></span>';
var value = '<span class="value">' + series.label + ': ' + formattedY + '</span><br>' + date;
var content = swatch + value;
return content;
}
});

View File

@ -4,10 +4,6 @@
// WRS components
@import "components/badges";
// (Eddie Ramirez): To be deprecated
// @import "components/sidebar";
// @import "components/topbar";
// @import "components/splash";
@import "components/charts";
@import "components/tables";

View File

@ -1,134 +0,0 @@
// Indent selected menu items
#sidebar .openstack-panel.active {
margin-left: 15px;
}
// Squish accordian pills
#sidebar-accordion {
a {
background-color: $main-nav-bg-color;
color: $main-nav-bg-color;
padding: .4em 1.2em;
background: transparent;
}
.panel > a{
background: transparent;
}
}
// Coloring of sidebar
#sidebar {
// Header highlight color
//.openstack-dashboard > a:hover,
.openstack-dashboard > a:focus,
li {
background-color: $sidebar-background-color;
}
.nav-pills.nav-stacked {
& > li {
& > a {
color: $windriver-white;
background: $main-nav-bg-color;
}
}
}
// Dashboard headers
#sidebar-accordion > li.panel > a{
//font-size: 15px;
border-radius: 9px;
background-color: $windriver-lighter-gray;
}
// Panel group headers
#sidebar-accordion li.openstack-panel-group > a {
//font-size: 15px;
color: $windriver-white;
text-align: left;
&:hover {
background-color: transparent;
}
}
// All links
li.openstack-dashboard a.openstack-panel {
color: $windriver-white;
// Link on hover
&:hover {
color: $windriver-lighter-red;
background-color: $sidebar-background-color;
}
}
// Selected panel
li.openstack-dashboard a.openstack-panel.active {
color: $sidebar-active-color;
background: $windriver-white;
border-left: 2px;
border-left-style: solid;
border-left-color: $sidebar-active-color;
}
}
#sidebar {
float: none;
display: table-cell;
height: 100%;
background-color: $sidebar-background-color;
.branding {
padding-bottom: 0px;
padding-top: 0px;
padding-left: 0px;
text-align: center;
/* vertical gradient (excluding IE9 and below - which clips the nav-tabs) */
background-color: mix($brand-bg-color, $brand-bg-highlight, 60%); // Old Browswers
background-image: -moz-linear-gradient(top, $brand-bg-color, $brand-bg-highlight); // FF 3.6+
background-image: -ms-linear-gradient(top, $brand-bg-color, $brand-bg-highlight); // IE10
background-image: -webkit-gradient(linear, 0 0, 0 100%, from($brand-bg-color), to($brand-bg-highlight)); // Safari 4+, Chrome 2+
background-image: -webkit-linear-gradient(top, $brand-bg-color, $brand-bg-highlight); // Safari 5.1+, Chrome 10+
background-image: -o-linear-gradient(top, $brand-bg-color, $brand-bg-highlight); // Opera 11.10
background-image: linear-gradient(top, $brand-bg-color, $brand-bg-highlight); // The standard
background-repeat: repeat-x;
.brand {
background: none;
padding-bottom: 0px;
margin-top: 0px;
a {
float: none;
color: $brand-text-color;
text-indent: inherit;
text-align: center;
text-decoration: none;
text-shadow: 2px 1px 15px #000;
font-size: 20px;
line-height: 20px;
margin: 20px 0px 0px 0px;
padding-top: 0px;
padding-bottom: 0px;
height: $brand-height;
width: $brand-width;
}
}
.system {
width: $sidebar-width;
overflow-wrap: break-word;
text-align: center;
color: $brand-text-color;
padding-top: 0px;
padding-bottom: 0px;
margin-bottom: 10px;
font-size: 15px;
}
}
}

View File

@ -1,65 +0,0 @@
#splash {
background: $splash-bg-color;
color: $splash-text-color;
.panel , .panel-heading, .panel-footer{
background: $splash-login-bg-color;
border-color: $splash-border-color;
}
.panel-body {
// Unstretch text fields
margin-right: 40px;
margin-left: 40px;
}
.panel-heading{
// White line
border-bottom-color: $splash-label-color;
/* vertical gradient (excluding IE9 and below - which clips the nav-tabs) */
background-color: mix($brand-bg-color, $splash-login-bg-color, 60%); // Old Browswers
background-image: -moz-linear-gradient(top, $brand-bg-color, $splash-login-bg-color); // FF 3.6+
background-image: -ms-linear-gradient(top, $brand-bg-color, $splash-login-bg-color); // IE10
background-image: -webkit-gradient(linear, 0 0, 0 100%, from($brand-bg-color), to($splash-login-bg-color)); // Safari 4+, Chrome 2+
background-image: -webkit-linear-gradient(top, $brand-bg-color, $splash-login-bg-color); // Safari 5.1+, Chrome 10+
background-image: -o-linear-gradient(top, $brand-bg-color, $splash-login-bg-color); // Opera 11.10
background-image: linear-gradient(top, $brand-bg-color, $splash-login-bg-color); // The standard
background-repeat: repeat-x;
}
.panel-footer {
// Hide lower line
border-top: none;
// Move over button
button {
margin-right: 40px;
}
}
.red-line {
height: 53px;
width: 43%;
border-bottom: 2px solid $windriver-red;
margin-bottom: -18px;
margin-left: -16px;
}
h3 {
display: block;
color: $splash-text-color;
text-align: center;
margin-bottom: 30px;
font-size: 32px;
line-height: 39px;
text-shadow: 2px 2px 4px #000000;
}
form label {
color: $splash-label-color;
font-weight: normal;
}
}

View File

@ -1,45 +0,0 @@
.navbar-fixed-top, .topbar {
padding: 0px 0px;
background-color: $topbar-background-color;
a.navbar-brand {
padding-left: 0px;
}
h1.brand a {
background: none;
}
.navbar-default .navbar-nav {
.dropdown-menu {
background-color: white;
}
& > li > a{
color: $topbar-text-color;
}
}
.context_selection{
float: left;
}
.user_settings {
float: right;
}
// Styling for time & alarms
.navbar-center {
color: $topbar-text-color;
padding-top: 0.8em;
display: table;
margin-left: auto;
margin-right: auto;
float: none;
.datetime {
padding-right: 13px;
}
}
}

View File

@ -16,7 +16,7 @@ setenv = VIRTUAL_ENV={envdir}
OS_STDOUT_CAPTURE=1
OS_STDERR_CAPTURE=1
OS_TEST_TIMEOUT=60
STX_DC_CLIENT = {env:STX_DC_CLIENT:git/distributedcloud-client}
STX_DC_CLIENT = {env:STX_DC_CLIENT:distributedcloud-client}
deps = -r{toxinidir}/test-requirements.txt
[testenv:linters]
@ -57,7 +57,7 @@ usedevelop = False
skip_install = True
deps = {[testenv]deps}
git+git://github.com/starlingx-staging/stx-horizon.git
-e{[tox]stxdir}/{env:STX_DC_CLIENT}
-e{[tox]stxdir}/{env:STX_DC_CLIENT}/distributedcloud-client
-e{[tox]stxdir}/config/sysinv/cgts-client/cgts-client
-e{[tox]stxdir}/config/sysinv/sysinv/sysinv
-e{[tox]stxdir}/fault/python-fmclient/fmclient