sinatra-hexacta 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/sinatra/extensions/antiquity.rb +34 -0
- data/lib/sinatra/extensions/date.rb +49 -0
- data/lib/sinatra/extensions/init.rb +4 -0
- data/lib/sinatra/extensions/notification.rb +41 -0
- data/lib/sinatra/handlers/errors.rb +10 -3
- data/lib/sinatra/handlers/init.rb +3 -1
- data/lib/sinatra/handlers/notifications.rb +17 -28
- data/lib/sinatra/handlers/params.rb +26 -0
- data/lib/sinatra/handlers/reports.rb +28 -1
- data/lib/sinatra/helpers/alerts.rb +27 -0
- data/lib/sinatra/helpers/cas.rb +92 -0
- data/lib/sinatra/helpers/charts.rb +20 -4
- data/lib/sinatra/helpers/init.rb +4 -0
- data/lib/sinatra/helpers/inputs.rb +2 -2
- data/lib/sinatra/helpers/libraries.rb +2 -2
- data/lib/sinatra/helpers/mailer.rb +74 -0
- data/lib/sinatra/helpers/reports.rb +27 -0
- data/lib/sinatra/helpers/schedule.rb +68 -0
- data/lib/sinatra/helpers/subscriptions.rb +1 -1
- data/lib/sinatra/hexacta.rb +13 -5
- data/lib/sinatra/public/css/app.min.1.css +130 -12
- data/lib/sinatra/public/js/app.js +49 -42
- data/lib/sinatra/public/vendors/chartist/chartist-plugin-legend.js +237 -0
- data/lib/sinatra/views/alerts/empty.slim +7 -0
- data/lib/sinatra/views/alerts/error.slim +7 -0
- data/lib/sinatra/views/alerts/info.slim +7 -0
- data/lib/sinatra/views/alerts/warning.slim +7 -0
- data/lib/sinatra/views/charts/bar.slim +56 -0
- data/lib/sinatra/views/charts/gauge.slim +30 -0
- data/lib/sinatra/views/charts/{simple_line.slim → line.slim} +7 -8
- data/lib/sinatra/views/charts/pie.slim +34 -0
- data/lib/sinatra/views/charts/stacked_bar.slim +36 -0
- data/lib/sinatra/views/inputs/multiple_select.slim +4 -0
- data/lib/sinatra/views/inputs/select.slim +3 -0
- data/lib/sinatra/views/libraries/include_js_after.slim +0 -24
- data/lib/sinatra/views/libraries/include_js_before.slim +1 -0
- data/lib/sinatra/views/notifications.slim +37 -31
- data/lib/sinatra/views/notifications/form.slim +4 -4
- data/lib/sinatra/views/notifications/new.slim +4 -4
- data/lib/sinatra/views/notifications/widget.slim +9 -5
- data/lib/sinatra/views/reports/pick_date.slim +14 -0
- data/lib/sinatra/views/reports/pick_dates.slim +16 -0
- data/lib/sinatra/views/reports/pick_month.slim +14 -0
- data/lib/sinatra/views/reports/pick_year.slim +14 -0
- metadata +26 -3
@@ -23,12 +23,30 @@ $(document).ready(function(){
|
|
23
23
|
// Fix modal inside other components
|
24
24
|
$('.modal').appendTo("body");
|
25
25
|
|
26
|
-
|
27
|
-
$("a[href=" + window.top.location.hash +"]").trigger('click');
|
28
|
-
}
|
26
|
+
$( ".paginator" ).clone().appendTo( "#content" );
|
29
27
|
|
30
|
-
$(
|
31
|
-
|
28
|
+
$('form').on('submit', function(e) {
|
29
|
+
$(this).find(':input[required]').each(function() {
|
30
|
+
if ($(this).val() == "" || $(this).val() == null) {
|
31
|
+
$(this).parent().removeClass("success");
|
32
|
+
$(this).parent().addClass("error");
|
33
|
+
} else {
|
34
|
+
$(this).parent().removeClass("error");
|
35
|
+
$(this).parent().addClass("success");
|
36
|
+
}
|
37
|
+
});
|
38
|
+
if ($(this).find('.error').length == 0 ) {
|
39
|
+
$(this).find('#submit').attr('disabled','disabled');
|
40
|
+
}
|
41
|
+
});
|
42
|
+
$('.chosen[required]').on('change', function(change, deselected) { //selected OR deselected
|
43
|
+
if ($(this).val() == "" || $(this).val() == null) {
|
44
|
+
$(this).parent().removeClass("success");
|
45
|
+
$(this).parent().addClass("error");
|
46
|
+
} else {
|
47
|
+
$(this).parent().removeClass("error");
|
48
|
+
$(this).parent().addClass("success");
|
49
|
+
}
|
32
50
|
});
|
33
51
|
/* --------------------------------------------------------
|
34
52
|
Layout
|
@@ -704,33 +722,6 @@ function enableButtons() {
|
|
704
722
|
};
|
705
723
|
})( jQuery );
|
706
724
|
|
707
|
-
/*
|
708
|
-
* Bootstrap Growl - Notifications popups
|
709
|
-
*/
|
710
|
-
function notify(message, type){
|
711
|
-
$('[data-growl="container"]').find('[data-growl="dismiss"]').trigger('click');
|
712
|
-
$.growl({
|
713
|
-
message: message
|
714
|
-
},{
|
715
|
-
type: type,
|
716
|
-
allow_dismiss: false,
|
717
|
-
label: 'Cancel',
|
718
|
-
className: 'btn-xs btn-inverse growl-animated',
|
719
|
-
placement: {
|
720
|
-
from: 'bottom',
|
721
|
-
align: 'left'
|
722
|
-
},
|
723
|
-
delay: 5000,
|
724
|
-
animate: {
|
725
|
-
enter: 'animated fadeInUp',
|
726
|
-
exit: 'animated fadeOutDown'
|
727
|
-
},
|
728
|
-
offset: {
|
729
|
-
x: 0,
|
730
|
-
y: 0
|
731
|
-
}
|
732
|
-
});
|
733
|
-
};
|
734
725
|
|
735
726
|
function encodeQueryData(data)
|
736
727
|
{
|
@@ -761,27 +752,43 @@ function encodeQueryData(data)
|
|
761
752
|
|
762
753
|
function buildFilterMap(offset) {
|
763
754
|
filter_map = {};
|
764
|
-
$("#form
|
755
|
+
$("#form :input").each(function() {
|
765
756
|
if ($(this).val() != null && $(this).val() != "") {
|
766
|
-
if ($(this).
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
757
|
+
if ($(this)[0].name != "") {
|
758
|
+
filter_map[$(this)[0].name] = $(this).val();
|
759
|
+
}
|
760
|
+
}
|
761
|
+
});
|
762
|
+
$("#form input[type=radio]").each(function() {
|
763
|
+
if ($(this).val() != null && $(this).val() != "") {
|
764
|
+
if ($(this).is(':checked')) {
|
773
765
|
filter_map[$(this)[0].name] = $(this).val();
|
774
766
|
}
|
775
767
|
}
|
776
768
|
});
|
777
769
|
if (offset != null) {
|
778
770
|
filter_map["offset"] = offset;
|
779
|
-
} else {
|
780
|
-
filter_map["offset"] = filter_map["offset"] - 1;
|
781
771
|
}
|
782
772
|
return filter_map;
|
783
773
|
}
|
784
774
|
|
775
|
+
function advance_search(url,offset,format) {
|
776
|
+
filter_map = buildFilterMap(offset);
|
777
|
+
filter_map["format"] = format;
|
778
|
+
if (format != 'xls') {
|
779
|
+
window.location.href = url + "?" + encodeQueryData(filter_map);
|
780
|
+
} else {
|
781
|
+
window.open(
|
782
|
+
url + "?" + encodeQueryData(filter_map),
|
783
|
+
'_blank' // <- This is what makes it open in a new window.
|
784
|
+
);
|
785
|
+
}
|
786
|
+
};
|
787
|
+
|
788
|
+
$(document).ready(function(){
|
789
|
+
$( ".paginator" ).clone().appendTo( "#content" );
|
790
|
+
});
|
791
|
+
|
785
792
|
function read_notify(id,url) {
|
786
793
|
$.ajax({
|
787
794
|
url: '/notifications/' + id,
|
@@ -0,0 +1,237 @@
|
|
1
|
+
(function (root, factory) {
|
2
|
+
if (typeof define === 'function' && define.amd) {
|
3
|
+
// AMD. Register as an anonymous module.
|
4
|
+
define(['chartist'], function (chartist) {
|
5
|
+
return (root.returnExportsGlobal = factory(chartist));
|
6
|
+
});
|
7
|
+
} else if (typeof exports === 'object') {
|
8
|
+
// Node. Does not work with strict CommonJS, but
|
9
|
+
// only CommonJS-like enviroments that support module.exports,
|
10
|
+
// like Node.
|
11
|
+
module.exports = factory(require('chartist'));
|
12
|
+
} else {
|
13
|
+
root['Chartist.plugins.legend'] = factory(root.Chartist);
|
14
|
+
}
|
15
|
+
}(this, function (Chartist) {
|
16
|
+
/**
|
17
|
+
* This Chartist plugin creates a legend to show next to the chart.
|
18
|
+
*
|
19
|
+
*/
|
20
|
+
'use strict';
|
21
|
+
|
22
|
+
var defaultOptions = {
|
23
|
+
className: '',
|
24
|
+
classNames: false,
|
25
|
+
removeAll: false,
|
26
|
+
legendNames: false,
|
27
|
+
clickable: true,
|
28
|
+
onClick: null,
|
29
|
+
position: 'top'
|
30
|
+
};
|
31
|
+
|
32
|
+
Chartist.plugins = Chartist.plugins || {};
|
33
|
+
|
34
|
+
Chartist.plugins.legend = function (options) {
|
35
|
+
|
36
|
+
// Catch invalid options
|
37
|
+
if (options && options.position) {
|
38
|
+
if (!(options.position === 'top' || options.position === 'bottom' || options.position instanceof HTMLElement)) {
|
39
|
+
throw Error('The position you entered is not a valid position');
|
40
|
+
}
|
41
|
+
if (options.position instanceof HTMLElement) {
|
42
|
+
// Detatch DOM element from options object, because Chartist.extend
|
43
|
+
// currently chokes on circular references present in HTMLElements
|
44
|
+
var cachedDOMPosition = options.position;
|
45
|
+
delete options.position;
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
options = Chartist.extend({}, defaultOptions, options);
|
50
|
+
|
51
|
+
if (cachedDOMPosition) {
|
52
|
+
// Reattatch the DOM Element position if it was removed before
|
53
|
+
options.position = cachedDOMPosition
|
54
|
+
}
|
55
|
+
|
56
|
+
return function legend(chart) {
|
57
|
+
|
58
|
+
function removeLegendElement() {
|
59
|
+
var legendElement = chart.container.querySelector('.ct-legend');
|
60
|
+
if (legendElement) {
|
61
|
+
legendElement.parentNode.removeChild(legendElement);
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
// Set a unique className for each series so that when a series is removed,
|
66
|
+
// the other series still have the same color.
|
67
|
+
function setSeriesClassNames() {
|
68
|
+
chart.data.series = chart.data.series.map(function (series, seriesIndex) {
|
69
|
+
if (typeof series !== 'object') {
|
70
|
+
series = {
|
71
|
+
value: series
|
72
|
+
};
|
73
|
+
}
|
74
|
+
series.className = series.className || chart.options.classNames.series + '-' + Chartist.alphaNumerate(seriesIndex);
|
75
|
+
return series;
|
76
|
+
});
|
77
|
+
}
|
78
|
+
|
79
|
+
function createLegendElement() {
|
80
|
+
var legendElement = document.createElement('ul');
|
81
|
+
legendElement.className = 'ct-legend';
|
82
|
+
if (chart instanceof Chartist.Pie) {
|
83
|
+
legendElement.classList.add('ct-legend-inside');
|
84
|
+
}
|
85
|
+
if (typeof options.className === 'string' && options.className.length > 0) {
|
86
|
+
legendElement.classList.add(options.className);
|
87
|
+
}
|
88
|
+
if (chart.options.width) {
|
89
|
+
legendElement.style.cssText = 'width: ' + chart.options.width + 'px;margin: 0 auto;';
|
90
|
+
}
|
91
|
+
return legendElement;
|
92
|
+
}
|
93
|
+
|
94
|
+
// Get the right array to use for generating the legend.
|
95
|
+
function getLegendNames(useLabels) {
|
96
|
+
return options.legendNames || (useLabels ? chart.data.labels : chart.data.series);
|
97
|
+
}
|
98
|
+
|
99
|
+
// Initialize the array that associates series with legends.
|
100
|
+
// -1 indicates that there is no legend associated with it.
|
101
|
+
function initSeriesMetadata(useLabels) {
|
102
|
+
var seriesMetadata = new Array(chart.data.series.length);
|
103
|
+
for (var i = 0; i < chart.data.series.length; i++) {
|
104
|
+
seriesMetadata[i] = {
|
105
|
+
data: chart.data.series[i],
|
106
|
+
label: useLabels ? chart.data.labels[i] : null,
|
107
|
+
legend: -1
|
108
|
+
};
|
109
|
+
}
|
110
|
+
return seriesMetadata;
|
111
|
+
}
|
112
|
+
|
113
|
+
function createNameElement(i, legendText, classNamesViable) {
|
114
|
+
var li = document.createElement('li');
|
115
|
+
li.classList.add('ct-series-' + i);
|
116
|
+
// Append specific class to a legend element, if viable classes are given
|
117
|
+
if (classNamesViable) {
|
118
|
+
li.classList.add(options.classNames[i]);
|
119
|
+
}
|
120
|
+
li.setAttribute('data-legend', i);
|
121
|
+
li.textContent = legendText;
|
122
|
+
return li;
|
123
|
+
}
|
124
|
+
|
125
|
+
// Append the legend element to the DOM
|
126
|
+
function appendLegendToDOM(legendElement) {
|
127
|
+
if (!(options.position instanceof HTMLElement)) {
|
128
|
+
switch (options.position) {
|
129
|
+
case 'top':
|
130
|
+
chart.container.insertBefore(legendElement, chart.container.childNodes[0]);
|
131
|
+
break;
|
132
|
+
|
133
|
+
case 'bottom':
|
134
|
+
chart.container.insertBefore(legendElement, null);
|
135
|
+
break;
|
136
|
+
}
|
137
|
+
} else {
|
138
|
+
// Appends the legend element as the last child of a given HTMLElement
|
139
|
+
options.position.insertBefore(legendElement, null);
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
function addClickHandler(legendElement, legends, seriesMetadata, useLabels) {
|
144
|
+
legendElement.addEventListener('click', function(e) {
|
145
|
+
var li = e.target;
|
146
|
+
if (li.parentNode !== legendElement || !li.hasAttribute('data-legend'))
|
147
|
+
return;
|
148
|
+
e.preventDefault();
|
149
|
+
|
150
|
+
var legendIndex = parseInt(li.getAttribute('data-legend'));
|
151
|
+
var legend = legends[legendIndex];
|
152
|
+
|
153
|
+
if (!legend.active) {
|
154
|
+
legend.active = true;
|
155
|
+
li.classList.remove('inactive');
|
156
|
+
} else {
|
157
|
+
legend.active = false;
|
158
|
+
li.classList.add('inactive');
|
159
|
+
|
160
|
+
var activeCount = legends.filter(function(legend) { return legend.active; }).length;
|
161
|
+
if (!options.removeAll && activeCount == 0) {
|
162
|
+
// If we can't disable all series at the same time, let's
|
163
|
+
// reenable all of them:
|
164
|
+
for (var i = 0; i < legends.length; i++) {
|
165
|
+
legends[i].active = true;
|
166
|
+
legendElement.childNodes[i].classList.remove('inactive');
|
167
|
+
}
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
var newSeries = [];
|
172
|
+
var newLabels = [];
|
173
|
+
|
174
|
+
for (var i = 0; i < seriesMetadata.length; i++) {
|
175
|
+
if (seriesMetadata[i].legend != -1 && legends[seriesMetadata[i].legend].active) {
|
176
|
+
newSeries.push(seriesMetadata[i].data);
|
177
|
+
newLabels.push(seriesMetadata[i].label);
|
178
|
+
}
|
179
|
+
}
|
180
|
+
|
181
|
+
chart.data.series = newSeries;
|
182
|
+
if (useLabels) {
|
183
|
+
chart.data.labels = newLabels;
|
184
|
+
}
|
185
|
+
|
186
|
+
chart.update();
|
187
|
+
|
188
|
+
if (options.onClick) {
|
189
|
+
options.onClick(chart, e);
|
190
|
+
}
|
191
|
+
});
|
192
|
+
}
|
193
|
+
|
194
|
+
removeLegendElement();
|
195
|
+
|
196
|
+
var legendElement = createLegendElement();
|
197
|
+
var useLabels = chart instanceof Chartist.Pie && chart.data.labels && chart.data.labels.length;
|
198
|
+
var legendNames = getLegendNames(useLabels);
|
199
|
+
var seriesMetadata = initSeriesMetadata(useLabels);
|
200
|
+
var legends = [];
|
201
|
+
|
202
|
+
// Check if given class names are viable to append to legends
|
203
|
+
var classNamesViable = Array.isArray(options.classNames) && options.classNames.length === legendNames.length;
|
204
|
+
|
205
|
+
// Loop through all legends to set each name in a list item.
|
206
|
+
legendNames.forEach(function (legend, i) {
|
207
|
+
var legendText = legend.name || legend;
|
208
|
+
var legendSeries = legend.series || [i];
|
209
|
+
|
210
|
+
var li = createNameElement(i, legendText, classNamesViable);
|
211
|
+
legendElement.appendChild(li);
|
212
|
+
|
213
|
+
legendSeries.forEach(function(seriesIndex) {
|
214
|
+
seriesMetadata[seriesIndex].legend = i;
|
215
|
+
});
|
216
|
+
|
217
|
+
legends.push({
|
218
|
+
text: legendText,
|
219
|
+
series: legendSeries,
|
220
|
+
active: true
|
221
|
+
});
|
222
|
+
});
|
223
|
+
|
224
|
+
chart.on('created', function (data) {
|
225
|
+
appendLegendToDOM(legendElement);
|
226
|
+
});
|
227
|
+
|
228
|
+
if (options.clickable) {
|
229
|
+
setSeriesClassNames();
|
230
|
+
addClickHandler(legendElement, legends, seriesMetadata, useLabels);
|
231
|
+
}
|
232
|
+
};
|
233
|
+
};
|
234
|
+
|
235
|
+
return Chartist.plugins.legend;
|
236
|
+
|
237
|
+
}));
|
@@ -0,0 +1,56 @@
|
|
1
|
+
.ct-chart.bar-chart id="#{id}"
|
2
|
+
|
3
|
+
.table-responsive.chart-table
|
4
|
+
table.table.table-striped
|
5
|
+
tbody
|
6
|
+
tr
|
7
|
+
-for label in labels
|
8
|
+
th #{label}
|
9
|
+
-for serie in series
|
10
|
+
tr
|
11
|
+
-for element in serie
|
12
|
+
td #{element}
|
13
|
+
|
14
|
+
|
15
|
+
javascript:
|
16
|
+
var labels = #{{labels}};
|
17
|
+
var series = #{{series}};
|
18
|
+
|
19
|
+
var options = {
|
20
|
+
seriesBarDistance: 30,
|
21
|
+
fullWidth: true,
|
22
|
+
chartPadding: {
|
23
|
+
right: 40
|
24
|
+
},
|
25
|
+
height: '300px',
|
26
|
+
showLabel: true,
|
27
|
+
plugins: [
|
28
|
+
Chartist.plugins.legend({
|
29
|
+
legendNames: #{{names}},
|
30
|
+
})
|
31
|
+
]
|
32
|
+
};
|
33
|
+
|
34
|
+
var responsiveOptions = [
|
35
|
+
['screen and (max-width: 640px)', {
|
36
|
+
seriesBarDistance: 5,
|
37
|
+
axisX: {
|
38
|
+
labelInterpolationFnc: function (value) {
|
39
|
+
return value[0];
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}]
|
43
|
+
];
|
44
|
+
|
45
|
+
new Chartist.Bar("##{id}", {
|
46
|
+
labels: labels,
|
47
|
+
series: series
|
48
|
+
},
|
49
|
+
options,
|
50
|
+
responsiveOptions
|
51
|
+
);
|
52
|
+
|
53
|
+
css:
|
54
|
+
##{{id}} .ct-bar {
|
55
|
+
stroke-width: #{{100/(labels.count*series.count)}}%
|
56
|
+
}
|