merge two heads
authornowmad@23.1.168.192.in-addr.arpa
Fri, 22 Jan 2016 14:31:17 +0100
changeset 101 9fb98e5f1b42
parent 100 1f93330f9d42 (diff)
parent 32 9765cf7cf817 (current diff)
child 102 976962b53ab9
merge two heads
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/adapters/application.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,8 @@
+import DS from 'ember-data';
+
+// export { default } from 'ember-data-fixture-adapter';
+
+export default DS.RESTAdapter.extend({
+  host: 'http://127.0.0.1:8000',
+  namespace: 'api',
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/components/player-component.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,122 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+  classNames: ['player-component'],
+  currentTime: "00:00",
+  duration: "00:00",
+  documentLoaded: Ember.observer('document.mediaArray', function() {
+    var mediaList = this.get('document').get("mediaList");
+    if ((typeof(mediaList) !== 'undefined') && (mediaList.length > 0)){
+      if (this.audio.src){
+        this.pause();
+        this.updateProgress(0);
+      }
+      var mp3 = mediaList.findBy('format', 'audio/mpeg');
+      this.audio.src = mp3.url;
+      this.audio.load();
+      this.set("currentTime", "00:00");
+    }
+
+  }),
+
+  didInsertElement: function(){
+    var _this = this;
+
+    this.audio = new Audio();
+
+    this.button = {
+      play: this.$('#action_play'),
+      progress: this.$('.progress')
+    };
+
+		this.$(document).on('touchmove', function(e){
+			e.preventDefault();
+		});
+
+		// seeker
+		this.button.progress.on('mousedown', function(e){
+			var r = _this.rotation(e.pageX, e.pageY);
+			_this.updateProgress(r);
+			_this.changeTime(r/360*100);
+		});
+
+    this.audio.addEventListener('loadedmetadata',function (){
+      var minutes = Math.floor( _this.audio.duration / 60);
+      var seconds =  Math.floor(_this.audio.duration) % 60;
+      _this.set('duration', ('0' + minutes).slice(-2)+':'+('0' + seconds).slice(-2));
+    });
+
+		// update bar onchange
+		this.audio.addEventListener('timeupdate',function (){
+			var curtime = _this.audio.currentTime,
+				percent = (curtime/_this.audio.duration)*100,
+				deg = 360/100*percent,
+        minutes = Math.floor( curtime / 60),
+        seconds =  Math.floor(curtime) % 60;
+      _this.set('currentTime', ('0' + minutes).slice(-2)+':'+('0' + seconds).slice(-2));
+			_this.updateProgress(deg);
+		});
+
+		// when the audio has finished playing
+		this.audio.addEventListener('ended', function(){
+      _this.pause();
+      _this.changeTime(0);
+      _this.updateProgress(0);
+		});
+  },
+  // change seeked time
+  changeTime: function(percent){
+    var t = (this.audio.duration*percent)/100;
+    this.audio.currentTime = t;
+  },
+  updateProgress: function(deg){
+    var $slice = this.$('.slice');
+
+    if (deg > 180 && !$slice.is('.gt50')) {
+      $slice.addClass('gt50');
+      $slice.append('<div class="pie fill"></div>');
+    } else if (deg < 180 && $slice.is('.gt50')) {
+      $slice.removeClass('gt50');
+      $slice.find('.fill').remove();
+    }
+
+    $slice.find('.pie').css({
+      '-moz-transform':'rotate('+deg+'deg)',
+      '-webkit-transform':'rotate('+deg+'deg)',
+      '-o-transform':'rotate('+deg+'deg)',
+      'transform':'rotate('+deg+'deg)'
+    });
+  },
+  rotation: function(x,y){
+    var offset = this.button.progress.offset();
+    var button_centerX = (offset.left) + (this.button.progress.width()/2);
+    var button_centerY = (offset.top) + (this.button.progress.height()/2);
+
+    var radians = Math.atan2(x - button_centerX, y - button_centerY);
+    var degree = Math.round( (radians * (180 / Math.PI) * -1) + 180 );
+    return degree;
+    //return (degree <= max ? degree : max);
+  },
+  play: function(){
+    this.audio.play();
+    this.button.play.addClass('playing');
+    this.button.play.text('Pause');
+  },
+  pause: function(){
+    this.audio.pause();
+    this.button.play.removeClass('playing');
+    this.button.play.text('Play');
+  },
+  actions: {
+    tooglePlay: function(){
+      if (this.button.play.is('.playing')) {
+        this.pause();
+      } else {
+        this.play();
+      }
+    },
+    prevNextDocument(change){
+      this.sendAction("action", change);
+    }
+  }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/components/visu-carto.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,131 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+  // storage: Ember.inject.service(),
+  didInsertElement: function(){
+    var _this = this;
+
+    var franceDataProvider = {
+        mapVar: AmCharts.maps.france2016Low,
+        getAreasFromMap:true,
+
+        areas: this.initArea(AmCharts.maps.france2016Low)
+    };
+
+    var worldDataProvider = {
+        map: "worldLow",
+        getAreasFromMap: true,
+        images: [{
+            id: "backButton",
+            label: "Back to continents map",
+            rollOverColor: "#CC0000",
+            labelRollOverColor: "#CC0000",
+            useTargetsZoomValues: true,
+            left: 30,
+            bottom: 30,
+            labelFontSize: 15,
+            selectable: true
+        }],
+        areas: this.initArea(AmCharts.maps.worldLow, franceDataProvider)
+    };
+
+
+    var continentsDataProvider = {
+        map: "continentsLow",
+
+        areas: [{
+            id: "africa",
+            linkToObject: worldDataProvider,
+            color: "#7CACAE",
+            passZoomValuesToTarget: true
+        }, {
+            id: "asia",
+            linkToObject: worldDataProvider,
+            color: "#fff",
+            selectable: false,
+            passZoomValuesToTarget: true
+        }, {
+            id: "australia",
+            linkToObject: worldDataProvider,
+            color: "#fff",
+            selectable: false,
+            passZoomValuesToTarget: true
+        }, {
+            id: "europe",
+            linkToObject: worldDataProvider,
+            color: "#2D7073",
+            passZoomValuesToTarget: true
+        }, {
+            id: "north_america",
+            linkToObject: worldDataProvider,
+            color: "#B0D1D3",
+            passZoomValuesToTarget: true
+        }, {
+            id: "south_america",
+            linkToObject: worldDataProvider,
+            color: "#fff",
+            selectable: false,
+            passZoomValuesToTarget: true
+        }]
+
+    };
+
+
+    var map = AmCharts.makeChart("mapdiv", {
+        type: "map",
+
+
+        areasSettings: {
+            autoZoom: true,
+            rollOverOutlineColor: "#000000",
+            selectedOutlineColor: "#CC0000",
+            selectedColor: "green",
+            color: "#fff"
+        },
+
+        dataProvider: continentsDataProvider,
+
+        listeners: [{event:"clickMapObject", method:handleMapObjectClick}]
+
+    });
+
+    function handleGoHome() {
+        map.dataProvider = continentsDataProvider;
+        map.validateNow();
+    }
+    function handleMapObjectClick (event) {
+      console.log("bbox: ", event.mapObject.displayObject.node.getBBox());
+        if (event.mapObject.id === "backButton") {
+            handleGoHome();
+        }
+        _this.sendAction('action', event.mapObject.title);
+    }
+
+    // monitor when home icon was clicked and also go to continents map
+    map.addListener("homeButtonClicked", handleGoHome);
+  },
+  initArea: function(area, dataProvider){
+    var _this = this;
+
+    var areaList = [];
+    var count = {};
+    area.svg.g.path.map(function(elt){
+      var length = _this.get("documents").filterBy("spatial", elt.title).toArray().length;
+      if (length > 0){
+        count[elt.id]= length;
+      }
+    });
+    area.svg.g.path.map(function(elt){
+
+      areaList.push({
+        id: elt.id,
+        linkToObject: (elt.id === "FR" ? dataProvider : ""),
+        color: ((typeof(count[elt.id]) === "undefined") ? "#fff" : "#2D7073"),
+        autoZoom: (elt.id === "FR" ? true : false),
+        selectable: true,
+        passZoomValuesToTarget: false
+      });
+    });
+    return areaList;
+  }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/components/visu-chrono.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,45 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+  didInsertElement: function(){
+    var _this = this;
+
+    if (this.get('container').lookup('controller:application').date !== null){
+      this.highlightQuery(this.get('container').lookup('controller:application').date);
+    }
+
+    var isMouseDown = false,
+      isHighlighted;
+    Ember.$("#chrono-table li").mousedown(function () {
+      isMouseDown = true;
+      Ember.$(this).toggleClass("highlighted");
+      isHighlighted = Ember.$(this).hasClass("highlighted");
+      _this.sendUpdate();
+      return false; // prevent text selection
+    }).mouseover(function () {
+      if (isMouseDown) {
+        Ember.$(this).toggleClass("highlighted", isHighlighted);
+        _this.sendUpdate();
+      }
+    }).bind("selectstart", function () {
+      return false;
+    });
+
+    Ember.$(document).mouseup(function () {
+      isMouseDown = false;
+    });
+  },
+  sendUpdate: function(){
+    var dateQuery = [];
+    Ember.$('.highlighted').map(function(index, elt) {
+      dateQuery.push(parseInt(Ember.$(elt).parent().attr('id')) + parseInt(Ember.$(elt).html()));
+    });
+    this.sendAction('action', dateQuery);
+  },
+  highlightQuery: function(list){
+    list.map(function(elt){
+      var year = Math.floor(parseInt(elt)/10)*10;
+      Ember.$("#"+year+" ."+(parseInt(elt)-year)).toggleClass("highlighted", true);
+    });
+  }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/components/visu-langues.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,186 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+  didInsertElement: function(){
+    var _this = this;
+    var margin = {top: 20, right: 0, bottom: 0, left: 0},
+        width = Ember.$("#chart_div").width(),
+        height = 600 - margin.top - margin.bottom,
+        formatNumber = d3.format(",d"),
+        transitioning;
+
+    var x = d3.scale.linear()
+        .domain([0, width])
+        .range([0, width]);
+
+    var y = d3.scale.linear()
+        .domain([0, height])
+        .range([0, height]);
+
+    var treemap = d3.layout.treemap()
+        .children(function(d, depth) { return depth ? null : d._children; })
+        .sort(function(a, b) { return a.value - b.value; })
+        .ratio(height / width * 0.5 * (1 + Math.sqrt(5)))
+        .round(false);
+
+    var svg = d3.select("#chart_div").append("svg")
+        .attr("width", width + margin.left + margin.right)
+        .attr("height", height + margin.bottom + margin.top)
+        .style("margin-left", -margin.left + "px")
+        .style("margin.right", -margin.right + "px")
+      .append("g")
+        .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
+        .style("shape-rendering", "crispEdges");
+
+    var grandparent = svg.append("g")
+        .attr("class", "grandparent");
+
+    grandparent.append("rect")
+        .attr("y", -margin.top)
+        .attr("width", width)
+        .attr("height", margin.top);
+
+    grandparent.append("text")
+        .attr("x", 6)
+        .attr("y", 6 - margin.top)
+        .attr("dy", ".75em");
+
+    d3.json("langues.json", function(root) {
+      initialize(root);
+      accumulate(root);
+      layout(root);
+      display(root);
+
+      function initialize(root) {
+        root.x = root.y = 0;
+        root.dx = width;
+        root.dy = height;
+        root.depth = 0;
+      }
+
+      // Aggregate the values for internal nodes. This is normally done by the
+      // treemap layout, but not here because of our custom implementation.
+      // We also take a snapshot of the original children (_children) to avoid
+      // the children being overwritten when when layout is computed.
+      function accumulate(d) {
+        return (d._children = d.children) ? d.value = d.children.reduce(function(p, v) { return p + accumulate(v); }, 0) : d.value;
+      }
+
+      // Compute the treemap layout recursively such that each group of siblings
+      // uses the same size (1×1) rather than the dimensions of the parent cell.
+      // This optimizes the layout for the current zoom state. Note that a wrapper
+      // object is created for the parent node for each group of siblings so that
+      // the parent’s dimensions are not discarded as we recurse. Since each group
+      // of sibling was laid out in 1×1, we must rescale to fit using absolute
+      // coordinates. This lets us use a viewport to zoom.
+      function layout(d) {
+        if (d._children) {
+          treemap.nodes({_children: d._children});
+          d._children.forEach(function(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);
+          });
+        }
+      }
+
+      function display(d) {
+        grandparent
+            .datum(d.parent)
+            .on("click", transition)
+          .select("text")
+            .text(name(d));
+
+        var g1 = svg.insert("g", ".grandparent")
+            .datum(d)
+            .attr("class", "depth");
+
+        var g = g1.selectAll("g")
+            .data(d._children)
+          .enter().append("g");
+
+        g.classed("bla", true).on("click", selectHandler);
+
+        g.filter(function(d) { return d._children; })
+            .classed("children", true)
+            .on("click", transition);
+
+        g.append("rect")
+            .attr("class", "parent")
+            // .attr("fill", (d.color || "#bbb"))
+            .call(rect)
+          .append("title")
+            .text(function(d) { return formatNumber(d.value); });
+
+        g.append("text")
+            .attr("dy", ".75em")
+            .text(function(d) { return d.name; })
+            .call(text);
+
+        function transition(d) {
+          if (transitioning || !d) { return; }
+          selectHandler(d);
+          transitioning = true;
+
+          var g2 = display(d),
+              t1 = g1.transition().duration(750),
+              t2 = g2.transition().duration(750);
+
+          // Update the domain only after entering new elements.
+          x.domain([d.x, d.x + d.dx]);
+          y.domain([d.y, d.y + d.dy]);
+
+          // Enable anti-aliasing during the transition.
+          svg.style("shape-rendering", null);
+
+          // Draw child nodes on top of parent nodes.
+          svg.selectAll(".depth").sort(function(a, b) { return a.depth - b.depth; });
+
+          // Fade-in entering text.
+          g2.selectAll("text").style("fill-opacity", 0);
+
+          // Transition to the new view.
+          t1.selectAll("text").call(text).style("fill-opacity", 0);
+          t2.selectAll("text").call(text).style("fill-opacity", 1);
+          t1.selectAll("rect").call(rect);
+          t2.selectAll("rect").call(rect);
+
+          // Remove the old node when the transition is finished.
+          t1.remove().each("end", function() {
+            svg.style("shape-rendering", "crispEdges");
+            transitioning = false;
+          });
+        }
+
+        function selectHandler (d){
+          if (d.name === "Global"){
+            return _this.sendAction('action', null);
+          }
+          _this.sendAction('action', d.name);
+        }
+
+        return g;
+      }
+
+      function text(text) {
+        text.attr("x", function(d) { return x(d.x) + 6; })
+            .attr("y", function(d) { return y(d.y) + 6; });
+      }
+
+      function rect(rect) {
+        rect.attr("x", function(d) { return x(d.x); })
+            .attr("y", function(d) { return y(d.y); })
+            .attr("width", function(d) { return x(d.x + d.dx) - x(d.x); })
+            .attr("height", function(d) { return y(d.y + d.dy) - y(d.y); })
+            .attr("fill", function(d) { return (d.color || "#bbb")});
+      }
+
+      function name(d) {
+        return d.parent ? name(d.parent) + "." + d.name : d.name;
+      }
+    });
+  }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/controllers/application.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,101 @@
+import Ember from 'ember';
+
+export default Ember.Controller.extend({
+  queryParams: ['location', 'langue', 'discours', 'date', 'thematique', 'detail'],
+  location: null,
+  langue: null,
+  discours: null,
+  date: [],
+  thematique: null,
+  detail: null,
+
+  currentId: null,
+  currentItem: Ember.computed('currentId', function() {
+    Ember.$(".result-item").toggleClass("playing", false);
+    Ember.$("#"+this.get('currentId')).toggleClass("playing", true);
+    if (this.get('currentId') === null){
+      return null;
+    }
+    return this.store.findRecord('document', this.get('currentId'));
+  }),
+  modalItem: Ember.computed('detail', function() {
+    return this.store.findRecord('document', this.get('detail'));
+  }),
+  filteredDocuments: Ember.computed('location', 'langue', 'discours', 'date', 'thematique', 'model', function() {
+    var location = this.get('location');
+    var langue = this.get('langue');
+    var discours = this.get('discours');
+    var date = this.get('date');
+    var thematique = this.get('thematique');
+
+    var documents = this.get('model');
+
+    if (location) {
+      documents = documents.filterBy('spatial', location);
+    }
+    if (langue) {
+      documents = documents.filterBy('language', langue);
+    }
+    if (discours) {
+      documents = documents.filterBy('type', discours);
+    }
+    if (date.length > 0) {
+      var temp = documents;
+      documents.map(function(elt){
+        if (date.indexOf(elt.get('created')) === -1){
+          temp = temp.without(elt);
+        }
+      });
+      documents = temp;
+    }
+    if (thematique) {
+      documents = documents.filterBy('thematique', thematique);
+    }
+    return documents;
+  }),
+  actions: {
+    deleteTag: function(query, item){
+      var newParams = null;
+
+      if (query === 'date'){
+        newParams = [];
+        Ember.$.each(this.get('date'), function(index, elt){
+          if (elt !== item){
+            newParams.push(elt);
+          }
+        });
+      }
+
+      this.set(query, newParams);
+    },
+    changeDocument: function(docDirection){
+      var direction = (docDirection === "next") ? 1 : -1;
+      var currentObject = this.get("filteredDocuments").findBy('id', this.get("currentItem").get('id'));
+      if ( currentObject !== 'undefined'){
+        var index = this.get("filteredDocuments").indexOf(currentObject);
+          if ( typeof(this.get("filteredDocuments").objectAt(index+direction)) !== 'undefined'){
+            return this.set('currentId', this.get("filteredDocuments").objectAt(index+direction).id);
+          }
+      }
+      return this.set('currentId', this.get('filteredDocuments').get('firstObject').id);
+    },
+    play: function(item){
+      this.set("currentId", item.id);
+    },
+    showMore: function(item){
+      if (Ember.$("#"+item.id).hasClass("show-more")){
+          Ember.$("#"+item.id).toggleClass("show-more", false);
+      } else{
+        Ember.$(".result-item").toggleClass("show-more", false);
+        Ember.$("#"+item.id).toggleClass("show-more", true);
+      }
+    },
+    toggleModal: function(item){
+      if (typeof(item) !== 'undefined'){
+        this.set("detail", item.id);
+      } else {
+        this.set("detail", null);
+      }
+    }
+  }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/controllers/tabs/carto.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,9 @@
+import Ember from 'ember';
+
+export default Ember.Controller.extend({
+  actions: {
+    updateUrl: function(selection){
+      this.transitionToRoute({queryParams: {location: selection}});
+    }
+  }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/controllers/tabs/chrono.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,9 @@
+import Ember from 'ember';
+
+export default Ember.Controller.extend({
+  actions: {
+    updateUrl: function(selection){
+      this.transitionToRoute({queryParams: {date: selection}});
+    }
+  }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/controllers/tabs/discours.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,9 @@
+import Ember from 'ember';
+
+export default Ember.Controller.extend({
+  actions: {
+    updateUrl: function(selection){
+      this.transitionToRoute({queryParams: {discours: selection}});
+    }
+  }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/controllers/tabs/langues.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,9 @@
+import Ember from 'ember';
+
+export default Ember.Controller.extend({
+  actions: {
+    updateUrl: function(selection){
+      this.transitionToRoute({queryParams: {langue: selection}});
+    }
+  }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/controllers/tabs/thematiques.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,9 @@
+import Ember from 'ember';
+
+export default Ember.Controller.extend({
+  actions: {
+    updateUrl: function(selection){
+      this.transitionToRoute({queryParams: {thematique: selection}});
+    }
+  }
+});
--- a/cms/app-client/app/controllers/visus/visu-carto.js	Sat Jan 16 00:33:26 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-import Ember from 'ember';
-import config from '../../config/environment';
-
-export default Ember.Controller.extend({
-  logoUrl: config.APP.baseStatic + "assets/images/logo.png"
-});
--- a/cms/app-client/app/index.html	Sat Jan 16 00:33:26 2016 +0100
+++ b/cms/app-client/app/index.html	Fri Jan 22 14:31:17 2016 +0100
@@ -21,19 +21,28 @@
       <h1>Corpus de la parole</h1>
       <div class="menu">
         <ul class="menu_main">
-          <li> <a href="#"> CORPUS </a> </li>
-          <li> <a href="#"> LANGUES </a> </li>
-          <li> <a href="#"> PROJET </a> </li>
-          <li> <a href="#"> RECHERCHE </a> </li>
+          <li class="sub-menu"> <a href="#/langues"> Langues </a> </li>
+          <li class="sub-menu"> <a href="#/cartographie"> Cartographie </a> </li>
+          <li class="sub-menu"> <a href="#/thematiques"> Thématiques </a> </li>
+          <li class="sub-menu"> <a href="#/discours"> Discours </a> </li>
+          <li class="sub-menu"> <a href="#/chronologie"> Chronologie </a> </li>
         </ul>
       </div>
     </div>
 
     {{content-for 'body'}}
-    <div id="corpus-app"></div>
+    <div id="corpus-app" class="corpus-app"></div>
 
+    <script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1.1','packages':['treemap']}]}"></script>
     <script src="assets/vendor.js"></script>
     <script src="assets/app-client.js"></script>
+    <script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
+    <script>
+      $(".menu_main .sub-menu").click(function(item, bla){
+        $(".menu_main .sub-menu").toggleClass("active", false);
+        $(item.currentTarget).toggleClass("active", true);
+      })
+    </script>
 
     {{content-for 'body-footer'}}
   </body>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/models/document.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,185 @@
+import DS from 'ember-data';
+import Ember from 'ember';
+import _ from 'lodash/lodash';
+
+var Document = DS.Model.extend({
+  // id: DS.attr('string'),
+  uri: DS.attr('string'),
+  title: DS.attr('string'),
+  language: DS.attr('string'),
+  publishers: DS.attr({defaultValue: []}),
+  contributors: DS.attr({defaultValue: []}),
+  mediaArray: DS.attr({defaultValue: []}),
+  mediaList: Ember.computed('mediaArray', function() {
+    var res = [];
+    var mp3 = null;
+    _.forEach(this.get('mediaArray'), function(m) {
+      if(m.format === 'audio/mpeg') {
+        mp3 = m;
+      } else if (m.format.startsWith('audio/')) {
+        res.push(m);
+      }
+    });
+    if(mp3) {
+      res.unshift(mp3);
+    }
+    return res;
+  })
+});
+
+Document.reopenClass({
+  FIXTURES: [
+    {
+      "id": "crdo-09-CAYCHAX_SOUND",
+      "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-09-CAYCHAX_SOUND",
+      "title": "ALLOc : Caychax : Parabole",
+      "language": "http://lexvo.org/id/iso639-3/oci",
+      "modified": "2010-10-25T18:16:38+02:00",
+      "publishers": [ ],
+      "contributors": [ ],
+      "mediaArray": [ ]
+    },
+    {
+        "id": "crdo-09-DUN_SOUND",
+        "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-09-DUN_SOUND",
+        "title": "ALLOc : Dun : Parabole",
+        "language": "http://lexvo.org/id/iso639-3/oci",
+        "modified": "2010-10-25T18:18:23+02:00",
+        "publishers": [ ],
+        "contributors": [ ],
+        "mediaArray": [ ]
+    },
+    {
+        "id": "crdo-09-LABASTIDE-DE-LORDAT_SOUND",
+        "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-09-LABASTIDE-DE-LORDAT_SOUND",
+        "title": "ALLOc : La Bastide-de-Lordat : Parabole",
+        "language": "http://lexvo.org/id/iso639-3/oci",
+        "modified": "2010-10-25T18:20:08+02:00",
+        "publishers": [ ],
+        "contributors": [ ],
+        "mediaArray": [ ]
+    },
+    {
+        "id": "crdo-09-LOUBENS_SOUND",
+        "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-09-LOUBENS_SOUND",
+        "title": "ALLOc : Loubens : Parabole",
+        "language": "http://lexvo.org/id/iso639-3/oci",
+        "modified": "2010-10-25T18:21:23+02:00",
+        "publishers": [ ],
+        "contributors": [ ],
+        "mediaArray": [ ]
+    },
+    {
+        "id": "crdo-09-MERENS-LES-VALS_SOUND",
+        "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-09-MERENS-LES-VALS_SOUND",
+        "title": "ALLOc : Mérens-les-Vals : Parabole",
+        "language": "http://lexvo.org/id/iso639-3/oci",
+        "modified": "2010-10-25T18:22:24+02:00",
+        "publishers": [ ],
+        "contributors": [ ],
+        "mediaArray": [ ]
+    },
+    {
+        "id": "crdo-09-MONTSEGUR_SOUND",
+        "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-09-MONTSEGUR_SOUND",
+        "title": "ALLOc : Montségur : Parabole",
+        "language": "http://lexvo.org/id/iso639-3/oci",
+        "modified": "2010-10-25T18:23:14+02:00",
+        "publishers": [ ],
+        "contributors": [ ],
+        "mediaArray": [ ]
+    },
+    {
+        "id": "crdo-09-PRAYOLS_SOUND",
+        "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-09-PRAYOLS_SOUND",
+        "title": "ALLOc : Prayols : Parabole",
+        "language": "http://lexvo.org/id/iso639-3/oci",
+        "modified": "2010-10-25T18:24:06+02:00",
+        "publishers": [ ],
+        "contributors": [ ],
+        "mediaArray": [ ]
+    },
+    {
+        "id": "crdo-09-QUERIGUT_SOUND",
+        "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-09-QUERIGUT_SOUND",
+        "title": "ALLOc : Quérigut : Parabole",
+        "language": "http://lexvo.org/id/iso639-3/oci",
+        "modified": "2010-10-25T18:24:56+02:00",
+        "publishers": [ ],
+        "contributors": [ ],
+        "mediaArray": [ ]
+    },
+    {
+        "id": "crdo-09-SIGUER_SOUND",
+        "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-09-SIGUER_SOUND",
+        "title": "ALLOc : Siguer : Parabole",
+        "language": "http://lexvo.org/id/iso639-3/oci",
+        "modified": "2010-10-25T18:25:51+02:00",
+        "publishers": [ ],
+        "contributors": [ ],
+        "mediaArray": [ ]
+    },
+    {
+        "id": "crdo-09-ST-MARTIN-D-OYDES_SOUND",
+        "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-09-ST-MARTIN-D-OYDES_SOUND",
+        "title": "ALLOc : Saint-Martin-d'Oydes : Parabole",
+        "language": "http://lexvo.org/id/iso639-3/oci",
+        "modified": "2010-10-25T18:26:22+02:00",
+        "publishers": [ ],
+        "contributors": [ ],
+        "mediaArray": [ ]
+    },
+    {
+        "id": "crdo-09-SURBA_SOUND",
+        "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-09-SURBA_SOUND",
+        "title": "ALLOc : Surba : Parabole",
+        "language": "http://lexvo.org/id/iso639-3/oci",
+        "modified": "2010-10-25T18:26:42+02:00",
+        "publishers": [ ],
+        "contributors": [ ],
+        "mediaArray": [ ]
+    },
+    {
+        "id": "crdo-11-GRAMAZIE_SOUND",
+        "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-11-GRAMAZIE_SOUND",
+        "title": "ALLOc : Gramazie : Parabole",
+        "language": "http://lexvo.org/id/iso639-3/oci",
+        "modified": "2010-10-25T18:27:39+02:00",
+        "publishers": [ ],
+        "contributors": [ ],
+        "mediaArray": [ ]
+    },
+    {
+        "id": "crdo-11-MOLLEVILLE_SOUND",
+        "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-11-MOLLEVILLE_SOUND",
+        "title": "ALLOc : Molleville : Parabole",
+        "language": "http://lexvo.org/id/iso639-3/oci",
+        "modified": "2010-10-25T18:28:06+02:00",
+        "publishers": [ ],
+        "contributors": [ ],
+        "mediaArray": [ ]
+    },
+    {
+        "id": "crdo-11-PUIVERT_SOUND",
+        "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-11-PUIVERT_SOUND",
+        "title": "ALLOc : Puivert : Parabole",
+        "language": "http://lexvo.org/id/iso639-3/oci",
+        "modified": "2010-10-25T18:28:40+02:00",
+        "publishers": [ ],
+        "contributors": [ ],
+        "mediaArray": [ ]
+    },
+    {
+        "id": "crdo-11-RIBOUISSE_SOUND",
+        "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-11-RIBOUISSE_SOUND",
+        "title": "ALLOc : Ribouisse : Parabole",
+        "language": "http://lexvo.org/id/iso639-3/oci",
+        "modified": "2010-10-25T18:29:32+02:00",
+        "publishers": [ ],
+        "contributors": [ ],
+        "mediaArray": [ ]
+    }
+  ]
+});
+
+export default Document;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/models/sound.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,349 @@
+import DS from 'ember-data';
+
+var Sound = DS.Model.extend({
+  title: DS.attr('string'),
+  description: DS.attr('string'),
+  interviewer: DS.attr('string'),
+  type: DS.attr('string'),
+  spatial: DS.attr('string'),
+  language: DS.attr('string'),
+  created: DS.attr('number'),
+  master: DS.attr('string')
+});
+
+Sound.reopenClass({
+  FIXTURES: [
+    {
+      "id": 0,
+      "title": "culpa exercitation",
+      "description": "Deserunt exercitation laborum veniam ex anim officia non cillum ut. Mollit quis minim officia quis incididunt exercitation eu ad.",
+      "interviewer": "Ferguson King",
+      "type": "Reunion",
+      "spatial": "Germany",
+      "language": "Français",
+      "created": 1977,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3921.mp3"
+    },
+    {
+      "id": 1,
+      "title": "excepteur ex",
+      "description": "Veniam irure deserunt esse veniam enim voluptate esse et consequat fugiat. Fugiat ullamco officia enim nulla.",
+      "interviewer": "Holly Sims",
+      "type": "Discours",
+      "spatial": "France",
+      "language": "Alsacien",
+      "created": 2001,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3924.mp3"
+    },
+    {
+      "id": 2,
+      "title": "fugiat fugiat",
+      "description": "Enim aute incididunt voluptate sit labore anim in irure id duis ut. Occaecat magna sit mollit commodo enim reprehenderit nulla magna.",
+      "interviewer": "Claudia Cunningham",
+      "type": "Entretien",
+      "spatial": "France",
+      "language": "Corse",
+      "created": 2004,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3924.mp3"
+    },
+    {
+      "id": 3,
+      "title": "officia fugiat",
+      "description": "Irure elit aute eu consequat est sunt cillum. Quis nisi consectetur cillum cupidatat id consectetur.",
+      "interviewer": "Hazel Foster",
+      "type": "Dialogue",
+      "spatial": "France",
+      "language": "Alsacien",
+      "created": 2001,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/138.mp3"
+    },
+    {
+      "id": 4,
+      "title": "nulla elit",
+      "description": "Anim ex consequat aliqua magna in aliquip ipsum voluptate est deserunt voluptate. Incididunt sit voluptate esse cillum qui ex irure cillum nulla cillum excepteur.",
+      "interviewer": "Colon Dotson",
+      "type": "Conversation",
+      "spatial": "Germany",
+      "language": "Breton",
+      "created": 1990,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3921.mp3"
+    },
+    {
+      "id": 5,
+      "title": "sunt laboris",
+      "description": "Ex quis aliqua aliquip incididunt dolore excepteur est incididunt occaecat aute anim. Veniam laborum tempor cupidatat aliquip nostrud anim ut dolor sint et aliquip.",
+      "interviewer": "Alisha Flores",
+      "type": "Discussion",
+      "spatial": "France",
+      "language": "Corse",
+      "created": 1972,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3924.mp3"
+    },
+    {
+      "id": 6,
+      "title": "fugiat laboris",
+      "description": "Do tempor amet duis occaecat. Est laboris ea voluptate ut adipisicing laboris exercitation eiusmod est irure ad laborum.",
+      "interviewer": "Hart Mccoy",
+      "type": "Conversation",
+      "spatial": "Germany",
+      "language": "Alsacien",
+      "created": 1987,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/138.mp3"
+    },
+    {
+      "id": 7,
+      "title": "elit sit",
+      "description": "Lorem magna adipisicing sit non excepteur aliqua tempor enim elit cupidatat voluptate laborum. Aliqua mollit consequat pariatur tempor.",
+      "interviewer": "Cecelia Gregory",
+      "type": "Bavardage",
+      "spatial": "Germany",
+      "language": "Breton",
+      "created": 1961,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/138.mp3"
+    },
+    {
+      "id": 8,
+      "title": "sit aliquip",
+      "description": "Ad sint anim elit eiusmod duis incididunt ipsum cupidatat culpa id proident amet. Ad in do aliquip irure est proident Lorem qui est veniam.",
+      "interviewer": "Cain Sweeney",
+      "type": "Dialogue",
+      "spatial": "Germany",
+      "language": "Corse",
+      "created": 1973,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/142.mp3"
+    },
+    {
+      "id": 9,
+      "title": "culpa ut",
+      "description": "Irure nostrud consequat aliqua sit est id aute dolor elit quis. Exercitation consequat commodo amet nostrud laboris minim aute ipsum eiusmod sunt nisi.",
+      "interviewer": "Clay Whitney",
+      "type": "Discussion",
+      "spatial": "Spain",
+      "language": "Alsacien",
+      "created": 2008,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3924.mp3"
+    },
+    {
+      "id": 10,
+      "title": "culpa non",
+      "description": "Qui et dolor cupidatat eiusmod. Cillum irure mollit est nostrud dolor non exercitation ipsum sint.",
+      "interviewer": "Isabelle Valencia",
+      "type": "Conversation",
+      "spatial": "Spain",
+      "language": "Français",
+      "created": 1975,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3924.mp3"
+    },
+    {
+      "id": 11,
+      "title": "sit occaecat",
+      "description": "Exercitation elit magna cillum pariatur fugiat minim fugiat. Occaecat minim sunt ex aute velit aliquip laboris aliquip dolore.",
+      "interviewer": "Sherri Morin",
+      "type": "Discussion",
+      "spatial": "France",
+      "language": "Français",
+      "created": 2008,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3924.mp3"
+    },
+    {
+      "id": 12,
+      "title": "ea dolor",
+      "description": "Ea ullamco cupidatat esse et eu est sint irure ex non. Pariatur consectetur et quis et cupidatat ea mollit cillum enim.",
+      "interviewer": "Golden Bird",
+      "type": "Conversation",
+      "spatial": "France",
+      "language": "Breton",
+      "created": 1960,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/138.mp3"
+    },
+    {
+      "id": 13,
+      "title": "laboris adipisicing",
+      "description": "Non ex culpa ullamco occaecat quis ut reprehenderit non in cupidatat reprehenderit laboris reprehenderit. Laboris irure Lorem aliquip consequat consequat consequat cillum elit incididunt ad anim Lorem sint excepteur.",
+      "interviewer": "Bianca Faulkner",
+      "type": "Conversation",
+      "spatial": "Spain",
+      "language": "Breton",
+      "created": 1997,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3924.mp3"
+    },
+    {
+      "id": 14,
+      "title": "sit veniam",
+      "description": "Cillum velit laborum irure velit consequat ipsum minim. Non in elit est Lorem excepteur mollit consectetur id.",
+      "interviewer": "Kidd Monroe",
+      "type": "Negociation",
+      "spatial": "Spain",
+      "language": "Alsacien",
+      "created": 2007,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3924.mp3"
+    },
+    {
+      "id": 15,
+      "title": "excepteur exercitation",
+      "description": "Et officia laboris pariatur culpa. Ullamco nisi eu non in.",
+      "interviewer": "Debora Palmer",
+      "type": "Conversation",
+      "spatial": "France",
+      "language": "Alsacien",
+      "created": 1969,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3921.mp3"
+    },
+    {
+      "id": 16,
+      "title": "consectetur officia",
+      "description": "Est tempor aliquip sit occaecat. Ullamco do anim labore consequat sunt enim ea.",
+      "interviewer": "Shaffer Workman",
+      "type": "Dialogue",
+      "spatial": "France",
+      "language": "Breton",
+      "created": 1998,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3921.mp3"
+    },
+    {
+      "id": 17,
+      "title": "fugiat eiusmod",
+      "description": "Quis sit mollit velit quis veniam ipsum commodo voluptate laborum pariatur dolor eiusmod nisi. Reprehenderit aliquip quis aliqua mollit culpa.",
+      "interviewer": "Shepherd Floyd",
+      "type": "Discussion",
+      "spatial": "Spain",
+      "language": "Corse",
+      "created": 1991,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3921.mp3"
+    },
+    {
+      "id": 18,
+      "title": "magna minim",
+      "description": "Amet enim in labore aliquip ipsum fugiat est ex quis. Voluptate adipisicing laboris nisi eu excepteur quis voluptate sit laborum ullamco proident aliquip duis aliquip.",
+      "interviewer": "Tamra Nixon",
+      "type": "Discussion",
+      "spatial": "France",
+      "language": "Français",
+      "created": 2009,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3924.mp3"
+    },
+    {
+      "id": 19,
+      "title": "occaecat aliquip",
+      "description": "Reprehenderit cillum id duis et quis nulla tempor tempor eu ipsum magna mollit laborum. Ullamco reprehenderit incididunt nostrud irure tempor adipisicing.",
+      "interviewer": "Bette Becker",
+      "type": "Discours",
+      "spatial": "France",
+      "language": "Français",
+      "created": 1975,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3921.mp3"
+    },
+    {
+      "id": 20,
+      "title": "minim minim",
+      "description": "Incididunt sit consequat laborum mollit nisi et ullamco aute ad nisi nostrud. Lorem quis id culpa culpa eu minim fugiat quis incididunt ex in sit adipisicing.",
+      "interviewer": "Marsh Gillespie",
+      "type": "Discussion",
+      "spatial": "Spain",
+      "language": "Français",
+      "created": 1964,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/142.mp3"
+    },
+    {
+      "id": 21,
+      "title": "commodo pariatur",
+      "description": "Duis elit consequat sint ipsum aliqua adipisicing ex consequat eiusmod qui ad laboris fugiat ipsum. Eiusmod eiusmod elit culpa veniam.",
+      "interviewer": "Guthrie Norman",
+      "type": "Argumentation",
+      "spatial": "France",
+      "language": "Corse",
+      "created": 1987,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/138.mp3"
+    },
+    {
+      "id": 22,
+      "title": "dolore voluptate",
+      "description": "Ullamco cupidatat tempor incididunt dolor enim proident aliqua dolor dolor nulla occaecat quis excepteur. Consectetur ea ut commodo sunt excepteur ad ut ex consectetur.",
+      "interviewer": "Rosalie Rogers",
+      "type": "Discussion",
+      "spatial": "Germany",
+      "language": "Français",
+      "created": 1997,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3921.mp3"
+    },
+    {
+      "id": 23,
+      "title": "ipsum veniam",
+      "description": "Duis enim cupidatat laboris duis ut sint. Nisi eiusmod ea dolore cillum et labore dolor pariatur labore cupidatat reprehenderit irure.",
+      "interviewer": "Bridget Espinoza",
+      "type": "Conversation",
+      "spatial": "Spain",
+      "language": "Alsacien",
+      "created": 1973,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3921.mp3"
+    },
+    {
+      "id": 24,
+      "title": "fugiat et",
+      "description": "Velit elit non consequat incididunt consectetur occaecat sint magna aliquip. In dolore sunt sit nulla veniam culpa laboris sunt incididunt voluptate ipsum.",
+      "interviewer": "Cox Bernard",
+      "type": "Entretien",
+      "spatial": "Germany",
+      "language": "Alsacien",
+      "created": 1988,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3924.mp3"
+    },
+    {
+      "id": 25,
+      "title": "cillum adipisicing",
+      "description": "Aliqua ullamco quis aliqua minim irure sunt excepteur in nostrud. Consectetur aute commodo proident ea aliquip officia et dolore veniam sint.",
+      "interviewer": "Wendi Leon",
+      "type": "Negociation",
+      "spatial": "France",
+      "language": "Français",
+      "created": 1992,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3924.mp3"
+    },
+    {
+      "id": 26,
+      "title": "magna consequat",
+      "description": "Velit duis id consectetur ad anim fugiat in pariatur aliqua esse aliquip sit dolore aliqua. Laborum incididunt enim ea occaecat officia pariatur veniam deserunt.",
+      "interviewer": "Celeste Price",
+      "type": "Discussion",
+      "spatial": "France",
+      "language": "Alsacien",
+      "created": 1973,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/138.mp3"
+    },
+    {
+      "id": 27,
+      "title": "proident non",
+      "description": "Ullamco amet sit qui reprehenderit eu aliquip magna culpa. Aliqua fugiat commodo est non minim irure aliquip proident ipsum laborum nulla qui quis irure.",
+      "interviewer": "Patty Heath",
+      "type": "Reunion",
+      "spatial": "France",
+      "language": "Breton",
+      "created": 1973,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/142.mp3"
+    },
+    {
+      "id": 28,
+      "title": "ad tempor",
+      "description": "Adipisicing quis consectetur veniam adipisicing exercitation in pariatur amet exercitation cillum irure. Magna ipsum do eu labore consectetur minim quis ipsum ipsum mollit quis consequat.",
+      "interviewer": "Angelica Black",
+      "type": "Bavardage",
+      "spatial": "Spain",
+      "language": "Français",
+      "created": 1992,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3921.mp3"
+    },
+    {
+      "id": 29,
+      "title": "fugiat eiusmod",
+      "description": "Anim sint in do anim irure non cupidatat veniam cillum pariatur adipisicing laboris labore ea. Mollit irure aute laboris incididunt aliqua.",
+      "interviewer": "Rosalinda Kramer",
+      "type": "Dialogue",
+      "spatial": "Germany",
+      "language": "Alsacien",
+      "created": 1972,
+      "master": "http://www.noiseaddicts.com/samples_1w72b820/3921.mp3"
+    }
+  ]
+});
+
+export default Sound;
--- a/cms/app-client/app/router.js	Sat Jan 16 00:33:26 2016 +0100
+++ b/cms/app-client/app/router.js	Fri Jan 22 14:31:17 2016 +0100
@@ -6,11 +6,17 @@
 });
 
 Router.map(function() {
-  this.route('visus/visu-langues', { path: '/langues' });
-  this.route('visus/visu-carto', { path: '/cartographie' });
-  this.route('visus/visu-thematiques', { path: '/thematiques' });
-  this.route('visus/visu-discours', { path: '/discours' });
-  this.route('visus/visu-chrono', { path: '/chronologie' });
+  this.route('tabs/detail', { path: '/detail/:document_id' });
+  this.route('tabs/langues', { path: '/langues' });
+  this.route('tabs/carto', { path: '/cartographie' });
+  this.route('tabs/thematiques', { path: '/thematiques' });
+  this.route('tabs/discours', { path: '/discours' });
+  this.route('tabs/chrono', { path: '/chronologie' });
+});
+
+Router.reopen({
+  onUrlChange: function() {
+  }.observes('currentPath')
 });
 
 export default Router;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/routes/application.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,34 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+  serializeQueryParam: function(value, urlKey) {
+    if (urlKey === 'date') {
+      return value;
+    }
+    return '' + value;
+  },
+  deserializeQueryParam: function(value, urlKey) {
+    if (urlKey === 'date') {
+      var arr = [];
+      for (var i = 0; i < value.length; i++) {
+        arr.push(parseInt(value[i]));
+      }
+      return arr;
+    }
+
+    return value;
+  },
+  model() {
+    return this.store.findAll('document');
+  },
+  actions: {
+    willTransition: function() {
+      var _this = this;
+      var queryParams = {};
+      this.controller.get('queryParams').map(function(elt){
+        queryParams[elt] = _this.controller.get(elt);
+      });
+      this.transitionTo({ queryParams: queryParams });
+    }
+  }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/routes/tabs/carto.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,9 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+  actions: {
+    queryParamsDidChange: function() {
+      console.log("carto params");
+    },
+  }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/routes/tabs/chrono.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,9 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+  actions: {
+    queryParamsDidChange: function() {
+      console.log("chrono params");
+    },
+  }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/routes/tabs/detail.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,7 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+  model(params) {
+    return this.store.findRecord('document', params.document_id);
+  }
+});
--- a/cms/app-client/app/styles/app.scss	Sat Jan 16 00:33:26 2016 +0100
+++ b/cms/app-client/app/styles/app.scss	Fri Jan 22 14:31:17 2016 +0100
@@ -1,11 +1,24 @@
 #corpus-app {
   border: 1px solid;
-  width: 940px;
-  height: 900px;
+  width: 1108px;
+  height: 600px;
   display: block;
   margin-left: auto;
   margin-right: auto;
   margin-bottom: 10px;
+
+  @import 'tabs/chrono';
+  @import 'tabs/carto';
+  @import 'tabs/langues';
+  @import 'tabs/discours';
+  @import 'tabs/thematiques';
+  @import 'tabs/detail';
+}
+
+.mapdiv{
+  width: 470px;
+  background-color: #FFFFFF;
+  height: 500px;
 }
 
 .corpus-app {
@@ -13,39 +26,30 @@
     @import 'container';
     @import 'player';
     @import 'results';
+    @import 'modal';
 
     &-container{
       display: block;
       width: 50%;
-      height: 900px;
+      height: 600px;
       float: left;
       border-top: none;
-      border-right: 1px solid grey;
     }
     &-wrapper{
-      height: 900px;
+      height: 600px;
       display : flex;
       flex-flow: column;
       border: none;
-    }
-    &-player,
-    &-results {
-      padding: 0 10px;
-      margin-bottom: 10px;
-      background-color: #eeeeee;
+      padding: 0 0 0 10px;
     }
     &-player{
       flex: 0 1 auto;
       float: left;
       border-left: none;
       border-top: none;
-    }
-    &-results {
-      flex: 1 1 auto;
-      float: left;
-      overflow: auto;
-      border-left: none;
-      border-top: none;
+      margin-bottom: 10px;
+      background-color: #eeeeee;
+      padding: 0 10px;
     }
   }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/styles/modal.scss	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,41 @@
+.overlay {
+    background-color: gray;
+    height: 100vh;
+    left: 0;
+    opacity: 0.77;
+    position: fixed;
+    right: 0;
+    top: 0;
+    z-index: 50;
+}
+
+.dialog {
+    background: #fff none repeat scroll 0 0;
+    border: 2px solid #ccc;
+    border-radius: 5px;
+    box-shadow: 0 0 10px #222;
+    min-height: 300px;
+    min-width: 500px;
+    height: auto;
+    width: auto;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    position: fixed;
+    z-index: 50;
+}
+
+.dialog-header,
+.dialog-body,
+.dialog-footer{
+  padding: 5px 10px 0;
+}
+
+.dialog-header h2{
+  margin: 0;
+}
+
+.dialog-body b{
+  display: inline-block;
+  min-width: 140px;
+}
--- a/cms/app-client/app/styles/player.scss	Sat Jan 16 00:33:26 2016 +0100
+++ b/cms/app-client/app/styles/player.scss	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,94 @@
+.player-component{
+  text-align: center;
+}
+
+#audio_player {
+  display: inline-block;
+  width: 80px;
+  height: 80px;
+  position: relative;
+  padding: 8px;
+  margin: 10px auto;
+  background: #fff;
+  border-radius: 88px;
+}
+#audio_player .background {
+  width: 60px;
+  height: 60px;
+  border: solid 10px #e5e5e5;
+  background: #fff;
+  border-radius: 80px;
+}
+#audio_player .btn {
+  cursor: pointer;
+}
+#audio_player .btn_play {
+  display: block;
+  width: 32px;
+  height: 32px;
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  margin-top: -16px;
+  margin-left: -16px;
+  text-indent: -900em;
+  z-index: 10;
+  background: url(images/button_play.png) 10px no-repeat;
+  background-size: 21px 31px;
+}
+/* pause */
+#audio_player .btn_play.playing {
+  background: url(images/button_pause.png) center no-repeat;
+  background-size: 28px 28px;
+}
+#audio_player .progress {
+  position: absolute;
+  width: 80px;
+  height: 80px;
+  top: 8px;
+  left: 8px;
+}
+#audio_player .progress .slice {
+  position: absolute;
+  width: 80px;
+  height: 80px;
+  clip: rect(0px,80px,80px,40px);
+}
+#audio_player .progress .slice.gt50 {
+  clip: rect(auto, auto, auto, auto);
+}
+#audio_player .progress .slice .pie {
+  border: 10px solid #276f84;
+  position: absolute;
+  width: 60px;
+  height: 60px;
+  clip: rect(0,40px,80px,0);
+  -moz-border-radius: 80px;
+  -webkit-border-radius: 80px;
+  border-radius: 80px;
+}
+#audio_player .progress .slice .pie.fill {
+  -moz-transform: rotate(180deg) !important;
+  -webkit-transform: rotate(180deg) !important;
+  -o-transform: rotate(180deg) !important;
+  transform: rotate(180deg) !important;
+}
+
+.audio-controls {
+    color: #2a768c;
+    cursor: pointer;
+    display: inline-block;
+    font-size: 30px;
+    margin: 43px 10px;
+    vertical-align: top;
+}
+
+.duration{
+  margin: -30px auto 0;
+  padding-left: 175px;
+  text-align: center;
+}
+
+.audio-wrapper{
+  display: inline-block;
+}
--- a/cms/app-client/app/styles/results.scss	Sat Jan 16 00:33:26 2016 +0100
+++ b/cms/app-client/app/styles/results.scss	Fri Jan 22 14:31:17 2016 +0100
@@ -1,1 +1,99 @@
+.result-header,
+.result-list{
+  background-color: #eeeeee;
+}
 
