# HG changeset patch # User ymh # Date 1478400256 -3600 # Node ID 5ef3bfef0bffbdca880b353f5495dce3bb82c4cb # Parent 4fbe94af93e856938dbf1915a6ff202b31bcdd2e add colors to visu chrono diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/app/adapters/application.js --- a/cms/app-client/app/adapters/application.js Fri Nov 04 19:03:25 2016 +0100 +++ b/cms/app-client/app/adapters/application.js Sun Nov 06 03:44:16 2016 +0100 @@ -4,6 +4,7 @@ const TYPE_PATH_MAP = { transcript: 'transcript', geostat: 'stats/geostats', + datestat: 'stats/datestats', theme: 'stats/themes' }; diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/app/components/visu-chrono-year.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cms/app-client/app/components/visu-chrono-year.js Sun Nov 06 03:44:16 2016 +0100 @@ -0,0 +1,61 @@ +import Ember from 'ember'; +import _ from 'lodash/lodash'; + +export default Ember.Component.extend({ + + colors: Ember.inject.service(), + filter: Ember.inject.service(), + + tagName: 'li', + classNameBindings: ['isDisabled:disabled', 'isDark:light-color', 'isHighlighted:highlighted'], + attributeBindings: ['style', 'title', 'id'], + + isDisabled: Ember.computed('range', 'year', 'count', function() { + let year = parseInt(this.get('year')); + let count = this.get('count'); + return (!_.inRange(year, this.get('range')[0], this.get('range')[1]+1)) || count === 0; + }), + + isHighlighted: Ember.computed('filter.dateList.[]', function() { + return _.contains(this.get('filter.dateList'), this.get('year')); + }), + isDark: Ember.computed('backgroundColor', 'isDisabled', function() { + let backgroundColor = this.get('backgroundColor'); + if(this.get('isDisabled')) { + return false; + } + return this.get('colors').getPerceptiveLuminance(this.get('backgroundColor')) >= 0.5; + }), + + backgroundColor: Ember.computed('count', 'maxCount', 'minCount', function() { + return this.get('colors').shadeLinear(this.get('count'), this.get('minCount'), this.get('maxCount')); + }), + + style: Ember.computed('backgroundColor', 'isDisabled', 'isHighlighted', function() { + let backgroundColor = this.get('backgroundColor'); + if(this.get('isDisabled') || this.get('isHighlighted')) { + return null; + } + return Ember.String.htmlSafe(`background-color: ${backgroundColor};`); + }), + id: Ember.computed.alias('year'), + count: Ember.computed('datestats.[]', function() { + let year = this.get('year'); + let count = this.get('datestats').get(`${year}`); + return count?count:0; + }), + title: Ember.computed('count', 'isDsabled', function() { + if(this.get('isDisabled')) { + return null; + } + let year = this.get('year'); + let count = this.get('count'); + return `${year} (${count})`; + }), + + year: null, + datestats: null, + range: null, + maxCount: null, + minCount: null, +}); diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/app/components/visu-chrono.js --- a/cms/app-client/app/components/visu-chrono.js Fri Nov 04 19:03:25 2016 +0100 +++ b/cms/app-client/app/components/visu-chrono.js Sun Nov 06 03:44:16 2016 +0100 @@ -4,89 +4,35 @@ export default Ember.Component.extend({ range: [], + rawdatestats: null, decades: Ember.computed('range', function() { var range = this.get('range'); - return _.range(Math.floor(range[0]/10)*10, Math.floor(range[1]/10)*10, 10); + return _.range(Math.floor(range[0]/10)*10, (Math.floor(range[1]/10)+1)*10, 10); }), + datestats: Ember.computed('rawdatestats.[]', function() { + var res = {}; + this.get('rawdatestats').forEach(function(s) { + res[s.get('id')] = s.get('count'); + }); + return Ember.Object.create(res); + }), + + counts: Ember.computed.mapBy('rawdatestats', 'count'), + maxCount: Ember.computed.max('counts'), + minCount: Ember.computed.min('counts'), + filter: Ember.inject.service(), - dateObserver: Ember.observer('date', function() { - var self = this; - this.$('li').removeClass('highlighted'); - this.get('date').forEach(function(date) { - self.$('li#' + date).addClass('highlighted'); - }); - }), - - date: Ember.computed('filter.date', { - get: function() { - const dates = this.get('filter').get('date'); - console.log("get DATES", dates); - if(dates === null) { - return []; - } - const res = _.reduce(dates, function(res, d) { - let m = d.match(/^(\d+)(?:-(\d+))?$/); - if(m) { - let start = parseInt(m[1]); - let end = parseInt(m[2]); - if(isNaN(end)) { - res.push(parseInt(m[1])); - } else { - res = res.concat(_.range(start,end+1)); - } - } - return res; - }, []).sort(); - console.log("GET DATE", res); - return res; - }, - set: function(key, values) { - var srcDateList = _.clone(values).sort(); - let start = null; - let end = null; - var pushValues = function(s,e,valuesList) { - if(s === e) { - valuesList.push(s.toString()); - } else { - valuesList.push(s.toString()+"-"+e.toString()); - } - }; - let dateList = _.reduce(srcDateList, function(res, d, i) { - if(start === null) { - start = end = d; - } - if(d > (end + 1)) { - pushValues(start, end, res); - start = end = d; - } else { - end = d; - } - if(i === (srcDateList.length - 1)) { - pushValues(start, end, res); - } - return res; - }, []); - console.log("SET DATE",key, values, dateList); - if(dateList.length === 0) { - dateList = null; - } - this.get('filter').set('date', dateList); - return srcDateList; - } - }), + date: Ember.computed.alias('filter.dateList'), elementId: "chrono-table", didInsertElement: function(){ + var self = this; - if (this.get('date') !== null){ - this.highlightQuery(this.get('date')); - } - var isMouseDown = false, isHighlighted, didHighlight, @@ -98,6 +44,9 @@ isMouseDown = true; var element = parseInt(Ember.$(this).attr('id')); + if(!_.inRange(element, self.get('range')[0], self.get('range')[1]+1)) { + return false; + } var elements = [element]; if(event.shiftKey) { while(previousElement !== element) { @@ -155,16 +104,6 @@ }); }, - highlightQuery: function(dates){ - console.log("highlightQuery", dates); - if(dates === null) { - return; - } - dates.map(function(date){ - Ember.$("#" + date).toggleClass("highlighted", true); - }); - }, - actions : { selectDecade: function(decade) { diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/app/components/visu-langues.js --- a/cms/app-client/app/components/visu-langues.js Fri Nov 04 19:03:25 2016 +0100 +++ b/cms/app-client/app/components/visu-langues.js Sun Nov 06 03:44:16 2016 +0100 @@ -7,6 +7,7 @@ constants: Ember.inject.service(), filter: Ember.inject.service(), + colors: Ember.inject.service(), filterObserver: Ember.observer('filter.language', function() { Ember.$('.node').removeClass("selected"); @@ -47,7 +48,6 @@ }) .round(false); - console.log('width', width, Ember.$('#' + self.get('elementId')).parent().width(), Ember.$('#' + self.get('elementId')).parent().parent().width(), Ember.$('#' + self.get('elementId')).parent().parent().parent().width()); var element = d3.select('#' + self.get('elementId')) .style("width", width + margin.left + margin.right + 'px') .style("height", height + margin.bottom + margin.top + 'px') @@ -122,14 +122,6 @@ .style("top", function(d) { return y(d.y) + 'px'; }); } - function hexadecimalToInteger(hexadecimal) { - var integer = []; - for(var i = 1; i < 7; i += 2) { - integer.push(parseInt(hexadecimal.slice(i, i + 2), 16)); - } - return integer; - } - function display(d) { breadcrumbs .datum(d.parent) @@ -149,21 +141,9 @@ 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; })); - function shade(d) { - var color = "#777777"; - var aColor = hexadecimalToInteger(color); - var solidColor = "#333333"; - var aSolidColor = hexadecimalToInteger(solidColor); - var aFillColor = []; - for(var i = 0; i < 3; i++) { - aFillColor.push((d.count - dMin) * (aSolidColor[i] - aColor[i]) / (dMax - dMin) + aColor[i]); - } - return '#' + (aFillColor.map(i => parseInt(i).toString(16))).join(''); - } - node.attr("class", function(d) { return "node" + ( d.id === self.get('filter').get('language') ? " selected" : "" ); }) .call(position) - .style("background-color", function(d) { return shade(d); }) + .style("background-color", function(d) { return self.get('colors').shadeLinear(d.count,dMin,dMax); }) .on("click", selectHandler); node.filter(function(d) { return d._children; }) diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/app/helpers/range.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cms/app-client/app/helpers/range.js Sun Nov 06 03:44:16 2016 +0100 @@ -0,0 +1,8 @@ +import Ember from 'ember'; +import _ from 'lodash/lodash'; + +export function range([start, nb, step]) { + return _.range(start, start+nb, step); +} + +export default Ember.Helper.helper(range); diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/app/models/datestat.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cms/app-client/app/models/datestat.js Sun Nov 06 03:44:16 2016 +0100 @@ -0,0 +1,5 @@ +import DS from 'ember-data'; + +export default DS.Model.extend({ + count: DS.attr('number') +}); diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/app/routes/tabs/chrono.js --- a/cms/app-client/app/routes/tabs/chrono.js Fri Nov 04 19:03:25 2016 +0100 +++ b/cms/app-client/app/routes/tabs/chrono.js Sun Nov 06 03:44:16 2016 +0100 @@ -7,7 +7,8 @@ model: function() { return RSVP.hash({ - range: [1948, 2015] + range: [1948, 2015], + datestats: this.get('store').findAll('datestat') }); }, diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/app/serializers/datestat.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cms/app-client/app/serializers/datestat.js Sun Nov 06 03:44:16 2016 +0100 @@ -0,0 +1,21 @@ +import DS from 'ember-data'; + +export default DS.Serializer.extend({ + + normalizeResponse: function(store, primaryModelClass, payload) { + var data = []; + Object.keys(payload['datestats']).forEach(function(key) { + data.push({ + 'id': key, + 'type': 'datestat', + 'attributes': { + 'count': payload['datestats'][key] + } + }); + }); + return { + 'data': data + }; + } + +}); diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/app/services/colors.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cms/app-client/app/services/colors.js Sun Nov 06 03:44:16 2016 +0100 @@ -0,0 +1,46 @@ +import Ember from 'ember'; +import chroma from 'chroma'; + +export const LINEAR_COLOR_START = "#777777"; +export const LINEAR_COLOR_END = "#333333"; + +export function shadeLinear(v, vmin, vmax) { + var s = chroma.scale([LINEAR_COLOR_START, LINEAR_COLOR_END]).mode('lab').domain([vmin,vmax]); + return s(v).hex(); +} + +export function shade(d) { + var aColor = chroma(LINEAR_COLOR_START).rgb(); + var aSolidColor = chroma(LINEAR_COLOR_END).rgb(); + var aFillColor = []; + for(var i = 0; i < 3; i++) { + aFillColor.push((d.count - dMin) * (aSolidColor[i] - aColor[i]) / (dMax - dMin) + aColor[i]); + } + return chroma.rgb(aFillColor).hex(); +} + +export function getComplement(c) { + let chromaColorHsl = chroma(c).hsl(); + console.log(chromaColorHsl[0]); + chromaColorHsl[0] += 180; + if (chromaColorHsl[0] > 360) { + chromaColorHsl[0] -= 360; + } + chromaColorHsl[0] /= 360; + + return chroma.hsl(chromaColorHsl).hex(); + +} + +export function getPerceptiveLuminance(c) { + var rgb = chroma(c).rgb(); + return 1 - ( 0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2])/255; +} + +export default Ember.Service.extend({ + shadeLinear: shadeLinear, + getComplement: getComplement, + getPerceptiveLuminance: getPerceptiveLuminance, + LINEAR_COLOR_START: LINEAR_COLOR_START, + LINEAR_COLOR_END: LINEAR_COLOR_END +}); diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/app/services/filter.js --- a/cms/app-client/app/services/filter.js Fri Nov 04 19:03:25 2016 +0100 +++ b/cms/app-client/app/services/filter.js Sun Nov 06 03:44:16 2016 +0100 @@ -89,6 +89,60 @@ return Ember.A(JSON.parse(value)); } return value; - } + }, + dateList: Ember.computed('date.[]', { + get: function() { + const dates = this.get('date'); + if(dates === null) { + return []; + } + const res = _.reduce(dates, function(res, d) { + let m = d.match(/^(\d+)(?:-(\d+))?$/); + if(m) { + let start = parseInt(m[1]); + let end = parseInt(m[2]); + if(isNaN(end)) { + res.push(parseInt(m[1])); + } else { + res = res.concat(_.range(start,end+1)); + } + } + return res; + }, []).sort(); + return res; + }, + set: function(key, values) { + var srcDateList = _.clone(values).sort(); + let start = null; + let end = null; + var pushValues = function(s,e,valuesList) { + if(s === e) { + valuesList.push(s.toString()); + } else { + valuesList.push(s.toString()+"-"+e.toString()); + } + }; + let dateList = _.reduce(srcDateList, function(res, d, i) { + if(start === null) { + start = end = d; + } + if(d > (end + 1)) { + pushValues(start, end, res); + start = end = d; + } else { + end = d; + } + if(i === (srcDateList.length - 1)) { + pushValues(start, end, res); + } + return res; + }, []); + if(dateList.length === 0) { + dateList = null; + } + this.set('date', dateList); + return srcDateList; + } + }), }); diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/app/styles/tabs/chrono.scss --- a/cms/app-client/app/styles/tabs/chrono.scss Fri Nov 04 19:03:25 2016 +0100 +++ b/cms/app-client/app/styles/tabs/chrono.scss Sun Nov 06 03:44:16 2016 +0100 @@ -25,8 +25,8 @@ margin: 0px; padding: 0px; font-size: 0px; + float: right; display: inline-block; - float: right; } #chrono-table li { @@ -43,8 +43,21 @@ box-sizing: border-box; } +#chrono-table li.disabled { + cursor: default; + color: $corpus-grey; +} + #chrono-table li.highlighted { font-weight: bold; color: $corpus-white; background-color: $corpus-blue; } + +#chrono-table li.light-color { + color: $corpus-white; +} + +#chrono-table li.dark-color { + color: $corpus-black; +} diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/app/templates/components/visu-chrono-year.hbs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cms/app-client/app/templates/components/visu-chrono-year.hbs Sun Nov 06 03:44:16 2016 +0100 @@ -0,0 +1,1 @@ +{{ year }} diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/app/templates/components/visu-chrono.hbs --- a/cms/app-client/app/templates/components/visu-chrono.hbs Fri Nov 04 19:03:25 2016 +0100 +++ b/cms/app-client/app/templates/components/visu-chrono.hbs Sun Nov 06 03:44:16 2016 +0100 @@ -1,90 +1,10 @@ -
- {{input type="checkbox" checked=(is-checked date 1960) indeterminate=(is-indeterminate date 1960) click=(action 'selectDecade' 1960)}} - -
+{{#each decades as |decade| }}
- {{input type="checkbox" checked=(is-checked date 1970) indeterminate=(is-indeterminate date 1970) click=(action 'selectDecade' 1970)}} - -
-
- {{input type="checkbox" checked=(is-checked date 1980) indeterminate=(is-indeterminate date 1980) click=(action 'selectDecade' 1980)}} -
-
- {{input type="checkbox" checked=(is-checked date 1990) indeterminate=(is-indeterminate date 1990) click=(action 'selectDecade' 1990)}} - -
-
- {{input type="checkbox" checked=(is-checked filter.date 2000) indeterminate=(is-indeterminate filter.date 2000) click=(action 'selectDecade' 2000)}} - -
-
- {{input type="checkbox" checked=(is-checked date 2010) indeterminate=(is-indeterminate filter.date 2010) click=(action 'selectDecade' 2010)}} - -
+{{/each}} \ No newline at end of file diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/app/templates/tabs/chrono.hbs --- a/cms/app-client/app/templates/tabs/chrono.hbs Fri Nov 04 19:03:25 2016 +0100 +++ b/cms/app-client/app/templates/tabs/chrono.hbs Sun Nov 06 03:44:16 2016 +0100 @@ -1,4 +1,4 @@

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.

- {{ visu-chrono range=model.range }} + {{ visu-chrono range=model.range rawdatestats=model.datestats }}
diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/bower.json --- a/cms/app-client/bower.json Fri Nov 04 19:03:25 2016 +0100 +++ b/cms/app-client/bower.json Sun Nov 06 03:44:16 2016 +0100 @@ -13,6 +13,7 @@ "lodash": "~4.11.1", "Faker": "~3.1.0", "store": "https://github.com/marcuswestin/store.js.git#v1.3.20", - "popcorn-js": "popcornjs#^1.5.11" + "popcorn-js": "popcornjs#^1.5.11", + "chroma-js": "gka/chroma.js#master" } } diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/ember-cli-build.js --- a/cms/app-client/ember-cli-build.js Fri Nov 04 19:03:25 2016 +0100 +++ b/cms/app-client/ember-cli-build.js Sun Nov 06 03:44:16 2016 +0100 @@ -29,9 +29,12 @@ // along with the exports of each module as its value. app.import('bower_components/popcorn-js/popcorn.js'); app.import('bower_components/ammap3/ammap/ammap.js'); + app.import('bower_components/chroma-js/chroma.js'); app.import('vendor/data/maps/worldLow.js'); app.import('vendor/data/maps/continentsLow.js'); app.import('vendor/data/maps/france2016Low.js'); + + //shims app.import('vendor/shims/ammaps.js', { exports: { 'ammaps': ['defaults'] @@ -42,6 +45,12 @@ 'popcorn': ['defaults'] } }); + app.import('vendor/shims/chroma.js', { + exports: { + 'chroma': ['defaults'] + } + }); + return app.toTree(); }; diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/tests/integration/components/visu-chrono-year-test.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cms/app-client/tests/integration/components/visu-chrono-year-test.js Sun Nov 06 03:44:16 2016 +0100 @@ -0,0 +1,24 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('visu-chrono-year', 'Integration | Component | visu chrono year', { + 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`{{visu-chrono-year}}`); + + assert.equal(this.$().text().trim(), ''); + + // Template block usage: + this.render(hbs` + {{#visu-chrono-year}} + template block text + {{/visu-chrono-year}} + `); + + assert.equal(this.$().text().trim(), 'template block text'); +}); diff -r 4fbe94af93e8 -r 5ef3bfef0bff cms/app-client/vendor/shims/chroma.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cms/app-client/vendor/shims/chroma.js Sun Nov 06 03:44:16 2016 +0100 @@ -0,0 +1,9 @@ +(function() { + function vendorModule() { + 'use strict'; + + return { 'default': self['chroma'] }; + } + + define('chroma', [], vendorModule); +})();