Commit 730c8041 authored by Romain Loth's avatar Romain Loth

project conf: allow local hit templates + more docs + more checks

parent ffc4d242
......@@ -7,26 +7,59 @@ Après commits de la semaine 26-30 juin 2017, une structure plus facile pour les
- une valeur dans les settings et un script bash à lancer 1 fois (adapt_html_paths.sh) suffisent à reconfigurer toute l'appli pour des routes de déploiement spécifiques (par exemple ajouter un prefixe comme 'static/tinawebJS' à tous les liens internes)
- un nouveau dossier twpresets contient des configurations toutes faites pour les cas de déploiement les plus fréquents
- les librairies tierces-parties ont été groupées permettant de les substituer avec plus de facilité lors de factorisation avec les mêmes libs déjà déployées autrement, ou lors de màj de ces librairies
- la structure "projet" gouverne l'organisation des données sous `data` selon le principe: un sous-dossier de `data` = un projet
```
|
├── 00.DOCUMENTATION
│   └── (fusionné avec ./doc)
├── data
│   └── (graphes par sous-projets)
├── explorerjs.html <= point d'entrée lancement
├── settings_explorerjs.js <= config générale
├── server_menu.json <= liste des sources gexf/json par projet
|
├── explorerjs.html <= **le point d'entrée / lancement**
|
├── settings_explorerjs.js <= la config générale
|
├── data <= les données (graphes par sous-projets)
│   │
│   ├── exemplemini <= nom d'un "projet"
│   │    │
│   │    └─ unfichiergraphe.gexf
│   │
| └── exemplemaxi <= un autre "projet"
│       │
│       ├─ unfichiergraphe.json <= les graphes peuvent être json ou gexf
│       │
│       ├─ unebaseassociee.csv <= on peut associer des bases de docs liés
│       │
│       ├─ unfichiergraphe2.gexf
│       │
│       ├─ unebaseassociee2.sql
│       │
│       ├─ hit_templates <= dossier des templates de résultats
│       │    │
│       │    └─ ma_template.html <= pour faire apparaitre les docs liés
│       │ (exemples sous twlibs/default_hit_templates)
│       ├─ (etc.)
│       │
│       └─ project_conf.json <= pour déclarer:
│ - types de nodes
│ - colorations/légendes des attributs des nodes
| - les bases associées pour les requêtes
| (et les templates de résultats ad hoc)
|
├── server_menu.json <= liste des sources gexf/json par projet (optionnelle: sert à afficher un menu)
├── favicon.ico
├── LICENSE
├── README.md
|
├── twbackends <= APIS externes
│   ├── phpAPI <= api CSV et CortextDB
│   └── twitterAPI2
|
├── twlibs <= librairies développées chez nous
│   ├── css
│   ├── fonts
│   ├── img
│   └── README.md
|
├── twlibs3 <= librairies tierces-parties
│   ├── bootstrap-3
│   ├── bootstrap-native
......@@ -37,6 +70,7 @@ Après commits de la semaine 26-30 juin 2017, une structure plus facile pour les
│   └── tweets
|
├── twmain <= ancien dossier tinawebJS
| | (contient l'essentiel des scripts)
│   ├── main.js
│   ├── extras_explorerjs.js <= ajouté à l'intérieur
│   ├── (etc)
......@@ -45,9 +79,11 @@ Après commits de la semaine 26-30 juin 2017, une structure plus facile pour les
├── twmodules <= modules internes
│   ├── crowdsourcingModule
│   └── histogramModule
├── twpresets <= variantes de settings
|
├── twpresets <= variantes de settings pour déploiement
│   ├── README.md
│   └── settings_explorerjs.comex.js
|
└── twtools
|
└── adapt_html_paths.sh <= "compile" un nouvel explorerjs.prod.html
......
......@@ -25,10 +25,10 @@ One minimal entry contains for each graph file of the project dir : a list of ex
The value **typename_of_nodes** should match the `type` or `category` attribute value of your nodes in the source gexf or json. It acts as a filter specifying the nodes that will be displayed in the ProjectExplorer GUI.
##### For a bipartite graph
If the source file has 2 types of nodes, the config should look like this:
If the source file has 2 types of nodes, a minimal config should look like this:
```json
{
"$$source_file.ext":{
"$$graph_source.ext":{
"node0": {"name": "$$typename_of_term_nodes"},
"node1": {"name": "$$typename_of_context_nodes"}
}
......@@ -77,7 +77,7 @@ Expected type is `"csv"` and you should fill the columns to search in and the te
"csv" : {
"file": "$$relpath/to/some.csv",
"qcols": ["list", "of", "cols", "to", "search", "in", "for", "node0"],
"delim": ";"
"delim": ";",
"template": "bib_details"
}
}
......@@ -124,6 +124,38 @@ Expected type is `"twitter"` and no additional conf is needed (POSS for the futu
}
```
In the exemple above, the results from the csv file `model_calibration.csv` will be styled in the interface **according to the `bib_details` template**.
The corresponding template must be called `bib_details.html` and placed under `data/your_project_dir/hit_templates`.
*Exemple template `bib_details.html`:*
```html
<li class="searchhit">
<p>
<b>$${tit}</b>
by
<span class="author">$${au}</span>
,
<i>$${src}</i>
[$${date}]
</p>
<p>
<span class="hit-keywords">
$${kws}
</span>
<span class="hit-text">
$${txt}
</span>
</p>
</li>
```
Such a template is a custom html file representing an element `<li class="searchhit">`, and can use the columns as template variables like so: `$${colname}`.
An additional variable `${{score}}` is always available in the templating context.
--------------------------------------------------------------------------------
```json
{
......@@ -153,6 +185,6 @@ Expected type is `"twitter"` and no additional conf is needed (POSS for the futu
}
```
In the last exemple, we have two nodetypes:
In this last exemple, we have two nodetypes:
- node0 allows both CSV and twitter relatedDocs tabs.
- node1 allows only the CSV relatedDocs tab.
......@@ -41,6 +41,9 @@ firefox explorerjs.html
```
=> An input in the upper right side allows you to open any gexf file.
###### Application and data structures
An overview of the application structure can be found in the extended documentation under [00.DOCUMENTATION/A-Introduction/app_structure.md](https://github.com/moma/ProjectExplorer/blob/master/00.DOCUMENTATION/A-Introduction/app_structure.md) (comments are in french).
###### Usage on a web server
To activate all features, you should:
1. configure a web server like apache or nginx, for instance on your localhost
......@@ -56,10 +59,11 @@ Once you have this webserver running and some source data files, you may also co
- it will be shown as a **menu** to select graphs in the interface
- it allows to define associated **node types** for each source
- it allows to define associated **search backends** for each source
- to use this, follow the guidelines in the **[Servermenu HOWTO](https://github.com/moma/ProjectExplorer/blob/master/00.DOCUMENTATION/A-Introduction/servermenu_config.md)**
- to use this, follow the guidelines in the **[Project config HOWTO](https://github.com/moma/ProjectExplorer/blob/master/00.DOCUMENTATION/A-Introduction/project_config.md)**
###### Integration in a larger app
To integrate ProjectExplorer in a larger web application, you may have several locations with subdirectories defined on your server. In this case, you'll need to use the provided path modification tool (see this [integration procedure example](https://github.com/moma/ProjectExplorer/tree/master/00.DOCUMENTATION/A-Introduction#integration-policy))
###### Advanced settings
For more information about other ProjectExplorer's settings (settings file, input modes, attribute processing options), please refer to the [developer's manual](https://github.com/moma/ProjectExplorer/blob/master/00.DOCUMENTATION/C-advanced/developer_manual.md).
......
......@@ -193,11 +193,11 @@ TW.conf = (function(TW){
// ------------
TWConf.paths = {
'ourlibs': 'twlibs',
'templates': 'twlibs/hit_templates',
'modules': 'twmodules',
'templates': 'twlibs/default_hit_templates', // some default templates
'sourceFile': "", // server-side gexf|json default source
'sourceMenu': "server_menu.json" // ...or server-side gexf|json source list
'sourceFile': null, // server: 1 default gexf|json graph source
'sourceMenu': "server_menu.json" // ...or server: a gexf|json sources list
}
Object.freeze(TWConf.paths) // /!\ to prevent path modification before load
......
## Related Documents PHP backend
##### Provides an API for "topPapers" search queries in tinawebJS
##### Provides an API for "topPapers" search queries in ProjectExplorer
These php files provide access to a CSV or sqlite database as an ajax endpoint for a "related documents" search in tinawebJS client.
These php files provide access to a CSV or sqlite database as an ajax endpoint for a "related documents" search in ProjectExplorer client.
Main use case is support for one-doc-by-row CSV files.
It means that the selection of a node (or a set of nodes) in the ProjectExplorer interface can trigger a simple search-engine query for documents containing the names of these nodes in the said CSV or sqlite DBs.
Main use case is support for one-doc-by-row CSV files showing, for instance, scientific articles, that will be displayed as "topPapers" for selected nodes in the interface.
#### Prerequisites
......@@ -55,49 +57,42 @@ To use the API for the "topPapers" embedded search in ProjectExplorer, the corre
```
Finally, to match the correct DB with the correct graph file:
- both should reside in `data/yoursubdir`
- the appropriate source database information needs to appear in `db.json` in order to associate the graph source file (eg gexf) with this related docs API:
- both should reside in `data/yoursubdir` where "yoursubdir" is the name of your project
- the appropriate source database information needs to appear in a file named `project_conf.json` in the same directory `data/yoursubdir`, in order to associate the nodes from the graph source file (eg gexf) with this related docs API:
For instance for a cortextDB associated with a graph with two types of nodes:
```json
{
"your.graph.gexf": {
"node0": {
"name": "terms",
"reldbtype": "CortextDB",
"reldbfile": "yourDB.db",
"reldbqtable": "yourTableWithTerms"
},
"node1": {
"name": "people",
"reldbtype": "CortextDB",
"reldbfile": "yourDB.db",
"reldbqtable": "yourTableWithSocialNodes"
}
}
}
```
Or for a csv example and a graph with one type of nodes:
```json
"data/yoursubdir": {
"graphs": {
"your.graph.gexf": {
"node0": {
"name": "terms",
"reldbtype": "CortextDB",
"reldbfile": "yourDB.db",
"reldbqtable": "yourTableWithTerms"
},
"node1": {
"name": "people",
"reldbtype": "CortextDB",
"reldbfile": "yourDB.db",
"reldbqtable": "yourTableWithSocialNodes"
},
}
}
},
"data/anothersubdir": {
"graphs": {
"another.graph.gexf": {
"node0": {
"name": "terms",
"reldbtype": "csv",
"reldbfile": "aCsvByDocs.csv",
"reldbqcols": ["title", "text", "keywords"]
},
"node1": {
"name": "people",
"reldbtype": "csv",
"reldbfile": "aCsvByDocs.csv",
"reldbqcols": ["authors", "editors"]
},
}
{
"another.graph.gexf": {
"node0": {
"name": "terms",
"reldbtype": "csv",
"reldbfile": "yourCsvFile.csv",
"reldbqcols": ["title", "text", "keywords"]
}
}
}
```
See more exemples and explanations in [servermenu_config.md](https://github.com/moma/ProjectExplorer/blob/master/00.DOCUMENTATION/A-Introduction/servermenu_config.md).
See more exemples and explanations in [project_config.md](https://github.com/moma/ProjectExplorer/blob/master/00.DOCUMENTATION/A-Introduction/project_config.md).
......@@ -18,7 +18,7 @@ function echodump($title, $anyObj, $output_mode = "json") {
function errmsg($message, $context, $more = "") {
echo "<p class='micromessage'>The relatedDocs DB conf for $context $message
(please read A-Introduction/servermenu_config.md).<br>$more</p>";
(please read A-Introduction/project_config.md).<br>$more</p>";
}
// reading project_conf.json associations
......
<li class="searchhit" title="$${score}">
<p>
<b>$${tit}</b>
by
<span class="author">$${au}</span>
,
<i>$${src}</i>
[$${date}]
</p>
<p>
<span class="hit-keywords">
$${kws}
</span>
<span class="hit-text">
$${txt}
</span>
</p>
</li>
......@@ -204,6 +204,10 @@ function alertCheckBox(eventCheck){
}
}
// fileChooser: added to the environment when user opens explorer as local file
// -----------
// TODO: because source files now get a project_conf.md, find a way to open it too if it exists
function createFilechooserEl () {
var inputComment = document.createElement("p")
......@@ -218,6 +222,8 @@ function createFilechooserEl () {
graphFileInput.classList.add('centered')
// NB file input will trigger mainStartGraph() when the user chooses something
graphFileInput.onchange = function() {
if (this.files && this.files[0]) {
......
......@@ -473,30 +473,60 @@ function getTopPapers(qWords, nodetypeId, chosenAPI, tgtDivId) {
}
}
// function searches for template files in that order:
// 1) project-local data/myproject/hit_templates directory
// 2) app default twlibs/default_hit_templates directory
function makeRendererFromTemplate(tmplName) {
let tmplURL = TW.conf.paths.templates + '/' + tmplName + '.html'
let gotTemplate = AjaxSync({ url: tmplURL });
let tmplStr = ''
let tmplURL
let gotTemplate
var tmplStr = ''
if (gotTemplate['OK']) {
tmplStr = gotTemplate.data
let defRenderer = function(jsonHit) {
return JSON.stringify(jsonHit, null, ' ').replace(/\n/g, '<br>') + '<br>'
}
if (! tmplName) {
return defRenderer
}
// we return a customized renderJsonToHtml function
return function(jsonHit) {
let htmlOut = tmplStr
for (key in jsonHit) {
// our tags look like this in the template ====> by $${author}, [$${date}]
let reKey = new RegExp('\\$\\$\\{'+key+'\\}', 'g')
// we replace them by value
htmlOut = htmlOut.replace(reKey, jsonHit[key])
// (1)
if (TW.Project) {
tmplURL = TW.Project + '/hit_templates/' + tmplName + '.html' ;
if (linkCheck(tmplURL)) {
gotTemplate = AjaxSync({ url: tmplURL });
}
}
// (2)
if (! gotTemplate || ! gotTemplate['OK']) {
tmplURL = TW.conf.paths.templates + '/' + tmplName + '.html'
if (linkCheck(tmplURL)) {
gotTemplate = AjaxSync({ url: tmplURL });
}
}
// we also replace any not found keys by 'N/A'
let reKeyAll = new RegExp('\\$\\$\\{[^\\}]+\\}', 'g')
htmlOut = htmlOut.replace(reKeyAll, "N/A")
if (gotTemplate && gotTemplate['OK']) {
tmplStr = gotTemplate.data
// we return a customized renderJsonToHtml function
return function(jsonHit) {
let htmlOut = tmplStr
for (key in jsonHit) {
// our tags look like this in the template ==> by $${author}, [$${date}]
let reKey = new RegExp('\\$\\$\\{'+key+'\\}', 'g')
// we replace them by value
htmlOut = htmlOut.replace(reKey, jsonHit[key])
}
// we also replace any not found keys by 'N/A'
let reKeyAll = new RegExp('\\$\\$\\{[^\\}]+\\}', 'g')
htmlOut = htmlOut.replace(reKeyAll, "N/A")
return htmlOut
return htmlOut
}
}
else {
console.error(`couldn't find template ${tmplName} at ${tmplURL},
using raw hits display`)
return defRenderer
}
}
......
......@@ -4,6 +4,7 @@
TW.File = "" // remember the currently opened file
TW.Project = "" // remember the project of currently opened file
// a system state is the summary of tina situation
TW.initialSystemState = {
......@@ -299,7 +300,8 @@ function syncRemoteGraphData () {
// inData: source data as str
// twInstance: a tinaweb object (gui, methods) to bind the graph to
//
// NB: function also uses TW.File to get the associated project_conf.json entry
// NB: function also uses TW.File to get the associated project dir and conf
// and TW.conf for all global settings
function mainStartGraph(inFormat, inData, twInstance) {
// Graph-related vars
......@@ -325,16 +327,30 @@ function mainStartGraph(inFormat, inData, twInstance) {
else {
let optNodeTypes = null
let optRelDBs = null
if (TW.sourcemode == "api") {
optNodeTypes = TW.conf.sourceAPI.nodetypes
}
else {
// try and retrieve associated conf
[optNodeTypes, optRelDBs] = readProjectConf(TW.File)
// we assume the filePath is of the form projectPath/sourceFile
// (NB these are server-side path so we got linux-style slashes)
let pathsplit = TW.File.match("^(.*)/([^/]+)$")
if (! pathsplit) {
console.warn (`couldn't make out project path from ${TW.File}:
won't read project conf and will try using defaults`)
}
else {
let srcDirname = pathsplit[1] ;
let srcBasename = pathsplit[2] ;
// export to global for getTopPapers function :/
if (optRelDBs) {
TW.currentRelDocsDBs = optRelDBs
// try and retrieve associated conf
[optNodeTypes, optRelDBs] = readProjectConf(srcDirname, srcBasename)
// export to globals for getTopPapers and makeRendererFromTemplate
if (optRelDBs) {
TW.currentRelDocsDBs = optRelDBs
TW.Project = srcDirname
}
}
}
......
......@@ -162,75 +162,79 @@ function readMenu(infofile) {
return [serverMenu, firstProject]
}
// read project_conf.json files
function readProjectConf(aFilePath) {
// read project_conf.json files in the project for this file
function readProjectConf(projectPath, filePath) {
let declaredNodetypes
let declaredDBConf
// we assume the filePath is of the form projectPath/sourceFile
let split = aFilePath.match("^(.*)/([^/]+)$")
if (! split) {
console.warn (`couldn't read associated conf for file, ${aFilePath}, will try using default nodetypes`)
// ££TODO declaredFacetOptions
let projectConfFile = projectPath + '/project_conf.json'
if (! linkCheck(projectConfFile)) {
console.warn (`no project_conf.json next to the file, ${filePath},
will try using default nodetypes`)
}
else {
let projectPath = split[1]
let filePath = split[2]
let projectConfFile = projectPath + '/project_conf.json'
if (! linkCheck(projectConfFile)) {
console.warn (`no project_conf.json next to the file, ${aFilePath}, will try using default nodetypes`)
}
else {
if (TW.conf.debug.logFetchers)
console.info(`attempting to load project conf ${projectConfFile}`)
if (TW.conf.debug.logFetchers) console.info(`attempting to load project conf ${projectConfFile}`)
var pjconfRes = AjaxSync({ url: projectConfFile, datatype:"json" });
var pjconfRes = AjaxSync({ url: projectConfFile, datatype:"json" });
if (TW.conf.debug.logFetchers) console.log('project conf AjaxSync result pjconfRes', pjconfRes)
if (TW.conf.debug.logFetchers)
console.log('project conf AjaxSync result pjconfRes', pjconfRes)
if (! pjconfRes['OK']
|| ! pjconfRes.data
|| ! pjconfRes.data[filePath] ) {
console.warn (`project_conf.json in ${projectPath} is not valid json or does not contain an entry for ${filePath}, will try using default nodetypes`)
}
else {
let confEntry = pjconfRes.data[filePath]
for (var ndtype in confEntry) {
if (! /node\d+/.test(ndtype)) {
console.warn (`project_conf.json in ${projectPath}, in the entry for ${filePath}, should only contain properties like 'node0', 'node1', etc.`)
if (! pjconfRes['OK']
|| ! pjconfRes.data
|| ! pjconfRes.data[filePath] ) {
console.warn (`project_conf.json in ${projectPath} is not valid json
or does not contain an entry for ${filePath},
will try using default nodetypes`)
}
else {
let confEntry = pjconfRes.data[filePath]
for (var ndtype in confEntry) {
if (! /node\d+/.test(ndtype)) {
console.warn (`project_conf.json in ${projectPath}, in the entry
for ${filePath}, should only contain properties
like 'node0', 'node1', etc.`)
}
else {
if (! confEntry[ndtype].name) {
console.warn (`project_conf.json in ${projectPath}, in the entry for
${filePath}.${ndtype}, should contain a 'name' slot`)
}
// valid case !
else {
if (! confEntry[ndtype].name) {
console.warn (`project_conf.json in ${projectPath}, in the entry for ${filePath}.${ndtype}, should contain a 'name' property`)
}
// valid case !
else {
if (! declaredNodetypes) declaredNodetypes = {}
if (! declaredNodetypes) declaredNodetypes = {}
// fill simple nodetypes
declaredNodetypes[ndtype] = confEntry[ndtype].name
}
// fill simple nodetypes
declaredNodetypes[ndtype] = confEntry[ndtype].name
}
// optional reldbs -----------------------
if (confEntry[ndtype].reldbs) {
if (! declaredDBConf) declaredDBConf = {}
// optional reldbs -----------------------
if (confEntry[ndtype].reldbs) {
if (! declaredDBConf) declaredDBConf = {}
// it must match because we tested well-formedness above
let ndtypeId = ndtype.match(/^node(\d+)/)[1]
// it must match because we tested well-formedness above
let ndtypeId = ndtype.match(/^node(\d+)/)[1]
declaredDBConf[ndtypeId] = {}
for (var dbtype in confEntry[ndtype].reldbs) {
if (! TW.conf.relatedDocsAPIS[dbtype]) {
console.info (`project_conf.json: ${projectPath}.${filePath}.${ndtype}: skipping unknown related docs db type **${dbtype}**. The only available db types are: ${Object.keys(TW.conf.relatedDocsAPIS)}.`)
}
else {
declaredDBConf[ndtypeId][dbtype] = confEntry[ndtype].reldbs[dbtype]
}
declaredDBConf[ndtypeId] = {}
for (var dbtype in confEntry[ndtype].reldbs) {
if (! TW.conf.relatedDocsAPIS[dbtype]) {
console.info (`project_conf.json: ${projectPath}.${filePath}.${ndtype}:
skipping unknown related docs db type **${dbtype}**.
The only available db types are:
${Object.keys(TW.conf.relatedDocsAPIS)}.`)
}
else {
declaredDBConf[ndtypeId][dbtype] = confEntry[ndtype].reldbs[dbtype]
}
}
// ----------------------------------------
}
// ----------------------------------------
}
}
}
......
......@@ -222,7 +222,7 @@ function sortNodeTypes(observedTypesDict, optionalNodeConf) {
let nbNodeTypes = 2
var declaredTypes = []
for (var i = 0 ; i < nbNodeTypes ; i++ ) {
if (optionalNodeConf["node"+i]) {
if (optionalNodeConf && optionalNodeConf["node"+i]) {
declaredTypes[i] = optionalNodeConf["node"+i]
if (TW.conf.debug.logSettings)
console.log("expected cat (from db.json addtional conf)", i, declaredTypes[i])
......
......@@ -20,9 +20,10 @@ TW.conf = (function(TW){
TWConf.sourcemode = "api" // accepted: "api" | "serverfile" | "servermenu" | "localfile"
// ...or remote bridge to default source api ajax queries
TWConf.sourceAPI={};
TWConf.sourceAPI["forNormalQuery"] = "services/api/graph";
TWConf.sourceAPI["forFilteredQuery"] = "services/api/graph";
TWConf.sourceAPI={}
TWConf.sourceAPI["nodetypes"] = {"node0": "NGram", "node1": "Document" }
TWConf.sourceAPI["forNormalQuery"] = "services/api/graph"
TWConf.sourceAPI["forFilteredQuery"] = "services/api/graph"
// Related documents (topPapers) data source
......@@ -55,6 +56,9 @@ TW.conf = (function(TW){
// create facets ?
TWConf.scanClusters = true
// use a facet for default color
TWConf.defaultColoring = null
// facetOptions: choose here the visual result of your node attributes
// -------------------------------------------------------------------
// 3 possible coloring functions
......@@ -189,11 +193,11 @@ TW.conf = (function(TW){
// ------------
TWConf.paths = {
'ourlibs': 'static/tinawebJS/twlibs',
'templates': 'static/tinawebJS/twlibs/hit_templates',
'modules': 'twmodules',
'modules': 'static/tinawebJS/twmodules',
'templates': 'static/tinawebJS/twlibs/default_hit_templates',
'sourceFile': "", // server-side .gexf|.json default source
'sourceMenu': "db.json" // ...or server-side gexf default source list
'sourceFile': null, // server: 1 default gexf|json graph source
'sourceMenu': "static/tinawebJS/server_menu.json" // ...or server: a gexf|json sources list
}
Object.freeze(TWConf.paths) // /!\ to prevent path modification before load
......
......@@ -20,9 +20,10 @@ TW.conf = (function(TW){
TWConf.sourcemode = "servermenu" // accepted: "api" | "serverfile" | "servermenu" | "localfile"
// ...or remote bridge to default source api ajax queries
TWConf.sourceAPI={};
TWConf.sourceAPI["forNormalQuery"] = "services/api/graph";
TWConf.sourceAPI["forFilteredQuery"] = "services/api/graph";
TWConf.sourceAPI={}
TWConf.sourceAPI["nodetypes"] = {"node0": "NGram", "node1": "Document" }
TWConf.sourceAPI["forNormalQuery"] = "services/api/graph"
TWConf.sourceAPI["forFilteredQuery"] = "services/api/graph"
// Related documents (topPapers) data source
......@@ -192,11 +193,11 @@ TW.conf = (function(TW){
// ------------
TWConf.paths = {
'ourlibs': 'twlibs',
'templates': 'twlibs/hit_templates',
'modules': 'twmodules',
'templates': 'twlibs/default_hit_templates', // some default templates
'sourceFile': "", // server-side .gexf|.json default source
'sourceMenu': "db.json" // ...or server-side gexf default source list
'sourceFile': null, // server: 1 default gexf|json graph source
'sourceMenu': "server_menu.json" // ...or server: a gexf|json sources list
}
Object.freeze(TWConf.paths) // /!\ to prevent path modification before load
......
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