+.result-header{
+  flex: 0 1 auto;
+  float: left;
+  padding: 0 10px;
+}
+
+.result-header .filters{
+  display: inline-block;
+  border-radius: 5px;
+  padding: 1px 5px;
+  color: #fff;
+}
+.result-header .filters.location{
+  background-color: #3985AB;
+}
+.result-header .filters.langue{
+  background-color: #B94A43;
+}
+.result-header .filters.discours{
+  background-color: #468842;
+}
+.result-header .filters.date{
+  background-color: #E50086;
+}
+.result-header .filters.thematique{
+  background-color: #F89406;
+}
+.result-header .fa{
+  display: inline-block;
+  margin-left: 5px;
+  position: relative;
+  top: 1px;
+  cursor: pointer;
+}
+
+.result-list{
+  flex: 1 1 auto;
+  float: left;
+  overflow: auto;
+  border: none;
+  background: #eeeeee;
+  padding: 5px 10px;
+}
+
+.result-item {
+  margin-bottom: 1px;
+  min-height: 64px;
+  cursor: pointer;
+  padding: 5px;
+  overflow: hidden;
+  background-color: #fff;
+  border-bottom: 1px solid #eee;
+  color: #777;
+  transition: all 0.4s ease 0s;
+}
+.result-item:hover {
+  // box-shadow: -1px -1px 5px 0px rgba(0,0,0,0.75);
+}
+
+.result-item .hidden-elt {
+  display: none;
+}
+.result-item.show-more .hidden-elt{
+  display: block;
+}
+
+.result-item.show-more {
+  box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
+  margin: 1rem 0rem;
+  z-index: 200;
+  // height: inherit;
+}
+
+.result-item .description{
+  margin-top: 10px;
+}
+
+.playing-indicator{
+    color: #287288;
+}
+
+.result-item.playing .playing-indicator {
+  background: rgba(0, 0, 0, 0) url("images/equalizer.png") no-repeat scroll 0 0 / 15px auto;
+  height: 14px;
+  margin: 2px 7px;
+  width: 15px;
+}
+.result-item.playing .playing-indicator:before {
+  content: none;
+}
+
+.result-item button{
+  margin-top: 10px;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/styles/tabs/carto.scss	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,5 @@
+#mapdiv{
+  width: 100%;
+  height: 600px;
+  background: #eeeeee;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/styles/tabs/chrono.scss	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,23 @@
+#chrono-table{
+  margin-top: 40px;
+}
+
+#chrono-table ul {
+  margin: 0;
+}
+
+#chrono-table li {
+  width:40px;
+  height:40px;
+  text-align:center;
+  vertical-align:middle;
+  background-color:#B0D1D3;
+  display: inline-block;
+  margin: 2px 0;
+  line-height: 30px;
+  cursor: pointer;
+}
+
+#chrono-table li.highlighted {
+  background-color:#2D7073;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/styles/tabs/detail.scss	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,18 @@
+.notice{
+  // padding: 10px;
+}
+
+.notice-header,
+.notice-body,
+.notice-footer{
+  padding: 10px 10px 0;
+}
+
+.notice-header h2{
+  margin: 0;
+}
+
+.notice-body b{
+  display: inline-block;
+  min-width: 140px;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/styles/tabs/discours.scss	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,13 @@
+.visu-discours p{
+  cursor: pointer;
+}
+
+.left{
+  float: left;
+  margin-left: 50px;
+}
+
+.right{
+  float: right;
+  margin-right: 50px;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/styles/tabs/langues.scss	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,45 @@
+#chart_div {
+  width: 100%;
+  height: 540px;
+  background: #ddd;
+}
+
+text {
+  pointer-events: none;
+}
+
+.grandparent text {
+  font-weight: bold;
+}
+
+rect {
+  /*fill: none;*/
+  stroke: #fff;
+}
+
+rect.parent,
+.grandparent rect {
+  stroke-width: 2px;
+}
+
+.grandparent rect {
+  fill: green;
+}
+
+.grandparent:hover rect {
+  fill: lightgreen;
+}
+
+.children rect.parent,
+.grandparent rect {
+  cursor: pointer;
+}
+
+.children rect.parent {
+  /*fill: #bbb;*/
+  fill-opacity: .5;
+}
+
+.children:hover rect.child {
+  /*fill: #bbb;*/
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/styles/tabs/thematiques.scss	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,51 @@
+input[type="text"] {
+  display: block;
+  margin: auto;
+  width: 250px;
+  font-family: sans-serif;
+  font-size: 18px;
+  appearance: none;
+  box-shadow: none;
+  border-radius: none;
+}
+input[type="text"]:focus {
+  outline: none;
+}
+
+.search-box{
+  display: block;
+    height: 100px;
+    width: 400px;
+    margin: 50px auto auto;
+}
+
+.search-box input[type="text"] {
+  padding: 10px;
+  border: none;
+  border-bottom: solid 2px #c9c9c9;
+  transition: border 0.3s;
+  outline: 30px solid #efefef;
+}
+.search-box input[type="text"]:focus,
+.search-box input[type="text"].focus {
+  border-bottom: solid 2px #969696;
+}
+
+.tag-cloud{
+  margin: 15px;
+  text-align: justify;
+}
+
+.tag-cloud span{
+  cursor: pointer;
+}
+
+.not-popular{
+  font-size: 1em;
+}
+.popular{
+  font-size: 1.3em;
+}
+.very-popular{
+  font-size: 1.6em;
+}
--- a/cms/app-client/app/templates/application.hbs	Sat Jan 16 00:33:26 2016 +0100
+++ b/cms/app-client/app/templates/application.hbs	Fri Jan 22 14:31:17 2016 +0100
@@ -1,21 +1,5 @@
+<div id="info-modal"></div>
 <div class="corpus-app-container">
-  <ul class="corpus-app-em-tab-list">
-    {{#link-to 'visus/visu-langues' tagName="li" class='corpus-app-em-tab'}}
-      {{link-to 'Langues' 'visus/visu-langues'}}
-    {{/link-to}}
-    {{#link-to 'visus/visu-carto' tagName="li" class='corpus-app-em-tab'}}
-      {{link-to 'Cartographie' 'visus/visu-carto'}}
-    {{/link-to}}
-    {{#link-to 'visus/visu-thematiques' tagName="li" class='corpus-app-em-tab'}}
-      {{link-to 'Thématiques' 'visus/visu-thematiques'}}
-    {{/link-to}}
-    {{#link-to 'visus/visu-discours' tagName="li" class='corpus-app-em-tab'}}
-      {{link-to 'Discours' 'visus/visu-discours'}}
-    {{/link-to}}
-    {{#link-to 'visus/visu-chrono' tagName="li" class='corpus-app-em-tab'}}
-      {{link-to 'Chronologie' 'visus/visu-chrono'}}
-    {{/link-to}}
-  </ul>
   {{outlet}}
 </div>
 
@@ -23,7 +7,28 @@
   <div class="corpus-app-player">
     {{partial "player"}}
   </div>
-  <div class="corpus-app-results">
-    {{partial "results"}}
-  </div>
+  {{partial "results"}}
 </div>
+
+{{#if detail}}
+  {{#ember-wormhole to='info-modal'}}
+    <div class="overlay" {{action 'toggleModal'}}></div>
+    <div class="dialog">
+      <div class="dialog-header">
+        <h2>Notice</h2>
+      </div>
+      <div class="dialog-body">
+        <p><b>Titre </b>{{modalItem.title}}</p>
+        <p><b>Langue </b>{{modalItem.language}}</p>
+        <p><b>Enregistré le </b>{{modalItem.modified}}</p>
+        <p><b>Interviewer </b>{{modalItem.publishers}}</p>
+        <p><b>Description </b>{{modalItem.description}}</p>
+        <p><b>Type de Discours </b>{{modalItem.type}}</p>
+        <p><b>Localisation </b>{{modalItem.spatial}}</p>
+      </div>
+      <div class="dialog-footer">
+        <button class="pull-right" {{action 'toggleModal'}}>Close</button>
+      </div>
+    </div>
+  {{/ember-wormhole}}
+{{/if}}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/templates/components/player-component.hbs	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,17 @@
+<div class="audio-wrapper">
+	<span class="audio-controls fa fa-backward" {{action 'prevNextDocument' 'previous'}}></span>
+	<div id="audio_player">
+		<span id="action_play" class="btn btn_play" {{action 'tooglePlay'}}>Play</span>
+		<div class="background"></div>
+		<div class="progress">
+			<div class="slice">
+				<div class="pie"></div>
+			</div>
+		</div>
+	</div>
+	<span class="audio-controls fa fa-forward fa-5" {{action 'prevNextDocument' 'next'}}></span>
+</div>
+
+<p class="duration">
+	{{currentTime}} / {{duration}}
+</p>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/templates/components/visu-carto.hbs	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,1 @@
+<div id="mapdiv"></div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/templates/components/visu-chrono.hbs	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,74 @@
+<div cellpadding="0" cellspacing="0" id="chrono-table">
+  <ul id="1960"> 1960 -
+    <li class="0">0</li>
+    <li class="1">1</li>
+    <li class="2">2</li>
+    <li class="3">3</li>
+    <li class="4">4</li>
+    <li class="5">5</li>
+    <li class="6">6</li>
+    <li class="7">7</li>
+    <li class="8">8</li>
+    <li class="9">9</li>
+  </ul>
+  <ul id="1970"> 1970 -
+    <li class="0">0</li>
+    <li class="1">1</li>
+    <li class="2">2</li>
+    <li class="3">3</li>
+    <li class="4">4</li>
+    <li class="5">5</li>
+    <li class="6">6</li>
+    <li class="7">7</li>
+    <li class="8">8</li>
+    <li class="9">9</li>
+  </ul>
+  <ul id="1980"> 1980 -
+    <li class="0">0</li>
+    <li class="1">1</li>
+    <li class="2">2</li>
+    <li class="3">3</li>
+    <li class="4">4</li>
+    <li class="5">5</li>
+    <li class="6">6</li>
+    <li class="7">7</li>
+    <li class="8">8</li>
+    <li class="9">9</li>
+  </ul>
+  <ul id="1990"> 1990 -
+    <li class="0">0</li>
+    <li class="1">1</li>
+    <li class="2">2</li>
+    <li class="3">3</li>
+    <li class="4">4</li>
+    <li class="5">5</li>
+    <li class="6">6</li>
+    <li class="7">7</li>
+    <li class="8">8</li>
+    <li class="9">9</li>
+  </ul>
+  <ul id="2000"> 2000 -
+    <li class="0">0</li>
+    <li class="1">1</li>
+    <li class="2">2</li>
+    <li class="3">3</li>
+    <li class="4">4</li>
+    <li class="5">5</li>
+    <li class="6">6</li>
+    <li class="7">7</li>
+    <li class="8">8</li>
+    <li class="9">9</li>
+  </ul>
+  <ul id="2010"> 2010 -
+    <li class="0">0</li>
+    <li class="1">1</li>
+    <li class="2">2</li>
+    <li class="3">3</li>
+    <li class="4">4</li>
+    <li class="5">5</li>
+    <li class="6">6</li>
+    <li class="7">7</li>
+    <li class="8">8</li>
+    <li class="9">9</li>
+  </ul>
+</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/templates/components/visu-langues.hbs	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,1 @@
+<div id="chart_div"></div>
--- a/cms/app-client/app/templates/player.hbs	Sat Jan 16 00:33:26 2016 +0100
+++ b/cms/app-client/app/templates/player.hbs	Fri Jan 22 14:31:17 2016 +0100
@@ -1,4 +1,7 @@
-<h2>This is the player</h2>
 <div class="corpus-app-content">
-  PLAYER
+
+  {{player-component action="changeDocument" document=currentItem}}
+
+  <p><strong>{{ currentItem.title }}</strong></p>
+  <p>{{ currentItem.language }}</p>
 </div>
--- a/cms/app-client/app/templates/results.hbs	Sat Jan 16 00:33:26 2016 +0100
+++ b/cms/app-client/app/templates/results.hbs	Fri Jan 22 14:31:17 2016 +0100
@@ -1,4 +1,36 @@
-<h2>This is the results</h2>
-<div class="corpus-app-content">
-  RESULTS
+<div class="result-header">
+  <p>
+    Filtres:
+    {{#if location}}
+      <span class="filters location">{{location}}<span class="fa fa-times" {{action 'deleteTag' 'location'}}></span></span>
+    {{/if}}
+    {{#if langue}}
+      <span class="filters langue">{{langue}}<span class="fa fa-times" {{action 'deleteTag' 'langue'}}></span></span>
+    {{/if}}
+    {{#if discours}}
+      <span class="filters discours">{{discours}}<span class="fa fa-times" {{action 'deleteTag' 'discours'}}></span></span>
+    {{/if}}
+    {{#if date}}
+      {{#each date as |item| }}
+        <span class="filters date">{{item}}<span class="fa fa-times" {{action 'deleteTag' 'date' item }}></span></span>
+      {{/each}}
+    {{/if}}
+    {{#if thematique}}
+      <span class="filters thematique">{{thematique}}<span class="fa fa-times" {{action 'deleteTag' 'thematique'}}></span></span>
+    {{/if}}
+  </p>
 </div>
+<div class='result-list'>
+  {{#each filteredDocuments as |item| }}
+    <div id="{{item.id}}" {{action "showMore" item}} class='result-item'>
+      <span class="playing-indicator fa fa-play-circle fa-lg fa-fw pull-right" {{action 'play' item}}></span>
+      <strong>{{ item.title }}</strong>
+      <div class="description">
+        {{item.language}}
+      </div>
+      <div class="hidden-elt">
+        <button class="pull-right" {{action 'toggleModal' item}}>Details</button>
+      </div>
+    </div>
+  {{/each}}
+</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/templates/tabs/carto.hbs	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,1 @@
+{{visu-carto action="updateUrl" documents=model}}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/templates/tabs/chrono.hbs	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,2 @@
+<h2>Selectionnez une date:</h2>
+{{visu-chrono action="updateUrl" query=model}}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/templates/tabs/detail.hbs	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,14 @@
+<div class="notice">
+  <div class="notice-header">
+    <h2>Notice</h2>
+  </div>
+  <div class="notice-body">
+    <p><b>Titre </b>{{model.title}}</p>
+    <p><b>Langue </b>{{model.language}}</p>
+    <p><b>Enregistré le </b>{{model.modified}}</p>
+    <p><b>Interviewer </b>{{model.publishers}}</p>
+    <p><b>Description </b>{{model.description}}</p>
+    <p><b>Type de Discours </b>{{model.type}}</p>
+    <p><b>Localisation </b>{{model.spatial}}</p>
+  </div>
+</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/templates/tabs/discours.hbs	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,30 @@
+<div class="visu-discours">
+  <div class='left'>
+    <p {{action 'updateUrl' 'Dialogue'}}>Dialogue</p>
+    <p {{action 'updateUrl' 'Conversation'}}>Conversation</p>
+    <p {{action 'updateUrl' 'Entretien'}}>Entretien</p>
+    <p {{action 'updateUrl' 'Discussion'}}>Discussion</p>
+    <p {{action 'updateUrl' 'Bavardage'}}>Bavardage</p>
+    <p {{action 'updateUrl' 'Argumentation'}}>Argumentation</p>
+    <p {{action 'updateUrl' 'Negociation'}}>Negociation</p>
+    <p {{action 'updateUrl' 'Reunion'}}>Reunion</p>
+    <p {{action 'updateUrl' 'Discours'}}>Discours</p>
+    <p {{action 'updateUrl' 'Lecture a haute voix'}}>Lecture a haute voix</p>
+    <p {{action 'updateUrl' 'Recitation'}}>Recitation</p>
+    <p {{action 'updateUrl' 'Recit personnel'}}>Recit personnel</p>
+    <p {{action 'updateUrl' 'Seminaire'}}>Seminaire</p>
+  </div>
+  <div class='right'>
+    <p {{action 'updateUrl' 'Colloque'}}>Colloque</p>
+    <p {{action 'updateUrl' 'Conte'}}>Conte</p>
+    <p {{action 'updateUrl' 'Fable'}}>Fable</p>
+    <p {{action 'updateUrl' 'Narration'}}>Narration</p>
+    <p {{action 'updateUrl' 'Chanson'}}>Chanson</p>
+    <p {{action 'updateUrl' 'Enquete par telephone'}}>Enquete par telephone</p>
+    <p {{action 'updateUrl' 'Questionnaire'}}>Questionnaire</p>
+    <p {{action 'updateUrl' 'Enquete'}}>Enquete</p>
+    <p {{action 'updateUrl' 'Enquetes linguistiques'}}>Enquetes linguistiques</p>
+    <p {{action 'updateUrl' 'Enquetes de terrain'}}>Enquetes de terrain</p>
+    <p {{action 'updateUrl' 'Musique instrumentale'}}>Musique instrumentale</p>
+  </div>
+</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/templates/tabs/langues.hbs	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,1 @@
+{{visu-langues action="updateUrl" query=model}}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/templates/tabs/thematiques.hbs	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,60 @@
+<div class="search-box">
+  {{input type="text" placeholder="Entrez une thématique" action="updateUrl"}}
+</div>
+
+<div class="tag-cloud">
+  <span {{action 'updateUrl' 'ipsum'}} class="popular">ipsum</span>
+  <span {{action 'Url' 'dolor'}} class="not-popular">dolor</span>
+  <span {{action 'updateUrl' 'sit'}} class="not-popular">sit</span>
+  <span {{action 'updateUrl' 'amet'}} class="popular">amet</span>
+  <span {{action 'updateUrl' 'consectetur'}} class="popular">consectetur</span>
+  <span {{action 'updateUrl' 'adipiscing'}} class="not-popular">adipiscing</span>
+  <span {{action 'updateUrl' 'elit'}} class="very-popular">elit</span>
+  <span {{action 'updateUrl' 'Curabitur'}} class="not-popular">Curabitur</span>
+  <span {{action 'updateUrl' 'non'}} class="popular">non</span>
+  <span {{action 'updateUrl' 'ipsum'}} class="not-popular">ipsum</span>
+  <span {{action 'updateUrl' 'dolor'}} class="very-popular">dolor</span>
+  <span {{action 'updateUrl' 'sit'}} class="not-popular">sit</span>
+  <span {{action 'updateUrl' 'amet'}} class="popular">amet</span>
+  <span {{action 'updateUrl' 'consectetur'}} class="popular">consectetur</span>
+  <span {{action 'updateUrl' 'adipiscing'}} class="not-popular">adipiscing</span>
+  <span {{action 'updateUrl' 'elit'}} class="not-popular">elit</span>
+  <span {{action 'updateUrl' 'Curabitur'}} class="popular">Curabitur</span>
+  <span {{action 'updateUrl' 'non'}} class="not-popular">non</span>
+  <span {{action 'updateUrl' 'ipsum'}} class="popular">ipsum</span>
+  <span {{action 'updateUrl' 'dolor'}} class="popular">dolor</span>
+  <span {{action 'updateUrl' 'sit'}} class="not-popular">sit</span>
+  <span {{action 'updateUrl' 'amet'}} class="not-popular">amet</span>
+  <span {{action 'updateUrl' 'consectetur'}} class="not-popular">consectetur</span>
+  <span {{action 'updateUrl' 'adipiscing'}} class="not-popular">adipiscing</span>
+  <span {{action 'updateUrl' 'elit'}} class="very-popular">elit</span>
+  <span {{action 'updateUrl' 'Curabitur'}} class="popular">Curabitur</span>
+  <span {{action 'updateUrl' 'non'}} class="very-popular">non</span>
+  <span {{action 'updateUrl' 'ipsum'}} class="popular">ipsum</span>
+  <span {{action 'updateUrl' 'dolor'}} class="not-popular">dolor</span>
+  <span {{action 'updateUrl' 'sit'}} class="not-popular">sit</span>
+  <span {{action 'updateUrl' 'amet'}} class="popular">amet</span>
+  <span {{action 'updateUrl' 'consectetur'}} class="popular">consectetur</span>
+  <span {{action 'updateUrl' 'adipiscing'}} class="not-popular">adipiscing</span>
+  <span {{action 'updateUrl' 'elit'}} class="very-popular">elit</span>
+  <span {{action 'updateUrl' 'Curabitur'}} class="not-popular">Curabitur</span>
+  <span {{action 'updateUrl' 'non'}} class="popular">non</span>
+  <span {{action 'updateUrl' 'ipsum'}} class="not-popular">ipsum</span>
+  <span {{action 'updateUrl' 'dolor'}} class="very-popular">dolor</span>
+  <span {{action 'updateUrl' 'sit'}} class="not-popular">sit</span>
+  <span {{action 'updateUrl' 'amet'}} class="popular">amet</span>
+  <span {{action 'updateUrl' 'consectetur'}} class="popular">consectetur</span>
+  <span {{action 'updateUrl' 'adipiscing'}} class="not-popular">adipiscing</span>
+  <span {{action 'updateUrl' 'elit'}} class="not-popular">elit</span>
+  <span {{action 'updateUrl' 'Curabitur'}} class="popular">Curabitur</span>
+  <span {{action 'updateUrl' 'non'}} class="not-popular">non</span>
+  <span {{action 'updateUrl' 'ipsum'}} class="popular">ipsum</span>
+  <span {{action 'updateUrl' 'dolor'}} class="popular">dolor</span>
+  <span {{action 'updateUrl' 'sit'}} class="not-popular">sit</span>
+  <span {{action 'updateUrl' 'amet'}} class="not-popular">amet</span>
+  <span {{action 'updateUrl' 'consectetur'}} class="not-popular">consectetur</span>
+  <span {{action 'updateUrl' 'adipiscing'}} class="not-popular">adipiscing</span>
+  <span {{action 'updateUrl' 'elit'}} class="very-popular">elit</span>
+  <span {{action 'updateUrl' 'Curabitur'}} class="popular">Curabitur</span>
+  <span {{action 'updateUrl' 'non'}} class="very-popular">non</span>
+</div>
--- a/cms/app-client/app/templates/visus/visu-carto.hbs	Sat Jan 16 00:33:26 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-<h2>Recherche par cartographie</h2>
-<p>With a Logo !</p>
-<img src={{logoUrl}} alt="Logo">
--- a/cms/app-client/app/templates/visus/visu-chrono.hbs	Sat Jan 16 00:33:26 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-<h2>Recherche par chronologie</h2>
--- a/cms/app-client/app/templates/visus/visu-discours.hbs	Sat Jan 16 00:33:26 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-<h2>Recherche par discours</h2>
--- a/cms/app-client/app/templates/visus/visu-langues.hbs	Sat Jan 16 00:33:26 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-<h2>Recherche par langues</h2>
--- a/cms/app-client/app/templates/visus/visu-thematiques.hbs	Sat Jan 16 00:33:26 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-<h2>Recherche par thematiques</h2>
--- a/cms/app-client/bower.json	Sat Jan 16 00:33:26 2016 +0100
+++ b/cms/app-client/bower.json	Fri Jan 22 14:31:17 2016 +0100
@@ -1,17 +1,26 @@
 {
   "name": "app-client",
   "dependencies": {
-    "ember": "1.13.7",
-    "ember-cli-shims": "ember-cli/ember-cli-shims#0.0.3",
+    "ember": "2.2.0",
+    "ember-cli-shims": "ember-cli/ember-cli-shims#0.0.6",
     "ember-cli-test-loader": "ember-cli-test-loader#0.1.3",
-    "ember-data": "1.13.8",
-    "ember-load-initializers": "ember-cli/ember-load-initializers#0.1.5",
-    "ember-qunit": "0.4.9",
-    "ember-qunit-notifications": "0.0.7",
-    "ember-resolver": "~0.1.18",
+    "ember-data": ">=2.1.0",
+    "ember-load-initializers": "ember-cli/ember-load-initializers#0.1.7",
+    "ember-qunit": ">=0.4.9",
+    "ember-qunit-notifications": ">=0.0.7",
+    "ember-resolver": ">=0.1.18",
     "jquery": "^1.11.3",
-    "loader.js": "ember-cli/loader.js#3.2.1",
+    "loader.js": "ember-cli/loader.js#3.5.0",
     "qunit": "~1.18.0",
-    "bootstrap-sass": "~3.3.5"
+    "bootstrap-sass": "bootstrap-sass-official#~3.3.6",
+    "ammap3": "~3.18.6",
+    "font-awesome": "~4.4.0"
+  },
+  "resolutions": {
+    "qunit-notifications": "~0.1.0",
+    "ember-load-initializers": "0.1.7",
+    "loader.js": "3.5.0",
+    "ember-cli-shims": "0.0.6",
+    "ember": "2.2.0"
   }
 }
--- a/cms/app-client/config/environment.js	Sat Jan 16 00:33:26 2016 +0100
+++ b/cms/app-client/config/environment.js	Fri Jan 22 14:31:17 2016 +0100
@@ -5,8 +5,12 @@
     rootElement: '#corpus-app',
     modulePrefix: 'app-client',
     environment: environment,
-    baseURL: '/corpus',
-    locationType: 'auto',
+    baseURL: '/corpus/',
+    // locationType: '',
+    // contentSecurityPolicy: {
+    //   'default-src': "'none'",
+    //   'style-src': "'self' 'http://localhost:4200'"
+    // },
     APP: {
       baseStatic: '',
       // Here you can pass flags/options to your application instance
@@ -21,6 +25,15 @@
     // ENV.APP.LOG_TRANSITIONS = true;
     // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
     // ENV.APP.LOG_VIEW_LOOKUPS = true;
+    ENV.contentSecurityPolicy = {
+      'default-src': "'none'",
+      'script-src': "'self' *",
+      'font-src': "'self'",
+      'connect-src': "'self' *",
+      'img-src': "'self'",
+      'style-src': "'self' *",
+      'media-src': "'self'"
+    };
   }
 
   if (environment === 'test') {
--- a/cms/app-client/ember-cli-build.js	Sat Jan 16 00:33:26 2016 +0100
+++ b/cms/app-client/ember-cli-build.js	Fri Jan 22 14:31:17 2016 +0100
@@ -26,6 +26,10 @@
   // modules that you would like to import into your application
   // please specify an object with the list of modules as keys
   // along with the exports of each module as its value.
+  app.import('bower_components/ammap3/ammap/ammap.js');
+  app.import('bower_components/ammap3/ammap/maps/js/worldLow.js');
+  app.import('bower_components/ammap3/ammap/maps/js/continentsLow.js');
+  app.import('bower_components/ammap3/ammap/maps/js/france2016Low.js');
 
   return app.toTree();
 };
--- a/cms/app-client/package.json	Sat Jan 16 00:33:26 2016 +0100
+++ b/cms/app-client/package.json	Fri Jan 22 14:31:17 2016 +0100
@@ -24,7 +24,9 @@
     "ember-cli-app-version": "0.5.0",
     "ember-cli-babel": "^5.1.3",
     "ember-cli-content-security-policy": "0.4.0",
+    "ember-cli-d3": "1.1.2",
     "ember-cli-dependency-checker": "^1.0.1",
+    "ember-cli-font-awesome": "1.3.0",
     "ember-cli-htmlbars": "0.7.9",
     "ember-cli-htmlbars-inline-precompile": "^0.2.0",
     "ember-cli-ic-ajax": "0.2.1",
@@ -35,7 +37,10 @@
     "ember-cli-sri": "^1.0.3",
     "ember-cli-uglify": "^1.2.0",
     "ember-data": "1.13.8",
+    "ember-data-fixture-adapter": "1.13.0",
     "ember-disable-proxy-controllers": "^1.0.0",
-    "ember-export-application-global": "^1.0.3"
+    "ember-export-application-global": "^1.0.3",
+    "ember-lodash": "0.0.6",
+    "ember-wormhole": "0.3.4"
   }
 }
Binary file cms/app-client/public/assets/images/button_pause.png has changed
Binary file cms/app-client/public/assets/images/button_play.png has changed
Binary file cms/app-client/public/assets/images/equalizer.png has changed
Binary file cms/app-client/public/assets/images/play-button.png has changed
Binary file cms/app-client/public/assets/images/playing.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/public/langues.json	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,194 @@
+{
+ "name": "Global",
+ "children": [
+  {
+    "id": "id de langue (code Lexvo de la langues)",
+    "name": "Français",
+    "value": 859
+  },
+  {
+    "name": "Alsacien",
+    "value": 851
+  },
+  {
+    "name": "Breton",
+    "value": 403
+  },
+  {
+    "name": "Occitan",
+    "value": 344
+  },
+  {
+    "name": "Judéo-espagnol",
+    "value": 77
+  },
+  {
+    "name": "Undetermined",
+    "value": 45
+  },
+  {
+    "name": "Langues régionales",
+    "value": 175,
+    "children": [
+      {
+        "name": "Langues d'oïl",
+        "value": 75
+      },
+      {
+        "name": "Francoprovençal",
+        "value": 60
+      },
+      {
+        "name": "Corse",
+        "value": 40
+      }
+    ]
+  },
+  {
+    "name": "Langues non territoriales",
+    "value": 48,
+    "children": [
+      {
+        "name": "Langue des signes française (LSF)",
+        "value": 40
+      },
+      {
+        "name": "Berbère",
+        "value": 8
+      }
+    ]
+  },
+  {
+    "name": "Les Creoles",
+    "value": 47,
+    "children": [
+      {
+        "name": "Creole de la Réunion",
+        "value": 32
+      },
+      {
+        "name": "Creole de la Guadeloupe",
+        "value": 15
+      }
+    ]
+  },
+  {
+    "name": "Guyane",
+    "value": 59,
+    "children": [
+      {
+        "name": "Ndyuka-Trio Pidgin (njt)",
+        "value": 31
+      },
+      {
+        "name": "Palikúr (plu)",
+        "value": 6
+      },
+      {
+        "name": "Guianese Creole French (gcr)",
+        "value": 4
+      },
+      {
+        "name": "Eastern Maroon Creole (djk)",
+        "value": 16
+      },
+      {
+        "name": "Sranan Tongo (srn)",
+        "value": 2
+      }
+    ]
+  },
+  {
+    "name": "Mayotte",
+    "value": 20,
+    "children": [
+      {
+        "name": "Maore Comorian (swb)",
+        "value": 2
+      },
+      {
+        "name": "Mauritian Sign Language (lsy)",
+        "value": 18
+      }
+    ]
+  },
+  {
+    "name": "Polynésie française",
+    "value": 13,
+    "children": [
+      {
+        "name": "West Uvean (uve)",
+        "value": 13
+      }
+    ]
+  },
+  {
+    "name": "Wallis et Futuna",
+    "value": 43,
+    "children": [
+      {
+        "name": "LanEast Futuna (fud)",
+        "value": 23
+      },
+      {
+        "name": "Wallisian (wls)",
+        "value": 20
+      }
+    ]
+  },
+  {
+    "name": "Nouvelle-Calédonie",
+    "value": 68,
+    "children": [
+      {
+        "name": "Wallisian (wls)",
+        "value": 15
+      },
+      {
+        "name": "Xârâcùù (ane)",
+        "value": 12
+      },
+      {
+        "name": "Cemuhî (cam)",
+        "value": 9
+      },
+      {
+        "name": "Xaragure (axx)",
+        "value": 9
+      },
+      {
+        "name": "Iaai (iai)",
+        "value": 8
+      },
+      {
+        "name": "Nêlêmwa-Nixumwak (nee)",
+        "value": 4
+      },
+      {
+        "name": "Dehu (dhv)",
+        "value": 2
+      },
+      {
+        "name": "Nengone (nen)",
+        "value": 2
+      },
+      {
+        "name": "Ajië (aji)",
+        "value": 1
+      },
+      {
+        "name": "Numee (kdk)",
+        "value": 1
+      },
+      {
+        "name": "Yuaga (nua)",
+        "value": 1
+      },
+      {
+        "name": "Bwatoo (bwa)",
+        "value": 4
+      }
+    ]
+  }
+ ]
+}
--- a/cms/app-client/public/styles.css	Sat Jan 16 00:33:26 2016 +0100
+++ b/cms/app-client/public/styles.css	Fri Jan 22 14:31:17 2016 +0100
@@ -3,9 +3,9 @@
 }
 .header {
   /*background-color: green;*/
-  width: 940px;
+  width: 1108px;
   height: 90px;
-  display: block;
+  display: table;
   margin-left: auto;
   margin-right: auto;
   margin-bottom: 1px;
@@ -37,8 +37,8 @@
   position:relative;
   left:50%;
   padding: 0;
-  display: inline-block;
-  width: 100%;
+  display: table;
+  width: auto;
   float: none;
   margin: 0 auto 0 auto;
 }
@@ -64,3 +64,8 @@
   font-weight: 900;
   background-color: bisque;
 }
+
+.sub-menu{
+  margin-right: 10px;
+  cursor: pointer;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/tests/integration/components/player-component-test.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,26 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('player-component', 'Integration | Component | player component', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  assert.expect(2);
+
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });
+
+  this.render(hbs`{{player-component}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:
+  this.render(hbs`
+    {{#player-component}}
+      template block text
+    {{/player-component}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/tests/integration/components/visu-carto-test.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,26 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('visu-carto', 'Integration | Component | visu carto', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  assert.expect(2);
+
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });
+
+  this.render(hbs`{{visu-carto}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:
+  this.render(hbs`
+    {{#visu-carto}}
+      template block text
+    {{/visu-carto}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/tests/integration/components/visu-chrono-test.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,26 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('visu-chrono', 'Integration | Component | visu chrono', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  assert.expect(2);
+
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });
+
+  this.render(hbs`{{visu-chrono}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:
+  this.render(hbs`
+    {{#visu-chrono}}
+      template block text
+    {{/visu-chrono}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/tests/integration/components/visu-langues-test.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,26 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('visu-langues', 'Integration | Component | visu langues', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  assert.expect(2);
+
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });
+
+  this.render(hbs`{{visu-langues}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:
+  this.render(hbs`
+    {{#visu-langues}}
+      template block text
+    {{/visu-langues}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/tests/unit/adapters/application-test.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,12 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('adapter:application', 'Unit | Adapter | application', {
+  // Specify the other units that are required for this test.
+  // needs: ['serializer:foo']
+});
+
+// Replace this with your real tests.
+test('it exists', function(assert) {
+  var adapter = this.subject();
+  assert.ok(adapter);
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/tests/unit/controllers/results-test.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,12 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('controller:results', {
+  // Specify the other units that are required for this test.
+  // needs: ['controller:foo']
+});
+
+// Replace this with your real tests.
+test('it exists', function(assert) {
+  var controller = this.subject();
+  assert.ok(controller);
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/tests/unit/models/sound-test.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,12 @@
+import { moduleForModel, test } from 'ember-qunit';
+
+moduleForModel('sound', 'Unit | Model | sound', {
+  // Specify the other units that are required for this test.
+  needs: []
+});
+
+test('it exists', function(assert) {
+  var model = this.subject();
+  // var store = this.store();
+  assert.ok(!!model);
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/tests/unit/routes/application-test.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,11 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('route:application', 'Unit | Route | application', {
+  // Specify the other units that are required for this test.
+  // needs: ['controller:foo']
+});
+
+test('it exists', function(assert) {
+  var route = this.subject();
+  assert.ok(route);
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/tests/unit/routes/results-test.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,11 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('route:results', 'Unit | Route | results', {
+  // Specify the other units that are required for this test.
+  // needs: ['controller:foo']
+});
+
+test('it exists', function(assert) {
+  var route = this.subject();
+  assert.ok(route);
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/tests/unit/routes/sound-test.js	Fri Jan 22 14:31:17 2016 +0100
@@ -0,0 +1,11 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('route:sound', 'Unit | Route | sound', {
+  // Specify the other units that are required for this test.
+  // needs: ['controller:foo']
+});
+
+test('it exists', function(assert) {
+  var route = this.subject();
+  assert.ok(route);
+});
--- a/cms/corpus_module/corpus.module	Sat Jan 16 00:33:26 2016 +0100
+++ b/cms/corpus_module/corpus.module	Fri Jan 22 14:31:17 2016 +0100
@@ -38,12 +38,13 @@
    '#tag' => 'meta', // The #tag is the html tag - <link />
    '#attributes' => array( // Set up an array of attributes inside the tag
      'name' => 'app-client/config/environment',
-     'content' => '%7B%22rootElement%22%3A%22%23corpus-app%22%2C%22modulePrefix%22%3A%22app-client%22%2C%22environment%22%3A%22production%22%2C%22baseURL%22%3A%22/corpus%22%2C%22locationType%22%3A%22auto%22%2C%22APP%22%3A%7B%22baseStatic%22%3A%22/'.drupal_get_path('module', 'corpus').'/app-client/%22%2C%22name%22%3A%22app-client%22%2C%22version%22%3A%220.0.0+%22%7D%2C%22contentSecurityPolicyHeader%22%3A%22Content-Security-Policy-Report-Only%22%2C%22contentSecurityPolicy%22%3A%7B%22default-src%22%3A%22%27none%27%22%2C%22script-src%22%3A%22%27self%27%22%2C%22font-src%22%3A%22%27self%27%22%2C%22connect-src%22%3A%22%27self%27%22%2C%22img-src%22%3A%22%27self%27%22%2C%22style-src%22%3A%22%27self%27%22%2C%22media-src%22%3A%22%27self%27%22%7D%2C%22exportApplicationGlobal%22%3Afalse%7D'
+     'content' => '%7B%22rootElement%22%3A%22%23corpus-app%22%2C%22modulePrefix%22%3A%22app-client%22%2C%22environment%22%3A%22production%22%2C%22baseURL%22%3A%22/corpus%22%2C%22APP%22%3A%7B%22baseStatic%22%3A%22%22%2C%22name%22%3A%22app-client%22%2C%22version%22%3A%220.0.0+%22%7D%2C%22contentSecurityPolicyHeader%22%3A%22Content-Security-Policy-Report-Only%22%2C%22contentSecurityPolicy%22%3A%7B%22default-src%22%3A%22%27none%27%22%2C%22script-src%22%3A%22%27self%27%20%27unsafe-eval%27%22%2C%22font-src%22%3A%22%27self%27%22%2C%22connect-src%22%3A%22%27self%27%22%2C%22img-src%22%3A%22%27self%27%22%2C%22style-src%22%3A%22%27self%27%22%2C%22media-src%22%3A%22%27self%27%22%7D%2C%22exportApplicationGlobal%22%3Atrue%7D'
    ),
  );
 
  drupal_add_html_head($element, 'ember_init');
 
+ drupal_add_js("https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1.1','packages':['treemap']}]}");
  drupal_add_js("{$path}/assets/vendor.js");
  drupal_add_css("{$path}/assets/vendor.css");
  drupal_add_css("{$path}/assets/{$app}.css");
@@ -51,5 +52,5 @@
  drupal_add_js("{$path}/assets/{$app}.js", array('type' => 'file', 'scope' => 'footer'));
  // drupal_add_js("{$path}/dist/assets/{$app}.js");
 
- return "<div id='corpus-app'></div>";
+ return "<div id='corpus-app' class='corpus-app'></div>";
 }