UI: Modularize scratch book and make it reusable as regular ui element, refactor charts

This commit is contained in:
Aysam Guerler
2014-03-24 04:50:52 -04:00
parent ce60083099
commit a5fa89551f
15 changed files with 1469 additions and 1590 deletions
@@ -1,10 +1,10 @@
// dependencies
define(['mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'plugin/library/ui', 'utils/utils', 'plugin/library/jobs', 'plugin/library/datasets',
'plugin/views/charts', 'plugin/views/chart',
'plugin/models/config', 'plugin/models/chart', 'plugin/models/charts', 'plugin/charts/types'],
function( Modal, Portlet, Ui, Utils, Jobs, Datasets,
ChartsView, ChartView,
Config, Chart, Charts, Types
define(['mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'plugin/library/ui', 'utils/utils', 'plugin/library/jobs', 'plugin/library/datasets', 'plugin/library/storage',
'plugin/views/viewer', 'plugin/views/editor',
'plugin/models/config', 'plugin/models/chart', 'plugin/charts/types'],
function( Modal, Portlet, Ui, Utils, Jobs, Datasets, Storage,
ViewerView, EditorView,
Config, Chart, Types
) {
// widget
@@ -23,91 +23,61 @@ return Backbone.View.extend(
this.modal = new Modal.View();
}
// create configuration model
//
// models
//
this.config = new Config();
// job/data /processor
this.jobs = new Jobs(this);
// create chart models
this.types = new Types();
this.chart = new Chart();
this.charts = new Charts(null, this);
// create dataset handler
//
// libraries
//
this.jobs = new Jobs(this);
this.datasets = new Datasets(this);
// create views
this.charts_view = new ChartsView(this);
this.chart_view = new ChartView(this);
// create portlet
if (!this.options.config.widget) {
this.portlet = new Portlet.View({icon : 'fa-bar-chart-o'});
} else {
this.portlet = $('<div></div>');
}
this.storage = new Storage(this);
//
// views
//
this.viewer_view = new ViewerView(this);
this.editor_view = new EditorView(this);
// append views
this.portlet.append(this.charts_view.$el);
this.portlet.append(this.chart_view.$el);
this.$el.append(this.viewer_view.$el);
this.$el.append(this.editor_view.$el);
// set element
if (!this.options.config.widget) {
this.setElement(this.portlet.$el);
// pick start screen
if (!this.storage.load()) {
// show editor
this.go('editor');
} else {
this.setElement(this.portlet);
}
// events
var self = this;
this.config.on('change:title', function() {
self._refreshTitle();
});
// render
this.render();
// load charts
this.charts.load();
// start with chart view
if (this.charts.length == 0) {
this.go('chart_view');
} else {
this.go('charts_view');
// show viewport
this.go('viewer');
// redraw chart
this.chart.trigger('redraw');
}
},
// loads a view and makes sure that all others are hidden
go: function(view_id) {
// hide all tooltips
$('.tooltip').hide();
// pick view
switch (view_id) {
case 'chart_view' :
this.chart_view.show();
this.charts_view.hide();
case 'editor' :
this.editor_view.show();
this.viewer_view.hide();
break;
case 'charts_view' :
this.chart_view.hide();
this.charts_view.show();
case 'viewer' :
this.editor_view.hide();
this.viewer_view.show();
break;
}
},
// render
render: function() {
this._refreshTitle();
},
// refresh title
_refreshTitle: function() {
var title = this.config.get('title');
if (title) {
title = ' - ' + title;
}
this.portlet.title('Charts' + title);
},
// execute command
execute: function(options) {
},
File diff suppressed because one or more lines are too long
@@ -0,0 +1,118 @@
// dependencies
define(['utils/utils', 'plugin/models/chart', 'plugin/models/group'], function(Utils, Chart, Group) {
// collection
return Backbone.Model.extend(
{
// viz model
vis: null,
// initialize
initialize: function(app) {
// link app
this.app = app;
// link chart
this.chart = this.app.chart;
// link options
this.options = this.app.options;
// initialize parameters
this.id = this.options.id;
// create visualization
this.vis = new Visualization({
type : 'charts',
config : {
dataset_id : this.options.config.dataset_id,
chart_dict : {}
}
});
// add visualization id
if (this.id) {
this.vis.id = this.id;
}
// add charts
var chart_dict = this.options.config.chart_dict;
if (chart_dict) {
this.vis.get('config').chart_dict = chart_dict;
}
},
// pack and save nested chart model
save: function() {
// link chart
var chart = this.app.chart;
// reset
this.vis.get('config').chart_dict = {};
// set title
var title = chart.get('title');
if (title != '') {
this.vis.set('title', title);
}
// create chart dictionary
var chart_dict = {
attributes : chart.attributes,
settings : chart.settings.attributes,
groups : []
};
// append groups
chart.groups.each(function(group) {
chart_dict.groups.push(group.attributes);
});
// add chart to charts array
this.vis.get('config').chart_dict = chart_dict;
// save visualization
var self = this;
this.vis.save()
.fail(function(xhr, status, message) {
console.error(xhr, status, message);
alert( 'Error loading data:\n' + xhr.responseText );
})
.then(function(response) {
if (response && response.id) {
self.id = response.id;
}
});
},
// load nested models/collections from packed dictionary
load: function() {
// get charts array
var chart_dict = this.vis.get('config').chart_dict;
// check
if (!chart_dict.attributes) {
return false;
}
// main
this.chart.set(chart_dict.attributes);
// get settings
this.chart.settings.set(chart_dict.settings);
// get groups
for (var j in chart_dict.groups) {
this.chart.groups.add(new Group(chart_dict.groups[j]));
}
// reset status
this.chart.state('ok', 'Loaded previously saved visualization.');
// return
return true;
}
});
});
@@ -1,114 +0,0 @@
// dependencies
define(['plugin/models/chart', 'plugin/models/group'], function(Chart, Group) {
// collection
return Backbone.Collection.extend(
{
// nested chart model contains collections
model : Chart,
// viz model
vis: null,
// initialize
initialize: function(options, app) {
// initialize parameters
this.app = app;
this.id = this.app.options.id;
// create visualization
this.vis = new Visualization({
type : 'charts',
config : {
dataset_id : this.app.options.config.dataset_id,
charts : []
}
});
// add visualization id
if (this.id) {
this.vis.id = this.id;
}
// add charts
var charts_array = this.app.options.config.charts;
if (charts_array) {
this.vis.get('config').charts = charts_array;
}
},
// pack and save nested chart models
save: function() {
// reset
this.vis.get('config').charts = [];
// pack nested chart models into arrays attributes
var self = this;
this.each(function(chart) {
// create chart dictionary
var chart_dict = {
attributes : chart.attributes,
settings : chart.settings.attributes,
groups : []
};
// append groups
chart.groups.each(function(group) {
chart_dict.groups.push(group.attributes);
});
// add chart to charts array
self.vis.get('config').charts.push(chart_dict);
});
// save visualization
var self = this;
this.vis.save()
.fail(function(xhr, status, message) {
console.error(xhr, status, message);
alert( 'Error loading data:\n' + xhr.responseText );
})
.then(function(response) {
if (response && response.id) {
self.id = response.id;
}
});
},
// load nested models/collections from packed dictionary
load: function() {
// get charts array
var charts_array = this.vis.get('config').charts;
// unpack chart models
for (var i in charts_array) {
// get chart details
var chart_dict = charts_array[i];
// construct chart model
var chart = new Chart();
// main
chart.set(chart_dict.attributes);
// get settings
chart.settings.set(chart_dict.settings);
// get groups
for (var j in chart_dict.groups) {
chart.groups.add(new Group(chart_dict.groups[j]));
}
// reset status
chart.state('ok', 'Loaded previously saved visualization.');
// add to collection
this.add(chart);
// trigger
chart.trigger('redraw', chart);
}
}
});
});
@@ -7,8 +7,7 @@ return Backbone.Model.extend(
// options
defaults : {
query_limit : 1000,
query_timeout : 500,
title : 'Create a new chart'
query_timeout : 500
}
});
@@ -1,227 +0,0 @@
// dependencies
define(['mvc/ui/ui-portlet', 'plugin/library/ui-table', 'plugin/library/ui', 'utils/utils', 'plugin/models/group', 'plugin/views/viewport',], function(Portlet, Table, Ui, Utils, Group, ViewportView) {
// widget
return Backbone.View.extend(
{
// initialize
initialize: function(app, options)
{
// link app
this.app = app;
// create viewport
this.viewport_view = new ViewportView(app);
// table
this.table = new Table.View({
content : 'Add charts to this table.',
ondblclick : function(chart_id) {
// attempt to load chart editor
self._showChartView(chart_id);
},
onchange : function(chart_id) {
// get chart
var chart = self.app.charts.get(chart_id);
// update main title
self.app.config.set('title', chart.get('title'));
// show viewport
self.viewport_view.showChart(chart_id);
}
});
// add table to portlet
var self = this;
this.portlet = new Portlet.View({
icon : 'fa-list',
title : 'List of created charts:',
height : 100,
operations : {
'new' : new Ui.ButtonIcon({
icon : 'fa-magic',
tooltip : 'Create a new Chart',
title : 'New',
onclick : function() {
self.app.go('chart_view');
self.app.chart.reset();
}
}),
'edit' : new Ui.ButtonIcon({
icon : 'fa-gear',
tooltip : 'Customize this Chart',
title : 'Customize',
onclick : function() {
// check if element has been selected
var chart_id = self.table.value();
if (!chart_id) {
return;
}
// attempt to load chart editor
self._showChartView(chart_id);
}
}),
'delete' : new Ui.ButtonIcon({
icon : 'fa-trash-o',
tooltip : 'Delete this Chart',
title : 'Delete',
onclick : function() {
// check if element has been selected
var chart_id = self.table.value();
if (!chart_id) {
return;
}
// title
var chart = self.app.charts.get(chart_id);
// make sure that chart is ready
self._wait (chart, function() {
self.app.modal.show({
title : 'Are you sure?',
body : 'The selected chart "' + chart.get('title') + '" will be irreversibly deleted.',
buttons : {
'Cancel' : function() {self.app.modal.hide();},
'Delete' : function() {
// hide modal
self.app.modal.hide();
// remove chart
self.app.charts.remove(chart_id);
// cleanup
self.app.jobs.cleanup(chart);
}
}
});
});
}
}),
}
});
this.portlet.append(this.table.$el);
// append portlet with table
if (!this.app.options.config.widget) {
this.$el.append(this.portlet.$el);
}
// append view port
this.$el.append(Utils.wrap(''));
this.$el.append(this.viewport_view.$el);
// events
var self = this;
this.app.charts.on('add', function(chart) {
// add
self._addChart(chart);
});
this.app.charts.on('remove', function(chart) {
// remove
self._removeChart(chart);
});
this.app.charts.on('change', function(chart) {
// replace
self._changeChart(chart);
});
},
// show
show: function() {
this.$el.show();
},
// hide
hide: function() {
$('.tooltip').hide();
this.$el.hide();
},
// add
_addChart: function(chart) {
// add title to table
var title = chart.get('title');
if (title == '') {
title = 'Untitled';
}
this.table.add(title);
// get chart type
var type = this.app.types.get(chart.get('type'));
this.table.add(type.title);
// add additional columns
this.table.add('Last change: ' + chart.get('date'));
this.table.prepend(chart.get('id'));
this.table.value(chart.get('id'));
},
// remove
_removeChart: function(chart) {
// remove from to table
this.table.remove(chart.id);
// save
this.app.charts.save();
// check if table is empty
if (this.table.size() == 0) {
this.app.go('chart_view');
this.app.chart.reset();
} else {
// select available chart
this.table.value(this.app.charts.last().id);
}
},
// change
_changeChart: function(chart) {
if (chart.get('type')) {
// add chart
this._addChart(chart);
// select available chart
this.table.value(chart.id);
}
},
// show chart editor
_showChartView: function(chart_id) {
var self = this;
var chart = this.app.charts.get(chart_id);
this._wait (chart, function() {
self.app.go('chart_view');
self.app.chart.copy(chart);
});
},
// wait for chart to be ready
_wait: function(chart, callback) {
// get chart
if (chart.ready()) {
callback();
} else {
// show modal
var self = this;
this.app.modal.show({
title : 'Please wait!',
body : 'The selected chart "' + chart.get('title') + '" is currently being processed. Please wait...',
buttons : {
'Close' : function() {self.app.modal.hide();},
'Retry' : function() {
// hide modal
self.app.modal.hide();
// retry
setTimeout(function() { self._wait(chart, callback); }, self.app.config.get('query_timeout'));
}
}
});
}
}
});
});
@@ -1,8 +1,8 @@
// dependencies
define(['mvc/ui/ui-tabs', 'plugin/library/ui-table', 'plugin/library/ui', 'utils/utils',
define(['mvc/ui/ui-tabs', 'plugin/library/ui-table', 'plugin/library/ui', 'mvc/ui/ui-portlet', 'utils/utils',
'plugin/models/chart', 'plugin/models/group',
'plugin/views/group', 'plugin/views/settings'],
function(Tabs, Table, Ui, Utils, Chart, Group, GroupView, SettingsView) {
function(Tabs, Table, Ui, Portlet, Utils, Chart, Group, GroupView, SettingsView) {
// widget
return Backbone.View.extend(
@@ -25,6 +25,38 @@ return Backbone.View.extend(
// configure options
this.options = Utils.merge(options, this.optionsDefault);
// create portlet
this.portlet = new Portlet.View({
icon : 'fa-bar-chart-o',
title: 'Editor',
operations : {
'save' : new Ui.ButtonIcon({
icon : 'fa-save',
tooltip : 'Draw Chart',
title : 'Draw',
onclick : function() {
// show viewport
self.app.go('viewer');
// save chart
self._saveChart();
}
}),
'back' : new Ui.ButtonIcon({
icon : 'fa-caret-left',
tooltip : 'Return to Viewer',
title : 'Return',
onclick : function() {
// show viewport
self.app.go('viewer');
// reset chart
self.app.storage.load();
}
})
}
});
//
// table with chart types
//
@@ -92,28 +124,6 @@ return Backbone.View.extend(
onnew : function() {
var group = self._addGroupModel();
self.tabs.show(group.id);
},
operations : {
'save' : new Ui.ButtonIcon({
icon : 'fa-save',
tooltip : 'Draw Chart',
title : 'Draw',
onclick : function() {
// show charts
self.app.go('charts_view');
// save chart
self._saveChart();
}
}),
'back' : new Ui.ButtonIcon({
icon : 'fa-caret-left',
tooltip : 'Return to Viewer',
title : 'Return',
onclick : function() {
self.app.go('charts_view');
}
})
}
});
@@ -157,8 +167,11 @@ return Backbone.View.extend(
$el : this.settings.$el
});
// append tabs
this.portlet.append(this.tabs.$el);
// elements
this.setElement(this.tabs.$el);
this.setElement(this.portlet.$el);
// hide back button on startup
this.tabs.hideOperation('back');
@@ -166,8 +179,7 @@ return Backbone.View.extend(
// chart events
var self = this;
this.chart.on('change:title', function(chart) {
self.title.value(chart.get('title'));
self.app.config.set('title', chart.get('title'));
self._refreshTitle();
});
this.chart.on('change:type', function(chart) {
self.table.value(chart.get('type'));
@@ -175,18 +187,8 @@ return Backbone.View.extend(
this.chart.on('reset', function(chart) {
self._resetChart();
});
// charts events
this.app.charts.on('add', function(chart) {
self.tabs.showOperation('back');
});
this.app.charts.on('remove', function(chart) {
if (self.app.charts.length == 0) {
self.tabs.hideOperation('back');
}
});
this.app.charts.on('reset', function(chart) {
self.tabs.hideOperation('back');
this.app.chart.on('redraw', function(chart) {
self.portlet.showOperation('back');
});
// groups events
@@ -214,10 +216,18 @@ return Backbone.View.extend(
// hide
hide: function() {
$('.tooltip').hide();
this.$el.hide();
},
// refresh title
_refreshTitle: function() {
var title = this.chart.get('title');
if (title) {
title = ' - ' + title;
}
this.portlet.title('Charts' + title);
},
// update
_refreshGroupKey: function() {
var self = this;
@@ -284,6 +294,9 @@ return Backbone.View.extend(
this.chart.set('type', 'bardiagram');
this.chart.set('dataset_id', this.app.options.config.dataset_id);
this.chart.set('title', 'New Chart');
// reset back button
this.portlet.hideOperation('back');
},
// create chart
@@ -300,21 +313,11 @@ return Backbone.View.extend(
this._addGroupModel();
}
// create/get chart
var current = this.app.charts.get(this.chart.id);
if (!current) {
current = this.chart.clone();
current.copy(this.chart);
this.app.charts.add(current);
} else {
current.copy(this.chart);
}
// trigger redraw
current.trigger('redraw', current);
this.chart.trigger('redraw');
// save
this.app.charts.save();
this.app.storage.save();
}
});
@@ -0,0 +1,106 @@
// dependencies
define(['utils/utils', 'plugin/library/ui', 'mvc/ui/ui-portlet',
'plugin/models/group', 'plugin/views/viewport',],
function(Utils, Ui, Portlet, Group, ViewportView) {
// widget
return Backbone.View.extend(
{
// initialize
initialize: function(app, options)
{
// link app
this.app = app;
// link chart
this.chart = this.app.chart;
// create viewport
this.viewport_view = new ViewportView(app);
// link this
var self = this;
// create portlet
this.portlet = new Portlet.View({
icon : 'fa-bar-chart-o',
title: 'Viewport',
operations: {
edit_button: new Ui.ButtonIcon({
icon : 'fa-gear',
tooltip : 'Customize Chart',
title : 'Customize',
onclick : function() {
// attempt to load chart editor
self._wait (self.app.chart, function() {
self.app.go('editor');
});
}
})
}
});
// append view port
this.portlet.append(this.viewport_view.$el);
// set element
this.setElement(this.portlet.$el);
// events
var self = this;
this.chart.on('change:title', function() {
self._refreshTitle();
});
},
// show
show: function() {
// show element
this.$el.show();
// trigger resize to refresh d3 element
$(window).trigger('resize');
},
// hide
hide: function() {
this.$el.hide();
},
// refresh title
_refreshTitle: function() {
var title = this.chart.get('title');
if (title) {
title = ' - ' + title;
}
this.portlet.title('Charts' + title);
},
// wait for chart to be ready
_wait: function(chart, callback) {
// get chart
if (chart.ready()) {
callback();
} else {
// show modal
var self = this;
this.app.modal.show({
title : 'Please wait!',
body : 'Your chart is currently being processed. Please wait...',
buttons : {
'Close' : function() {self.app.modal.hide();},
'Retry' : function() {
// hide modal
self.app.modal.hide();
// retry
setTimeout(function() { self._wait(chart, callback); }, self.app.config.get('query_timeout'));
}
}
});
}
}
});
});
@@ -5,14 +5,8 @@ define(['mvc/ui/ui-portlet', 'plugin/library/ui', 'utils/utils'],
// widget
return Backbone.View.extend(
{
// list
list: {},
// options
optionsDefault :
{
height : 300
},
// height
height : 300,
// initialize
initialize: function(app, options)
@@ -20,117 +14,63 @@ return Backbone.View.extend(
// link app
this.app = app;
// link chart
this.chart = this.app.chart;
// link options
this.options = Utils.merge(options, this.optionsDefault);
// add table to portlet
this.portlet = new Portlet.View({
title : 'title',
height : this.options.height,
overflow : 'hidden'
});
// set this element
this.setElement(this.portlet.$el);
// create element
this.setElement($(this._template()));
// events
var self = this;
// remove
this.app.charts.on('remove', function(chart) {
self._removeChart(chart.id);
this.chart.on('redraw', function() {
self._draw(self.chart);
});
// redraw
this.app.charts.on('redraw', function(chart) {
self._drawChart(chart);
});
},
// show
showChart: function(chart_id) {
// show
this.show();
// hide all
this.hideCharts();
// identify selected item from list
var item = this.list[chart_id];
if (item) {
// get chart
var chart = this.app.charts.get(chart_id);
// update portlet
this.portlet.title(chart.get('title'));
// show selected chart
item.$el.show();
// this trigger d3 update events
$(window).trigger('resize');
}
},
// hide charts
hideCharts: function() {
this.$el.find('.item').hide();
},
// show
show: function() {
$('.tooltip').hide();
this.$el.show();
},
// hide
hide: function() {
$('.tooltip').hide();
this.$el.hide();
},
// add
_drawChart: function(chart) {
_draw: function(chart) {
// link this
var self = this;
// check
if (!chart.ready()) {
self.app.log('viewport:_drawChart()', 'Invalid attempt to draw chart before completion.');
this.app.log('viewport:_drawChart()', 'Invalid attempt to draw chart before completion.');
return;
}
// backup chart details
var chart_id = chart.id;
// make sure that svg does not exist already
this._removeChart(chart_id);
// create id
var id = '#' + chart_id;
// create element
var $chart_el = $(this._template({id: id}));
// add to portlet
this.portlet.append($chart_el);
// find svg element
var svg = d3.select($chart_el.find('svg')[0]);
// add chart to list
this.list[chart_id] = {
svg : svg,
$el : $chart_el
// clear svg
if (this.svg) {
this.svg.remove();
}
// create
this.svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
this.svg.setAttribute('height', this.height);
this.$el.append(this.svg);
// find svg element
this.svg = d3.select(this.$el.find('svg')[0]);
// clear all previous handlers (including redraw listeners)
chart.off('change:state');
// link status handler
chart.on('change:state', function() {
// get info element
var $info = $chart_el.find('#info');
var $info = self.$el.find('#info');
// get icon
var $icon = $info.find('#icon');
@@ -168,7 +108,7 @@ return Backbone.View.extend(
var self = this;
require(['plugin/charts/' + chart_type + '/' + chart_type], function(ChartView) {
// create chart
var view = new ChartView(self.app, {svg : svg});
var view = new ChartView(self.app, {svg : self.svg});
// request data
if (chart_settings.execute) {
@@ -181,31 +121,18 @@ return Backbone.View.extend(
});
},
// remove
_removeChart: function(id) {
var item = this.list[id];
if (item) {
// remove svg element
item.svg.remove();
// find div element (if any)
item.$el.remove();
}
},
// template
_template: function(options) {
return '<div id="' + options.id.substr(1) + '" class="item">' +
'<span id="info">' +
_template: function() {
return '<div>' +
'<div id="info" style="text-align: center; margin-top: 20px;">' +
'<span id="icon" style="font-size: 1.2em; display: inline-block;"/>' +
'<span id="text" style="position: relative; margin-left: 5px; top: -1px; font-size: 1.0em;"/>' +
'</span>' +
'<svg style="height: auto;"/>' +
'</div>' +
'</div>';
},
// create default chart request
_defaultRequestString : function(chart) {
_defaultRequestString: function(chart) {
// get chart settings
var chart_settings = this.app.types.get(chart.get('type'));
@@ -226,7 +153,7 @@ return Backbone.View.extend(
},
// create default chart request
_defaultSettingsString : function(chart) {
_defaultSettingsString: function(chart) {
// configure settings
var settings_string = '';
@@ -241,7 +168,7 @@ return Backbone.View.extend(
},
// create default chart request
_defaultRequestDictionary : function(chart) {
_defaultRequestDictionary: function(chart) {
// get chart settings
var chart_settings = this.app.types.get(chart.get('type'));
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -1279,9 +1279,9 @@ label{font-weight:normal}
.upload-ftp .upload-ftp-warning{text-align:center;margin-top:20px}
.upload-settings .upload-settings-cover{position:absolute;width:100%;height:100%;top:0px;left:0px;background:#fff;opacity:0.4;cursor:no-drop}
.no-highlight{-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-ms-user-select:none;}
.portlet-view{min-width:300px}.portlet-view .portlet-title-icon{float:left;font-size:1.2em;padding-top:3px}
.portlet-view .portlet-title{overflow:hidden}
.portlet-view .portlet-title-text{float:left;padding-top:1px}
.portlet-view{min-width:300px}.portlet-view .portlet-title-icon{float:left;font-size:1.2em;padding-top:4px}
.portlet-view .portlet-title{overflow:hidden;padding:2px 5px 2px 10px}
.portlet-view .portlet-title-text{float:left;padding-top:2px}
.portlet-view .portlet-operations{float:right;cursor:pointer}
.portlet-view .portlet-buttons{height:50px;padding:10px}
.portlet-view .portlet-content{height:inherit;padding:10px}
+3 -2
View File
@@ -11,16 +11,17 @@
.portlet-title-icon {
float: left;
font-size: 1.2em;
padding-top: 3px;
padding-top: 4px;
}
.portlet-title {
overflow: hidden;
padding: 2px 5px 2px 10px;
}
.portlet-title-text {
float: left;
padding-top: 1px;
padding-top: 2px;
}
.portlet-operations {