Commit 8a00269a authored by arturo's avatar arturo

>>> continue

parent 2b96ca23
Pipeline #2041 failed with stage
......@@ -12,7 +12,7 @@ import Data.HTTP.Method (Method(..))
import Data.Maybe (Maybe(..))
import Effect.Aff (Aff, launchAff_)
import Effect.Class (liftEffect)
import Gargantext.Components.PhyloExplorer.JSON (PhyloJSONSet)
import Gargantext.Components.PhyloExplorer.JSON (PhyloJSONSet(..))
import Gargantext.Components.PhyloExplorer.Layout (layout)
import Gargantext.Components.PhyloExplorer.Types (PhyloDataSet, parsePhyloJSONSet)
import Gargantext.Sessions (Session)
......
'use strict';
exports._drawPhylo = drawPhylo;
// set javascript date from a string year
function yearToDate(year) {
var d = new Date()
......@@ -10,39 +12,39 @@ function yearToDate(year) {
}
function stringToDate(str) {
var arr = (str.replace('"','')).split('-');
var d = new Date();
d.setYear(parseInt(arr[0]));
d.setMonth(parseInt(arr[1]));
d.setMonth(d.getMonth() - 1);
d.setDate(parseInt(arr[2]));
return d;
var arr = (str.replace('"','')).split('-');
var d = new Date();
d.setYear(parseInt(arr[0]));
d.setMonth(parseInt(arr[1]));
d.setMonth(d.getMonth() - 1);
d.setDate(parseInt(arr[2]));
return d;
}
function utcStringToDate(str) {
var arr = ((str.replace('"','')).replace(' UTC','')).split(/[\s-:]+/);
var d = new Date();
d.setYear(parseInt(arr[0]));
d.setMonth(parseInt(arr[1]));
d.setDate(parseInt(arr[2]));
d.setHours(parseInt(arr[3]),parseInt(arr[4]),parseInt(arr[5]))
return d;
var arr = ((str.replace('"','')).replace(' UTC','')).split(/[\s-:]+/);
var d = new Date();
d.setYear(parseInt(arr[0]));
d.setMonth(parseInt(arr[1]));
d.setDate(parseInt(arr[2]));
d.setHours(parseInt(arr[3]),parseInt(arr[4]),parseInt(arr[5]))
return d;
}
function stringArrToArr(str) {
var arr = ((str.replace('["','')).replace('"]','')).split('","');
return arr;
var arr = ((str.replace('["','')).replace('"]','')).split('","');
return arr;
}
function intArrToArr(int) {
var arr = ((int.replace('[','')).replace(']','')).split(',');
return arr;
var arr = ((int.replace('[','')).replace(']','')).split(',');
return arr;
}
function yearToDateHacked(w) {
var d = new Date(2020,0,0);
d.setDate(d.getDate() + (w * 7));
return d
var d = new Date(2020,0,0);
d.setDate(d.getDate() + (w * 7));
return d
}
function toCoord(id) {
......@@ -54,40 +56,40 @@ function toCoord(id) {
function toXLabels(branches, groups, xMax) {
var xLabels = branches.map(function(b) {
var bId = b.bId,
xs = groups.filter(g => g.bId == bId).map(g => g.x),
inf = Math.min(...xs),
sup = Math.max(...xs);
return { x : b.x2,
label : b.label.replace(/\"/g, '').replace(/\|/g, ''),
inf : inf,
sup : sup,
bId : bId};
var bId = b.bId,
xs = groups.filter(g => g.bId == bId).map(g => g.x),
inf = Math.min(...xs),
sup = Math.max(...xs);
return { x : b.x2,
label : b.label.replace(/\"/g, '').replace(/\|/g, ''),
inf : inf,
sup : sup,
bId : bId};
})
return xLabels.map(function(b,i){
var prec = 0,
succ = xMax;
var prec = 0,
succ = xMax;
if (i != 0)
prec = xLabels[i -1].sup
if (i != 0)
prec = xLabels[i -1].sup
if (i != (xLabels.length - 1))
succ = xLabels[i + 1].inf
if (i != (xLabels.length - 1))
succ = xLabels[i + 1].inf
var w = Math.min(...[(b.x - prec) / 2,(succ - b.x) / 2]),
inf = b.x - w,
sup = b.x + w;
var w = Math.min(...[(b.x - prec) / 2,(succ - b.x) / 2]),
inf = b.x - w,
sup = b.x + w;
inf = (b.inf < inf) ? b.inf : inf + (w / 10);
sup = (b.sup > sup) ? b.sup : sup - (w / 10);
inf = (b.inf < inf) ? b.inf : inf + (w / 10);
sup = (b.sup > sup) ? b.sup : sup - (w / 10);
return { x : (sup + inf) / 2,
label : b.label,
inf : inf,
sup : sup,
bId : b.bId};
return { x : (sup + inf) / 2,
label : b.label,
inf : inf,
sup : sup,
bId : b.bId};
})
}
......@@ -116,6 +118,7 @@ function xOverFlow(ticks,arr) {
var branchFocus = [];
function addMarkX(ticks,ws,ids) {
ticks.each(function(t,i){
d3.select(this)
......@@ -139,6 +142,7 @@ function setMarkYLabel(labels) {
})
}
function addMarkY(ticks) {
ticks.each(function(d,i){
if (d3.timeYear(d) < d) {
......@@ -168,6 +172,7 @@ function removeDays(date, days) {
return result;
}
function setYDomain(labels) {
var ts = ["week","month","day","year","epoch"];
......@@ -207,20 +212,21 @@ function setYDomain(labels) {
return [inf,sup];
}
function groupTermsBy(elements, attr) {
let grouped = {},
curr = "";
for (var i = 0; i < elements.length; i++) {
let from = elements[i].getAttribute(attr)
if (curr != from) {
grouped[from] = [[(elements[i]).getAttribute("gx"),(elements[i]).getAttribute("gy"),(elements[i]).getAttribute("bid")]];
curr = from
} else {
grouped[from].push([(elements[i]).getAttribute("gx"),(elements[i]).getAttribute("gy"),(elements[i]).getAttribute("bid")]);
let grouped = {},
curr = "";
for (var i = 0; i < elements.length; i++) {
let from = elements[i].getAttribute(attr)
if (curr != from) {
grouped[from] = [[(elements[i]).getAttribute("gx"),(elements[i]).getAttribute("gy"),(elements[i]).getAttribute("bid")]];
curr = from
} else {
grouped[from].push([(elements[i]).getAttribute("gx"),(elements[i]).getAttribute("gy"),(elements[i]).getAttribute("bid")]);
}
}
}
return Object.values(grouped);
};
return Object.values(grouped);
};
function findValueByPrefix(prefix) {
......@@ -235,6 +241,7 @@ function findValueByPrefix(prefix) {
return null;
}
function highlightSource() {
let checkSource = document.getElementById("checkSource");
let value = checkSource.options[checkSource.selectedIndex].value;
......@@ -266,47 +273,47 @@ function highlightSource() {
.classed("peak-focus-source", true);
})
}
}
function drawWordCloud (groups) {
}
let labels = {},
count = 0;
function drawWordCloud (groups) {
d3.selectAll(".word-cloud").remove();
let labels = {},
count = 0;
groups.forEach(function(g){
let gid = (g.getAttribute("id")).replace("group","");
let terms = d3.selectAll(".term").filter(".g-" + gid).nodes();
terms.forEach(function(t){
count ++;
if (labels[t.getAttribute("fdt")] == undefined) {
labels[t.getAttribute("fdt")] = {"freq" : 1, "label" : t.getAttribute("label")}
} else {
labels[t.getAttribute("fdt")].freq = labels[t.getAttribute("fdt")].freq + 1
}
})
});
d3.selectAll(".word-cloud").remove();
labels = (Object.values(labels)).map(function(l){
return {"freq":(l.freq / count),"label":l.label};
}).sort(function(l1,l2){
return l2.freq - l1.freq;
groups.forEach(function(g){
let gid = (g.getAttribute("id")).replace("group","");
let terms = d3.selectAll(".term").filter(".g-" + gid).nodes();
terms.forEach(function(t){
count ++;
if (labels[t.getAttribute("fdt")] == undefined) {
labels[t.getAttribute("fdt")] = {"freq" : 1, "label" : t.getAttribute("label")}
} else {
labels[t.getAttribute("fdt")].freq = labels[t.getAttribute("fdt")].freq + 1
}
})
});
let y = 20
let opacity = d3.scaleLinear().domain([Math.log((labels[labels.length - 1]).freq),Math.log((labels[0]).freq)]).range([0.5,1]);
labels.forEach(function(l){
y = y + 12;
window.svg3.append("text")
.attr("class","word-cloud")
.attr("x", 10)
.attr("y", y)
.style("opacity", opacity(Math.log(l.freq)))
.text(l.label);
})
}
labels = (Object.values(labels)).map(function(l){
return {"freq":(l.freq / count),"label":l.label};
}).sort(function(l1,l2){
return l2.freq - l1.freq;
})
let y = 20
let opacity = d3.scaleLinear().domain([Math.log((labels[labels.length - 1]).freq),Math.log((labels[0]).freq)]).range([0.5,1]);
labels.forEach(function(l){
y = y + 12;
window.svg3.append("text")
.attr("class","word-cloud")
.attr("x", 10)
.attr("y", y)
.style("opacity", opacity(Math.log(l.freq)))
.text(l.label);
})
}
function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
......@@ -430,7 +437,6 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
.attr("height",div3.height)
.append("g");
/* labels */
var firstDate = Math.min(...groups.map(g => (g.from).getFullYear()))
......@@ -492,10 +498,10 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
/* links */
function findGroup (id, xsc, ysc) {
var group = groups.find(g => g.gId == id),
x = xsc(group.x);
y = ysc(group.to);
return [x,y]
var group = groups.find(g => g.gId == id),
x = xsc(group.x);
y = ysc(group.to);
return [x,y]
}
var linkGen = d3.linkVertical();
......@@ -716,6 +722,7 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
});
});
function landingView() {
window.ldView = true;
doubleClick()
......@@ -756,8 +763,8 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
/* groups */
function textWidth(text) {
const context = document.createElement("canvas").getContext("2d");
return context.measureText(text).width;
const context = document.createElement("canvas").getContext("2d");
return context.measureText(text).width;
}
function toLines(words,fdt,role,targetWidth) {
......@@ -789,7 +796,9 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
for (let i = 0, n = lines.length; i < n; ++i) {
const dy = (Math.abs(i - n / 2 + 0.5) + 2) * lineHeight;
const dx = lines[i].width / 2;
radius = Math.max(radius, Math.sqrt(dx ** 2 + dy ** 2));
const sdy = Math.pow(dy, 2);
const sdx = Math.pow(dx, 2);
radius = Math.max(radius, Math.sqrt(sdx + sdy));
}
return radius;
}
......@@ -902,7 +911,6 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
d3.selectAll(".header").raise();
function findRole(r) {
if (r == 0) {
return " emerging";
......@@ -1048,81 +1056,79 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
}
}
}
function termClick (txt,idx,nodeId,typeNode) {
function termClick (txt,idx,nodeId,typeNode) {
// remove old focus
initPath()
// remove old focus
initPath()
// catch the last transformations
if (typeNode == "group") {
var transform = d3.select("#group" + nodeId).node().getAttribute("transform");
} else if (typeNode == "head") {
var transform = d3.select("#head" + nodeId).node().getAttribute("transform");
} else {
var transform = (d3.selectAll(".header").nodes())[0].getAttribute("transform");
}
// catch the last transformations
if (typeNode == "group") {
var transform = d3.select("#group" + nodeId).node().getAttribute("transform");
} else if (typeNode == "head") {
var transform = d3.select("#head" + nodeId).node().getAttribute("transform");
} else {
var transform = (d3.selectAll(".header").nodes())[0].getAttribute("transform");
}
// focus
// focus
document.querySelector("#phyloPhylo").innerHTML = txt;
document.querySelector("#phyloPhylo").classList.add("phylo-focus");
document.querySelector("#phyloSearch").setAttribute("href",'https://en.wikipedia.org/w/index.php?search="' + txt + '"')
document.querySelector("#phyloPhylo").innerHTML = txt;
document.querySelector("#phyloPhylo").classList.add("phylo-focus");
document.querySelector("#phyloSearch").setAttribute("href",'https://en.wikipedia.org/w/index.php?search="' + txt + '"')
// highlight the groups
// highlight the groups
var terms = document.getElementsByClassName("fdt-" + idx),
periods = groupTermsBy(terms,"from");
var terms = document.getElementsByClassName("fdt-" + idx),
periods = groupTermsBy(terms,"from");
var groups = [];
var groups = [];
for (var i = 0; i < terms.length; i++) {
groups.push(d3.select("#group" + (terms[i]).getAttribute("gid")));
branchFocus.push((terms[i]).getAttribute("bid"));
}
for (var i = 0; i < terms.length; i++) {
groups.push(d3.select("#group" + (terms[i]).getAttribute("gid")));
branchFocus.push((terms[i]).getAttribute("bid"));
}
highlightGroups(groups.map(g => g.node()));
drawWordCloud(groups.map(g => g.node()));
// highlight the cross branches links
var bids = [];
for (var i = 0; i < periods.length; i++) {
if (i != periods.length - 1) {
for (var j = 0; j < periods[i].length; j++) {
bids.push(periods[i][j][2])
var x1 = periods[i][j][0],
y1 = periods[i][j][1];
for (var k = 0; k < periods[i + 1].length; k++) {
var x2 = periods[i + 1][k][0],
y2 = periods[i + 1][k][1];
if ((periods[i][j][2] != periods[i + 1][k][2]) && (!bids.includes(periods[i + 1][k][2]))) {
// draw the links between branches
panel
.append("path")
.attr("class","term-path")
.attr("d", function(d) {
return "M" + x1 + "," + y1
+ "C" + x2 + "," + y1
+ " " + x2 + "," + y2
+ " " + x2 + "," + y2;
})
.attr("transform",transform)
.style("stroke-opacity", 0.4)
.lower();
highlightGroups(groups.map(g => g.node()));
drawWordCloud(groups.map(g => g.node()));
// highlight the cross branches links
var bids = [];
for (var i = 0; i < periods.length; i++) {
if (i != periods.length - 1) {
for (var j = 0; j < periods[i].length; j++) {
bids.push(periods[i][j][2])
var x1 = periods[i][j][0],
y1 = periods[i][j][1];
for (var k = 0; k < periods[i + 1].length; k++) {
var x2 = periods[i + 1][k][0],
y2 = periods[i + 1][k][1];
if ((periods[i][j][2] != periods[i + 1][k][2]) && (!bids.includes(periods[i + 1][k][2]))) {
// draw the links between branches
panel
.append("path")
.attr("class","term-path")
.attr("d", function(d) {
return "M" + x1 + "," + y1
+ "C" + x2 + "," + y1
+ " " + x2 + "," + y2
+ " " + x2 + "," + y2;
})
.attr("transform",transform)
.style("stroke-opacity", 0.4)
.lower();
}
bids.push(periods[i + 1][k][2])
}
bids.push(periods[i + 1][k][2])
}
}
}
}
d3.selectAll(".path-unfocus").lower();
}
d3.selectAll(".path-unfocus").lower();
}
function peakOver (b,i) {
function peakOver (b,i) {
d3.select("#peak-" + i).classed("peak-focus",false);
d3.select("#peak-" + i).classed("peak-over",true);
label.text(b.label.replace(/"/g,''))
......@@ -1291,101 +1297,102 @@ function drawPhylo(branches, periods, groups, links, aLinks, bLinks, frame) {
function exportViz() {
const xmlns = "http://www.w3.org/2000/xmlns/";
const xlinkns = "http://www.w3.org/1999/xlink";
const svgns = "http://www.w3.org/2000/svg";
const xmlns = "http://www.w3.org/2000/xmlns/";
const xlinkns = "http://www.w3.org/1999/xlink";
const svgns = "http://www.w3.org/2000/svg";
var time = new Date();
var time = new Date();
serialize(svg.node(),"phylomemy-" + Date.parse(time.toString()) + ".svg")
serialize(svg.node(),"phylomemy-" + Date.parse(time.toString()) + ".svg")
function serialize(graph,name) {
graph = graph.cloneNode(true);
const fragment = window.location.href + "#";
const walker = document.createTreeWalker(graph, NodeFilter.SHOW_ELEMENT, null, false);
while (walker.nextNode()) {
for (const attr of walker.currentNode.attributes) {
if (attr.value.includes(fragment)) {
attr.value = attr.value.replace(fragment, "#");
function serialize(graph,name) {
graph = graph.cloneNode(true);
const fragment = window.location.href + "#";
const walker = document.createTreeWalker(graph, NodeFilter.SHOW_ELEMENT, null, false);
while (walker.nextNode()) {
for (const attr of walker.currentNode.attributes) {
if (attr.value.includes(fragment)) {
attr.value = attr.value.replace(fragment, "#");
}
}
}
graph.setAttributeNS(xmlns, "xmlns", svgns);
graph.setAttributeNS(xmlns, "xmlns:xlink", xlinkns);
var cssStyleText = getCSSStyles( graph );
appendCSS( cssStyleText, graph );
const serializer = new window.XMLSerializer;
const string = serializer.serializeToString(graph);
var svgBlob = new Blob([string], {type: "image/svg+xml"});
var svgUrl = URL.createObjectURL(svgBlob);
var downloadLink = document.createElement("a");
downloadLink.href = svgUrl;
downloadLink.download = name;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
};
function getCSSStyles( parentElement ) {
var selectorTextArr = [];
// Add Parent element Id and Classes to the list
selectorTextArr.push( '#'+parentElement.id );
for (var c = 0; c < parentElement.classList.length; c++)
if ( !contains('.'+parentElement.classList[c], selectorTextArr) )
selectorTextArr.push( '.'+parentElement.classList[c] );
// Add Children element Ids and Classes to the list
var nodes = parentElement.getElementsByTagName("*");
for (var i = 0; i < nodes.length; i++) {
var id = nodes[i].id;
if ( !contains('#'+id, selectorTextArr) )
selectorTextArr.push( '#'+id );
var classes = nodes[i].classList;
for (var c = 0; c < classes.length; c++)
if ( !contains('.'+classes[c], selectorTextArr) )
selectorTextArr.push( '.'+classes[c] );
}
}
}
graph.setAttributeNS(xmlns, "xmlns", svgns);
graph.setAttributeNS(xmlns, "xmlns:xlink", xlinkns);
var cssStyleText = getCSSStyles( graph );
appendCSS( cssStyleText, graph );
const serializer = new window.XMLSerializer;
const string = serializer.serializeToString(graph);
var svgBlob = new Blob([string], {type: "image/svg+xml"});
var svgUrl = URL.createObjectURL(svgBlob);
var downloadLink = document.createElement("a");
downloadLink.href = svgUrl;
downloadLink.download = name;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
};
function getCSSStyles( parentElement ) {
var selectorTextArr = [];
// Add Parent element Id and Classes to the list
selectorTextArr.push( '#'+parentElement.id );
for (var c = 0; c < parentElement.classList.length; c++)
if ( !contains('.'+parentElement.classList[c], selectorTextArr) )
selectorTextArr.push( '.'+parentElement.classList[c] );
// Add Children element Ids and Classes to the list
var nodes = parentElement.getElementsByTagName("*");
for (var i = 0; i < nodes.length; i++) {
var id = nodes[i].id;
if ( !contains('#'+id, selectorTextArr) )
selectorTextArr.push( '#'+id );
var classes = nodes[i].classList;
for (var c = 0; c < classes.length; c++)
if ( !contains('.'+classes[c], selectorTextArr) )
selectorTextArr.push( '.'+classes[c] );
}
// Extract CSS Rules
var extractedCSSText = "";
for (var i = 0; i < document.styleSheets.length; i++) {
var s = document.styleSheets[i];
// Extract CSS Rules
var extractedCSSText = "";
for (var i = 0; i < document.styleSheets.length; i++) {
var s = document.styleSheets[i];
try {
if(!s.cssRules) continue;
} catch( e ) {
if(e.name !== 'SecurityError') throw e; // for Firefox
continue;
}
try {
if(!s.cssRules) continue;
} catch( e ) {
if(e.name !== 'SecurityError') throw e; // for Firefox
continue;
}
var cssRules = s.cssRules;
for (var r = 0; r < cssRules.length; r++) {
if ( contains( cssRules[r].selectorText, selectorTextArr ) )
extractedCSSText += cssRules[r].cssText;
}
}
var cssRules = s.cssRules;
for (var r = 0; r < cssRules.length; r++) {
if ( contains( cssRules[r].selectorText, selectorTextArr ) )
extractedCSSText += cssRules[r].cssText;
}
}
return extractedCSSText;
return extractedCSSText;
function contains(str,arr) {
return arr.indexOf( str ) === -1 ? false : true;
}
function contains(str,arr) {
return arr.indexOf( str ) === -1 ? false : true;
}
}
}
function appendCSS( cssText, element ) {
var styleElement = document.createElement("style");
styleElement.setAttribute("type","text/css");
styleElement.innerHTML = cssText;
var refNode = element.hasChildNodes() ? element.children[0] : null;
element.insertBefore( styleElement, refNode );
}
}
function appendCSS( cssText, element ) {
var styleElement = document.createElement("style");
styleElement.setAttribute("type","text/css");
styleElement.innerHTML = cssText;
var refNode = element.hasChildNodes() ? element.children[0] : null;
element.insertBefore( styleElement, refNode );
}
}
}
}
module Gargantext.Components.PhyloExplorer.Draw where
import Gargantext.Prelude
import Data.Function.Uncurried (Fn7, runFn7)
import Effect (Effect)
import Gargantext.Components.PhyloExplorer.Types (AncestorLink, Branch, BranchLink, Group, Link, Period)
foreign import _drawPhylo :: Fn7
(Array Branch)
(Array Period)
(Array Group)
(Array Link)
(Array AncestorLink)
(Array BranchLink)
(Array Number)
(Effect Unit)
drawPhylo ::
Array Branch
-> Array Period
-> Array Group
-> Array Link
-> Array AncestorLink
-> Array BranchLink
-> Array Number
-> Effect Unit
drawPhylo = runFn7 _drawPhylo
......@@ -134,31 +134,32 @@ type EdgeData =
)
data RawEdge
= GroupToGroup
= GroupToAncestor
{ _gvid :: Int
, constraint :: String
, arrowhead :: String
, edgeType :: String
, lbl :: String
, penwidth :: String
, style :: String
| EdgeData
}
| BranchToGroup
| GroupToGroup
{ _gvid :: Int
, arrowhead :: String
, constraint :: String
, edgeType :: String
, lbl :: String
, penwidth :: String
| EdgeData
}
| BranchToBranch
| BranchToGroup
{ _gvid :: Int
, arrowhead :: String
, style :: String
, edgeType :: String
| EdgeData
}
| GroupToAncestor
| BranchToBranch
{ _gvid :: Int
, arrowhead :: String
, lbl :: String
, penwidth :: String
, style :: String
| EdgeData
}
......
......@@ -4,29 +4,16 @@ module Gargantext.Components.PhyloExplorer.Layout
import Gargantext.Prelude
import DOM.Simple (Window, window)
import DOM.Simple (window)
import DOM.Simple.Console (log2)
import Data.Array as Array
import Data.Date as Date
import Data.FoldableWithIndex (forWithIndex_)
import Data.Int as Int
import Data.Maybe (Maybe(..), maybe)
import Data.Number as Number
import Data.String as String
import Data.Symbol (SProxy(..))
import Data.Traversable (for, for_)
import Data.Tuple as Tuple
import Data.Tuple.Nested ((/\))
import Effect (Effect)
import FFI.Simple (maybeGetProperty, (..), (...), (.=), (.?))
import Gargantext.Components.PhyloExplorer.Types (GlobalTerm(..), Group(..), PhyloDataSet(..))
import Gargantext.Components.PhyloExplorer.Draw (drawPhylo)
import Gargantext.Components.PhyloExplorer.JSON (RawEdge(..))
import Gargantext.Components.PhyloExplorer.Types (PhyloDataSet(..), setGlobalDependencies)
import Gargantext.Utils (nbsp)
import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
import Record (get)
import Toestand as T
import Type.Proxy (Proxy(..))
here :: R2.Here
here = R2.here "Gargantext.Components.PhyloExplorer"
......@@ -46,6 +33,16 @@ layoutCpt = here.component "layout" cpt where
R.useEffectOnce' $ do
setGlobalDependencies window (PhyloDataSet o)
drawPhylo
o.branches
o.periods
o.groups
o.links
o.ancestorLinks
o.branchLinks
o.bb
-- @hightlightSource
let
......@@ -259,59 +256,6 @@ layoutCpt = here.component "layout" cpt where
]
setGlobalDependencies :: Window -> PhyloDataSet -> Effect Unit
setGlobalDependencies w (PhyloDataSet o)
= do
_ <- pure $ (w .= "freq") {}
_ <- pure $ (w .= "nbBranches") o.nbBranches
_ <- pure $ (w .= "nbDocs") o.nbDocs
_ <- pure $ (w .= "nbFoundations") o.nbFoundations
_ <- pure $ (w .= "nbGroups") o.nbGroups
_ <- pure $ (w .= "nbPeriods") o.nbPeriods
_ <- pure $ (w .= "nbTerms") o.nbTerms
_ <- pure $ (w .= "sources") o.sources
_ <- pure $ (w .= "terms") []
_ <- pure $ (w .= "timeScale") o.timeScale
_ <- pure $ (w .= "weighted") o.weighted
(freq :: Array Int) <- pure $ w .. "freq"
(terms :: Array GlobalTerm) <- pure $ w .. "terms"
for_ o.groups \(Group g) -> do
let
f = g.foundation
l = g.label
log2 "group" g
-- For each entries in group.foundation array,
-- increment consequently the global window.keys array
-- forWithIndex_ f \i _ ->
-- let i' = show i
-- in case (freq .? i') of
-- Nothing -> pure $ (freq .= i') 0
-- Just v -> pure $ (freq .= i') (v +1)
for_ f \i ->
let i' = show i
in case (freq .? i') of
Nothing -> pure $ (freq .= i') 0
Just v -> pure $ (freq .= i') (v +1)
-- For each entries in group.foundation array,
-- if the global window.terms does not have it in property,
-- append an item to the global window.terms
for_ f \i ->
let i' = show i
in case (terms .? i') of
Nothing -> pure unit
Just _ -> void <<< pure $ (terms .= i') $ GlobalTerm
{ label: l .. i'
, fdt : f .. i'
}
--------------------------------------------------------
type PhyloCorpusProps = ()
......
......@@ -49,32 +49,3 @@ function utcStringToDate(str) {
exports.yearToDate = yearToDate;
exports.stringToDate = stringToDate;
exports.utcStringToDate = utcStringToDate;
function draw(json) {
var links = json.edges.filter(edges => edges.edgeType == "link").map(function(l){
return { lId : parseInt(l._gvid),
from : parseInt(l.tail) ,
to : parseInt(l.head) ,
label : l.label}
});
var aLinks = json.edges.filter(edges => edges.edgeType == "ancestorLink").map(function(l){
return { lId : parseInt(l._gvid),
from : parseInt(l.tail) ,
to : parseInt(l.head) ,
label : l.label }
});
var bLinks = json.edges.filter(edges => edges.edgeType == "branchLink").map(function(l){
return { from : parseInt(l.tail) ,
to : parseInt(l.head) }
});
window.terms = Object.values(window.terms)
// draw the phylo
drawPhylo(branches,periods,groups,links,aLinks,bLinks,bb);
}
module Gargantext.Components.PhyloExplorer.Types
( PhyloDataSet(..)
, Branch(..), Period(..), Group(..)
, Link(..), AncestorLink(..), BranchLink(..)
, GlobalTerm(..)
, parsePhyloJSONSet
, setGlobalDependencies
) where
import Gargantext.Prelude
import DOM.Simple (Window)
import DOM.Simple.Console (log2)
import Data.Array as Array
import Data.Date as Date
import Data.Foldable (for_)
import Data.FoldableWithIndex (forWithIndex_)
import Data.Generic.Rep (class Generic)
import Data.Int as Int
import Data.Maybe (Maybe(..), maybe)
......@@ -17,19 +23,25 @@ import Data.Show.Generic (genericShow)
import Data.String as String
import Data.Tuple as Tuple
import Data.Tuple.Nested ((/\))
import Gargantext.Components.PhyloExplorer.JSON (PhyloJSONSet(..), RawObject(..))
import Effect (Effect)
import FFI.Simple (applyTo, (..), (.=), (.?))
import Gargantext.Components.PhyloExplorer.JSON (PhyloJSONSet(..), RawEdge(..), RawObject(..))
import Unsafe.Coerce (unsafeCoerce)
-- @WIP Date or foreign?
-- @WIP PureScript Date or stick to JavaScript foreign?
foreign import yearToDate :: String -> Date.Date
foreign import stringToDate :: String -> Date.Date
foreign import utcStringToDate :: String -> Date.Date
newtype PhyloDataSet = PhyloDataSet
{ bb :: Array Number
{ ancestorLinks :: Array AncestorLink
, bb :: Array Number
, branchLinks :: Array BranchLink
, branches :: Array Branch
, groups :: Array Group
, links :: Array Link
, nbBranches :: Int
, nbDocs :: Int
, nbFoundations :: Int
......@@ -48,9 +60,12 @@ instance Show PhyloDataSet where show = genericShow
parsePhyloJSONSet :: PhyloJSONSet -> PhyloDataSet
parsePhyloJSONSet (PhyloJSONSet o) = PhyloDataSet
{ bb : parseBB o.bb
{ ancestorLinks
, bb : parseBB o.bb
, branchLinks
, branches
, groups
, links
, nbBranches : parseInt o.phyloBranches
, nbDocs : parseInt o.phyloDocs
, nbFoundations : parseInt o.phyloFoundations
......@@ -64,10 +79,14 @@ parsePhyloJSONSet (PhyloJSONSet o) = PhyloDataSet
}
where
epochTS = o.phyloTimeScale == "epoch"
branches = parseBranches o.objects
groups = parseGroups epochTS o.objects
periods = parsePeriods epochTS o.objects
epochTS = o.phyloTimeScale == "epoch"
ancestorLinks = parseAncestorLinks o.edges
branchLinks = parseBranchLinks o.edges
branches = parseBranches o.objects
groups = parseGroups epochTS o.objects
links = parseLinks o.edges
periods = parsePeriods epochTS o.objects
-----------------------------------------------------------
......@@ -173,6 +192,107 @@ parseGroups epoch
-----------------------------------------------------------
data Link = Link
{ from :: Int
, lId :: Int
, label :: String -- @WIP: undefined in Mèmiescape v2, still needed?
, to :: Int
}
derive instance Generic Link _
derive instance Eq Link
instance Show Link where show = genericShow
parseLinks :: Array RawEdge -> Array Link
parseLinks
= Array.filter filter
>>> map parse
>>> Array.catMaybes
where
-- @WIP: necessary?
-- bc. GroupToGroup as 1-1 relation with "edgeType=link"
filter :: RawEdge -> Boolean
filter (GroupToGroup o) = o.edgeType == "link"
filter _ = false
parse :: RawEdge -> Maybe Link
parse (GroupToGroup o) = Just $ Link
{ from : o.tail
, lId : o._gvid
, label : ""
, to : o.head
}
parse _ = Nothing
-----------------------------------------------------------
data AncestorLink = AncestorLink
{ from :: Int
, lId :: Int
, label :: String -- @WIP: undefined in Mèmiescape v2, still needed?
, to :: Int
}
derive instance Generic AncestorLink _
derive instance Eq AncestorLink
instance Show AncestorLink where show = genericShow
parseAncestorLinks :: Array RawEdge -> Array AncestorLink
parseAncestorLinks
= Array.filter filter
>>> map parse
>>> Array.catMaybes
where
-- @WIP: necessary?
-- bc. GroupToAncestor as 1-1 relation with "edgeType=ancestorLink"
filter :: RawEdge -> Boolean
filter (GroupToAncestor o) = o.edgeType == "ancestorLink"
filter _ = false
parse :: RawEdge -> Maybe AncestorLink
parse (GroupToAncestor o) = Just $ AncestorLink
{ from : o.tail
, lId : o._gvid
, label : ""
, to : o.head
}
parse _ = Nothing
-----------------------------------------------------------
data BranchLink = BranchLink
{ from :: Int
, to :: Int
}
derive instance Generic BranchLink _
derive instance Eq BranchLink
instance Show BranchLink where show = genericShow
parseBranchLinks :: Array RawEdge -> Array BranchLink
parseBranchLinks
= Array.filter filter
>>> map parse
>>> Array.catMaybes
where
-- @WIP: necessary?
-- bc. BranchToGroup as 1-1 relation with "edgeType=branchLink"
filter :: RawEdge -> Boolean
filter (BranchToGroup o) = o.edgeType == "branchLink"
filter _ = false
parse :: RawEdge -> Maybe BranchLink
parse (BranchToGroup o) = Just $ BranchLink
{ from : o.tail
, to : o.head
}
parse _ = Nothing
-----------------------------------------------------------
data GlobalTerm = GlobalTerm
{ label :: String
, fdt :: String
......@@ -182,6 +302,55 @@ derive instance Generic GlobalTerm _
derive instance Eq GlobalTerm
instance Show GlobalTerm where show = genericShow
setGlobalDependencies :: Window -> PhyloDataSet -> Effect Unit
setGlobalDependencies w (PhyloDataSet o)
= do
_ <- pure $ (w .= "freq") {}
_ <- pure $ (w .= "nbBranches") o.nbBranches
_ <- pure $ (w .= "nbDocs") o.nbDocs
_ <- pure $ (w .= "nbFoundations") o.nbFoundations
_ <- pure $ (w .= "nbGroups") o.nbGroups
_ <- pure $ (w .= "nbPeriods") o.nbPeriods
_ <- pure $ (w .= "nbTerms") o.nbTerms
_ <- pure $ (w .= "sources") o.sources
_ <- pure $ (w .= "terms") []
_ <- pure $ (w .= "timeScale") o.timeScale
_ <- pure $ (w .= "weighted") o.weighted
(freq :: Array Int) <- pure $ w .. "freq"
(terms :: Array GlobalTerm) <- pure $ w .. "terms"
for_ o.groups \(Group g) -> do
let
f = g.foundation
l = g.label
forWithIndex_ f \idx val ->
let
idx' = show idx
val' = show val
-- For each entries in group.foundation array,
-- increment consequently the global window.keys array
in case (freq .? val') of
Nothing -> pure $ (freq .= val') 0
Just v -> pure $ (freq .= val') (v +1)
-- For each entries in group.foundation array,
-- if the global window.terms does not have it in property,
-- append an item to the global window.terms
*> case (terms .? val') of
Just _ -> pure unit
Nothing -> void <<< pure $ (terms .= val') $ GlobalTerm
{ label: l .. idx'
, fdt : val'
}
-- @XXX: FFI.Simple `(...)` throws error (JavaScript issue)
-- need to decompose computation
void do
new <- pure $ applyTo (terms .. "flat") terms []
pure $ (w .= "terms") new
-----------------------------------------------------------
parseInt :: String -> Int
......
......@@ -9,6 +9,7 @@ import Effect (Effect)
import FFI.Simple ((...))
import Gargantext.Components.App (app)
import Gargantext.Utils.Reactix as R2
import Graphics.D3.Base (D3, d3)
import Prelude (Unit, ($))
main :: Effect Unit
......@@ -17,3 +18,7 @@ main = paint $ toMaybe (document ... "getElementById" $ [ "app" ])
paint :: Maybe Element -> Effect Unit
paint Nothing = log "[main] Container not found"
paint (Just c) = R2.render (app {} []) c
-- @WIP
d3charge :: D3
d3charge = d3
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment