# HG changeset patch # User ymh # Date 1481280075 -3600 # Node ID 762fc0eb494689674bde51817f400dcba033374e # Parent a8effb60ccb67336ab4b857c957855ad0b4260bc Migrate d3js to v4 and correct d3js visualisations i.e. bug 3.20. Breadcrumb navigation for the language treemap has been improved diff -r a8effb60ccb6 -r 762fc0eb4946 build/build.sh --- a/build/build.sh Sun Dec 04 13:49:44 2016 +0100 +++ b/build/build.sh Fri Dec 09 11:41:15 2016 +0100 @@ -16,34 +16,34 @@ } function install() { - pushd "$DIR" + pushd "$DIR" > /dev/null echoblue "---> preparing bo client" - pushd ../server/bo_client + pushd ../server/bo_client > /dev/null /usr/local/bin/npm install ./node_modules/.bin/bower install - popd + popd > /dev/null echoblue "---> preparing bo client done" echoblue "---> preparing back" - pushd ../server/src + pushd ../server/src > /dev/null php composer.phar install /usr/local/bin/npm install ./node_modules/.bin/bower install - popd + popd > /dev/null echoblue "---> preparing back done" echoblue "---> preparing app-client" - pushd ../cms/app-client + pushd ../cms/app-client > /dev/null /usr/local/bin/npm install ./node_modules/.bin/bower install - popd + popd > /dev/null echoblue "---> preparing app-client done" echoblue "---> preparing module" - pushd ../cms + pushd ../cms > /dev/null npm install - popd + popd > /dev/null echoblue "---> preparing module done" @@ -111,7 +111,7 @@ echo "do_install: $do_install" [[ "$do_install" == true ]] && echoblue "DO INSTALL" && install; -pushd "$DIR" +pushd "$DIR" > /dev/null echoblue "---> cleaning build folder" rm -fr root @@ -121,28 +121,28 @@ mkdir -p root/var/www/corpusdelaparole/drupal/sites/all/modules echoblue "---> building back" -pushd ../server/src +pushd ../server/src > /dev/null version=$(sed -n "s/[[:space:]]*\'version\'[[:space:]]*=>[[:space:]]*\'\([\.0-9]*\)\'/\1/p" config/version.php) version=${version:-0.0.0} npm install ./node_modules/.bin/bower install ./node_modules/.bin/gulp copy-build ${build_option_back} -popd +popd > /dev/null echoblue "---> building back done" echoblue "---> building app-client" -pushd ../cms/app-client +pushd ../cms/app-client > /dev/null npm install ./node_modules/.bin/bower install ./node_modules/.bin/ember build ${build_option} -popd +popd > /dev/null echoblue "---> building app-client done" echoblue "---> building module" -pushd ../cms +pushd ../cms > /dev/null npm install ./node_modules/.bin/gulp copy-build ${build_option} --version="$version" -popd +popd > /dev/null echoblue "---> building package" vagrant ssh -c "/vagrant/build_rpm.sh" @@ -156,5 +156,22 @@ popd > /dev/null +echoblue "--> archiving dist" + +pushd "$DIR/dist" > /dev/null + +rm -f corpusdelaparole-back_*_*.tar.gz +ARCHIVE_NAME="corpusdelaparole-back_$(date +%Y-%m-%d)_${version}" + +mkdir "$ARCHIVE_NAME" + +cp bootstrap-puppet.sh corpusdelaparole-$version-*.noarch.rpm installDrupal.sh puppet-corpusdelaparole-$version-*.noarch.rpm "$ARCHIVE_NAME" + +tar zcvf "${ARCHIVE_NAME}.tar.gz" "$ARCHIVE_NAME" + +rm -fr "$ARCHIVE_NAME" + +popd > /dev/null + echoblue "---> done" diff -r a8effb60ccb6 -r 762fc0eb4946 build/build_puppet.sh --- a/build/build_puppet.sh Sun Dec 04 13:49:44 2016 +0100 +++ b/build/build_puppet.sh Fri Dec 09 11:41:15 2016 +0100 @@ -98,5 +98,28 @@ popd > /dev/null +echoblue "--> archiving dist" + +pushd ../server/src > /dev/null +version=$(sed -n "s/[[:space:]]*\'version\'[[:space:]]*=>[[:space:]]*\'\([\.0-9]*\)\'/\1/p" config/version.php) +version=${version:-0.0.0} +popd > /dev/null + +pushd "$DIR/dist" > /dev/null + +rm -f corpusdelaparole-back_*_*.tar.gz +ARCHIVE_NAME="corpusdelaparole-back_$(date +%Y-%m-%d)_${version}" + +mkdir "$ARCHIVE_NAME" + +cp bootstrap-puppet.sh corpusdelaparole-$version-*.noarch.rpm installDrupal.sh puppet-corpusdelaparole-$version-*.noarch.rpm "$ARCHIVE_NAME" + +tar zcvf "${ARCHIVE_NAME}.tar.gz" "$ARCHIVE_NAME" + +rm -fr "$ARCHIVE_NAME" + +popd > /dev/null + + echoblue "---> done" diff -r a8effb60ccb6 -r 762fc0eb4946 cms/app-client/app/adapters/application.js --- a/cms/app-client/app/adapters/application.js Sun Dec 04 13:49:44 2016 +0100 +++ b/cms/app-client/app/adapters/application.js Fri Dec 09 11:41:15 2016 +0100 @@ -7,7 +7,8 @@ datestat: 'stats/datestats', dateminmax: 'stats/dateminmax', theme: 'stats/themes', - discourse: 'stats/discourses' + discourse: 'stats/discourses', + language: 'stats/languages' }; export default RESTAdapter.extend({ diff -r a8effb60ccb6 -r 762fc0eb4946 cms/app-client/app/components/discourses-component.js --- a/cms/app-client/app/components/discourses-component.js Sun Dec 04 13:49:44 2016 +0100 +++ b/cms/app-client/app/components/discourses-component.js Fri Dec 09 11:41:15 2016 +0100 @@ -1,13 +1,18 @@ import Ember from 'ember'; -import d3 from 'd3'; +import * as d3 from 'd3-selection'; +import * as d3h from 'd3-hierarchy'; +import * as d3s from 'd3-scale'; import _ from 'lodash/lodash'; +const MINIMUM_CIRCLE_WIDTH = 60.0; + export default Ember.Component.extend({ classNames: ['discourses-component'], constants: Ember.inject.service(), filter: Ember.inject.service(), + utils: Ember.inject.service(), discourseObserver: Ember.observer('filter.discourse', function() { Ember.$('.item').removeClass("selected"); @@ -25,22 +30,36 @@ var discourses = this.get('discourses'); var array = discourses.map(function (d) { return d.get('count'); }); - var oldMin = Math.min(...array), - oldMax = Math.max(...array); - var sum = array.reduce(function(a, b) { return a + b; }); - var average = sum / array.length; - var newMin = Math.floor((average - oldMin)), - newMax = Math.floor((oldMax - average)); var width = self.$().parent().width(); var height = self.$().parent().height() - self.$().siblings().outerHeight(true); - var bubble = d3.layout.pack() - .sort(function comparator(a, b) { return a.value + b.value; }) + //Determine the minimum circle width + var longerStr = _.max( + [].concat(...(discourses.map(function(d) { return d.get('label').split(' ');}))), + function(s) { return s.length; } + ); + var w = this.get('utils').getWidthOfText(longerStr, '11px'); + // we try to take into account the fact that there is at least 2 lines + var minimum_circle_width = Math.max( Math.sqrt((w*w)+Math.pow(11+11/2, 2)) + 10, MINIMUM_CIRCLE_WIDTH); + + // to avoid division by zero. In any case it makes no sense to consider dimensions + // under MINIMUM_CIRCLE_WIDTH + var scaleFactor = minimum_circle_width/Math.max(minimum_circle_width, Math.min(width, height)); + + var min = Math.min(...array), + max = Math.max(...array); + + var scale = d3s.scaleLinear(); + // The range is the range for font sizes + var fontScale = d3s.scaleQuantize().domain([min, max]).range(_.range(10, 14)); + + if((min/max) < scaleFactor) { + scale = scale.domain([min, max]).range([scaleFactor, 1]); + } + + var bubble = d3h.pack() .size([width, height]) - .value(function(d){ - return Math.floor((((d.value - oldMin) * (newMax - newMin)) / (oldMax - oldMin)) + newMin); - }) .padding(10); var element = d3.select('#' + self.get('elementId')) @@ -49,8 +68,10 @@ .style('position','absolute') .style('left', -100000); - var bubbles = bubble.nodes(self.createNodes()); + var root = d3h.hierarchy(self.createNodes()) + .sum(function(d) {return scale(d.value);}); + var bubbles = bubble(root).descendants(); var nodes = element .selectAll() .data(bubbles); @@ -59,20 +80,20 @@ .attr("class", function(d) { return ( d.children ? "category": "item" ) + ( (self.get('filter').get('discourse') !== null && _.contains(self.get('filter').get('discourse'), d.id)) ? " selected" : "" ) ; }); var item = element.selectAll(".item") - .attr("data-id", function(d) { return d.id; }) + .attr("data-id", function(d) { return d.data.id; }) .style("left", function(d) { return ( d.x - d.r) + "px"; }) .style("top", function(d) { return ( d.y - d.r) + "px"; }) .style("width", function(d) { return (d.r * 2) + "px"; }) .style("height", function(d) { return (d.r * 2) + "px"; }) - .style("background-color", function(d) { return d.fill; }) - .style("border-color", function(d) { return d.stroke; }) - .style("font-size", function(d) { return Math.floor((((d.value - oldMin) * (13 - 10)) / (oldMax - oldMin)) + 10) + 'px'; }) + .style("background-color", function(d) { return d.data.fill; }) + .style("border-color", function(d) { return d.data.stroke; }) + .style("font-size", function(d) { return fontScale(d.data.count) + 'px'; }) .on('click', function(d) { - self.get('filter').setFilter('discourse', d.id); + self.get('filter').setFilter('discourse', d.data.id); }); item.append("span") - .html(function(d) { return d.name + ' (' + d.count + ')'; }) + .html(function(d) { return d.data.name + ' (' + d.data.count + ')'; }) .style("margin-left", function() { return ( Ember.$(this).width() > Ember.$(this).parent().width() ? - ( Ember.$(this).width() / 2 ) + ( Ember.$(this).parent().width() / 2 ) : 0 ) + 'px'; }) .style("margin-top", function() { return Ember.$(this).parent().height() / 2 - Ember.$(this).height() / 2 + 'px'; }); diff -r a8effb60ccb6 -r 762fc0eb4946 cms/app-client/app/components/visu-langues.js --- a/cms/app-client/app/components/visu-langues.js Sun Dec 04 13:49:44 2016 +0100 +++ b/cms/app-client/app/components/visu-langues.js Fri Dec 09 11:41:15 2016 +0100 @@ -1,221 +1,237 @@ import Ember from 'ember'; -import d3 from 'd3'; -import ENV from 'app-client/config/environment'; +import * as d3 from 'd3-selection'; +import * as d3h from 'd3-hierarchy'; +import * as d3s from 'd3-scale'; +import * as d3t from 'd3-transition'; +import * as d3e from 'd3-ease'; import _ from 'lodash/lodash'; -import URI from 'urijs'; +// inspired by http://bl.ocks.org/ganeshv/6a8e9ada3ab7f2d88022 +// and https://bost.ocks.org/mike/treemap/ export default Ember.Component.extend({ - constants: Ember.inject.service(), - filter: Ember.inject.service(), - colors: Ember.inject.service(), + constants: Ember.inject.service(), + filter: Ember.inject.service(), + colors: Ember.inject.service(), + utils: 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"); - }), + 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, - didInsertElement: function(){ - var self = this; - var baseurl = (ENV.APP.backRootURL || ENV.rootURL).replace(/\/$/,"")+'/api/v1'; - var url = URI(baseurl+"/stats/languages").search(this.get('filter').get('queryParamsValuesURI')); + firstRender: true, + + filterLanguageObserver: Ember.observer('filter.language', function () { + Ember.$('.node').removeClass("selected"); + Ember.$('.node[data-id="' + this.get('filter').get('language') + '"]').addClass("selected"); + }), - d3.json(url.href(), function(data) { - var margin = { top: 30, right: 0, bottom: 0, left: 0 }; - var width = Ember.$('#' + self.get('elementId')).width(); - var height = Ember.$('#' + self.get('elementId')).height() - margin.top - margin.bottom; + filterOtherModified: false, - var languages = data['languages']; - var array = Object.keys(languages).map(function (key) { return languages[key]; }); - var oldMin = Math.min(...array), - oldMax = Math.max(...array); - var sum = array.reduce(function(a, b) { return a + b; }); - var average = sum / array.length; - var newMin = Math.floor((average - oldMin)), - newMax = Math.floor((oldMax - average)); + filterOtherObserver: Ember.observer('filter.date.[]', 'filter.discourse.[]', 'filter.theme.[]', 'filter.location', function() { + this.set('filterOtherModified', true); + this.set('firstRender', true); + }), - var x = d3.scale.linear() - .domain([0, width]) - .range([0, width]), - y = d3.scale.linear() - .domain([0, height]) - .range([0, height]); + didRender: function () { - var treemap = d3.layout.treemap() - .children(function(d, depth) { return depth ? null : d._children; }) - .sort(function(a, b) { return a.value - b.value; }) - .value(function(d){ - return Math.floor((((d.value - oldMin) * (newMax - newMin)) / (oldMax - oldMin)) + newMin); - }) - .round(false); + if(!this.get('filterOtherModified') && !this.get('firstRender')) { + return; + } + this.set('firstRender', false); + this.set('filterOtherModified', false); + var self = this; - var element = d3.select('#' + self.get('elementId')) - .style("width", width + margin.left + margin.right + 'px') - .style("height", height + margin.bottom + margin.top + 'px') - .style("margin-left", -margin.left + "px") - .style("margin-right", -margin.right + "px") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")") - .style("shape-rendering", "crispEdges"); + var margin = { top: 30, right: 0, bottom: 0, left: 0 }; + var width = Ember.$('#' + this.get('elementId')).width(); + var height = Ember.$('#' + this.get('elementId')).height() - margin.top - margin.bottom; + var ratio = (1+Math.sqrt(5))/2; - var breadcrumbs = element.insert("div", ":first-child") - .attr("class", "breadcrumbs") - .attr("y", -margin.top) - .style("width", width + 'px') - .style("height", margin.top + 'px'); + var languages = this.get('languages'); + var languagesMap = languages.reduce(function (res, l) { res[l.get('id')] = l.get('count'); return res; }, {}); - var root = _.cloneDeep(self.constants.LANGUAGES_TREEMAP); - root.x = root.y = 0; - root.dx = width; - root.dy = height; - root.depth = 0; - var transitioning = false; - - accumulate(root); - layout(root); - display(root); + var treemap = d3h.treemap() + .size([width/ratio, height]) + .tile(d3h.treemapSquarify.ratio(1)); - function accumulate(d) { - d._children = d.children; - if(d.children) { - d.value = d.children.reduce(function(p, v) { return p + accumulate(v); }, 0); - } else if (d.values) { - d.value = d.values.reduce(function(p, v) { return p + (languages[v] ? languages[v] : 0); }, 0); - } else { - d.value = languages[d.id] ? languages[d.id] : 0; - } - return d.value; - } + var element = d3.select('#' + this.get('elementId')) + .style("width", width + margin.left + margin.right + 'px') + .style("height", height + margin.bottom + margin.top + 'px') + .style("margin-left", -margin.left + "px") + .style("margin-right", -margin.right + "px"); + + var breadcrumbs = element.select("div.breadcrumbs"); - function layout(d) { - if (d._children) { - treemap.nodes({_children: d._children}); - d._children.forEach(function(c) { - function getCount(node, count = 0) { - var c = languages[node.id]; - if(typeof c === 'undefined') { - if(node._children) { - node._children.forEach(function(child) { - count = getCount(child, count); - }); - } else if(node.values) { - count = node.values.reduce(function(p, v) { return p + (languages[v] ? languages[v] : 0); }, count); - } - return count; - } else { - return count + c; - } - } - c.count = getCount(c); - c.x = d.x + c.x * d.dx; - c.y = d.y + c.y * d.dy; - c.dx *= d.dx; - c.dy *= d.dy; - c.parent = d; - layout(c); - }); - } - } + if(breadcrumbs.empty()) { + breadcrumbs = element.insert("div", ":first-child") + .attr("class", "breadcrumbs") + .attr("y", -margin.top) + .style("width", width + 'px') + .style("height", margin.top + 'px'); + } + + var root = _.cloneDeep(this.constants.LANGUAGES_TREEMAP); + + function ancestors(d) { + let ancestors = []; + let currentNode = d; + while (currentNode.parent) { + ancestors.unshift(currentNode = currentNode.parent); + } + return ancestors; + } - function position() { - return this.style("width", function(d) { return x(d.x + d.dx) - x(d.x) + 'px'; }) - .style("height", function(d) { return y(d.y + d.dy) - y(d.y) + 'px'; }) - .style("left", function(d) { return x(d.x) + 'px'; }) - .style("top", function(d) { return y(d.y) + 'px'; }); - } - - function display(d) { - breadcrumbs - .datum(d.parent) - .html(name(d)) - .on("click", transition); - - var nodes = element.append("div") - .attr("class", "nodes") - .datum(d); + // This function set the count and parent attributes + function decorateData(d) { + if (d.children) { + d.count = d.children.reduce(function (p, v) { v.parent = d; return p + decorateData(v); }, 0); + } else if (d.values) { + d.count = d.values.reduce(function (p, v) { return p + (languagesMap[v] ? languagesMap[v] : 0); }, 0); + } else { + d.count = languagesMap[d.id] ? languagesMap[d.id] : 0; + } + return d.count; + } + decorateData(root); - var node = nodes.selectAll() - .data(d._children) - .enter() - .append("div") - .attr("data-id", function(d) { return d.id; }); - - 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 " + colorClass(_d) + ( _d.id === self.get('filter').get('language') ? " selected" : "" ); }) - .call(position) - .style("background-color", backgroundColor) - .on("click", selectHandler); - - node.filter(function(d) { return d._children; }) - .classed("children", true) - .on("click", transition) - .append("i") - .attr("class", "fa fa-folder-o"); - - node.append("span") - .html(function(d) { return d.name + ' (' + d.count + ')'; }); + // Clean tree with empty nodes + function cleanTree(n) { + if(n.children) { + n.children = n.children.filter(function(c) { return c.count !== 0;}); + n.children.forEach(function(c) { + cleanTree(c); + }); + } + } + cleanTree(root); - function transition(d) { - if (transitioning || !d) { - return; - } + var transitioning = false; - selectHandler(d); - transitioning = true; - - var newNode = display(d), - transitionNodes = node.transition().duration(750), - transitionNewNodes = newNode.transition().duration(750); + display(root, 1); - x.domain([d.x, d.x + d.dx]); - y.domain([d.y, d.y + d.dy]); - - element.style("shape-rendering", null); + function transition(d, node, nodeWrapper) { + if (transitioning || !d) { + return; + } - element.selectAll(".node").sort(function(a, b) { return a.depth - b.depth; }); - - newNode.selectAll().style("fill-opacity", 0); - - transitionNodes.style("opacity", 0) - .call(position); + selectHandler(d); + transitioning = true; - transitionNewNodes.style("opacity", 1) - .call(position); - - transitionNodes.remove().each("end", function() { - element.style("shape-rendering", "crispEdges"); - transitioning = false; - }); - } + var t = d3t.transition().duration(750).ease(d3e.easeLinear); + var newNode = display(d, 0); + var transitionNodes = node.transition(t); + var transitionNewNodes = newNode.transition(t); - function selectHandler (d){ - if (d.id){ - self.get('filter').setFilter('language', d.id); - } - } + newNode.style("fill-opacity", 0); + transitionNodes.style("opacity", 0).remove().on("end", function () { + nodeWrapper.remove(); + transitioning = false; + }); + transitionNewNodes.style("opacity", 1); - return node; - } - - function name(d) { - return d.parent ? name(d.parent) + '' + d.name + '' : '' + d.name + ''; - } - - }); } + function selectHandler(d) { + if (d.id) { + self.get('filter').setFilter('language', d.id); + } + } + + function display(rData, opacity) { + + var countArray = rData.children.map(function (d) { return d.count; }); + var dMin = Math.min.apply(null, countArray); + var dMax = Math.max.apply(null, countArray); + var globalMin = rData.children.reduce(function minRec(m, c) { + if(c.count < m) { + m = c.count; + } + if(c.children) { + m = c.children.reduce(minRec, m); + } + return m; + }, dMax); + var dataScale = d3s.scaleLinear().domain([globalMin, dMax]).range([globalMin, dMax]); + + var nameArray = rData.children.reduce(function (res, d) { + res = res.concat(d.name.split(/[\s\-]/)); + return res; + }, ["(nnnnn)"]).sort(function(a,b) { return b.length - a.length; }); + + var w = self.get('utils').getWidthOfText(nameArray[0], '11px'); + var p = w*w/(width*height); + + if(dMin/dMax < p) { + dataScale = dataScale.range([p*100,100]); + } + + var rNode = d3h.hierarchy(rData) + .sum(function (d) { return (d.children) ? 0 : dataScale(d.count); }) + .sort(function (a, b) { return b.value - a.value; }); + + self.setProperties({ minCount: dMin, maxCount: dMax }); + var scale = self.get('scale'); + var backgroundColor = function (_d) { return scale(_d.data.count); }; + var colorClass = function (_d) { return (self.get('colors').getPerceptiveLuminance(backgroundColor(_d)) >= 0.5) ? 'light-color' : 'dark-color'; }; + + var nodeWrapper = element.append("div") + .attr("class", "nodes") + .datum(rNode); + + var descendants = treemap(rNode).descendants().filter(function (c) { return c.depth === rNode.depth + 1; }); + + var node = nodeWrapper.selectAll() + .data(descendants) + .enter() + .append("div") + .attr("data-id", function (d) { return d.data.id; }); + + + node.attr("class", function (_d) { return "node " + colorClass(_d) + (_d.id === self.get('filter').get('language') ? " selected" : ""); }) + .style("width", function (d) { return (Math.round(d.x1 * ratio) - Math.round(d.x0 * ratio)) + 'px'; }) + .style("height", function (d) { return (d.y1 - d.y0) + 'px'; }) + .style("left", function (d) { return Math.round(d.x0*ratio) + 'px'; }) + .style("top", function (d) { return d.y0 + 'px'; }) + .style("background-color", backgroundColor) + .style('opacity', opacity) + .attr('title', function (d) { return d.data.name + ' (' + d.data.count + ')'; }) + .on("click", function (d) { selectHandler(d.data); }); + + node.filter(function (d) { return d.children; }) + .classed("children", true) + .on("click", function (d) { transition(d.data, node, nodeWrapper); }) + .append("i") + .attr("class", "fa fa-folder-o"); + + node.append("span") + .html(function (d) { return d.data.name + ' (' + d.data.count + ')'; }); + + breadcrumbs + .selectAll("span") + .remove(); + let i = 0; + ancestors(rNode.data).forEach(function (a) { + breadcrumbs + .append("span") + .attr('class', (i++) ? "level" : "root") + .html(a.name) + .datum(a) + .on("click", function (d) { transition(d, node, nodeWrapper); }); + }); + breadcrumbs + .append("span") + .attr('class', (i) ? "level" : "root") + .html(rNode.data.name) + .datum(rNode.data); + + return node; + } + + } + }); diff -r a8effb60ccb6 -r 762fc0eb4946 cms/app-client/app/helpers/annotation-content.js --- a/cms/app-client/app/helpers/annotation-content.js Sun Dec 04 13:49:44 2016 +0100 +++ b/cms/app-client/app/helpers/annotation-content.js Fri Dec 09 11:41:15 2016 +0100 @@ -1,7 +1,7 @@ import Ember from 'ember'; export function annotationContent(params/*, hash*/) { - if(!params || params.length==0) { + if(!params || (params.length === 0)) { return ""; } diff -r a8effb60ccb6 -r 762fc0eb4946 cms/app-client/app/models/language.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cms/app-client/app/models/language.js Fri Dec 09 11:41:15 2016 +0100 @@ -0,0 +1,5 @@ +import DS from 'ember-data'; + +export default DS.Model.extend({ + count: DS.attr('number') +}); diff -r a8effb60ccb6 -r 762fc0eb4946 cms/app-client/app/models/transcript.js --- a/cms/app-client/app/models/transcript.js Sun Dec 04 13:49:44 2016 +0100 +++ b/cms/app-client/app/models/transcript.js Fri Dec 09 11:41:15 2016 +0100 @@ -2,8 +2,8 @@ export default DS.Model.extend({ - title: DS.attr(), - annotations: DS.attr(), - sections: DS.attr(), - + title: DS.attr(), + annotations: DS.attr(), + sections: DS.attr(), + }); diff -r a8effb60ccb6 -r 762fc0eb4946 cms/app-client/app/routes/tabs/langues.js --- a/cms/app-client/app/routes/tabs/langues.js Sun Dec 04 13:49:44 2016 +0100 +++ b/cms/app-client/app/routes/tabs/langues.js Fri Dec 09 11:41:15 2016 +0100 @@ -2,10 +2,15 @@ export default Ember.Route.extend({ - player: Ember.inject.service(), + player: Ember.inject.service(), + filter: Ember.inject.service(), - activate: function() { - this.get('player').set('window', false); - } + model() { + return this.get('store').query('language', this.get('filter').get('queryParamsValues')); + }, + + activate() { + this.get('player').set('window', false); + } }); diff -r a8effb60ccb6 -r 762fc0eb4946 cms/app-client/app/serializers/language.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cms/app-client/app/serializers/language.js Fri Dec 09 11:41:15 2016 +0100 @@ -0,0 +1,22 @@ +import DS from 'ember-data'; + +export default DS.JSONSerializer.extend({ + + normalizeResponse: function(store, primaryModelClass, payload) { + var data = []; + var languages = payload['languages']; + Object.keys(languages).forEach(function(key) { + data.push({ + 'id': key, + 'type': 'language', + 'attributes': { + 'count': languages[key] + } + }); + }); + return { + 'data': data + }; + } + +}); diff -r a8effb60ccb6 -r 762fc0eb4946 cms/app-client/app/services/utils.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cms/app-client/app/services/utils.js Fri Dec 09 11:41:15 2016 +0100 @@ -0,0 +1,27 @@ + +import Ember from 'ember'; + +export default Ember.Service.extend({ + + // inspired by http://stackoverflow.com/a/39089679 + getWidthOfText(txt, fontsize){ + // Create dummy span + var e = document.createElement('span'); + + // set the base font defined in app.scss + //e.className = 'base-font'; + e.style.fontFamily = 'sans-serif'; + // Set font-size + e.style.fontSize = fontsize; + // Set text + e.innerHTML = txt; + // Return width + e.style.visibility = 'hidden'; + + document.body.appendChild(e); + let w = e.offsetWidth; + document.body.removeChild(e); + + return w; + } +}); diff -r a8effb60ccb6 -r 762fc0eb4946 cms/app-client/app/styles/app.scss --- a/cms/app-client/app/styles/app.scss Sun Dec 04 13:49:44 2016 +0100 +++ b/cms/app-client/app/styles/app.scss Fri Dec 09 11:41:15 2016 +0100 @@ -36,8 +36,12 @@ outline:0; } +.base-font { + font-family: sans-serif; +} + #corpus-app { - font-family: sans-serif; + @extend .base-font; font-size: 12px; line-height: initial; } diff -r a8effb60ccb6 -r 762fc0eb4946 cms/app-client/app/styles/tabs/langues.scss --- a/cms/app-client/app/styles/tabs/langues.scss Sun Dec 04 13:49:44 2016 +0100 +++ b/cms/app-client/app/styles/tabs/langues.scss Fri Dec 09 11:41:15 2016 +0100 @@ -5,71 +5,70 @@ #tabs-langues .breadcrumbs, #tabs-langues .node { - cursor: pointer; + cursor: pointer; } #tabs-langues .breadcrumbs:hover, #tabs-langues .node:hover, #tabs-langues .node.selected { - background-color: $corpus-blue!important; - color: $corpus-white!important; + background-color: $corpus-blue!important; + color: $corpus-white!important; } #tabs-langues .breadcrumbs { - background-color: $corpus-white; + background-color: $corpus-white; color: $corpus-black; position: relative; - line-height: 30px; - padding: 0 10px; - border-bottom: 1px solid $corpus-white; - box-sizing: border-box; + line-height: 30px; + padding: 0 10px; + border-bottom: 1px solid $corpus-white; + box-sizing: border-box; } #tabs-langues .breadcrumbs .root:only-child { - font-weight: bold; + font-weight: bold; } #tabs-langues .breadcrumbs .level::before { - content: '>'; - margin: 0 10px; - font-weight: normal; + content: '>'; + margin: 0 10px; + font-weight: normal; } #tabs-langues .breadcrumbs .level:last-child { - font-weight: bold; + font-weight: bold; } #tabs-langues .nodes { - width: inherit; - position: absolute; + width: inherit; + position: absolute; } #tabs-langues .node { - position: absolute; - margin: 0; - padding: 0; - border-left: 1px solid $corpus-white; - border-bottom: 1px solid $corpus-white; - padding: 10px; - box-sizing: border-box; - color: $corpus-white; + position: absolute; + margin: 0; + border-left: 1px solid $corpus-white; + border-bottom: 1px solid $corpus-white; + padding: 5px; + box-sizing: border-box; + color: $corpus-white; } #tabs-langues .node:hover { - border-right: none; + border-right: none; } #tabs-langues .node .fa { - margin-right: 5px; + margin-right: 5px; } #tabs-langues .node .fa::before { - font-size: 14px; - line-height: 12px; + font-size: 14px; + line-height: 12px; } #tabs-langues .node .count { - font-weight: bold; + font-weight: bold; } #tabs-langues .light-color { diff -r a8effb60ccb6 -r 762fc0eb4946 cms/app-client/app/templates/tabs/langues.hbs --- a/cms/app-client/app/templates/tabs/langues.hbs Sun Dec 04 13:49:44 2016 +0100 +++ b/cms/app-client/app/templates/tabs/langues.hbs Fri Dec 09 11:41:15 2016 +0100 @@ -1,3 +1,3 @@
- {{visu-langues}} + {{visu-langues languages=model}}
\ No newline at end of file diff -r a8effb60ccb6 -r 762fc0eb4946 cms/app-client/ember-cli-build.js --- a/cms/app-client/ember-cli-build.js Sun Dec 04 13:49:44 2016 +0100 +++ b/cms/app-client/ember-cli-build.js Fri Dec 09 11:41:15 2016 +0100 @@ -2,6 +2,7 @@ /* global require, module */ var EmberApp = require('ember-cli/lib/broccoli/ember-app'); + module.exports = function(defaults) { var app = new EmberApp(defaults, { // Add options here diff -r a8effb60ccb6 -r 762fc0eb4946 cms/app-client/mirage/config.js --- a/cms/app-client/mirage/config.js Sun Dec 04 13:49:44 2016 +0100 +++ b/cms/app-client/mirage/config.js Fri Dec 09 11:41:15 2016 +0100 @@ -31,34 +31,44 @@ return transcripts.find(id).transcript; }); - this.get('/stats/languages', 'languages'); + this.get('/stats/languages', ({languages}, request) => { + let qParams = request.queryParams['discourse']; + if(qParams) { + var res = []; + let allLanguages = languages.all().models; + let i=0; + while(i { - console.log("DISCOURSES", request.queryParams, discourses.all(), discourses.all().models); - if(request.queryParams['discourse']) { + let qParams = request.queryParams['discourse']; + if(qParams) { var res = []; - request.queryParams.discourse.forEach( did => { - let d = discourses.find(did); - if(d) { - res.push(d); - } - }); let allDiscourses = discourses.all().models; let i=0; - while(i