add dynamic date range calculation for dates, and add color gradient component, add color gradient for language and chrono
--- a/cms/app-client/app/adapters/application.js Mon Nov 14 17:23:43 2016 +0100
+++ b/cms/app-client/app/adapters/application.js Tue Nov 15 17:42:57 2016 +0100
@@ -5,6 +5,7 @@
transcript: 'transcript',
geostat: 'stats/geostats',
datestat: 'stats/datestats',
+ dateminmax: 'stats/dateminmax',
theme: 'stats/themes'
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/components/color-gradient.js Tue Nov 15 17:42:57 2016 +0100
@@ -0,0 +1,30 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+
+ classNames: ['color-gradient'],
+
+ colors: Ember.inject.service(),
+
+ domainStart: 0,
+ domainEnd: 100,
+ scale: null,
+
+ scaleProxy: Ember.computed('scale', function() {
+ let scaleRaw = this.get('scale');
+ if(scaleRaw === null) {
+ return this.get('colors').getScaleLinear(this.get('domainStart'), this.get('domainEnd'));
+ } else {
+ return scaleRaw;
+ }
+ }),
+
+ domainMed: Ember.computed('domainStart', 'domainEnd', function() {
+ return Math.round((this.get('domainEnd')-this.get('domainStart'))/2);
+ }),
+
+ colorList: Ember.computed('scale', function() {
+ return this.get('scaleProxy').colors(100);
+ })
+
+});
--- a/cms/app-client/app/components/visu-carto.js Mon Nov 14 17:23:43 2016 +0100
+++ b/cms/app-client/app/components/visu-carto.js Tue Nov 15 17:42:57 2016 +0100
@@ -7,6 +7,7 @@
export default Ember.Component.extend({
constants: Ember.inject.service(),
+ colors: Ember.inject.service(),
map: null,
@@ -175,8 +176,8 @@
'areasSettings': {
'autoZoom': false,
'selectable': true,
- 'color': '#777777',
- 'colorSolid': '#333333',
+ 'color': this.get('colors').LINEAR_COLOR_START,
+ 'colorSolid': this.get('colors').LINEAR_COLOR_END,
'colorOutline': '#253946',
'selectedColor': '#0085cb',
'rollOverColor': '#0085cb',
--- a/cms/app-client/app/components/visu-chrono-year.js Mon Nov 14 17:23:43 2016 +0100
+++ b/cms/app-client/app/components/visu-chrono-year.js Tue Nov 15 17:42:57 2016 +0100
@@ -10,6 +10,8 @@
classNameBindings: ['isDisabled:disabled', 'isDark:light-color', 'isHighlighted:highlighted'],
attributeBindings: ['style', 'title', 'id'],
+ colorScale: null,
+
isDisabled: Ember.computed('range', 'year', 'count', function() {
let year = parseInt(this.get('year'));
let count = this.get('count');
@@ -27,8 +29,9 @@
return this.get('colors').getPerceptiveLuminance(backgroundColor) >= 0.5;
}),
- backgroundColor: Ember.computed('count', 'maxCount', 'minCount', function() {
- return this.get('colors').shadeLinear(this.get('count'), this.get('minCount'), this.get('maxCount'));
+ backgroundColor: Ember.computed('count', function() {
+ return this.get('scale')(this.get('count'));
+ //return this.get('colors').shadeLinear(this.get('count'), this.get('minCount'), this.get('maxCount'));
}),
style: Ember.computed('backgroundColor', 'isDisabled', 'isHighlighted', function() {
@@ -56,6 +59,4 @@
year: null,
datestats: null,
range: null,
- maxCount: null,
- minCount: null,
});
--- a/cms/app-client/app/components/visu-chrono.js Mon Nov 14 17:23:43 2016 +0100
+++ b/cms/app-client/app/components/visu-chrono.js Tue Nov 15 17:42:57 2016 +0100
@@ -3,11 +3,21 @@
export default Ember.Component.extend({
- range: [],
+ colors: Ember.inject.service(),
+ filter: Ember.inject.service(),
+
+ range: null,
rawdatestats: null,
- decades: Ember.computed('range', function() {
- var range = this.get('range');
+ rangeArray: Ember.computed('range', 'range.[]', function() {
+ let range = this.get('range');
+ let resArray = [];
+ range.forEach(function(s) { resArray.push(parseInt(s.id)); });
+ return resArray.sort();
+ }),
+
+ decades: Ember.computed('rangeArray', function() {
+ var range = this.get('rangeArray');
return _.range(Math.floor(range[0]/10)*10, (Math.floor(range[1]/10)+1)*10, 10);
}),
@@ -22,8 +32,9 @@
counts: Ember.computed.mapBy('rawdatestats', 'count'),
maxCount: Ember.computed.max('counts'),
minCount: Ember.computed.min('counts'),
-
- filter: Ember.inject.service(),
+ colorScale: Ember.computed('maxCount', 'minCount', function() {
+ return this.get('colors').getScaleLinear(this.get('minCount'), this.get('maxCount'));
+ }),
date: Ember.computed.alias('filter.dateList'),
@@ -43,8 +54,10 @@
if(event.button === 0) {
isMouseDown = true;
- var element = parseInt(Ember.$(this).attr('id'));
- if(!_.inRange(element, self.get('range')[0], self.get('range')[1]+1)) {
+ var $elem = Ember.$(this);
+ var element = parseInt($elem.attr('id'));
+ var range = self.get('rangeArray');
+ if(!$elem.hasClass('highlighted') && !_.inRange(element, range[0], range[1]+1)) {
return false;
}
var elements = [element];
--- a/cms/app-client/app/components/visu-langues.js Mon Nov 14 17:23:43 2016 +0100
+++ b/cms/app-client/app/components/visu-langues.js Tue Nov 15 17:42:57 2016 +0100
@@ -10,6 +10,14 @@
filter: Ember.inject.service(),
colors: Ember.inject.service(),
+ scale: Ember.computed('maxCount', 'minCount', function() {
+ let maxCount = this.get('maxCount');
+ let minCount = this.get('minCount');
+ return this.get('colors').getScaleLinear(minCount, maxCount);
+ }),
+ maxCount: 0,
+ minCount: 0,
+
filterObserver: Ember.observer('filter.language', function() {
Ember.$('.node').removeClass("selected");
Ember.$('.node[data-id="' + this.get('filter').get('language') + '"]').addClass("selected");
@@ -142,10 +150,14 @@
var dMin = Math.min.apply(null, d._children.map(function(d){ return d.count; }));
var dMax = Math.max.apply(null, d._children.map(function(d){ return d.count; }));
+ self.setProperties({minCount: dMin, maxCount: dMax});
+ var scale = self.get('scale');
+ var backgroundColor = function(_d) { return scale(_d.count);};
+ var colorClass = function(_d) { return (self.get('colors').getPerceptiveLuminance(backgroundColor(_d)) >= 0.5)?'light-color':'dark-color'; };
- node.attr("class", function(d) { return "node" + ( d.id === self.get('filter').get('language') ? " selected" : "" ); })
+ node.attr("class", function(_d) { return "node " + colorClass(_d) + ( _d.id === self.get('filter').get('language') ? " selected" : "" ); })
.call(position)
- .style("background-color", function(d) { return self.get('colors').shadeLinear(d.count,dMin,dMax); })
+ .style("background-color", backgroundColor)
.on("click", selectHandler);
node.filter(function(d) { return d._children; })
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/helpers/color-gradient-style.js Tue Nov 15 17:42:57 2016 +0100
@@ -0,0 +1,7 @@
+import Ember from 'ember';
+
+export function colorGradientStyle(color) {
+ return Ember.String.htmlSafe(`background-color: ${color}`);
+}
+
+export default Ember.Helper.helper(colorGradientStyle);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/models/dateminmax.js Tue Nov 15 17:42:57 2016 +0100
@@ -0,0 +1,4 @@
+import DS from 'ember-data';
+
+export default DS.Model.extend({
+});
--- a/cms/app-client/app/routes/tabs/chrono.js Mon Nov 14 17:23:43 2016 +0100
+++ b/cms/app-client/app/routes/tabs/chrono.js Tue Nov 15 17:42:57 2016 +0100
@@ -8,7 +8,7 @@
model: function() {
return RSVP.hash({
- range: [1948, 2015], // TODO: make it dynamic
+ range: this.get('store').query('dateminmax', {}),
datestats: this.get('store').query('datestat', this.get('filter').get('queryParamsValues'))
});
},
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/serializers/dateminmax.js Tue Nov 15 17:42:57 2016 +0100
@@ -0,0 +1,18 @@
+import DS from 'ember-data';
+
+export default DS.Serializer.extend({
+
+ normalizeResponse: function(store, primaryModelClass, payload) {
+ var data = [];
+ payload['dateminmax'].forEach(function(key) {
+ data.push({
+ 'id': key,
+ 'type': 'dateminmax'
+ });
+ });
+ return {
+ 'data': data
+ };
+ }
+
+});
--- a/cms/app-client/app/services/colors.js Mon Nov 14 17:23:43 2016 +0100
+++ b/cms/app-client/app/services/colors.js Tue Nov 15 17:42:57 2016 +0100
@@ -4,8 +4,12 @@
export const LINEAR_COLOR_START = "#777777";
export const LINEAR_COLOR_END = "#333333";
+export function getScaleLinear(vmin, vmax) {
+ return chroma.scale([LINEAR_COLOR_START, LINEAR_COLOR_END]).mode('lab').domain([vmin,vmax]);
+}
+
export function shadeLinear(v, vmin, vmax) {
- var s = chroma.scale([LINEAR_COLOR_START, LINEAR_COLOR_END]).mode('lab').domain([vmin,vmax]);
+ var s = getScaleLinear(vmin, vmax);
return s(v).hex();
}
@@ -37,6 +41,7 @@
}
export default Ember.Service.extend({
+ getScaleLinear: getScaleLinear,
shadeLinear: shadeLinear,
getComplement: getComplement,
getPerceptiveLuminance: getPerceptiveLuminance,
--- a/cms/app-client/app/styles/app.scss Mon Nov 14 17:23:43 2016 +0100
+++ b/cms/app-client/app/styles/app.scss Tue Nov 15 17:42:57 2016 +0100
@@ -60,6 +60,7 @@
@import 'components/toolbar-component';
@import 'components/notice-component';
@import 'components/transcript-component';
+@import 'components/color-gradient';
h1, h2, h3, h4, h5, h6 {
@@ -122,7 +123,7 @@
.corpus-app-wrapper {
background-color: $corpus-light-grey;
- border-left: 1px solid $corpus-black;
+ border-left: 1px solid $corpus-black;
position: relative;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/styles/components/color-gradient.scss Tue Nov 15 17:42:57 2016 +0100
@@ -0,0 +1,37 @@
+.color-gradient {
+ width: 85%;
+ white-space: nowrap;
+ position: relative;
+ display: inline-block;
+ top: 4px;
+ padding-bottom: 1.2em;
+}
+
+.color-gradient .grad-step {
+ display: inline-block;
+ height: 1.5em;
+ width: 1%;
+}
+
+.color-gradient .domain-min {
+ position: absolute;
+ left: 0;
+ font-size: 0.8em;
+ bottom: 3px;
+}
+
+.color-gradient .domain-med {
+ position: absolute;
+ right: 25%;
+ left: 25%;
+ text-align: center;
+ font-size: 0.8em;
+ bottom: 3px;
+}
+
+.color-gradient .domain-max {
+ position: absolute;
+ right: 0;
+ font-size: 0.8em;
+ bottom: 3px;
+}
--- a/cms/app-client/app/styles/components/notice-component.scss Mon Nov 14 17:23:43 2016 +0100
+++ b/cms/app-client/app/styles/components/notice-component.scss Tue Nov 15 17:42:57 2016 +0100
@@ -22,7 +22,7 @@
color: $corpus-grey;
padding-right: 0.5em;
padding-left: 0.5em;
-
+ text-decoration: none;
}
body.videoscreen .notice-component {
--- a/cms/app-client/app/styles/tabs/chrono.scss Mon Nov 14 17:23:43 2016 +0100
+++ b/cms/app-client/app/styles/tabs/chrono.scss Tue Nov 15 17:42:57 2016 +0100
@@ -1,7 +1,7 @@
#tabs-chrono p {
padding: 0px 20px;
text-align: center;
- margin: 25px 0px 50px 0px;
+ margin: 25px 0px 25px 0px;
line-height: 22px;
color: $corpus-black;
}
@@ -46,12 +46,18 @@
#chrono-table li.disabled {
cursor: default;
color: $corpus-grey;
+ pointer-events: none;
+}
+
+#chrono-table .color-gradient {
+ width: 150px;
}
#chrono-table li.highlighted {
font-weight: bold;
color: $corpus-white;
background-color: $corpus-blue;
+ pointer-events: initial;
}
#chrono-table li.light-color {
--- a/cms/app-client/app/styles/tabs/langues.scss Mon Nov 14 17:23:43 2016 +0100
+++ b/cms/app-client/app/styles/tabs/langues.scss Tue Nov 15 17:42:57 2016 +0100
@@ -71,4 +71,26 @@
#tabs-langues .node .count {
font-weight: bold;
-}
\ No newline at end of file
+}
+
+#tabs-langues .light-color {
+ color: $corpus-white;
+}
+
+#tabs-langues .dark-color {
+ color: $corpus-black;
+}
+
+#tabs-langues .color-gradient-wrapper {
+ position: absolute;
+ width: 100px;
+ top: 1px;
+ right: 5px;
+}
+
+#tabs-langues .color-gradient-wrapper .color-gradient {
+ position: relative;
+ width: 100%;
+ height: 1.75em;
+ font-size: 0.75em;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/templates/components/color-gradient.hbs Tue Nov 15 17:42:57 2016 +0100
@@ -0,0 +1,4 @@
+{{#each colorList as |c index|}}<span class="grad-step" style={{color-gradient-style c}}></span>{{/each}}
+<span class="domain-min">{{domainStart}}</span>
+<span class="domain-med">{{domainMed}}</span>
+<span class="domain-max">{{domainEnd}}</span>
\ No newline at end of file
--- a/cms/app-client/app/templates/components/visu-chrono.hbs Mon Nov 14 17:23:43 2016 +0100
+++ b/cms/app-client/app/templates/components/visu-chrono.hbs Tue Nov 15 17:42:57 2016 +0100
@@ -1,9 +1,10 @@
+<div>{{ color-gradient domainStart=minCount domainEnd=maxCount scale=colorScale }}</div>
{{#each decades as |decade| }}
<div class="interval">
{{input type="checkbox" checked=(is-checked date decade) indeterminate=(is-indeterminate date decade) click=(action 'selectDecade' decade)}}
<ul class="{{ decade }}">
{{#each (range decade 10) as |year| }}
- {{ visu-chrono-year datestats=datestats year=year range=range maxCount=maxCount minCount=minCount }}
+ {{ visu-chrono-year datestats=datestats year=year range=rangeArray scale=colorScale }}
{{/each}}
</ul>
</div>
--- a/cms/app-client/app/templates/components/visu-langues.hbs Mon Nov 14 17:23:43 2016 +0100
+++ b/cms/app-client/app/templates/components/visu-langues.hbs Tue Nov 15 17:42:57 2016 +0100
@@ -0,0 +1,3 @@
+<div class="color-gradient-wrapper">
+{{ color-gradient domainStart=minCount domainEnd=maxCount scale=scale }}
+</div>
\ No newline at end of file
--- a/cms/app-client/app/templates/tabs/chrono.hbs Mon Nov 14 17:23:43 2016 +0100
+++ b/cms/app-client/app/templates/tabs/chrono.hbs Tue Nov 15 17:42:57 2016 +0100
@@ -1,4 +1,4 @@
<div id="tabs-chrono">
- <p>Cocher les cases de gauche pour sélectionner des décennies ou cliquez pour sélectionner une année et glisser pour en selectionner plusieurs.</p>
+ <p>Cocher les cases de gauche pour sélectionner des décennies ou cliquez pour sélectionner une année et glisser pour en selectionner plusieurs.</p>
{{ visu-chrono range=model.range rawdatestats=model.datestats }}
</div>
--- a/cms/app-client/mirage/config.js Mon Nov 14 17:23:43 2016 +0100
+++ b/cms/app-client/mirage/config.js Tue Nov 15 17:42:57 2016 +0100
@@ -40,6 +40,8 @@
this.get('/stats/datestats', 'datestats');
+ this.get('/stats/dateminmax', 'dateminmax');
+
this.get('/resolvers/lexvo/:ids', ({lexvos}, request) => {
var langIds = decodeURIComponent(request.params.ids);
var resMap = _.reduce(langIds.split(','), function(res, id) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/mirage/fixtures/dateminmax.js Tue Nov 15 17:42:57 2016 +0100
@@ -0,0 +1,4 @@
+export default [
+ { 'id': "1948" },
+ { 'id': "2015" }
+];
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/mirage/models/dateminmax.js Tue Nov 15 17:42:57 2016 +0100
@@ -0,0 +1,4 @@
+import { Model } from 'ember-cli-mirage';
+
+export default Model.extend({
+});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/mirage/serializers/dateminmax.js Tue Nov 15 17:42:57 2016 +0100
@@ -0,0 +1,9 @@
+import { JSONAPISerializer } from 'ember-cli-mirage';
+
+import _ from 'lodash/lodash';
+
+export default JSONAPISerializer.extend({
+ serialize(response) {
+ return {'dateminmax': _(response.models).map((dateinfo) => { return parseInt(dateinfo.id);}).value()};
+ }
+});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/tests/integration/components/color-gradient-test.js Tue Nov 15 17:42:57 2016 +0100
@@ -0,0 +1,24 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('color-gradient', 'Integration | Component | color gradient', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });
+
+ this.render(hbs`{{color-gradient}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:
+ this.render(hbs`
+ {{#color-gradient}}
+ template block text
+ {{/color-gradient}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
--- a/server/src/app/Http/Controllers/Api/DateStatsController.php Mon Nov 14 17:23:43 2016 +0100
+++ b/server/src/app/Http/Controllers/Api/DateStatsController.php Tue Nov 15 17:42:57 2016 +0100
@@ -12,23 +12,8 @@
class DateStatsController extends Controller
{
- /**
- * Display the specified resource.
- *
- * @return \Illuminate\Http\Response
- */
- public function index(Request $request)
- {
-
-
- $filterManager = new CorpusFilterManager();
- $filters = $filterManager->prepareFilters($request);
- unset($filters['dates']);
- $qFilterParts = $filterManager->buildESFilters($filters);
-
- $query = $filterManager->buildQuery($qFilterParts);
-
- $esQuery = [
+ private function getStatQuery($query) {
+ return [
'index' => config('elasticsearch.index'),
'body' => [
"size" => 0,
@@ -60,6 +45,70 @@
]
]
];
+ }
+
+ private function getMinMaxQuery($query) {
+ return [
+ 'index' => config('elasticsearch.index'),
+ 'body' => [
+ "size" => 0,
+ "query" => $query,
+ "aggs" => [
+ "datestats" => [
+ "nested"=> [
+ "path" => "creation_years"
+ ],
+ "aggs" => [
+ "minyear" => [
+ "min" => [ "field"=> "creation_years.year" ]
+ ],
+ "maxyear" => [
+ "max" => [ "field"=> "creation_years.year" ]
+ ]
+ ]
+ ]
+ ]
+ ]
+ ];
+ }
+
+ private function getDocQuery(Request $request) {
+ $filterManager = new CorpusFilterManager();
+ $filters = $filterManager->prepareFilters($request);
+ unset($filters['dates']);
+ $qFilterParts = $filterManager->buildESFilters($filters);
+
+ return $filterManager->buildQuery($qFilterParts);
+ }
+
+ /**
+ * Display the min max date stats
+ */
+ public function minmax(Request $request) {
+ $query = $this->getDocQuery($request);
+
+ $esQuery = $this->getMinMaxQuery($query);
+ $esRes = Es::search($esQuery);
+
+ $datestats = [];
+
+ $max = intval($esRes['aggregations']['datestats']['maxyear']['value']);
+ $min = intval($esRes['aggregations']['datestats']['maxyear']['value']);
+
+ return response()->json(['dateminmax' => [ $min, $max ] ]);
+ }
+
+ /**
+ * Display the dates stats
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function index(Request $request)
+ {
+
+ $query = $this->getDocQuery($request);
+
+ $esQuery = $this->getStatQuery($query);
$esRes = Es::search($esQuery);
$datestats = [];
--- a/server/src/routes/api.php Mon Nov 14 17:23:43 2016 +0100
+++ b/server/src/routes/api.php Tue Nov 15 17:42:57 2016 +0100
@@ -31,6 +31,7 @@
Route::get('themes', 'Api\ThemeController@index');
Route::get('discourses', 'Api\DiscourseController@index');
Route::get('datestats', 'Api\DateStatsController@index');
+ Route::get('dateminmax', 'Api\DateStatsController@minmax');
Route::get('geostats', 'Api\GeoStatsController@index');
});
});