active_frontend 14.0.81 → 14.0.82
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/active_frontend/version.rb +1 -1
- data/lib/generators/active_frontend/templates/install.js +1 -0
- data/lib/generators/active_frontend/templates/install.scss +1 -0
- data/vendor/assets/javascripts/active_frontend.js +1 -0
- data/vendor/assets/javascripts/extensions/_cohort.js +342 -0
- data/vendor/assets/stylesheets/active_frontend.scss +1 -0
- data/vendor/assets/stylesheets/components/_cohort.scss +87 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20013c44be81d37cbe7d143efa16e805360ad598
|
4
|
+
data.tar.gz: 4076e7c6bac0423fa158d0abda3a76a1e83b5ac3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e986cf2dcd0f9c5254e9cdd36aba02fe9ec5aa8df655985c9032ddb04bbb0c4e7389d94b0b4c03cbdcb399b144fa14b71bd42c8d32b581049ea8d7774f13d13
|
7
|
+
data.tar.gz: 39214e183f7a88a3d5c0ea20fce94ebc3ff02cd61fd9a1d037860a0b69de3ef2e96b068e5435312ce7b44a0a8538fc16571751ac177a499d901df5ebe0f675a9
|
@@ -0,0 +1,342 @@
|
|
1
|
+
;(function(globals) {
|
2
|
+
var TYPE_PERCENTAGE = 'percentage';
|
3
|
+
var TYPE_ABSOLUTE = 'absolute';
|
4
|
+
|
5
|
+
var cohortDefaults = {
|
6
|
+
monthNames: [
|
7
|
+
'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September',
|
8
|
+
'October', 'November', 'December'
|
9
|
+
],
|
10
|
+
shortMonthNames: [
|
11
|
+
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
|
12
|
+
],
|
13
|
+
repeatLevels: {
|
14
|
+
'low': [0, 10],
|
15
|
+
'medium-low': [10, 20],
|
16
|
+
'medium': [20, 30],
|
17
|
+
'medium-high': [30, 40],
|
18
|
+
'high': [40, 60],
|
19
|
+
'hot': [60, 70],
|
20
|
+
'extra-hot': [70, 100]
|
21
|
+
},
|
22
|
+
labels: {
|
23
|
+
time: 'Time',
|
24
|
+
total: 'Total',
|
25
|
+
weekOf: 'Week of'
|
26
|
+
},
|
27
|
+
emptyPlaceholder: '---',
|
28
|
+
timeInterval: 'monthly',
|
29
|
+
drawEmptyCells: true,
|
30
|
+
rawNumberOnHover: true,
|
31
|
+
initialIntervalNumber: 1,
|
32
|
+
percentagePercision: 1,
|
33
|
+
classPrefix: 'cohort-',
|
34
|
+
|
35
|
+
formatHeaderLabel: function(i) {
|
36
|
+
return (this.initialIntervalNumber - 1 + i).toString();
|
37
|
+
},
|
38
|
+
formatDailyLabel: function(date, i) {
|
39
|
+
date.setDate(date.getDate() + i);
|
40
|
+
return this.monthNames[date.getMonth()] + ' ' + date.getDate() + ', ' + getYear(date);
|
41
|
+
},
|
42
|
+
formatWeeklyLabel: function(date, i) {
|
43
|
+
date.setDate(date.getDate() + i * 7);
|
44
|
+
return this.labels.weekOf + ' ' + this.shortMonthNames[date.getMonth()] + ' ' +
|
45
|
+
date.getDate() + ', ' + getYear(date);
|
46
|
+
},
|
47
|
+
formatMonthlyLabel: function(date, i) {
|
48
|
+
date.setMonth(date.getMonth() + i);
|
49
|
+
return this.monthNames[date.getMonth()] + ' ' + getYear(date);
|
50
|
+
},
|
51
|
+
formatYearlyLabel: function(date, i) {
|
52
|
+
return date.getYear() + 1900 + i;
|
53
|
+
}
|
54
|
+
},
|
55
|
+
|
56
|
+
defaults = cohortDefaults;
|
57
|
+
|
58
|
+
function extend() {
|
59
|
+
var target = arguments[0];
|
60
|
+
|
61
|
+
if (arguments.length === 1) return target;
|
62
|
+
|
63
|
+
for (var i = 1; i < arguments.length; i++) {
|
64
|
+
var source = arguments[i];
|
65
|
+
for (var prop in source) target[prop] = source[prop];
|
66
|
+
}
|
67
|
+
|
68
|
+
return target;
|
69
|
+
}
|
70
|
+
|
71
|
+
function isNumber(val) {
|
72
|
+
return Object.prototype.toString.call(val) === '[object Number]';
|
73
|
+
}
|
74
|
+
|
75
|
+
function isEmpty(val) {
|
76
|
+
return val === null || val === undefined || val === '';
|
77
|
+
}
|
78
|
+
|
79
|
+
function getYear(date) {
|
80
|
+
return date.getFullYear ? date.getFullYear() : date.getYear() + 1900;
|
81
|
+
}
|
82
|
+
|
83
|
+
function formatValue(value, base, valueType) {
|
84
|
+
if (valueType === TYPE_ABSOLUTE) {
|
85
|
+
return value;
|
86
|
+
} else if (isNumber(value) && base > 0) {
|
87
|
+
return (value / base * 100).toFixed(cohortDefaults.percentagePercision);
|
88
|
+
} else if (isNumber(value)) {
|
89
|
+
return '0.00';
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
function setText(element, text) {
|
94
|
+
if (document.all) {
|
95
|
+
element.innerText = text;
|
96
|
+
} else {
|
97
|
+
element.textContent = text;
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
function setTitle(element, text, type) {
|
102
|
+
if (type === TYPE_ABSOLUTE) {
|
103
|
+
element.dataset.originalTitle = text;
|
104
|
+
} else {
|
105
|
+
element.dataset.originalTitle = text + '%';
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
function addClass(element, className) {
|
110
|
+
if (!new RegExp(className).test(element.className)) {
|
111
|
+
element.className += ' ' + className;
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
115
|
+
function removeClass(element, className) {
|
116
|
+
element.className = element.className.replace(className, '');
|
117
|
+
}
|
118
|
+
|
119
|
+
function prefixClass(className, classPrefix) {
|
120
|
+
var prefixedClass = [],
|
121
|
+
classes = className.split(/\s+/);
|
122
|
+
|
123
|
+
for (var i in classes) {
|
124
|
+
prefixedClass.push(classPrefix + classes[i]);
|
125
|
+
}
|
126
|
+
|
127
|
+
return prefixedClass.join(' ');
|
128
|
+
}
|
129
|
+
|
130
|
+
var draw = function(cohort, values, container) {
|
131
|
+
if (!values) throw new Error ('Please provide the values data');
|
132
|
+
if (!container) throw new Error ('Please provide the values container');
|
133
|
+
|
134
|
+
var config = cohort.config,
|
135
|
+
initialDate = cohort.initialDate;
|
136
|
+
|
137
|
+
function create(el, options) {
|
138
|
+
options = options || {};
|
139
|
+
|
140
|
+
el = document.createElement(el);
|
141
|
+
|
142
|
+
if ((className = options.className)) {
|
143
|
+
delete options.className;
|
144
|
+
el.className = prefixClass(className, config.classPrefix);
|
145
|
+
}
|
146
|
+
|
147
|
+
if (!isEmpty(options.text)) {
|
148
|
+
var text = options.text.toString();
|
149
|
+
setText(el, text);
|
150
|
+
delete options.text;
|
151
|
+
}
|
152
|
+
|
153
|
+
if (options.tooltip) {
|
154
|
+
el.dataset.hover = 'tooltip';
|
155
|
+
el.dataset.container = 'body';
|
156
|
+
delete options.tooltip;
|
157
|
+
}
|
158
|
+
|
159
|
+
for (var option in options) {
|
160
|
+
if ((opt = options[option])) el[option] = opt;
|
161
|
+
}
|
162
|
+
|
163
|
+
return el;
|
164
|
+
}
|
165
|
+
|
166
|
+
function drawHeader(data) {
|
167
|
+
var th = create('tr'),
|
168
|
+
monthLength = data[0].length;
|
169
|
+
|
170
|
+
th.appendChild(create('th', { text: config.labels.time, className: 'time' }));
|
171
|
+
|
172
|
+
for (var i = 0; i < monthLength; i++) {
|
173
|
+
if (i > config.maxColumns) break;
|
174
|
+
var text = i === 0 ? config.labels.total : config.formatHeaderLabel(i);
|
175
|
+
th.appendChild(create('th', { text: text, className: 'total' }));
|
176
|
+
}
|
177
|
+
|
178
|
+
return th;
|
179
|
+
}
|
180
|
+
|
181
|
+
function formatTimeLabel(initial, timeInterval, i) {
|
182
|
+
var date = new Date(initial.getTime()),
|
183
|
+
formatFn = null;
|
184
|
+
|
185
|
+
if (timeInterval === 'daily') {
|
186
|
+
formatFn = 'formatDailyLabel';
|
187
|
+
} else if (timeInterval === 'weekly') {
|
188
|
+
formatFn = 'formatWeeklyLabel';
|
189
|
+
} else if (timeInterval === 'monthly') {
|
190
|
+
formatFn = 'formatMonthlyLabel';
|
191
|
+
} else if (timeInterval === 'yearly') {
|
192
|
+
formatFn = 'formatYearlyLabel';
|
193
|
+
} else {
|
194
|
+
throw new Error('Interval not supported');
|
195
|
+
}
|
196
|
+
|
197
|
+
return config[formatFn].call(config, date, i);
|
198
|
+
}
|
199
|
+
|
200
|
+
function drawCells(data) {
|
201
|
+
var fragment = document.createDocumentFragment(),
|
202
|
+
startMonth = config.maxRows ? data.length - config.maxRows : 0,
|
203
|
+
classNameFor = function(value) {
|
204
|
+
var levels = config.repeatLevels,
|
205
|
+
floatValue = value && parseFloat(value),
|
206
|
+
highestLevel = null,
|
207
|
+
classNames = ['percentage'];
|
208
|
+
|
209
|
+
for (var level in levels) {
|
210
|
+
if (floatValue >= levels[level][0] && floatValue < levels[level][1]) {
|
211
|
+
classNames.push(level);
|
212
|
+
return classNames.join(' ');
|
213
|
+
}
|
214
|
+
|
215
|
+
highestLevel = level;
|
216
|
+
}
|
217
|
+
|
218
|
+
classNames.push(highestLevel);
|
219
|
+
return classNames.join(' ');
|
220
|
+
};
|
221
|
+
|
222
|
+
for (var i = startMonth; i < data.length; i++) {
|
223
|
+
var tr = create('tr'),
|
224
|
+
row = data[i],
|
225
|
+
baseValue = row[0];
|
226
|
+
|
227
|
+
tr.appendChild(create('td', {
|
228
|
+
className: 'label',
|
229
|
+
text: formatTimeLabel(initialDate, config.timeInterval, i)
|
230
|
+
}));
|
231
|
+
|
232
|
+
for (var j = 0; j < data[0].length; j++) {
|
233
|
+
if (j > config.maxColumns) break;
|
234
|
+
|
235
|
+
var value = row[j],
|
236
|
+
cellValue = j === 0 ? value : formatValue(value, baseValue, TYPE_PERCENTAGE),
|
237
|
+
opts = {};
|
238
|
+
|
239
|
+
if (!isEmpty(cellValue)) {
|
240
|
+
var title = j > 0 && config.rawNumberOnHover ? value : null;
|
241
|
+
|
242
|
+
opts = {
|
243
|
+
text: cellValue,
|
244
|
+
title: title,
|
245
|
+
className: j === 0 ? 'total' : classNameFor(cellValue),
|
246
|
+
tooltip: title !== null
|
247
|
+
};
|
248
|
+
} else if (config.drawEmptyCells) {
|
249
|
+
opts = { text: config.emptyPlaceholder, className: 'empty' };
|
250
|
+
}
|
251
|
+
|
252
|
+
tr.appendChild(create('td', opts));
|
253
|
+
}
|
254
|
+
|
255
|
+
fragment.appendChild(tr);
|
256
|
+
}
|
257
|
+
|
258
|
+
return fragment;
|
259
|
+
}
|
260
|
+
|
261
|
+
var mainContainer = create('div', { className: 'container' }),
|
262
|
+
table = create('table', { className: 'table' });
|
263
|
+
|
264
|
+
table.appendChild(drawHeader(values));
|
265
|
+
table.appendChild(drawCells(values));
|
266
|
+
|
267
|
+
if ((title = config.title)) {
|
268
|
+
mainContainer.appendChild(create('div', { text: title, className: 'title' }));
|
269
|
+
}
|
270
|
+
|
271
|
+
mainContainer.appendChild(table);
|
272
|
+
|
273
|
+
container.innerHTML = '';
|
274
|
+
container.appendChild(mainContainer);
|
275
|
+
};
|
276
|
+
|
277
|
+
var Cohort = function(opts) {
|
278
|
+
if (!(initialDate = opts.initialDate)) throw new Error('The initialDate is a required argument');
|
279
|
+
delete opts.initialDate;
|
280
|
+
|
281
|
+
this.initialDate = initialDate;
|
282
|
+
this.valueType = TYPE_PERCENTAGE;
|
283
|
+
this.config = extend({}, Cohort.getDefaults(), opts || {});
|
284
|
+
|
285
|
+
this.toggleValues = function() {
|
286
|
+
this.valueType = this.valueType === TYPE_PERCENTAGE ? TYPE_ABSOLUTE : TYPE_PERCENTAGE;
|
287
|
+
var table = opts.container.getElementsByTagName('table')[0];
|
288
|
+
|
289
|
+
for (var rowIndex = 0; rowIndex < opts.values.length; rowIndex++) {
|
290
|
+
var tr = table.children[rowIndex + 1];
|
291
|
+
|
292
|
+
for (var cellIndex = 1; cellIndex < opts.values[rowIndex].length; cellIndex++) {
|
293
|
+
var td = tr.children[cellIndex + 1];
|
294
|
+
var absValue = formatValue(opts.values[rowIndex][cellIndex], opts.values[rowIndex][0], TYPE_ABSOLUTE);
|
295
|
+
var perValue = formatValue(opts.values[rowIndex][cellIndex], opts.values[rowIndex][0], TYPE_PERCENTAGE);
|
296
|
+
|
297
|
+
if (this.valueType === TYPE_ABSOLUTE) {
|
298
|
+
setText(td, absValue);
|
299
|
+
setTitle(td, perValue, TYPE_PERCENTAGE);
|
300
|
+
removeClass(td, prefixClass('percentage', this.config.classPrefix));
|
301
|
+
} else {
|
302
|
+
setText(td, perValue);
|
303
|
+
setTitle(td, absValue, TYPE_ABSOLUTE);
|
304
|
+
addClass(td, prefixClass('percentage', this.config.classPrefix));
|
305
|
+
}
|
306
|
+
}
|
307
|
+
}
|
308
|
+
};
|
309
|
+
};
|
310
|
+
|
311
|
+
extend(Cohort, {
|
312
|
+
getDefaults: function() {
|
313
|
+
return defaults;
|
314
|
+
},
|
315
|
+
setDefaults: function(def) {
|
316
|
+
defaults = extend({}, cohortDefaults, def);
|
317
|
+
},
|
318
|
+
resetDefaults: function() {
|
319
|
+
defaults = cohortDefaults;
|
320
|
+
},
|
321
|
+
draw: function(options) {
|
322
|
+
var cohort = new Cohort(options);
|
323
|
+
draw(cohort, options.values, options.container);
|
324
|
+
return cohort;
|
325
|
+
}
|
326
|
+
});
|
327
|
+
|
328
|
+
if (typeof jQuery !== 'undefined' && jQuery !== null) {
|
329
|
+
jQuery.fn.cohort = function(options) {
|
330
|
+
return this.each(function() {
|
331
|
+
options.container = this;
|
332
|
+
return Cohort.draw(options);
|
333
|
+
});
|
334
|
+
};
|
335
|
+
}
|
336
|
+
|
337
|
+
if (globals.exports) {
|
338
|
+
globals.exports = Cohort;
|
339
|
+
} else {
|
340
|
+
globals.Cohort = Cohort;
|
341
|
+
}
|
342
|
+
})(typeof module === 'function' ? module : window);
|
@@ -0,0 +1,87 @@
|
|
1
|
+
// Table of Contents
|
2
|
+
// ==================================================
|
3
|
+
// Cohort
|
4
|
+
|
5
|
+
// scss-lint:disable ImportantRule
|
6
|
+
// scss-lint:disable NestingDepth
|
7
|
+
|
8
|
+
// Cohort
|
9
|
+
// ==================================================
|
10
|
+
.cohort-title {
|
11
|
+
font-size: text-size(b);
|
12
|
+
font-weight: text-weight(semibold);
|
13
|
+
padding-bottom: 20px;
|
14
|
+
text-align: center;
|
15
|
+
}
|
16
|
+
.cohort-table {
|
17
|
+
background: light-color(light-haze);
|
18
|
+
border: 1px solid color(dark-haze);
|
19
|
+
border-spacing: 0;
|
20
|
+
border-collapse: collapse;
|
21
|
+
font-size: text-size(b);
|
22
|
+
margin: auto;
|
23
|
+
max-width: 100%;
|
24
|
+
width: 100%;
|
25
|
+
|
26
|
+
tr:first-child {
|
27
|
+
th {
|
28
|
+
border-bottom-width: 3px;
|
29
|
+
|
30
|
+
&:last-child { border-right: 0; }
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
td,
|
35
|
+
th {
|
36
|
+
text-align: center;
|
37
|
+
padding: 8px;
|
38
|
+
}
|
39
|
+
|
40
|
+
th {
|
41
|
+
border-bottom: 1px solid color(dark-haze);
|
42
|
+
border-right: 1px solid color(dark-haze);
|
43
|
+
font-weight: text-weight(semibold);
|
44
|
+
}
|
45
|
+
}
|
46
|
+
.cohort-percentage {
|
47
|
+
&::after {
|
48
|
+
content: '%';
|
49
|
+
margin-left: 2px;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
.cohort-label,
|
53
|
+
.cohort-total {
|
54
|
+
border-bottom: 1px solid color(dark-haze);
|
55
|
+
border-right: 1px solid color(dark-haze);
|
56
|
+
font-weight: text-weight(semibold);
|
57
|
+
}
|
58
|
+
.cohort-label {
|
59
|
+
text-align: left !important;
|
60
|
+
width: 140px;
|
61
|
+
}
|
62
|
+
.cohort-total {
|
63
|
+
border-right-width: 3px;
|
64
|
+
font-weight: text-weight(normal);
|
65
|
+
width: 80px;
|
66
|
+
}
|
67
|
+
.cohort-empty {
|
68
|
+
background: color(white);
|
69
|
+
border-bottom: 1px solid color(dark-haze);
|
70
|
+
border-right: 1px solid color(dark-haze);
|
71
|
+
}
|
72
|
+
.cohort-low,
|
73
|
+
.cohort-medium-low,
|
74
|
+
.cohort-medium,
|
75
|
+
.cohort-medium-high,
|
76
|
+
.cohort-high,
|
77
|
+
.cohort-hot,
|
78
|
+
.cohort-extra-hot { color: color(white); }
|
79
|
+
@each $name, $multiplier in (low: 3, medium-low: 2, medium: 1) {
|
80
|
+
.cohort-#{$name} { background: lighten(color(primary), percentage((7.5 * $multiplier) / 100)); }
|
81
|
+
}
|
82
|
+
.cohort-medium-high {
|
83
|
+
background: color(primary);
|
84
|
+
}
|
85
|
+
@each $name, $multiplier in (high: 1, hot: 2, extra-hot: 3) {
|
86
|
+
.cohort-#{$name} { background: darken(color(primary), percentage((7.5 * $multiplier) / 100)); }
|
87
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_frontend
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 14.0.
|
4
|
+
version: 14.0.82
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Juan Gomez
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-04-
|
11
|
+
date: 2017-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -247,6 +247,7 @@ files:
|
|
247
247
|
- vendor/assets/javascripts/base/_typeahead.js
|
248
248
|
- vendor/assets/javascripts/extensions/_calendar.js
|
249
249
|
- vendor/assets/javascripts/extensions/_chart.js
|
250
|
+
- vendor/assets/javascripts/extensions/_cohort.js
|
250
251
|
- vendor/assets/javascripts/extensions/_copy.js
|
251
252
|
- vendor/assets/javascripts/extensions/_map.js
|
252
253
|
- vendor/assets/javascripts/extensions/_wysiwyg.js
|
@@ -277,6 +278,7 @@ files:
|
|
277
278
|
- vendor/assets/stylesheets/components/_carousel.scss
|
278
279
|
- vendor/assets/stylesheets/components/_chart.scss
|
279
280
|
- vendor/assets/stylesheets/components/_choicepicker.scss
|
281
|
+
- vendor/assets/stylesheets/components/_cohort.scss
|
280
282
|
- vendor/assets/stylesheets/components/_collapse.scss
|
281
283
|
- vendor/assets/stylesheets/components/_colorpicker.scss
|
282
284
|
- vendor/assets/stylesheets/components/_datepicker.scss
|